@aippy/runtime 0.4.1-dev.1 → 0.4.2-dev.0
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 +17 -6
- package/dist/ai/credits.d.ts +12 -0
- package/dist/ai/index.d.ts +2 -0
- package/dist/ai/index.js +20 -16
- package/dist/ai/viggle/generate.d.ts +24 -0
- package/dist/{container-message-KgL1paGV.js → container-message-yZltTPi4.js} +1 -1
- package/dist/core/index.js +1 -1
- package/dist/helper-7v3LLvbl.js +373 -0
- package/dist/index/index.js +53 -49
- package/dist/tweaks/index.js +1 -1
- package/dist/{useTweaks-v5wEZGGm.js → useTweaks-C7BEMpV3.js} +21 -27
- package/package.json +11 -3
- package/dist/helper-CZqFi-QF.js +0 -241
package/README.md
CHANGED
|
@@ -17,14 +17,19 @@ import { AippyConfig, mergeConfig } from '@aippy/runtime/core';
|
|
|
17
17
|
|
|
18
18
|
const config = mergeConfig({
|
|
19
19
|
debug: true,
|
|
20
|
-
apiBaseUrl: 'https://api.example.com'
|
|
20
|
+
apiBaseUrl: 'https://api.example.com',
|
|
21
21
|
});
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
### Device APIs
|
|
25
25
|
|
|
26
26
|
```typescript
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
camera,
|
|
29
|
+
geolocation,
|
|
30
|
+
sensors,
|
|
31
|
+
fileSystem,
|
|
32
|
+
} from '@aippy/runtime/device';
|
|
28
33
|
|
|
29
34
|
// Camera
|
|
30
35
|
const stream = await camera.getStream();
|
|
@@ -32,13 +37,13 @@ const photo = await camera.capturePhoto({ quality: 'high' });
|
|
|
32
37
|
|
|
33
38
|
// Geolocation
|
|
34
39
|
const position = await geolocation.getCurrentPosition();
|
|
35
|
-
const watchId = geolocation.watchPosition(
|
|
40
|
+
const watchId = geolocation.watchPosition(pos => {
|
|
36
41
|
console.log('Position:', pos);
|
|
37
42
|
});
|
|
38
43
|
|
|
39
44
|
// Sensors
|
|
40
45
|
const orientation = await sensors.getOrientation();
|
|
41
|
-
const cleanup = sensors.watchOrientation(
|
|
46
|
+
const cleanup = sensors.watchOrientation(data => {
|
|
42
47
|
console.log('Orientation:', data);
|
|
43
48
|
});
|
|
44
49
|
|
|
@@ -78,7 +83,7 @@ const patchedCtx = patchAudioContext(ctx);
|
|
|
78
83
|
// Unlock audio on user interaction (required on iOS)
|
|
79
84
|
button.onclick = async () => {
|
|
80
85
|
await patchedCtx.unlock();
|
|
81
|
-
|
|
86
|
+
|
|
82
87
|
// Use native Web Audio API as normal
|
|
83
88
|
const osc = patchedCtx.createOscillator();
|
|
84
89
|
osc.connect(patchedCtx.destination);
|
|
@@ -90,7 +95,9 @@ button.onclick = async () => {
|
|
|
90
95
|
### AI (Backend Proxy Adapter)
|
|
91
96
|
|
|
92
97
|
```typescript
|
|
93
|
-
// Default base URL: https://api.aippy.
|
|
98
|
+
// Default base URL: https://api.aippy.ai/aisdk/v1/ (no /api prefix)
|
|
99
|
+
// Resolved by core/env.ts at runtime — api.aippy.dev only when the page host
|
|
100
|
+
// ends in .aippynow.com or is localhost; everything else gets prod.
|
|
94
101
|
|
|
95
102
|
import { streamText, experimental_generateImage as generateImage } from 'ai';
|
|
96
103
|
import { aippyAIProvider } from '@aippy/runtime/ai';
|
|
@@ -120,6 +127,10 @@ const image = await generateImage({
|
|
|
120
127
|
console.log(image.image?.base64);
|
|
121
128
|
```
|
|
122
129
|
|
|
130
|
+
The AI module adds `getCredits` and `deductCredits` in the unreleased source; published `@aippy/runtime@0.4.1` does not include them. Use them only after installing a published release containing both exports (`>= 0.4.2`), and verify the installed module declarations before importing.
|
|
131
|
+
|
|
132
|
+
The server checks the balance atomically and prevents duplicate charges for the same event and amount; changed charge details return HTTP 409. Insufficient balance uses the existing runtime error and host notification. Call credits functions from UI handlers with error handling. Use explicit deductions for custom actions; model generation already charges credits. See the [AI module](./src/ai/README.md) and `aippy-ai-sdk` skill for usage.
|
|
133
|
+
|
|
123
134
|
## Packages
|
|
124
135
|
|
|
125
136
|
- `@aippy/runtime/core` - Core types and configuration
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AippyOpenAIConfig } from './shared';
|
|
2
|
+
export interface CreditsRequestOptions extends AippyOpenAIConfig {
|
|
3
|
+
signal?: AbortSignal;
|
|
4
|
+
}
|
|
5
|
+
export interface DeductCreditsOptions extends CreditsRequestOptions {
|
|
6
|
+
/** One UUID per business action. Retries must reuse both the UUID and amount. */
|
|
7
|
+
eventId: string;
|
|
8
|
+
}
|
|
9
|
+
/** Return the authenticated user's VIP plus regular credit balance. */
|
|
10
|
+
export declare function getCredits(options?: CreditsRequestOptions): Promise<number>;
|
|
11
|
+
/** Deduct a positive integer amount. The server checks the balance atomically. */
|
|
12
|
+
export declare function deductCredits(amount: number, options: DeductCreditsOptions): Promise<void>;
|
package/dist/ai/index.d.ts
CHANGED
|
@@ -41,4 +41,6 @@ export type { AippyOpenAIConfig } from './openai';
|
|
|
41
41
|
export { aippyChatConfig, type AippyUseChatOptions, type AippyUIConfig, type AippyChatConfig, UI_CHAT_ENDPOINT, } from './ui';
|
|
42
42
|
export { DEFAULT_BASE_URL, DEFAULT_UI_BASE_URL, DEFAULT_CHAT_MODEL, DEFAULT_CHAT_SYSTEM, resolveOpenAIConfig, resolveUIConfig, } from './shared';
|
|
43
43
|
export { normalizeError } from './errors';
|
|
44
|
+
export { getCredits, deductCredits, type CreditsRequestOptions, type DeductCreditsOptions, } from './credits';
|
|
45
|
+
export { generateCharacter3D, generateMotion, type GenerateCharacter3DInput, type GenerateMotionInput, type ViggleAsset, } from './viggle/generate';
|
|
44
46
|
export { type AIConfig, type AIConfigValue, type AIConfigItem, type NumberAIConfigItem, type BooleanAIConfigItem, type TextAIConfigItem, type EnumAIConfigItem, type AIConfigError, type AIConfigValues, validateAIConfig, parseAIConfig, loadAIConfig, getAIConfigValue, sendAIConfigToContainer, createAIConfig, } from './config';
|
package/dist/ai/index.js
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
import { D as
|
|
1
|
+
import { D as r, d as i, e as n, c as A, U as C, a as t, b as g, m as I, h as f, i as _, j as p, k as E, g as T, l as U, n as d, p as D, r as l, f as L, s as m, v } from "../helper-7v3LLvbl.js";
|
|
2
2
|
import "react";
|
|
3
3
|
import "../bridge-CtB9L5kL.js";
|
|
4
4
|
export {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
r as DEFAULT_BASE_URL,
|
|
6
|
+
i as DEFAULT_CHAT_MODEL,
|
|
7
|
+
n as DEFAULT_CHAT_SYSTEM,
|
|
8
|
+
A as DEFAULT_UI_BASE_URL,
|
|
9
9
|
C as UI_CHAT_ENDPOINT,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
D as
|
|
10
|
+
t as aippyAIProvider,
|
|
11
|
+
g as aippyChatConfig,
|
|
12
|
+
I as createAIConfig,
|
|
13
|
+
f as deductCredits,
|
|
14
|
+
_ as generateCharacter3D,
|
|
15
|
+
p as generateMotion,
|
|
16
|
+
E as getAIConfigValue,
|
|
17
|
+
T as getCredits,
|
|
18
|
+
U as loadAIConfig,
|
|
19
|
+
d as normalizeError,
|
|
20
|
+
D as parseAIConfig,
|
|
21
|
+
l as resolveOpenAIConfig,
|
|
22
|
+
L as resolveUIConfig,
|
|
23
|
+
m as sendAIConfigToContainer,
|
|
24
|
+
v as validateAIConfig
|
|
21
25
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface GenerateCharacter3DInput {
|
|
2
|
+
imageUrl?: string;
|
|
3
|
+
prompt?: string;
|
|
4
|
+
signal?: AbortSignal;
|
|
5
|
+
}
|
|
6
|
+
export interface GenerateMotionInput {
|
|
7
|
+
text: string;
|
|
8
|
+
durationSeconds?: number;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
11
|
+
export interface ViggleAsset {
|
|
12
|
+
url: string;
|
|
13
|
+
thumbnailUrl?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create a rigged `.vsplat` character and wait until its CDN URL is ready.
|
|
17
|
+
* Call this from a user gesture. The request goes to the Aippy backend.
|
|
18
|
+
*/
|
|
19
|
+
export declare function generateCharacter3D(input: GenerateCharacter3DInput): Promise<ViggleAsset>;
|
|
20
|
+
/**
|
|
21
|
+
* Create a 441-joint GLB motion from text and wait until its CDN URL is ready.
|
|
22
|
+
* Call this from a user gesture. The request goes to the Aippy backend.
|
|
23
|
+
*/
|
|
24
|
+
export declare function generateMotion(input: GenerateMotionInput): Promise<ViggleAsset>;
|
package/dist/core/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { D as r, g as s, m as o } from "../config-B0A7gHQM.js";
|
|
2
2
|
import { _ as t, r as i } from "../bridge-CtB9L5kL.js";
|
|
3
3
|
import { A as R, a as E, E as c, b as m, c as A } from "../errors-B3bDbQbD.js";
|
|
4
|
-
import { S as f, V as g, c as l, a as y, g as _, s as d } from "../container-message-
|
|
4
|
+
import { S as f, V as g, c as l, a as y, g as _, s as d } from "../container-message-yZltTPi4.js";
|
|
5
5
|
import { A as D, C as O, R as F, a as I, p as S } from "../runtime-CmoG3v2m.js";
|
|
6
6
|
export {
|
|
7
7
|
D as AippyRuntime,
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { createOpenAICompatible as S } from "@ai-sdk/openai-compatible";
|
|
2
|
+
import { j as v } from "./url-c26cuIpu.js";
|
|
3
|
+
import { AISDKError as c, DefaultChatTransport as U } from "ai";
|
|
4
|
+
import { E as u, b as m, a as g } from "./errors-B3bDbQbD.js";
|
|
5
|
+
import { r as d } from "./bridge-CtB9L5kL.js";
|
|
6
|
+
import { s as I, a as T } from "./container-message-yZltTPi4.js";
|
|
7
|
+
const M = `${d()}/aisdk/v1/`, Z = `${d()}/aisdk/v1/ui/`, $ = "gpt-5-nano", N = "";
|
|
8
|
+
function C(t = {}) {
|
|
9
|
+
return {
|
|
10
|
+
baseUrl: t.baseUrl ?? `${d()}/aisdk/v1/`
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function R(t = {}) {
|
|
14
|
+
return {
|
|
15
|
+
baseUrl: t.baseUrl ?? `${d()}/aisdk/v1/ui/`
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function D(t, e) {
|
|
19
|
+
const r = t.status;
|
|
20
|
+
if (e && typeof e == "object" && "error" in e) {
|
|
21
|
+
const s = e, o = s.error.code, n = o != null ? `AippyAIError_${o}` : `AippyAIError_${r}`, a = e;
|
|
22
|
+
return "appMessage" in a && a.appMessage !== void 0 && I(a.appMessage), new c({
|
|
23
|
+
name: n,
|
|
24
|
+
message: `${u.RUNTIME} ${s.error.message}`,
|
|
25
|
+
cause: {
|
|
26
|
+
type: s.error.type ?? void 0,
|
|
27
|
+
param: s.error.param ?? void 0,
|
|
28
|
+
status: r
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (e && typeof e == "object" && e !== null) {
|
|
33
|
+
const s = e;
|
|
34
|
+
"appMessage" in s && s.appMessage !== void 0 && I(s.appMessage);
|
|
35
|
+
}
|
|
36
|
+
return new c({
|
|
37
|
+
name: `AippyAIError_${r}`,
|
|
38
|
+
message: `${u.RUNTIME} Request failed with status ${r}`,
|
|
39
|
+
cause: { status: r }
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function l() {
|
|
43
|
+
return async (t, e) => {
|
|
44
|
+
const r = await T(e?.headers), s = await globalThis.fetch(t, { ...e, headers: r });
|
|
45
|
+
if (!s.ok) {
|
|
46
|
+
const o = await s.text().catch(() => null);
|
|
47
|
+
let n = null;
|
|
48
|
+
if (o)
|
|
49
|
+
try {
|
|
50
|
+
n = JSON.parse(o);
|
|
51
|
+
} catch {
|
|
52
|
+
n = { message: o };
|
|
53
|
+
}
|
|
54
|
+
throw D(s, n);
|
|
55
|
+
}
|
|
56
|
+
return s;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const L = [
|
|
60
|
+
"gpt-image-1",
|
|
61
|
+
"gpt-image-1-mini",
|
|
62
|
+
"gpt-image-1.5"
|
|
63
|
+
];
|
|
64
|
+
function j(t) {
|
|
65
|
+
try {
|
|
66
|
+
const e = JSON.parse(t);
|
|
67
|
+
if (e.model && L.some((r) => e.model.startsWith(r))) {
|
|
68
|
+
const { response_format: r, ...s } = e;
|
|
69
|
+
return JSON.stringify(s);
|
|
70
|
+
}
|
|
71
|
+
} catch {
|
|
72
|
+
}
|
|
73
|
+
return t;
|
|
74
|
+
}
|
|
75
|
+
function ee(t = {}) {
|
|
76
|
+
const { baseUrl: e } = C(t), r = l();
|
|
77
|
+
return S({
|
|
78
|
+
name: "aippy",
|
|
79
|
+
baseURL: e,
|
|
80
|
+
fetch: async (o, n) => o.toString().includes("/images/generations") && n?.method?.toUpperCase() === "POST" && n?.body ? r(o, {
|
|
81
|
+
...n,
|
|
82
|
+
body: j(n.body)
|
|
83
|
+
}) : r(o, n),
|
|
84
|
+
// Enable structured outputs support (json_schema response format)
|
|
85
|
+
// This is required for Output.object() and Output.array() to work properly
|
|
86
|
+
supportsStructuredOutputs: !0
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
const F = "/chat";
|
|
90
|
+
function te(t = {}) {
|
|
91
|
+
const { baseUrl: e } = R(t), r = t.model ?? $, s = t.system ?? N, o = t.api ?? v(e, F), n = { model: r, system: s }, a = l();
|
|
92
|
+
return {
|
|
93
|
+
transport: new U({
|
|
94
|
+
api: o,
|
|
95
|
+
body: n,
|
|
96
|
+
// Ensure token is fetched fresh for every request
|
|
97
|
+
fetch: a
|
|
98
|
+
})
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
async function re(t = {}) {
|
|
102
|
+
const e = await E("GET", "credits", t);
|
|
103
|
+
return (!e || typeof e != "object" || !("credits" in e) || !Number.isSafeInteger(e.credits)) && b(), e.credits;
|
|
104
|
+
}
|
|
105
|
+
async function se(t, e) {
|
|
106
|
+
(!Number.isSafeInteger(t) || t <= 0) && w("deductCredits amount must be a positive safe integer"), (typeof e?.eventId != "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(
|
|
107
|
+
e.eventId
|
|
108
|
+
)) && w("deductCredits eventId must be a UUID");
|
|
109
|
+
const r = await E("POST", "credits/deduct", e, {
|
|
110
|
+
amount: t,
|
|
111
|
+
eventId: e.eventId.toLowerCase()
|
|
112
|
+
});
|
|
113
|
+
(!r || typeof r != "object" || !("success" in r) || r.success !== !0) && b();
|
|
114
|
+
}
|
|
115
|
+
async function E(t, e, r, s) {
|
|
116
|
+
const { baseUrl: o } = C(r), n = await l()(v(o, e), {
|
|
117
|
+
method: t,
|
|
118
|
+
cache: "no-store",
|
|
119
|
+
signal: r.signal,
|
|
120
|
+
headers: s === void 0 ? void 0 : { "Content-Type": "application/json" },
|
|
121
|
+
body: s === void 0 ? void 0 : JSON.stringify(s)
|
|
122
|
+
});
|
|
123
|
+
try {
|
|
124
|
+
return await n.json();
|
|
125
|
+
} catch (a) {
|
|
126
|
+
if (r.signal?.aborted)
|
|
127
|
+
throw r.signal.reason ?? a;
|
|
128
|
+
if (a instanceof Error && a.name === "AbortError")
|
|
129
|
+
throw a;
|
|
130
|
+
b();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function w(t) {
|
|
134
|
+
throw new c({
|
|
135
|
+
name: "AippyAIError_credits_input",
|
|
136
|
+
message: `${u.CODE} ${t}`
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function b() {
|
|
140
|
+
throw new c({
|
|
141
|
+
name: "AippyAIError_credits_response",
|
|
142
|
+
message: `${u.RUNTIME} Invalid credits response`
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function y(t) {
|
|
146
|
+
return [...t].length;
|
|
147
|
+
}
|
|
148
|
+
const x = 3e3, P = 5e3, J = 300 * 1e3, H = 360 * 1e3;
|
|
149
|
+
async function ne(t) {
|
|
150
|
+
const e = t.prompt?.trim() ?? "", r = t.imageUrl?.trim() ?? "";
|
|
151
|
+
!e && !r && f("generateCharacter3D requires an https imageUrl or a prompt"), y(e) > 1e3 && f("generateCharacter3D prompt must be at most 1000 characters"), r && !r.startsWith("https://") && f("generateCharacter3D imageUrl must be an https URL");
|
|
152
|
+
const s = {};
|
|
153
|
+
r && (s.imageUrl = r), e && (s.prompt = e);
|
|
154
|
+
const o = t;
|
|
155
|
+
return O(
|
|
156
|
+
"viggle/characters",
|
|
157
|
+
s,
|
|
158
|
+
o.pollIntervalMs ?? x,
|
|
159
|
+
o.timeoutMs ?? J,
|
|
160
|
+
t.signal
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
async function oe(t) {
|
|
164
|
+
const e = t.text?.trim() ?? "";
|
|
165
|
+
(y(e) < 1 || y(e) > 400) && f("generateMotion text must be 1 to 400 characters"), t.durationSeconds != null && (!Number.isInteger(t.durationSeconds) || t.durationSeconds < 3 || t.durationSeconds > 60) && f("generateMotion durationSeconds must be an integer from 3 to 60");
|
|
166
|
+
const r = { text: e };
|
|
167
|
+
t.durationSeconds != null && (r.durationSeconds = t.durationSeconds);
|
|
168
|
+
const s = t;
|
|
169
|
+
return O(
|
|
170
|
+
"viggle/motions",
|
|
171
|
+
r,
|
|
172
|
+
s.pollIntervalMs ?? P,
|
|
173
|
+
s.timeoutMs ?? H,
|
|
174
|
+
t.signal
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
async function O(t, e, r, s, o) {
|
|
178
|
+
const n = l(), a = Date.now();
|
|
179
|
+
let i = await A(n, t, {
|
|
180
|
+
method: "POST",
|
|
181
|
+
headers: { "Content-Type": "application/json" },
|
|
182
|
+
body: JSON.stringify(e),
|
|
183
|
+
signal: o
|
|
184
|
+
});
|
|
185
|
+
for (; i.status !== "ready"; )
|
|
186
|
+
i.status === "failed" && h(i.error || "Viggle generation failed"), Date.now() - a > s && h("Viggle generation timed out"), await k(r, o), i = await A(n, `${t}/${i.id}`, {
|
|
187
|
+
method: "GET",
|
|
188
|
+
signal: o
|
|
189
|
+
});
|
|
190
|
+
return i.url || h("Viggle generation finished without a file URL"), { url: i.url, thumbnailUrl: i.thumbnailUrl };
|
|
191
|
+
}
|
|
192
|
+
async function A(t, e, r) {
|
|
193
|
+
return await (await t(V(M, e), {
|
|
194
|
+
...r,
|
|
195
|
+
cache: "no-store"
|
|
196
|
+
})).json();
|
|
197
|
+
}
|
|
198
|
+
function V(t, e) {
|
|
199
|
+
return `${t.replace(/\/$/, "")}/${e.replace(/^\//, "")}`;
|
|
200
|
+
}
|
|
201
|
+
function k(t, e) {
|
|
202
|
+
if (e?.aborted)
|
|
203
|
+
throw e.reason ?? new DOMException("The operation was aborted", "AbortError");
|
|
204
|
+
return new Promise((r, s) => {
|
|
205
|
+
const o = setTimeout(r, t);
|
|
206
|
+
e?.addEventListener(
|
|
207
|
+
"abort",
|
|
208
|
+
() => {
|
|
209
|
+
clearTimeout(o), s(
|
|
210
|
+
e.reason ?? new DOMException("The operation was aborted", "AbortError")
|
|
211
|
+
);
|
|
212
|
+
},
|
|
213
|
+
{ once: !0 }
|
|
214
|
+
);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
function f(t) {
|
|
218
|
+
throw new c({
|
|
219
|
+
name: "AippyAIError_viggle_input",
|
|
220
|
+
message: `${u.CODE} ${t}`
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
function h(t) {
|
|
224
|
+
throw new c({
|
|
225
|
+
name: "AippyAIError_viggle",
|
|
226
|
+
message: `${u.RUNTIME} ${t}`
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
function _(t) {
|
|
230
|
+
const e = [];
|
|
231
|
+
if (!t || typeof t != "object")
|
|
232
|
+
throw m("AIConfig must be an object", g.INVALID_CONFIG);
|
|
233
|
+
const r = t;
|
|
234
|
+
for (const [s, o] of Object.entries(r)) {
|
|
235
|
+
if (!o || typeof o != "object") {
|
|
236
|
+
e.push({ key: s, message: "Item must be an object" });
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
const n = o;
|
|
240
|
+
typeof n.index != "number" && e.push({ key: s, message: "index must be a number" }), typeof n.name != "string" && e.push({ key: s, message: "name must be a string" }), typeof n.description != "string" && e.push({ key: s, message: "description must be a string" });
|
|
241
|
+
const a = n.type;
|
|
242
|
+
if (!["number", "boolean", "text", "enum"].includes(a)) {
|
|
243
|
+
e.push({
|
|
244
|
+
key: s,
|
|
245
|
+
message: `type must be one of: number, boolean, text, enum (got: ${a})`
|
|
246
|
+
});
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
if (a === "number")
|
|
250
|
+
typeof n.value != "number" && e.push({ key: s, message: 'value must be a number for type "number"' }), n.min !== void 0 && typeof n.min != "number" && e.push({ key: s, message: "min must be a number" }), n.max !== void 0 && typeof n.max != "number" && e.push({ key: s, message: "max must be a number" }), n.step !== void 0 && typeof n.step != "number" && e.push({ key: s, message: "step must be a number" });
|
|
251
|
+
else if (a === "boolean")
|
|
252
|
+
typeof n.value != "boolean" && e.push({ key: s, message: 'value must be a boolean for type "boolean"' });
|
|
253
|
+
else if (a === "text")
|
|
254
|
+
typeof n.value != "string" && e.push({ key: s, message: 'value must be a string for type "text"' });
|
|
255
|
+
else if (a === "enum") {
|
|
256
|
+
if (!Array.isArray(n.options))
|
|
257
|
+
e.push({ key: s, message: 'options must be an array for type "enum"' });
|
|
258
|
+
else if (n.options.length === 0)
|
|
259
|
+
e.push({ key: s, message: 'options array cannot be empty for type "enum"' });
|
|
260
|
+
else
|
|
261
|
+
for (let p = 0; p < n.options.length; p++)
|
|
262
|
+
typeof n.options[p] != "string" && e.push({
|
|
263
|
+
key: s,
|
|
264
|
+
message: `options[${p}] must be a string`
|
|
265
|
+
});
|
|
266
|
+
typeof n.value != "string" ? e.push({ key: s, message: 'value must be a string for type "enum"' }) : Array.isArray(n.options) && !n.options.includes(n.value) && e.push({
|
|
267
|
+
key: s,
|
|
268
|
+
message: `value "${n.value}" is not in options: [${n.options.join(", ")}]`
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
n.group !== void 0 && typeof n.group != "string" && e.push({ key: s, message: "group must be a string" });
|
|
272
|
+
}
|
|
273
|
+
if (e.length > 0)
|
|
274
|
+
throw m(
|
|
275
|
+
`AIConfig validation failed with ${e.length} error(s)`,
|
|
276
|
+
g.INVALID_CONFIG,
|
|
277
|
+
{ errors: e }
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
function ae(t) {
|
|
281
|
+
let e;
|
|
282
|
+
try {
|
|
283
|
+
e = JSON.parse(t);
|
|
284
|
+
} catch (r) {
|
|
285
|
+
throw m(
|
|
286
|
+
`Invalid JSON: ${r instanceof Error ? r.message : String(r)}`,
|
|
287
|
+
g.INVALID_CONFIG
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
return _(e), e;
|
|
291
|
+
}
|
|
292
|
+
function B(t) {
|
|
293
|
+
return _(t), t;
|
|
294
|
+
}
|
|
295
|
+
function G(t, e) {
|
|
296
|
+
const r = t[e];
|
|
297
|
+
if (!r)
|
|
298
|
+
throw m(
|
|
299
|
+
`AIConfig key "${e}" not found`,
|
|
300
|
+
g.INVALID_CONFIG,
|
|
301
|
+
{ key: e }
|
|
302
|
+
);
|
|
303
|
+
return r.value;
|
|
304
|
+
}
|
|
305
|
+
function q(t) {
|
|
306
|
+
if (!(typeof window > "u"))
|
|
307
|
+
try {
|
|
308
|
+
const e = window.webkit?.messageHandlers?.aippyListener;
|
|
309
|
+
if (e)
|
|
310
|
+
try {
|
|
311
|
+
const r = {
|
|
312
|
+
command: "ai.initialize",
|
|
313
|
+
parameters: JSON.stringify(t)
|
|
314
|
+
};
|
|
315
|
+
e.postMessage(r);
|
|
316
|
+
} catch (r) {
|
|
317
|
+
console.warn("❌ [Aippy AI Config] Failed to send config to iOS app:", r);
|
|
318
|
+
}
|
|
319
|
+
if (window.parent && window.parent !== window)
|
|
320
|
+
try {
|
|
321
|
+
const r = {
|
|
322
|
+
type: "ai.initialize",
|
|
323
|
+
config: JSON.stringify(t)
|
|
324
|
+
};
|
|
325
|
+
window.parent.postMessage(r, "*");
|
|
326
|
+
} catch (r) {
|
|
327
|
+
console.warn("❌ [Aippy AI Config] Failed to send config to parent window:", r);
|
|
328
|
+
}
|
|
329
|
+
} catch (e) {
|
|
330
|
+
console.warn("⚠️ [Aippy AI Config] Failed to send config:", e);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function ie(t) {
|
|
334
|
+
const e = B(t);
|
|
335
|
+
return q(e), new Proxy({}, {
|
|
336
|
+
get(r, s) {
|
|
337
|
+
if (typeof s == "string")
|
|
338
|
+
try {
|
|
339
|
+
return G(e, s);
|
|
340
|
+
} catch {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
has(r, s) {
|
|
345
|
+
return typeof s != "string" ? !1 : s in e;
|
|
346
|
+
},
|
|
347
|
+
ownKeys(r) {
|
|
348
|
+
return Object.keys(e);
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
export {
|
|
353
|
+
M as D,
|
|
354
|
+
F as U,
|
|
355
|
+
ee as a,
|
|
356
|
+
te as b,
|
|
357
|
+
Z as c,
|
|
358
|
+
$ as d,
|
|
359
|
+
N as e,
|
|
360
|
+
R as f,
|
|
361
|
+
re as g,
|
|
362
|
+
se as h,
|
|
363
|
+
ne as i,
|
|
364
|
+
oe as j,
|
|
365
|
+
G as k,
|
|
366
|
+
B as l,
|
|
367
|
+
ie as m,
|
|
368
|
+
D as n,
|
|
369
|
+
ae as p,
|
|
370
|
+
C as r,
|
|
371
|
+
q as s,
|
|
372
|
+
_ as v
|
|
373
|
+
};
|
package/dist/index/index.js
CHANGED
|
@@ -1,97 +1,101 @@
|
|
|
1
1
|
import { D as r, g as s, m as o } from "../config-B0A7gHQM.js";
|
|
2
2
|
import { _ as i, g as n, r as p } from "../bridge-CtB9L5kL.js";
|
|
3
|
-
import { A as m, a as
|
|
4
|
-
import { S as
|
|
5
|
-
import { A as U, C as _, R as
|
|
6
|
-
import { CameraAPI as
|
|
3
|
+
import { A as m, a as c, E as f, b as C, c as g } from "../errors-B3bDbQbD.js";
|
|
4
|
+
import { S as d, V as l, c as I, a as E, g as S, s as x } from "../container-message-yZltTPi4.js";
|
|
5
|
+
import { A as U, C as _, R as D, a as T, p as h } from "../runtime-CmoG3v2m.js";
|
|
6
|
+
import { CameraAPI as y, FileSystemAPI as F, GeolocationAPI as M, SensorsAPI as P, camera as O, fileSystem as b, geolocation as L, isMotionSupported as w, isOrientationSupported as H, requestMotionPermission as N, sensors as V, vibrate as k, watchMotion as B, watchOrientation as j } from "../device/index.js";
|
|
7
7
|
import { P as G, a as z, c as K, b as W, g as X, i as Y, p as J, r as Q, s as Z } from "../app-version-checker-Bz7FrEZz.js";
|
|
8
8
|
import { a as ee, P as ae, p as re, b as se } from "../pwa-C5nXU0DN.js";
|
|
9
9
|
import { j as te } from "../url-c26cuIpu.js";
|
|
10
|
-
import { a as ne, b as pe } from "../useTweaks-
|
|
11
|
-
import { c as me, b as
|
|
12
|
-
import { reportScore as
|
|
13
|
-
import { D as xe, d as Re, e as Ue, c as _e, U as
|
|
14
|
-
import { c as
|
|
15
|
-
import { hasNativeBridge as
|
|
10
|
+
import { a as ne, b as pe } from "../useTweaks-C7BEMpV3.js";
|
|
11
|
+
import { c as me, b as ce, i as fe, p as Ce, u as ge, a as ue } from "../useSound-z_eIn0KH.js";
|
|
12
|
+
import { reportScore as le, sendEvent as Ie, updateScore as Ee } from "../leaderboard/index.js";
|
|
13
|
+
import { D as xe, d as Re, e as Ue, c as _e, U as De, a as Te, b as he, m as ve, h as ye, i as Fe, j as Me, k as Pe, g as Oe, l as be, n as Le, p as we, r as He, f as Ne, s as Ve, v as ke } from "../helper-7v3LLvbl.js";
|
|
14
|
+
import { c as je, u as qe } from "../hooks-D5lkty5r.js";
|
|
15
|
+
import { hasNativeBridge as ze } from "../native-bridge-BnvipFJc.js";
|
|
16
16
|
export {
|
|
17
17
|
U as AippyRuntime,
|
|
18
18
|
m as AippyRuntimeError,
|
|
19
|
-
|
|
19
|
+
y as CameraAPI,
|
|
20
20
|
_ as Cancellable,
|
|
21
21
|
xe as DEFAULT_BASE_URL,
|
|
22
22
|
Re as DEFAULT_CHAT_MODEL,
|
|
23
23
|
Ue as DEFAULT_CHAT_SYSTEM,
|
|
24
24
|
r as DEFAULT_CONFIG,
|
|
25
25
|
_e as DEFAULT_UI_BASE_URL,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
c as ERROR_CODES,
|
|
27
|
+
f as ERROR_PREFIX,
|
|
28
|
+
F as FileSystemAPI,
|
|
29
|
+
M as GeolocationAPI,
|
|
30
30
|
ee as PWAUtils,
|
|
31
31
|
ae as PerformanceMonitor,
|
|
32
32
|
G as PlatformDetector,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
D as ReceiveChannel,
|
|
34
|
+
d as SDK_NAME,
|
|
35
|
+
P as SensorsAPI,
|
|
36
|
+
De as UI_CHAT_ENDPOINT,
|
|
37
|
+
l as VERSION,
|
|
38
38
|
i as _resetCachedApiBaseUrl,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
Te as aippyAIProvider,
|
|
40
|
+
he as aippyChatConfig,
|
|
41
|
+
T as aippyRuntime,
|
|
42
42
|
ne as aippyTweaks,
|
|
43
43
|
pe as aippyTweaksRuntime,
|
|
44
44
|
O as camera,
|
|
45
45
|
z as checkFeatureSupport,
|
|
46
|
-
|
|
46
|
+
je as clearUserInfoCache,
|
|
47
47
|
K as compareVersions,
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
ve as createAIConfig,
|
|
49
|
+
I as createAippyHeaders,
|
|
50
50
|
E as createAippyHeadersAsync,
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
C as createCodeError,
|
|
52
|
+
g as createError,
|
|
53
53
|
me as createHiddenMediaElement,
|
|
54
|
+
ye as deductCredits,
|
|
54
55
|
b as fileSystem,
|
|
56
|
+
Fe as generateCharacter3D,
|
|
57
|
+
Me as generateMotion,
|
|
55
58
|
L as geolocation,
|
|
56
|
-
|
|
59
|
+
Pe as getAIConfigValue,
|
|
57
60
|
n as getAuthTokenAsync,
|
|
58
61
|
W as getAvailableFeatures,
|
|
59
62
|
s as getConfigFromEnv,
|
|
63
|
+
Oe as getCredits,
|
|
60
64
|
X as getFeatureVersionRequirements,
|
|
61
65
|
S as getVersionInfo,
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
ze as hasNativeBridge,
|
|
67
|
+
ce as isIOSDevice,
|
|
64
68
|
Y as isInIframe,
|
|
65
|
-
|
|
69
|
+
fe as isMediaStreamAudioSupported,
|
|
66
70
|
w as isMotionSupported,
|
|
67
71
|
H as isOrientationSupported,
|
|
68
72
|
te as joinUrl,
|
|
69
|
-
|
|
73
|
+
be as loadAIConfig,
|
|
70
74
|
o as mergeConfig,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
Le as normalizeError,
|
|
76
|
+
we as parseAIConfig,
|
|
77
|
+
Ce as patchAudioContext,
|
|
74
78
|
re as performanceMonitor,
|
|
75
79
|
J as platform,
|
|
76
|
-
|
|
80
|
+
h as processMotionData,
|
|
77
81
|
se as pwa,
|
|
78
|
-
|
|
82
|
+
le as reportScore,
|
|
79
83
|
N as requestMotionPermission,
|
|
80
84
|
Q as requireFeatureSupport,
|
|
81
85
|
p as resolveApiBaseUrl,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
He as resolveOpenAIConfig,
|
|
87
|
+
Ne as resolveUIConfig,
|
|
88
|
+
Ve as sendAIConfigToContainer,
|
|
89
|
+
Ie as sendEvent,
|
|
86
90
|
x as sendMessageToContainer,
|
|
87
91
|
V as sensors,
|
|
88
92
|
Z as showAlert,
|
|
89
93
|
Ee as updateScore,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
ge as useAudioContext,
|
|
95
|
+
ue as useSound,
|
|
96
|
+
qe as useUserInfo,
|
|
97
|
+
ke as validateAIConfig,
|
|
98
|
+
k as vibrate,
|
|
99
|
+
B as watchMotion,
|
|
100
|
+
j as watchOrientation
|
|
97
101
|
};
|
package/dist/tweaks/index.js
CHANGED
|
@@ -1,26 +1,20 @@
|
|
|
1
|
-
var
|
|
2
|
-
var m = (i, e, t) => e in i ?
|
|
1
|
+
var h = Object.defineProperty;
|
|
2
|
+
var m = (i, e, t) => e in i ? h(i, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[e] = t;
|
|
3
3
|
var r = (i, e, t) => m(i, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
-
import { useReducer as
|
|
4
|
+
import { useReducer as g, useEffect as v } from "react";
|
|
5
5
|
import { b as T, a as C } from "./errors-B3bDbQbD.js";
|
|
6
|
-
const I = /* @__PURE__ */ new Set(["number", "color", "boolean", "text"
|
|
7
|
-
function
|
|
6
|
+
const I = /* @__PURE__ */ new Set(["number", "color", "boolean", "text"]), O = /^#(?:[0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
|
|
7
|
+
function R(i) {
|
|
8
8
|
const e = i.value;
|
|
9
|
-
|
|
10
|
-
if (typeof e == "number") return "number";
|
|
11
|
-
if (typeof e == "string") {
|
|
12
|
-
if (O.test(e)) return "color";
|
|
13
|
-
if (R.test(e)) return "image";
|
|
14
|
-
}
|
|
15
|
-
return "text";
|
|
9
|
+
return typeof e == "boolean" ? "boolean" : typeof e == "number" ? "number" : typeof e == "string" && O.test(e) ? "color" : "text";
|
|
16
10
|
}
|
|
17
|
-
function
|
|
11
|
+
function A(i) {
|
|
18
12
|
const e = {};
|
|
19
13
|
for (const [t, n] of Object.entries(i))
|
|
20
14
|
if (I.has(n.type))
|
|
21
15
|
e[t] = n;
|
|
22
16
|
else {
|
|
23
|
-
const a =
|
|
17
|
+
const a = R(n);
|
|
24
18
|
console.warn(
|
|
25
19
|
`⚠️ [Aippy Tweaks] Invalid type "${n.type}" for key "${t}", auto-corrected to "${a}"`
|
|
26
20
|
), e[t] = { ...n, type: a };
|
|
@@ -53,7 +47,7 @@ class k {
|
|
|
53
47
|
});
|
|
54
48
|
}
|
|
55
49
|
}
|
|
56
|
-
class
|
|
50
|
+
class E {
|
|
57
51
|
constructor(e, t) {
|
|
58
52
|
r(this, "values", {});
|
|
59
53
|
r(this, "subject", new k());
|
|
@@ -81,7 +75,7 @@ class S {
|
|
|
81
75
|
}
|
|
82
76
|
// React Hook integration
|
|
83
77
|
useState(e) {
|
|
84
|
-
const [t, n] =
|
|
78
|
+
const [t, n] = g(() => this.getValue(e), this.getValue(e));
|
|
85
79
|
return v(() => {
|
|
86
80
|
const a = this.subject.subscribe((s) => {
|
|
87
81
|
s === e && n();
|
|
@@ -92,7 +86,7 @@ class S {
|
|
|
92
86
|
}, [e]), t;
|
|
93
87
|
}
|
|
94
88
|
}
|
|
95
|
-
class
|
|
89
|
+
class S {
|
|
96
90
|
constructor() {
|
|
97
91
|
r(this, "tweaksInstance", null);
|
|
98
92
|
r(this, "tweaksDidWarn", !1);
|
|
@@ -104,8 +98,8 @@ class N {
|
|
|
104
98
|
tweaks(e) {
|
|
105
99
|
if (this.tweaksInstance)
|
|
106
100
|
return this.tweaksDidWarn || (this.tweaksDidWarn = !0, console.warn("⚠️ [Aippy Tweaks] tweaks() is expected to only be called once, returning previous value")), this.tweaksInstance;
|
|
107
|
-
e =
|
|
108
|
-
const t = new k(), n = new
|
|
101
|
+
e = A(e), this.originalConfig = { ...e };
|
|
102
|
+
const t = new k(), n = new E(t, e), a = {};
|
|
109
103
|
for (const s of Object.keys(e))
|
|
110
104
|
a[s] = {
|
|
111
105
|
useState: () => n.useState(s)
|
|
@@ -173,15 +167,15 @@ class N {
|
|
|
173
167
|
let a = 0;
|
|
174
168
|
for (const [o, c] of Object.entries(e))
|
|
175
169
|
if (c && typeof c == "object" && "value" in c) {
|
|
176
|
-
const
|
|
170
|
+
const p = c, w = this.originalConfig[o];
|
|
177
171
|
if (!w) {
|
|
178
172
|
console.warn(`⚠️ [Aippy Tweaks] Key "${o}" not found in original config, skipping`);
|
|
179
173
|
continue;
|
|
180
174
|
}
|
|
181
175
|
const b = /* @__PURE__ */ new Set(["tweakKey", "valueBefore", "tweaksType", "editType"]), f = { ...w };
|
|
182
|
-
for (const [d, l] of Object.entries(
|
|
176
|
+
for (const [d, l] of Object.entries(p))
|
|
183
177
|
b.has(d) || l != null && (f[d] = l);
|
|
184
|
-
n[o] = f, t[o] =
|
|
178
|
+
n[o] = f, t[o] = p.value, a++;
|
|
185
179
|
}
|
|
186
180
|
if (a === 0) {
|
|
187
181
|
console.warn("⚠️ [Aippy Tweaks] No valid values found in iOS data:", e);
|
|
@@ -197,11 +191,11 @@ class N {
|
|
|
197
191
|
}
|
|
198
192
|
}
|
|
199
193
|
}
|
|
200
|
-
const
|
|
201
|
-
tweaks: (i) =>
|
|
202
|
-
},
|
|
203
|
-
typeof window < "u" && (window.aippyTweaksRuntime = y, window.processNativeData =
|
|
194
|
+
const u = new S(), y = {
|
|
195
|
+
tweaks: (i) => u.tweaks(i)
|
|
196
|
+
}, V = y.tweaks;
|
|
197
|
+
typeof window < "u" && (window.aippyTweaksRuntime = y, window.processNativeData = u.processNativeData.bind(u));
|
|
204
198
|
export {
|
|
205
|
-
|
|
199
|
+
V as a,
|
|
206
200
|
y as b
|
|
207
201
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aippy/runtime",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2-dev.0",
|
|
4
4
|
"description": "Aippy Runtime SDK - Runtime SDK for Aippy projects",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -67,12 +67,14 @@
|
|
|
67
67
|
"url": "https://discord.com/invite/G94ZAx6gVq"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
|
+
"@ai-sdk/react": "^3.0.210",
|
|
70
71
|
"@eslint/js": "^9.36.0",
|
|
71
72
|
"@types/node": "^24.5.2",
|
|
72
73
|
"@types/react": "^19.2.2",
|
|
73
74
|
"@types/ua-parser-js": "^0.7.39",
|
|
74
75
|
"@typescript-eslint/eslint-plugin": "^8.44.1",
|
|
75
76
|
"@typescript-eslint/parser": "^8.44.1",
|
|
77
|
+
"ai": "^6.0.208",
|
|
76
78
|
"eslint": "^9.36.0",
|
|
77
79
|
"prettier": "^3.6.2",
|
|
78
80
|
"react": "^19.1.1",
|
|
@@ -82,14 +84,20 @@
|
|
|
82
84
|
"zod": "^3.25.76"
|
|
83
85
|
},
|
|
84
86
|
"dependencies": {
|
|
85
|
-
"@ai-sdk/openai-compatible": "^2.0.
|
|
86
|
-
"ai": "^6.0.14",
|
|
87
|
+
"@ai-sdk/openai-compatible": "^2.0.51",
|
|
87
88
|
"ua-parser-js": "^2.0.5"
|
|
88
89
|
},
|
|
89
90
|
"peerDependencies": {
|
|
91
|
+
"@ai-sdk/react": "^3.0.0",
|
|
92
|
+
"ai": "^6.0.0",
|
|
90
93
|
"react": "^19.1.1",
|
|
91
94
|
"typescript": ">=5.0.0"
|
|
92
95
|
},
|
|
96
|
+
"peerDependenciesMeta": {
|
|
97
|
+
"@ai-sdk/react": {
|
|
98
|
+
"optional": true
|
|
99
|
+
}
|
|
100
|
+
},
|
|
93
101
|
"engines": {
|
|
94
102
|
"node": ">=20.0.0",
|
|
95
103
|
"pnpm": ">=10.0.0"
|
package/dist/helper-CZqFi-QF.js
DELETED
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import { createOpenAICompatible as d } from "@ai-sdk/openai-compatible";
|
|
2
|
-
import { r as f } from "./bridge-CtB9L5kL.js";
|
|
3
|
-
import { s as m, a as b } from "./container-message-KgL1paGV.js";
|
|
4
|
-
import { AISDKError as c, DefaultChatTransport as h } from "ai";
|
|
5
|
-
import { E as g, b as p, a as u } from "./errors-B3bDbQbD.js";
|
|
6
|
-
import { j as A } from "./url-c26cuIpu.js";
|
|
7
|
-
const j = `${f()}/aisdk/v1/`, x = `${f()}/aisdk/v1/ui/`, I = "gpt-5-nano", v = "";
|
|
8
|
-
function w(o = {}) {
|
|
9
|
-
return {
|
|
10
|
-
baseUrl: o.baseUrl ?? `${f()}/aisdk/v1/`
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
function C(o = {}) {
|
|
14
|
-
return {
|
|
15
|
-
baseUrl: o.baseUrl ?? `${f()}/aisdk/v1/ui/`
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
function O(o, e) {
|
|
19
|
-
const r = o.status;
|
|
20
|
-
if (e && typeof e == "object" && "error" in e) {
|
|
21
|
-
const t = e, n = t.error.code, s = n != null ? `AippyAIError_${n}` : `AippyAIError_${r}`, a = e;
|
|
22
|
-
return "appMessage" in a && a.appMessage !== void 0 && m(a.appMessage), new c({
|
|
23
|
-
name: s,
|
|
24
|
-
message: `${g.RUNTIME} ${t.error.message}`,
|
|
25
|
-
cause: {
|
|
26
|
-
type: t.error.type ?? void 0,
|
|
27
|
-
param: t.error.param ?? void 0,
|
|
28
|
-
status: r
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
if (e && typeof e == "object" && e !== null) {
|
|
33
|
-
const t = e;
|
|
34
|
-
"appMessage" in t && t.appMessage !== void 0 && m(t.appMessage);
|
|
35
|
-
}
|
|
36
|
-
return new c({
|
|
37
|
-
name: `AippyAIError_${r}`,
|
|
38
|
-
message: `${g.RUNTIME} Request failed with status ${r}`,
|
|
39
|
-
cause: { status: r }
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
function l() {
|
|
43
|
-
return async (o, e) => {
|
|
44
|
-
const r = await b(e?.headers), t = await globalThis.fetch(o, { ...e, headers: r });
|
|
45
|
-
if (!t.ok) {
|
|
46
|
-
const n = await t.text().catch(() => null);
|
|
47
|
-
let s = null;
|
|
48
|
-
if (n)
|
|
49
|
-
try {
|
|
50
|
-
s = JSON.parse(n);
|
|
51
|
-
} catch {
|
|
52
|
-
s = { message: n };
|
|
53
|
-
}
|
|
54
|
-
throw O(t, s);
|
|
55
|
-
}
|
|
56
|
-
return t;
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
const E = [
|
|
60
|
-
"gpt-image-1",
|
|
61
|
-
"gpt-image-1-mini",
|
|
62
|
-
"gpt-image-1.5"
|
|
63
|
-
];
|
|
64
|
-
function _(o) {
|
|
65
|
-
try {
|
|
66
|
-
const e = JSON.parse(o);
|
|
67
|
-
if (e.model && E.some((r) => e.model.startsWith(r))) {
|
|
68
|
-
const { response_format: r, ...t } = e;
|
|
69
|
-
return JSON.stringify(t);
|
|
70
|
-
}
|
|
71
|
-
} catch {
|
|
72
|
-
}
|
|
73
|
-
return o;
|
|
74
|
-
}
|
|
75
|
-
function J(o = {}) {
|
|
76
|
-
const { baseUrl: e } = w(o), r = l();
|
|
77
|
-
return d({
|
|
78
|
-
name: "aippy",
|
|
79
|
-
baseURL: e,
|
|
80
|
-
fetch: async (n, s) => n.toString().includes("/images/generations") && s?.method?.toUpperCase() === "POST" && s?.body ? r(n, {
|
|
81
|
-
...s,
|
|
82
|
-
body: _(s.body)
|
|
83
|
-
}) : r(n, s),
|
|
84
|
-
// Enable structured outputs support (json_schema response format)
|
|
85
|
-
// This is required for Output.object() and Output.array() to work properly
|
|
86
|
-
supportsStructuredOutputs: !0
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
const S = "/chat";
|
|
90
|
-
function B(o = {}) {
|
|
91
|
-
const { baseUrl: e } = C(o), r = o.model ?? I, t = o.system ?? v, n = o.api ?? A(e, S), s = { model: r, system: t }, a = l();
|
|
92
|
-
return {
|
|
93
|
-
transport: new h({
|
|
94
|
-
api: n,
|
|
95
|
-
body: s,
|
|
96
|
-
// Ensure token is fetched fresh for every request
|
|
97
|
-
fetch: a
|
|
98
|
-
})
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
function y(o) {
|
|
102
|
-
const e = [];
|
|
103
|
-
if (!o || typeof o != "object")
|
|
104
|
-
throw p("AIConfig must be an object", u.INVALID_CONFIG);
|
|
105
|
-
const r = o;
|
|
106
|
-
for (const [t, n] of Object.entries(r)) {
|
|
107
|
-
if (!n || typeof n != "object") {
|
|
108
|
-
e.push({ key: t, message: "Item must be an object" });
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
const s = n;
|
|
112
|
-
typeof s.index != "number" && e.push({ key: t, message: "index must be a number" }), typeof s.name != "string" && e.push({ key: t, message: "name must be a string" }), typeof s.description != "string" && e.push({ key: t, message: "description must be a string" });
|
|
113
|
-
const a = s.type;
|
|
114
|
-
if (!["number", "boolean", "text", "enum"].includes(a)) {
|
|
115
|
-
e.push({
|
|
116
|
-
key: t,
|
|
117
|
-
message: `type must be one of: number, boolean, text, enum (got: ${a})`
|
|
118
|
-
});
|
|
119
|
-
continue;
|
|
120
|
-
}
|
|
121
|
-
if (a === "number")
|
|
122
|
-
typeof s.value != "number" && e.push({ key: t, message: 'value must be a number for type "number"' }), s.min !== void 0 && typeof s.min != "number" && e.push({ key: t, message: "min must be a number" }), s.max !== void 0 && typeof s.max != "number" && e.push({ key: t, message: "max must be a number" }), s.step !== void 0 && typeof s.step != "number" && e.push({ key: t, message: "step must be a number" });
|
|
123
|
-
else if (a === "boolean")
|
|
124
|
-
typeof s.value != "boolean" && e.push({ key: t, message: 'value must be a boolean for type "boolean"' });
|
|
125
|
-
else if (a === "text")
|
|
126
|
-
typeof s.value != "string" && e.push({ key: t, message: 'value must be a string for type "text"' });
|
|
127
|
-
else if (a === "enum") {
|
|
128
|
-
if (!Array.isArray(s.options))
|
|
129
|
-
e.push({ key: t, message: 'options must be an array for type "enum"' });
|
|
130
|
-
else if (s.options.length === 0)
|
|
131
|
-
e.push({ key: t, message: 'options array cannot be empty for type "enum"' });
|
|
132
|
-
else
|
|
133
|
-
for (let i = 0; i < s.options.length; i++)
|
|
134
|
-
typeof s.options[i] != "string" && e.push({
|
|
135
|
-
key: t,
|
|
136
|
-
message: `options[${i}] must be a string`
|
|
137
|
-
});
|
|
138
|
-
typeof s.value != "string" ? e.push({ key: t, message: 'value must be a string for type "enum"' }) : Array.isArray(s.options) && !s.options.includes(s.value) && e.push({
|
|
139
|
-
key: t,
|
|
140
|
-
message: `value "${s.value}" is not in options: [${s.options.join(", ")}]`
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
s.group !== void 0 && typeof s.group != "string" && e.push({ key: t, message: "group must be a string" });
|
|
144
|
-
}
|
|
145
|
-
if (e.length > 0)
|
|
146
|
-
throw p(
|
|
147
|
-
`AIConfig validation failed with ${e.length} error(s)`,
|
|
148
|
-
u.INVALID_CONFIG,
|
|
149
|
-
{ errors: e }
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
function H(o) {
|
|
153
|
-
let e;
|
|
154
|
-
try {
|
|
155
|
-
e = JSON.parse(o);
|
|
156
|
-
} catch (r) {
|
|
157
|
-
throw p(
|
|
158
|
-
`Invalid JSON: ${r instanceof Error ? r.message : String(r)}`,
|
|
159
|
-
u.INVALID_CONFIG
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
return y(e), e;
|
|
163
|
-
}
|
|
164
|
-
function U(o) {
|
|
165
|
-
return y(o), o;
|
|
166
|
-
}
|
|
167
|
-
function N(o, e) {
|
|
168
|
-
const r = o[e];
|
|
169
|
-
if (!r)
|
|
170
|
-
throw p(
|
|
171
|
-
`AIConfig key "${e}" not found`,
|
|
172
|
-
u.INVALID_CONFIG,
|
|
173
|
-
{ key: e }
|
|
174
|
-
);
|
|
175
|
-
return r.value;
|
|
176
|
-
}
|
|
177
|
-
function T(o) {
|
|
178
|
-
if (!(typeof window > "u"))
|
|
179
|
-
try {
|
|
180
|
-
const e = window.webkit?.messageHandlers?.aippyListener;
|
|
181
|
-
if (e)
|
|
182
|
-
try {
|
|
183
|
-
const r = {
|
|
184
|
-
command: "ai.initialize",
|
|
185
|
-
parameters: JSON.stringify(o)
|
|
186
|
-
};
|
|
187
|
-
e.postMessage(r);
|
|
188
|
-
} catch (r) {
|
|
189
|
-
console.warn("❌ [Aippy AI Config] Failed to send config to iOS app:", r);
|
|
190
|
-
}
|
|
191
|
-
if (window.parent && window.parent !== window)
|
|
192
|
-
try {
|
|
193
|
-
const r = {
|
|
194
|
-
type: "ai.initialize",
|
|
195
|
-
config: JSON.stringify(o)
|
|
196
|
-
};
|
|
197
|
-
window.parent.postMessage(r, "*");
|
|
198
|
-
} catch (r) {
|
|
199
|
-
console.warn("❌ [Aippy AI Config] Failed to send config to parent window:", r);
|
|
200
|
-
}
|
|
201
|
-
} catch (e) {
|
|
202
|
-
console.warn("⚠️ [Aippy AI Config] Failed to send config:", e);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
function P(o) {
|
|
206
|
-
const e = U(o);
|
|
207
|
-
return T(e), new Proxy({}, {
|
|
208
|
-
get(r, t) {
|
|
209
|
-
if (typeof t == "string")
|
|
210
|
-
try {
|
|
211
|
-
return N(e, t);
|
|
212
|
-
} catch {
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
},
|
|
216
|
-
has(r, t) {
|
|
217
|
-
return typeof t != "string" ? !1 : t in e;
|
|
218
|
-
},
|
|
219
|
-
ownKeys(r) {
|
|
220
|
-
return Object.keys(e);
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
export {
|
|
225
|
-
j as D,
|
|
226
|
-
S as U,
|
|
227
|
-
J as a,
|
|
228
|
-
B as b,
|
|
229
|
-
x as c,
|
|
230
|
-
I as d,
|
|
231
|
-
v as e,
|
|
232
|
-
C as f,
|
|
233
|
-
N as g,
|
|
234
|
-
P as h,
|
|
235
|
-
U as l,
|
|
236
|
-
O as n,
|
|
237
|
-
H as p,
|
|
238
|
-
w as r,
|
|
239
|
-
T as s,
|
|
240
|
-
y as v
|
|
241
|
-
};
|