nuxt-edge-ai 0.1.4 → 0.2.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 CHANGED
@@ -5,6 +5,8 @@
5
5
  [![license](https://img.shields.io/npm/l/nuxt-edge-ai.svg)](./LICENSE)
6
6
  [![nuxt](https://img.shields.io/badge/Nuxt-4.x-00DC82?logo=nuxt.js&logoColor=white)](https://nuxt.com/)
7
7
  [![ci](https://github.com/otadk/nuxt-edge-ai/actions/workflows/ci.yml/badge.svg)](https://github.com/otadk/nuxt-edge-ai/actions/workflows/ci.yml)
8
+ [![oosmetrics](https://api.oosmetrics.com/api/v1/badge/achievement/69a77845-965e-4d85-a153-e43023059704.svg)](https://oosmetrics.com/repo/otadk/nuxt-edge-ai)
9
+ [![oosmetrics](https://api.oosmetrics.com/api/v1/badge/achievement/5e00ff2f-b279-4ba3-a4de-4f53d9ca2c0c.svg)](https://oosmetrics.com/repo/otadk/nuxt-edge-ai)
8
10
 
9
11
  `nuxt-edge-ai` is a Nuxt module for building local-first AI applications with a real server-side WASM inference runtime and an optional remote API fallback.
10
12
 
package/dist/module.mjs CHANGED
@@ -150,17 +150,52 @@ const module$1 = defineNuxtModule({
150
150
  method: "post",
151
151
  handler: resolver.resolve("./runtime/server/api/chat-completions.post")
152
152
  });
153
+ addServerHandler({
154
+ route: `${routeBase}/classify`,
155
+ method: "post",
156
+ handler: resolver.resolve("./runtime/server/api/classify.post")
157
+ });
158
+ addServerHandler({
159
+ route: `${routeBase}/embed`,
160
+ method: "post",
161
+ handler: resolver.resolve("./runtime/server/api/embed.post")
162
+ });
163
+ addServerHandler({
164
+ route: `${routeBase}/summarize`,
165
+ method: "post",
166
+ handler: resolver.resolve("./runtime/server/api/summarize.post")
167
+ });
168
+ addServerHandler({
169
+ route: `${routeBase}/translate`,
170
+ method: "post",
171
+ handler: resolver.resolve("./runtime/server/api/translate.post")
172
+ });
173
+ addServerHandler({
174
+ route: `${routeBase}/fill-mask`,
175
+ method: "post",
176
+ handler: resolver.resolve("./runtime/server/api/fill-mask.post")
177
+ });
153
178
  addTypeTemplate({
154
179
  filename: "types/nuxt-edge-ai.d.ts",
155
180
  getContents: () => `import type { NuxtApp } from '#app'
156
181
  import type {
157
182
  EdgeAIChatCompletionRequest,
158
183
  EdgeAIChatCompletionResponse,
184
+ EdgeAIClassifyRequest,
185
+ EdgeAIClassifyResponse,
159
186
  EdgeAIClientOptions,
187
+ EdgeAIEmbedRequest,
188
+ EdgeAIEmbedResponse,
189
+ EdgeAIFillMaskRequest,
190
+ EdgeAIFillMaskResponse,
160
191
  EdgeAIGenerateRequest,
161
192
  EdgeAIGenerateResponse,
162
193
  EdgeAIHealthResponse,
163
- EdgeAIPullResponse
194
+ EdgeAIPullResponse,
195
+ EdgeAISummarizeRequest,
196
+ EdgeAISummarizeResponse,
197
+ EdgeAITranslateRequest,
198
+ EdgeAITranslateResponse,
164
199
  } from 'nuxt-edge-ai'
165
200
  import type { EdgeAI } from 'nuxt-edge-ai'
166
201
 
@@ -179,6 +214,11 @@ declare module '#app' {
179
214
  generate: (payload: EdgeAIGenerateRequest) => Promise<EdgeAIGenerateResponse>
180
215
  chatCompletions: (payload: EdgeAIChatCompletionRequest) => Promise<EdgeAIChatCompletionResponse>
181
216
  health: () => Promise<EdgeAIHealthResponse>
217
+ classify: (payload: EdgeAIClassifyRequest) => Promise<EdgeAIClassifyResponse>
218
+ embed: (payload: EdgeAIEmbedRequest) => Promise<EdgeAIEmbedResponse>
219
+ summarize: (payload: EdgeAISummarizeRequest) => Promise<EdgeAISummarizeResponse>
220
+ translate: (payload: EdgeAITranslateRequest) => Promise<EdgeAITranslateResponse>
221
+ fillMask: (payload: EdgeAIFillMaskRequest) => Promise<EdgeAIFillMaskResponse>
182
222
  }
183
223
  }
184
224
  }
@@ -1,4 +1,4 @@
1
- import type { EdgeAIChatCompletionRequest, EdgeAIChatCompletionResponse, EdgeAIGenerateRequest, EdgeAIGenerateResponse, EdgeAIHealthResponse, EdgeAIPullResponse, EdgeAIStreamCallbacks, EdgeAIStreamState, StreamPart } from './types.js';
1
+ import type { EdgeAIChatCompletionRequest, EdgeAIChatCompletionResponse, EdgeAIClassifyRequest, EdgeAIClassifyResponse, EdgeAIEmbedRequest, EdgeAIEmbedResponse, EdgeAIFillMaskRequest, EdgeAIFillMaskResponse, EdgeAIGenerateRequest, EdgeAIGenerateResponse, EdgeAIHealthResponse, EdgeAIPullResponse, EdgeAIStreamCallbacks, EdgeAIStreamState, EdgeAISummarizeRequest, EdgeAISummarizeResponse, EdgeAITranslateRequest, EdgeAITranslateResponse, StreamPart } from './types.js';
2
2
  export interface EdgeAIClientOptions {
3
3
  baseURL: string;
4
4
  apiKey?: string;
@@ -23,6 +23,11 @@ export declare class EdgeAI {
23
23
  health(): Promise<EdgeAIHealthResponse>;
24
24
  pull(): Promise<EdgeAIPullResponse>;
25
25
  generate(payload: EdgeAIGenerateRequest): Promise<EdgeAIGenerateResponse>;
26
+ classify(payload: EdgeAIClassifyRequest): Promise<EdgeAIClassifyResponse>;
27
+ embed(payload: EdgeAIEmbedRequest): Promise<EdgeAIEmbedResponse>;
28
+ summarize(payload: EdgeAISummarizeRequest): Promise<EdgeAISummarizeResponse>;
29
+ translate(payload: EdgeAITranslateRequest): Promise<EdgeAITranslateResponse>;
30
+ fillMask(payload: EdgeAIFillMaskRequest): Promise<EdgeAIFillMaskResponse>;
26
31
  private streamChatCompletion;
27
32
  streamChatCompletionGenerator(payload: EdgeAIChatCompletionRequest): AsyncGenerator<string, EdgeAIStreamState, unknown>;
28
33
  stop(state: EdgeAIStreamState): void;
@@ -124,6 +124,36 @@ export class EdgeAI {
124
124
  body: payload
125
125
  });
126
126
  }
127
+ classify(payload) {
128
+ return this.request("/classify", {
129
+ method: "POST",
130
+ body: payload
131
+ });
132
+ }
133
+ embed(payload) {
134
+ return this.request("/embed", {
135
+ method: "POST",
136
+ body: payload
137
+ });
138
+ }
139
+ summarize(payload) {
140
+ return this.request("/summarize", {
141
+ method: "POST",
142
+ body: payload
143
+ });
144
+ }
145
+ translate(payload) {
146
+ return this.request("/translate", {
147
+ method: "POST",
148
+ body: payload
149
+ });
150
+ }
151
+ fillMask(payload) {
152
+ return this.request("/fill-mask", {
153
+ method: "POST",
154
+ body: payload
155
+ });
156
+ }
127
157
  // Streaming chat completion with callbacks
128
158
  async streamChatCompletion(payload, callbacks) {
129
159
  const abortController = new AbortController();
@@ -1,5 +1,5 @@
1
1
  import type { EdgeAI } from '../client.js';
2
- import type { EdgeAIChatCompletionRequest, EdgeAIChatCompletionResponse, EdgeAIGenerateRequest, EdgeAIGenerateResponse, EdgeAIHealthResponse, EdgeAIPullResponse } from '../types.js';
2
+ import type { EdgeAIChatCompletionRequest, EdgeAIChatCompletionResponse, EdgeAIClassifyRequest, EdgeAIEmbedRequest, EdgeAIFillMaskRequest, EdgeAIGenerateRequest, EdgeAIGenerateResponse, EdgeAIHealthResponse, EdgeAIPullResponse, EdgeAISummarizeRequest, EdgeAITranslateRequest } from '../types.js';
3
3
  export interface UseEdgeAIOptions {
4
4
  onStreamStart?: () => void;
5
5
  onStreamToken?: (token: string) => void;
@@ -29,6 +29,11 @@ export declare function useEdgeAI(options?: UseEdgeAIOptions): {
29
29
  generate(payload: EdgeAIGenerateRequest): Promise<EdgeAIGenerateResponse>;
30
30
  chatCompletions(payload: EdgeAIChatCompletionRequest): Promise<EdgeAIChatCompletionResponse>;
31
31
  health(): Promise<EdgeAIHealthResponse>;
32
+ classify(payload: EdgeAIClassifyRequest): Promise<import("../types.js").EdgeAIClassifyResponse>;
33
+ embed(payload: EdgeAIEmbedRequest): Promise<import("../types.js").EdgeAIEmbedResponse>;
34
+ summarize(payload: EdgeAISummarizeRequest): Promise<import("../types.js").EdgeAISummarizeResponse>;
35
+ translate(payload: EdgeAITranslateRequest): Promise<import("../types.js").EdgeAITranslateResponse>;
36
+ fillMask(payload: EdgeAIFillMaskRequest): Promise<import("../types.js").EdgeAIFillMaskResponse>;
32
37
  isLoading: import("vue").Ref<boolean, boolean>;
33
38
  isStreaming: import("vue").Ref<boolean, boolean>;
34
39
  streamedContent: import("vue").Ref<string, string>;
@@ -194,19 +194,17 @@ export function useEdgeAI(options = {}) {
194
194
  model: payload.model || defaultModel
195
195
  };
196
196
  try {
197
- const response = await fetch(
198
- routeBase.startsWith("http") ? `${routeBase}/chat/completions` : new URL(`${routeBase}/chat/completions`, window.location.origin).toString(),
199
- {
200
- method: "POST",
201
- headers: {
202
- "content-type": "application/json",
203
- "accept": "text/event-stream",
204
- "x-vercel-ai-ui-message-stream": "v1"
205
- },
206
- body: JSON.stringify({ ...payload, stream: true }),
207
- signal: abortController.value.signal
208
- }
209
- );
197
+ const fetchUrl = routeBase.startsWith("http") ? `${routeBase}/chat/completions` : new URL(`${routeBase}/chat/completions`, window.location.origin).toString();
198
+ const response = await fetch(fetchUrl, {
199
+ method: "POST",
200
+ headers: {
201
+ "content-type": "application/json",
202
+ "accept": "text/event-stream",
203
+ "x-vercel-ai-ui-message-stream": "v1"
204
+ },
205
+ body: JSON.stringify({ ...payload, stream: true }),
206
+ signal: abortController.value.signal
207
+ });
210
208
  if (!response.ok) {
211
209
  const errorText = await response.text();
212
210
  throw new Error(`Stream request failed with ${response.status}: ${errorText}`);
@@ -263,10 +261,15 @@ export function useEdgeAI(options = {}) {
263
261
  case "error": {
264
262
  throw new Error(part.errorText || "Stream error");
265
263
  }
264
+ default: {
265
+ break;
266
+ }
266
267
  }
267
268
  }
268
269
  }
269
- if (done) break;
270
+ if (done) {
271
+ break;
272
+ }
270
273
  }
271
274
  } finally {
272
275
  reader.releaseLock();
@@ -311,6 +314,22 @@ export function useEdgeAI(options = {}) {
311
314
  health() {
312
315
  return edgeAIService.health();
313
316
  },
317
+ // Task-specific methods
318
+ classify(payload) {
319
+ return edgeAIService.client.classify(payload);
320
+ },
321
+ embed(payload) {
322
+ return edgeAIService.client.embed(payload);
323
+ },
324
+ summarize(payload) {
325
+ return edgeAIService.client.summarize(payload);
326
+ },
327
+ translate(payload) {
328
+ return edgeAIService.client.translate(payload);
329
+ },
330
+ fillMask(payload) {
331
+ return edgeAIService.client.fillMask(payload);
332
+ },
314
333
  // Streaming state (reactive refs)
315
334
  isLoading,
316
335
  isStreaming,
@@ -1,5 +1,5 @@
1
1
  import { EdgeAI } from './client.js';
2
- import type { EdgeAIChatCompletionRequest, EdgeAIChatCompletionResponse, EdgeAIGenerateRequest, EdgeAIGenerateResponse, EdgeAIHealthResponse, EdgeAIPullResponse } from './types.js';
2
+ import type { EdgeAIChatCompletionRequest, EdgeAIChatCompletionResponse, EdgeAIClassifyRequest, EdgeAIClassifyResponse, EdgeAIEmbedRequest, EdgeAIEmbedResponse, EdgeAIFillMaskRequest, EdgeAIFillMaskResponse, EdgeAIGenerateRequest, EdgeAIGenerateResponse, EdgeAIHealthResponse, EdgeAIPullResponse, EdgeAISummarizeRequest, EdgeAISummarizeResponse, EdgeAITranslateRequest, EdgeAITranslateResponse } from './types.js';
3
3
  declare const _default: import("nuxt/app").Plugin<{
4
4
  edgeAI: {
5
5
  routeBase: string;
@@ -14,6 +14,11 @@ declare const _default: import("nuxt/app").Plugin<{
14
14
  generate(payload: EdgeAIGenerateRequest): Promise<EdgeAIGenerateResponse>;
15
15
  chatCompletions(payload: EdgeAIChatCompletionRequest): Promise<EdgeAIChatCompletionResponse>;
16
16
  health(): Promise<EdgeAIHealthResponse>;
17
+ classify(payload: EdgeAIClassifyRequest): Promise<EdgeAIClassifyResponse>;
18
+ embed(payload: EdgeAIEmbedRequest): Promise<EdgeAIEmbedResponse>;
19
+ summarize(payload: EdgeAISummarizeRequest): Promise<EdgeAISummarizeResponse>;
20
+ translate(payload: EdgeAITranslateRequest): Promise<EdgeAITranslateResponse>;
21
+ fillMask(payload: EdgeAIFillMaskRequest): Promise<EdgeAIFillMaskResponse>;
17
22
  };
18
23
  }> & import("nuxt/app").ObjectPlugin<{
19
24
  edgeAI: {
@@ -29,6 +34,11 @@ declare const _default: import("nuxt/app").Plugin<{
29
34
  generate(payload: EdgeAIGenerateRequest): Promise<EdgeAIGenerateResponse>;
30
35
  chatCompletions(payload: EdgeAIChatCompletionRequest): Promise<EdgeAIChatCompletionResponse>;
31
36
  health(): Promise<EdgeAIHealthResponse>;
37
+ classify(payload: EdgeAIClassifyRequest): Promise<EdgeAIClassifyResponse>;
38
+ embed(payload: EdgeAIEmbedRequest): Promise<EdgeAIEmbedResponse>;
39
+ summarize(payload: EdgeAISummarizeRequest): Promise<EdgeAISummarizeResponse>;
40
+ translate(payload: EdgeAITranslateRequest): Promise<EdgeAITranslateResponse>;
41
+ fillMask(payload: EdgeAIFillMaskRequest): Promise<EdgeAIFillMaskResponse>;
32
42
  };
33
43
  }>;
34
44
  export default _default;
@@ -44,6 +44,36 @@ export default defineNuxtPlugin(() => {
44
44
  },
45
45
  health() {
46
46
  return $fetch(`${routeBase}/health`);
47
+ },
48
+ classify(payload) {
49
+ return $fetch(`${routeBase}/classify`, {
50
+ method: "POST",
51
+ body: payload
52
+ });
53
+ },
54
+ embed(payload) {
55
+ return $fetch(`${routeBase}/embed`, {
56
+ method: "POST",
57
+ body: payload
58
+ });
59
+ },
60
+ summarize(payload) {
61
+ return $fetch(`${routeBase}/summarize`, {
62
+ method: "POST",
63
+ body: payload
64
+ });
65
+ },
66
+ translate(payload) {
67
+ return $fetch(`${routeBase}/translate`, {
68
+ method: "POST",
69
+ body: payload
70
+ });
71
+ },
72
+ fillMask(payload) {
73
+ return $fetch(`${routeBase}/fill-mask`, {
74
+ method: "POST",
75
+ body: payload
76
+ });
47
77
  }
48
78
  }
49
79
  }
@@ -6,7 +6,7 @@ const defaultGeneration = {
6
6
  repetitionPenalty: 1.05
7
7
  };
8
8
  export const builtinModelPresets = {
9
- distilgpt2: {
9
+ "distilgpt2": {
10
10
  label: "DistilGPT2",
11
11
  description: "Small baseline text-generation model for quick smoke tests.",
12
12
  model: {
@@ -18,6 +18,78 @@ export const builtinModelPresets = {
18
18
  ...defaultGeneration
19
19
  }
20
20
  }
21
+ },
22
+ "distilbert-sst2": {
23
+ label: "DistilBERT Sentiment",
24
+ description: "Sentiment analysis (positive/negative) using DistilBERT fine-tuned on SST-2.",
25
+ model: {
26
+ id: "Xenova/distilbert-base-uncased-finetuned-sst-2-english",
27
+ task: "text-classification",
28
+ allowRemote: true,
29
+ dtype: "fp32"
30
+ }
31
+ },
32
+ "minilm-l6-v2": {
33
+ label: "MiniLM Embedding",
34
+ description: "384-dimensional text embeddings using all-MiniLM-L6-v2. Ideal for semantic search and RAG.",
35
+ model: {
36
+ id: "Xenova/all-MiniLM-L6-v2",
37
+ task: "feature-extraction",
38
+ allowRemote: true,
39
+ dtype: "fp32"
40
+ }
41
+ },
42
+ "distilbart-cnn": {
43
+ label: "DistilBART Summarization",
44
+ description: "Text summarization using DistilBART fine-tuned on CNN/DailyMail.",
45
+ model: {
46
+ id: "Xenova/distilbart-cnn-6-6",
47
+ task: "summarization",
48
+ allowRemote: true,
49
+ dtype: "fp32",
50
+ generation: {
51
+ ...defaultGeneration,
52
+ maxNewTokens: 128
53
+ }
54
+ }
55
+ },
56
+ "opus-mt-en-zh": {
57
+ label: "Opus-MT en\u2192zh",
58
+ description: "English to Chinese translation using Helsinki-NLP Opus-MT.",
59
+ model: {
60
+ id: "Xenova/opus-mt-en-zh",
61
+ task: "translation",
62
+ allowRemote: true,
63
+ dtype: "fp32",
64
+ generation: {
65
+ ...defaultGeneration,
66
+ maxNewTokens: 256
67
+ }
68
+ }
69
+ },
70
+ "opus-mt-zh-en": {
71
+ label: "Opus-MT zh\u2192en",
72
+ description: "Chinese to English translation using Helsinki-NLP Opus-MT.",
73
+ model: {
74
+ id: "Xenova/opus-mt-zh-en",
75
+ task: "translation",
76
+ allowRemote: true,
77
+ dtype: "fp32",
78
+ generation: {
79
+ ...defaultGeneration,
80
+ maxNewTokens: 256
81
+ }
82
+ }
83
+ },
84
+ "bert-base-uncased": {
85
+ label: "BERT Fill-Mask",
86
+ description: "Masked token prediction using BERT base uncased. Use [MASK] token in your text.",
87
+ model: {
88
+ id: "Xenova/bert-base-uncased",
89
+ task: "fill-mask",
90
+ allowRemote: true,
91
+ dtype: "fp32"
92
+ }
21
93
  }
22
94
  };
23
95
  export function resolveGenerationDefaults(defaults, overrides) {
@@ -30,11 +102,11 @@ export function resolveGenerationDefaults(defaults, overrides) {
30
102
  };
31
103
  }
32
104
  export function mergeModelConfig(base, overrides) {
33
- const fallbackPreset = builtinModelPresets.distilgpt2;
34
- const source = overrides?.id || base?.id || fallbackPreset.model.id;
105
+ const resolvedId = overrides?.id || base?.id || builtinModelPresets.distilgpt2.model.id;
106
+ const resolvedTask = overrides?.task ?? base?.task ?? "text-generation";
35
107
  return {
36
- id: source,
37
- task: overrides?.task ?? base?.task ?? "text-generation",
108
+ id: resolvedId,
109
+ task: resolvedTask,
38
110
  localPath: overrides?.localPath ?? base?.localPath,
39
111
  allowRemote: overrides?.allowRemote ?? base?.allowRemote ?? true,
40
112
  dtype: overrides?.dtype ?? base?.dtype,
@@ -1,2 +1,2 @@
1
- declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<import("../../types.js").EdgeAIChatCompletionResponse | undefined>>;
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<import("../../types.js").EdgeAIChatCompletionResponse | null>>;
2
2
  export default _default;
@@ -21,6 +21,7 @@ export default defineEventHandler(async (event) => {
21
21
  const wantsStreaming = body.stream === true || wantsEventStream;
22
22
  if (wantsStreaming) {
23
23
  const streamResponse = !body.stream || wantsUIMessageStream ? createEdgeAIChatCompletionStream(config, body) : createEdgeAIChatCompletionOpenAIStream(config, body);
24
+ event.node.res.statusCode = 200;
24
25
  for (const [key, value] of Object.entries(streamResponse.headers)) {
25
26
  event.node.res.setHeader(key, value);
26
27
  }
@@ -35,7 +36,7 @@ export default defineEventHandler(async (event) => {
35
36
  reader.releaseLock();
36
37
  event.node.res.end();
37
38
  }
38
- return;
39
+ return null;
39
40
  }
40
41
  return createEdgeAIChatCompletion(config, body);
41
42
  });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<import("../../types.js").EdgeAIClassifyResponse>>;
2
+ export default _default;
@@ -0,0 +1,14 @@
1
+ import { createError, defineEventHandler, readBody } from "h3";
2
+ import { useRuntimeConfig } from "#imports";
3
+ import { classifyEdgeAIText } from "../utils/edge-ai-engine.js";
4
+ export default defineEventHandler(async (event) => {
5
+ const body = await readBody(event);
6
+ if (!body?.text?.trim()) {
7
+ throw createError({ statusCode: 400, statusMessage: "Text is required." });
8
+ }
9
+ const config = useRuntimeConfig().edgeAI;
10
+ return classifyEdgeAIText(config, {
11
+ text: body.text.trim(),
12
+ model: body.model
13
+ });
14
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<import("../../types.js").EdgeAIEmbedResponse>>;
2
+ export default _default;
@@ -0,0 +1,15 @@
1
+ import { createError, defineEventHandler, readBody } from "h3";
2
+ import { useRuntimeConfig } from "#imports";
3
+ import { embedEdgeAIText } from "../utils/edge-ai-engine.js";
4
+ export default defineEventHandler(async (event) => {
5
+ const body = await readBody(event);
6
+ if (!body?.texts || (Array.isArray(body.texts) ? body.texts.length === 0 : !body.texts.trim())) {
7
+ throw createError({ statusCode: 400, statusMessage: "Texts (string or string array) is required." });
8
+ }
9
+ const config = useRuntimeConfig().edgeAI;
10
+ return embedEdgeAIText(config, {
11
+ texts: body.texts,
12
+ pooling: body.pooling,
13
+ model: body.model
14
+ });
15
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<import("../../types.js").EdgeAIFillMaskResponse>>;
2
+ export default _default;
@@ -0,0 +1,15 @@
1
+ import { createError, defineEventHandler, readBody } from "h3";
2
+ import { useRuntimeConfig } from "#imports";
3
+ import { fillMaskEdgeAIText } from "../utils/edge-ai-engine.js";
4
+ export default defineEventHandler(async (event) => {
5
+ const body = await readBody(event);
6
+ if (!body?.text?.trim()) {
7
+ throw createError({ statusCode: 400, statusMessage: "Text with [MASK] token is required." });
8
+ }
9
+ const config = useRuntimeConfig().edgeAI;
10
+ return fillMaskEdgeAIText(config, {
11
+ text: body.text.trim(),
12
+ model: body.model,
13
+ topK: body.topK
14
+ });
15
+ });
@@ -1,2 +1,2 @@
1
- declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<import("../../types.js").EdgeAIGenerateResponse>>;
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<import("../../types.js").EdgeAIGenerateResponse | import("../../types.js").EdgeAIClassifyResponse | import("../../types.js").EdgeAIEmbedResponse | import("../../types.js").EdgeAISummarizeResponse | import("../../types.js").EdgeAITranslateResponse | import("../../types.js").EdgeAIFillMaskResponse>>;
2
2
  export default _default;
@@ -1,8 +1,56 @@
1
1
  import { createError, defineEventHandler, readBody } from "h3";
2
2
  import { useRuntimeConfig } from "#imports";
3
- import { generateEdgeAIText } from "../utils/edge-ai-engine.js";
3
+ import {
4
+ classifyEdgeAIText,
5
+ embedEdgeAIText,
6
+ fillMaskEdgeAIText,
7
+ generateEdgeAIText,
8
+ resolvePromptFromMessages,
9
+ summarizeEdgeAIText,
10
+ translateEdgeAIText
11
+ } from "../utils/edge-ai-engine.js";
4
12
  export default defineEventHandler(async (event) => {
5
13
  const body = await readBody(event);
14
+ const config = useRuntimeConfig().edgeAI;
15
+ if (body?.task && body.task !== "text-generation") {
16
+ switch (body.task) {
17
+ case "text-classification": {
18
+ const text = body.prompt?.trim();
19
+ if (!text) {
20
+ throw createError({ statusCode: 400, statusMessage: "Text (prompt) is required for classification." });
21
+ }
22
+ return classifyEdgeAIText(config, { text, model: body.model });
23
+ }
24
+ case "feature-extraction": {
25
+ const texts = body.prompt?.trim() || body.messages && resolvePromptFromMessages(body.messages);
26
+ if (!texts) {
27
+ throw createError({ statusCode: 400, statusMessage: "Text (prompt or messages) is required for embedding." });
28
+ }
29
+ return embedEdgeAIText(config, { texts, model: body.model });
30
+ }
31
+ case "summarization": {
32
+ const text = body.prompt?.trim();
33
+ if (!text) {
34
+ throw createError({ statusCode: 400, statusMessage: "Text (prompt) is required for summarization." });
35
+ }
36
+ return summarizeEdgeAIText(config, { text, model: body.model, generation: body.generation });
37
+ }
38
+ case "translation": {
39
+ const text = body.prompt?.trim();
40
+ if (!text) {
41
+ throw createError({ statusCode: 400, statusMessage: "Text (prompt) is required for translation." });
42
+ }
43
+ return translateEdgeAIText(config, { text, model: body.model });
44
+ }
45
+ case "fill-mask": {
46
+ const text = body.prompt?.trim();
47
+ if (!text) {
48
+ throw createError({ statusCode: 400, statusMessage: "Text (prompt) with [MASK] is required for fill-mask." });
49
+ }
50
+ return fillMaskEdgeAIText(config, { text, model: body.model });
51
+ }
52
+ }
53
+ }
6
54
  const prompt = body?.prompt?.trim();
7
55
  const hasMessages = Array.isArray(body?.messages) && body.messages.length > 0;
8
56
  if (!prompt && !hasMessages) {
@@ -11,7 +59,6 @@ export default defineEventHandler(async (event) => {
11
59
  statusMessage: "Prompt or messages are required."
12
60
  });
13
61
  }
14
- const config = useRuntimeConfig().edgeAI;
15
62
  return generateEdgeAIText(config, {
16
63
  prompt,
17
64
  remote: body.remote,
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<import("../../types.js").EdgeAISummarizeResponse>>;
2
+ export default _default;
@@ -0,0 +1,15 @@
1
+ import { createError, defineEventHandler, readBody } from "h3";
2
+ import { useRuntimeConfig } from "#imports";
3
+ import { summarizeEdgeAIText } from "../utils/edge-ai-engine.js";
4
+ export default defineEventHandler(async (event) => {
5
+ const body = await readBody(event);
6
+ if (!body?.text?.trim()) {
7
+ throw createError({ statusCode: 400, statusMessage: "Text is required." });
8
+ }
9
+ const config = useRuntimeConfig().edgeAI;
10
+ return summarizeEdgeAIText(config, {
11
+ text: body.text.trim(),
12
+ model: body.model,
13
+ generation: body.generation
14
+ });
15
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<import("../../types.js").EdgeAITranslateResponse>>;
2
+ export default _default;
@@ -0,0 +1,14 @@
1
+ import { createError, defineEventHandler, readBody } from "h3";
2
+ import { useRuntimeConfig } from "#imports";
3
+ import { translateEdgeAIText } from "../utils/edge-ai-engine.js";
4
+ export default defineEventHandler(async (event) => {
5
+ const body = await readBody(event);
6
+ if (!body?.text?.trim()) {
7
+ throw createError({ statusCode: 400, statusMessage: "Text is required." });
8
+ }
9
+ const config = useRuntimeConfig().edgeAI;
10
+ return translateEdgeAIText(config, {
11
+ text: body.text.trim(),
12
+ model: body.model
13
+ });
14
+ });
@@ -1,4 +1,58 @@
1
- import type { EdgeAIChatCompletionRequest, EdgeAIChatCompletionResponse, EdgeAIGenerateRequest, EdgeAIGenerateResponse, EdgeAIHealthResponse, EdgeAIServerRuntimeConfig, EdgeAIPullResponse } from '../../types.js';
1
+ import type { EdgeAIChatCompletionRequest, EdgeAIChatCompletionResponse, EdgeAIChatCompletionStreamResponse, EdgeAIClassifyRequest, EdgeAIClassifyResponse, EdgeAIEmbedRequest, EdgeAIEmbedResponse, EdgeAIFillMaskRequest, EdgeAIFillMaskResponse, EdgeAIGenerateRequest, EdgeAIGenerateResponse, EdgeAIGenerationOptions, EdgeAIHealthResponse, EdgeAIModelInfo, EdgeAIRemoteMessage, EdgeAIRemoteConfig, EdgeAIServerRuntimeConfig, EdgeAISummarizeRequest, EdgeAISummarizeResponse, EdgeAITranslateRequest, EdgeAITranslateResponse, EdgeAIPullResponse } from '../../types.js';
2
+ interface RemoteChatCompletionResponse {
3
+ id?: string;
4
+ model?: string;
5
+ choices?: Array<{
6
+ message?: {
7
+ role?: string;
8
+ content?: string | Array<{
9
+ type?: string;
10
+ text?: string;
11
+ }>;
12
+ reasoning_details?: unknown;
13
+ [key: string]: unknown;
14
+ };
15
+ text?: string;
16
+ delta?: {
17
+ role?: string;
18
+ content?: string;
19
+ };
20
+ finish_reason?: string | null;
21
+ }>;
22
+ output_text?: string;
23
+ output?: Array<{
24
+ content?: Array<{
25
+ text?: string;
26
+ type?: string;
27
+ }>;
28
+ }>;
29
+ }
30
+ export declare function resolveLocalModelSource(config: EdgeAIServerRuntimeConfig, modelOverride?: string): EdgeAIModelInfo;
31
+ export declare function resolveRemoteModelSource(config: EdgeAIServerRuntimeConfig, modelOverride?: string): EdgeAIModelInfo;
32
+ export declare function resolveGenerationOptions(defaults?: EdgeAIGenerationOptions, overrides?: EdgeAIGenerateRequest['generation']): {
33
+ maxNewTokens: number;
34
+ temperature: number;
35
+ topP: number;
36
+ doSample: boolean;
37
+ repetitionPenalty: number;
38
+ };
39
+ export declare function extractGeneratedText(prompt: string, output: unknown): string;
40
+ export declare function extractTextFromMessageContent(content: unknown): string;
41
+ export declare function resolvePromptFromMessages(messages?: EdgeAIRemoteMessage[]): string;
42
+ export declare function resolvePrompt(input: EdgeAIGenerateRequest): string;
43
+ export declare function buildRemoteMessages(config: EdgeAIServerRuntimeConfig, input: EdgeAIGenerateRequest): EdgeAIRemoteMessage[];
44
+ export declare function buildAssistantMessage(payload: RemoteChatCompletionResponse, text: string): EdgeAIRemoteMessage;
45
+ export declare function estimateTokenCount(text: string): number;
46
+ export declare function toChatCompletionResponse(request: EdgeAIChatCompletionRequest, result: EdgeAIGenerateResponse): EdgeAIChatCompletionResponse;
47
+ export declare function toChatCompletionStreamChunk(id: string, model: string, delta: Partial<EdgeAIRemoteMessage>, finishReason?: 'stop' | null): EdgeAIChatCompletionStreamResponse;
48
+ export declare function resolveRemoteApiKey(config: EdgeAIRemoteConfig): string | undefined;
49
+ export declare function joinUrl(baseURL: string, path: string): string;
50
+ export declare function extractRemoteText(payload: RemoteChatCompletionResponse): string;
51
+ export declare function classifyEdgeAIText(config: EdgeAIServerRuntimeConfig, request: EdgeAIClassifyRequest): Promise<EdgeAIClassifyResponse>;
52
+ export declare function embedEdgeAIText(config: EdgeAIServerRuntimeConfig, request: EdgeAIEmbedRequest): Promise<EdgeAIEmbedResponse>;
53
+ export declare function summarizeEdgeAIText(config: EdgeAIServerRuntimeConfig, request: EdgeAISummarizeRequest): Promise<EdgeAISummarizeResponse>;
54
+ export declare function translateEdgeAIText(config: EdgeAIServerRuntimeConfig, request: EdgeAITranslateRequest): Promise<EdgeAITranslateResponse>;
55
+ export declare function fillMaskEdgeAIText(config: EdgeAIServerRuntimeConfig, request: EdgeAIFillMaskRequest): Promise<EdgeAIFillMaskResponse>;
2
56
  export declare function getEdgeAIHealth(config: EdgeAIServerRuntimeConfig): Promise<EdgeAIHealthResponse>;
3
57
  export declare function pullEdgeAIModel(config: EdgeAIServerRuntimeConfig): Promise<EdgeAIPullResponse>;
4
58
  export declare function generateEdgeAIText(config: EdgeAIServerRuntimeConfig, input: EdgeAIGenerateRequest): Promise<EdgeAIGenerateResponse>;
@@ -11,3 +65,4 @@ export declare function createEdgeAIChatCompletionOpenAIStream(config: EdgeAISer
11
65
  stream: ReadableStream<string>;
12
66
  headers: Record<string, string>;
13
67
  };
68
+ export {};