@lastbrain/ai-ui-core 1.0.17 → 1.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/createClient.d.ts.map +1 -1
- package/dist/client/createClient.js +28 -16
- package/dist/errors/normalizeError.d.ts.map +1 -1
- package/dist/errors/normalizeError.js +7 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/client/createClient.ts +31 -18
- package/src/errors/normalizeError.ts +8 -0
- package/src/types/index.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createClient.d.ts","sourceRoot":"","sources":["../../src/client/createClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,cAAc,EACd,cAAc,EACd,eAAe,EACf,cAAc,EACd,eAAe,EACf,QAAQ,EACT,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"createClient.d.ts","sourceRoot":"","sources":["../../src/client/createClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,cAAc,EACd,cAAc,EACd,eAAe,EACf,cAAc,EACd,eAAe,EACf,QAAQ,EACT,MAAM,UAAU,CAAC;AA4FlB,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY;qBAsBnB,OAAO,CAAC,QAAQ,EAAE,CAAC;wBAqCd,aAAa,KAAG,OAAO,CAAC,cAAc,CAAC;yBAoCtC,cAAc,KAAG,OAAO,CAAC,eAAe,CAAC;iBAoCjD,cAAc,KAAG,OAAO,CAAC,eAAe,CAAC;qBAkBvC,OAAO,CAAC,QAAQ,CAAC;EAyB9C"}
|
|
@@ -12,7 +12,7 @@ async function fetchWithRetry(url, options, retryConfig) {
|
|
|
12
12
|
const response = await fetch(url, options);
|
|
13
13
|
if (!response.ok) {
|
|
14
14
|
const errorData = await response.json().catch(() => ({}));
|
|
15
|
-
const error = new Error(errorData
|
|
15
|
+
const error = new Error(JSON.stringify(errorData) || `HTTP ${response.status}`);
|
|
16
16
|
error.status = response.status;
|
|
17
17
|
error.response = { status: response.status };
|
|
18
18
|
throw error;
|
|
@@ -37,19 +37,31 @@ async function fetchWithRetry(url, options, retryConfig) {
|
|
|
37
37
|
throw lastError;
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
|
-
* Build URL for API endpoint with proper
|
|
41
|
-
* For baseUrl="/api/ai"
|
|
42
|
-
* For baseUrl="/api/
|
|
40
|
+
* Build URL for API endpoint with proper routing
|
|
41
|
+
* For internal app (baseUrl="/api/ai"): use internal routes like /generate-text, /auth/status
|
|
42
|
+
* For external app (baseUrl="/api/lastbrain"): use proxy routes like /text-ai, /status
|
|
43
43
|
*/
|
|
44
44
|
function buildUrl(baseUrl, endpoint) {
|
|
45
|
-
const
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
const isInternalApp = baseUrl.includes("/api/ai");
|
|
46
|
+
// Map endpoints for internal vs external context
|
|
47
|
+
const endpointMap = {
|
|
48
|
+
// Text and image generation
|
|
49
|
+
"text-ai": { internal: "/generate-text", external: "/text-ai" },
|
|
50
|
+
"image-ai": { internal: "/generate-image", external: "/image-ai" },
|
|
51
|
+
// Auth endpoints need /auth/ prefix for internal
|
|
52
|
+
status: { internal: "/auth/status", external: "/status" },
|
|
53
|
+
provider: { internal: "/auth/provider", external: "/provider" },
|
|
54
|
+
// Other endpoints
|
|
55
|
+
"track-usage": { internal: "/track-usage", external: "/track-usage" },
|
|
56
|
+
"ai/embed": { internal: "/ai/embed", external: "/ai/embed" },
|
|
57
|
+
};
|
|
58
|
+
const mapping = endpointMap[endpoint];
|
|
59
|
+
if (mapping) {
|
|
60
|
+
const finalEndpoint = isInternalApp ? mapping.internal : mapping.external;
|
|
61
|
+
return `${baseUrl}${finalEndpoint}`;
|
|
50
62
|
}
|
|
51
|
-
|
|
52
|
-
return
|
|
63
|
+
// Fallback for unmapped endpoints
|
|
64
|
+
return `${baseUrl}/${endpoint}`;
|
|
53
65
|
}
|
|
54
66
|
export function createClient(config) {
|
|
55
67
|
const timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
@@ -98,7 +110,7 @@ export function createClient(config) {
|
|
|
98
110
|
}
|
|
99
111
|
async function generateText(req) {
|
|
100
112
|
try {
|
|
101
|
-
const url =
|
|
113
|
+
const url = buildUrl(config.baseUrl, "text-ai");
|
|
102
114
|
const response = await fetchWithRetry(url, {
|
|
103
115
|
method: "POST",
|
|
104
116
|
headers: createHeaders(),
|
|
@@ -108,7 +120,7 @@ export function createClient(config) {
|
|
|
108
120
|
// Track prompt usage if promptId is provided
|
|
109
121
|
if (req.promptId) {
|
|
110
122
|
try {
|
|
111
|
-
await fetch(
|
|
123
|
+
await fetch(buildUrl(config.baseUrl, "track-usage"), {
|
|
112
124
|
method: "POST",
|
|
113
125
|
headers: createHeaders(),
|
|
114
126
|
body: JSON.stringify({ promptId: req.promptId }),
|
|
@@ -128,7 +140,7 @@ export function createClient(config) {
|
|
|
128
140
|
}
|
|
129
141
|
async function generateImage(req) {
|
|
130
142
|
try {
|
|
131
|
-
const url =
|
|
143
|
+
const url = buildUrl(config.baseUrl, "image-ai");
|
|
132
144
|
const response = await fetchWithRetry(url, {
|
|
133
145
|
method: "POST",
|
|
134
146
|
headers: createHeaders(),
|
|
@@ -138,7 +150,7 @@ export function createClient(config) {
|
|
|
138
150
|
// Track prompt usage if promptId is provided
|
|
139
151
|
if (req.promptId) {
|
|
140
152
|
try {
|
|
141
|
-
await fetch(
|
|
153
|
+
await fetch(buildUrl(config.baseUrl, "track-usage"), {
|
|
142
154
|
method: "POST",
|
|
143
155
|
headers: createHeaders(),
|
|
144
156
|
body: JSON.stringify({ promptId: req.promptId }),
|
|
@@ -158,7 +170,7 @@ export function createClient(config) {
|
|
|
158
170
|
}
|
|
159
171
|
async function embed(req) {
|
|
160
172
|
try {
|
|
161
|
-
const url =
|
|
173
|
+
const url = buildUrl(config.baseUrl, "ai/embed");
|
|
162
174
|
return await fetchWithRetry(url, {
|
|
163
175
|
method: "POST",
|
|
164
176
|
headers: createHeaders(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalizeError.d.ts","sourceRoot":"","sources":["../../src/errors/normalizeError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"normalizeError.d.ts","sourceRoot":"","sources":["../../src/errors/normalizeError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,eAAe,CA0G1D"}
|
|
@@ -31,6 +31,13 @@ export function normalizeError(error) {
|
|
|
31
31
|
status,
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
|
+
if (status === 402) {
|
|
35
|
+
return {
|
|
36
|
+
code: ErrorCode.INSUFFICIENT_TOKENS,
|
|
37
|
+
message: error?.message || "Insufficient balance",
|
|
38
|
+
status,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
34
41
|
if (status === 503) {
|
|
35
42
|
return {
|
|
36
43
|
code: ErrorCode.PROVIDER_DOWN,
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,eAAe,GAAG,sBAAsB,GAAG,cAAc,CAAC;CACxE;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -38,7 +38,7 @@ async function fetchWithRetry<T>(
|
|
|
38
38
|
if (!response.ok) {
|
|
39
39
|
const errorData = await response.json().catch(() => ({}));
|
|
40
40
|
const error: any = new Error(
|
|
41
|
-
errorData
|
|
41
|
+
JSON.stringify(errorData) || `HTTP ${response.status}`
|
|
42
42
|
);
|
|
43
43
|
error.status = response.status;
|
|
44
44
|
error.response = { status: response.status };
|
|
@@ -70,23 +70,34 @@ async function fetchWithRetry<T>(
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
|
-
* Build URL for API endpoint with proper
|
|
74
|
-
* For baseUrl="/api/ai"
|
|
75
|
-
* For baseUrl="/api/
|
|
73
|
+
* Build URL for API endpoint with proper routing
|
|
74
|
+
* For internal app (baseUrl="/api/ai"): use internal routes like /generate-text, /auth/status
|
|
75
|
+
* For external app (baseUrl="/api/lastbrain"): use proxy routes like /text-ai, /status
|
|
76
76
|
*/
|
|
77
77
|
function buildUrl(baseUrl: string, endpoint: string): string {
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
const isInternalApp = baseUrl.includes("/api/ai");
|
|
79
|
+
|
|
80
|
+
// Map endpoints for internal vs external context
|
|
81
|
+
const endpointMap: Record<string, { internal: string; external: string }> = {
|
|
82
|
+
// Text and image generation
|
|
83
|
+
"text-ai": { internal: "/generate-text", external: "/text-ai" },
|
|
84
|
+
"image-ai": { internal: "/generate-image", external: "/image-ai" },
|
|
85
|
+
// Auth endpoints need /auth/ prefix for internal
|
|
86
|
+
status: { internal: "/auth/status", external: "/status" },
|
|
87
|
+
provider: { internal: "/auth/provider", external: "/provider" },
|
|
88
|
+
// Other endpoints
|
|
89
|
+
"track-usage": { internal: "/track-usage", external: "/track-usage" },
|
|
90
|
+
"ai/embed": { internal: "/ai/embed", external: "/ai/embed" },
|
|
91
|
+
};
|
|
83
92
|
|
|
84
|
-
|
|
93
|
+
const mapping = endpointMap[endpoint];
|
|
94
|
+
if (mapping) {
|
|
95
|
+
const finalEndpoint = isInternalApp ? mapping.internal : mapping.external;
|
|
96
|
+
return `${baseUrl}${finalEndpoint}`;
|
|
85
97
|
}
|
|
86
98
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return url;
|
|
99
|
+
// Fallback for unmapped endpoints
|
|
100
|
+
return `${baseUrl}/${endpoint}`;
|
|
90
101
|
}
|
|
91
102
|
|
|
92
103
|
export function createClient(config: ClientConfig) {
|
|
@@ -150,7 +161,8 @@ export function createClient(config: ClientConfig) {
|
|
|
150
161
|
|
|
151
162
|
async function generateText(req: AiTextRequest): Promise<AiTextResponse> {
|
|
152
163
|
try {
|
|
153
|
-
const url =
|
|
164
|
+
const url = buildUrl(config.baseUrl, "text-ai");
|
|
165
|
+
|
|
154
166
|
const response = await fetchWithRetry<AiTextResponse>(
|
|
155
167
|
url,
|
|
156
168
|
{
|
|
@@ -165,7 +177,7 @@ export function createClient(config: ClientConfig) {
|
|
|
165
177
|
// Track prompt usage if promptId is provided
|
|
166
178
|
if (req.promptId) {
|
|
167
179
|
try {
|
|
168
|
-
await fetch(
|
|
180
|
+
await fetch(buildUrl(config.baseUrl, "track-usage"), {
|
|
169
181
|
method: "POST",
|
|
170
182
|
headers: createHeaders(),
|
|
171
183
|
body: JSON.stringify({ promptId: req.promptId }),
|
|
@@ -185,7 +197,8 @@ export function createClient(config: ClientConfig) {
|
|
|
185
197
|
|
|
186
198
|
async function generateImage(req: AiImageRequest): Promise<AiImageResponse> {
|
|
187
199
|
try {
|
|
188
|
-
const url =
|
|
200
|
+
const url = buildUrl(config.baseUrl, "image-ai");
|
|
201
|
+
|
|
189
202
|
const response = await fetchWithRetry<AiImageResponse>(
|
|
190
203
|
url,
|
|
191
204
|
{
|
|
@@ -200,7 +213,7 @@ export function createClient(config: ClientConfig) {
|
|
|
200
213
|
// Track prompt usage if promptId is provided
|
|
201
214
|
if (req.promptId) {
|
|
202
215
|
try {
|
|
203
|
-
await fetch(
|
|
216
|
+
await fetch(buildUrl(config.baseUrl, "track-usage"), {
|
|
204
217
|
method: "POST",
|
|
205
218
|
headers: createHeaders(),
|
|
206
219
|
body: JSON.stringify({ promptId: req.promptId }),
|
|
@@ -220,7 +233,7 @@ export function createClient(config: ClientConfig) {
|
|
|
220
233
|
|
|
221
234
|
async function embed(req: AiEmbedRequest): Promise<AiEmbedResponse> {
|
|
222
235
|
try {
|
|
223
|
-
const url =
|
|
236
|
+
const url = buildUrl(config.baseUrl, "ai/embed");
|
|
224
237
|
return await fetchWithRetry<AiEmbedResponse>(
|
|
225
238
|
url,
|
|
226
239
|
{
|
|
@@ -45,6 +45,14 @@ export function normalizeError(error: any): NormalizedError {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
if (status === 402) {
|
|
49
|
+
return {
|
|
50
|
+
code: ErrorCode.INSUFFICIENT_TOKENS,
|
|
51
|
+
message: error?.message || "Insufficient balance",
|
|
52
|
+
status,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
if (status === 503) {
|
|
49
57
|
return {
|
|
50
58
|
code: ErrorCode.PROVIDER_DOWN,
|
package/src/types/index.ts
CHANGED
|
@@ -37,6 +37,8 @@ export interface AiImageRequest {
|
|
|
37
37
|
size?: string;
|
|
38
38
|
n?: number;
|
|
39
39
|
promptId?: string; // Track which prompt was used
|
|
40
|
+
storeOutputs?: boolean; // Whether to store outputs (external API)
|
|
41
|
+
artifactTitle?: string; // Title for stored artifacts
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
export interface AiImageResponse {
|