@m5kdev/backend 0.8.4 → 0.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { ServerResultAsync } from "../base/base.dto.mjs";
2
2
  import { BaseTableRepository } from "../base/base.repository.mjs";
3
- import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
4
3
  import { InferInsertModel, InferSelectModel } from "drizzle-orm";
4
+ import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
5
5
  import { LibSQLDatabase } from "drizzle-orm/libsql";
6
6
 
7
7
  //#region src/modules/ai/ai.repository.d.ts
@@ -1,5 +1,5 @@
1
- import { ai_db_exports } from "./ai.db.mjs";
2
1
  import { BaseTableRepository } from "../base/base.repository.mjs";
2
+ import { ai_db_exports } from "./ai.db.mjs";
3
3
  import { eq, sql } from "drizzle-orm";
4
4
  import { ok } from "neverthrow";
5
5
  //#region src/modules/ai/ai.repository.ts
@@ -35,6 +35,8 @@ type AIServiceGenerateTextParams = Omit<GenerateTextParams, "model" | "prompt" |
35
35
  model: string;
36
36
  removeMDash?: boolean;
37
37
  ctx?: AIServiceActorContext;
38
+ retryAttempts?: number;
39
+ retryModels?: string[];
38
40
  };
39
41
  type AIServiceGenerateObjectParams<T extends ZodType> = Omit<GenerateTextParams, "model" | "prompt" | "messages" | "output"> & GenerateTextInput & {
40
42
  model: string;
@@ -42,6 +44,15 @@ type AIServiceGenerateObjectParams<T extends ZodType> = Omit<GenerateTextParams,
42
44
  repairAttempts?: number;
43
45
  repairModel?: string;
44
46
  ctx?: AIServiceActorContext;
47
+ retryAttempts?: number;
48
+ retryModels?: string[];
49
+ };
50
+ type AIServiceOptions = {
51
+ retryAttempts?: number;
52
+ retryModels?: string[];
53
+ repairAttempts?: number;
54
+ repairModel?: string;
55
+ removeMDash?: boolean;
45
56
  };
46
57
  declare class AIService<MastraInstance extends Mastra> extends BaseService<{
47
58
  aiUsage?: AiUsageRepository;
@@ -54,6 +65,7 @@ declare class AIService<MastraInstance extends Mastra> extends BaseService<{
54
65
  mastra?: MastraInstance;
55
66
  openrouter?: OpenRouterProvider;
56
67
  replicate?: Replicate;
68
+ options?: AIServiceOptions;
57
69
  constructor(repositories: {
58
70
  aiUsage?: AiUsageRepository;
59
71
  }, services: {
@@ -62,7 +74,7 @@ declare class AIService<MastraInstance extends Mastra> extends BaseService<{
62
74
  mastra?: MastraInstance;
63
75
  openrouter?: OpenRouterProvider;
64
76
  replicate?: Replicate;
65
- });
77
+ }, options?: AIServiceOptions);
66
78
  getMastra(): MastraInstance;
67
79
  prepareModel(model: string): ReturnType<OpenRouterProvider["chat"]>;
68
80
  prepareEmbeddingModel(model: string): ReturnType<OpenRouterProvider["textEmbeddingModel"]>;
@@ -1,5 +1,5 @@
1
- import { repairJsonPrompt } from "./ai.prompts.mjs";
2
1
  import { BaseService } from "../base/base.service.mjs";
2
+ import { repairJsonPrompt } from "./ai.prompts.mjs";
3
3
  import { err, ok } from "neverthrow";
4
4
  import { OPENAI_TEXT_EMBEDDING_3_SMALL } from "@m5kdev/commons/modules/ai/ai.constants";
5
5
  import { arrayToPseudoXML } from "@m5kdev/commons/modules/ai/ai.utils";
@@ -13,11 +13,13 @@ var AIService = class extends BaseService {
13
13
  mastra;
14
14
  openrouter;
15
15
  replicate;
16
- constructor(repositories, services, libs) {
16
+ options;
17
+ constructor(repositories, services, libs, options) {
17
18
  super(repositories, services);
18
19
  this.mastra = libs.mastra;
19
20
  this.openrouter = libs.openrouter;
20
21
  this.replicate = libs.replicate;
22
+ this.options = options;
21
23
  }
22
24
  getMastra() {
23
25
  if (!this.mastra) throw new Error("Mastra is not available");
@@ -134,8 +136,8 @@ var AIService = class extends BaseService {
134
136
  }
135
137
  async generateText(params) {
136
138
  return this.throwableAsync(async () => {
137
- const { removeMDash = true, model, prompt, messages, ctx, ...rest } = params;
138
- const result = await generateText(messages ? {
139
+ const { removeMDash = this.options?.removeMDash ?? true, model, prompt, messages, ctx, retryAttempts = this.options?.retryAttempts ?? 0, retryModels = this.options?.retryModels ?? [], ...rest } = params;
140
+ const request = messages ? {
139
141
  ...rest,
140
142
  model: this.prepareModel(model),
141
143
  messages
@@ -143,26 +145,48 @@ var AIService = class extends BaseService {
143
145
  ...rest,
144
146
  model: this.prepareModel(model),
145
147
  prompt
146
- });
147
- if (this.repository.aiUsage) {
148
- const createUsageResult = await this.repository.aiUsage.create({
149
- userId: ctx?.actor?.userId,
148
+ };
149
+ try {
150
+ const result = await generateText(request);
151
+ if (this.repository.aiUsage) {
152
+ const createUsageResult = await this.repository.aiUsage.create({
153
+ userId: ctx?.actor?.userId,
154
+ model,
155
+ provider: "openrouter",
156
+ feature: "generateText",
157
+ traceId: result.providerMetadata?.openrouter?.traceId?.toString(),
158
+ inputTokens: result.usage.inputTokens,
159
+ outputTokens: result.usage.outputTokens,
160
+ totalTokens: result.usage.totalTokens,
161
+ cost: (result?.providerMetadata?.openrouter?.usage)?.cost ?? 0
162
+ });
163
+ if (createUsageResult.isErr()) return err(createUsageResult.error);
164
+ }
165
+ return ok(removeMDash ? result.text.replace(/\u2013|\u2014/g, "-") : result.text);
166
+ } catch (error) {
167
+ if (retryAttempts <= 0) throw error;
168
+ this.logger.warn(`generateText failed, retrying (${retryAttempts} attempts left)`, {
150
169
  model,
151
- provider: "openrouter",
152
- feature: "generateText",
153
- traceId: result.providerMetadata?.openrouter?.traceId?.toString(),
154
- inputTokens: result.usage.inputTokens,
155
- outputTokens: result.usage.outputTokens,
156
- totalTokens: result.usage.totalTokens,
157
- cost: (result?.providerMetadata?.openrouter?.usage)?.cost ?? 0
170
+ error
171
+ });
172
+ const delay = Math.min(1e3 * 2 ** ((this.options?.retryAttempts ?? 3) - retryAttempts), 1e4);
173
+ await new Promise((resolve) => setTimeout(resolve, delay));
174
+ const nextModel = retryModels?.[0] ?? model;
175
+ const nextRetryModels = retryModels ? [...retryModels.slice(1), model] : void 0;
176
+ return this.generateText({
177
+ ...rest,
178
+ ...messages ? { messages } : { prompt },
179
+ model: nextModel,
180
+ removeMDash,
181
+ ctx,
182
+ retryAttempts: retryAttempts - 1,
183
+ retryModels: nextRetryModels
158
184
  });
159
- if (createUsageResult.isErr()) return err(createUsageResult.error);
160
185
  }
161
- return ok(removeMDash ? result.text.replace(/\u2013|\u2014/g, "-") : result.text);
162
186
  });
163
187
  }
164
188
  async generateObject(params) {
165
- const { model, schema, prompt, messages, repairAttempts = 0, repairModel, ctx, ...rest } = params;
189
+ const { model, schema, prompt, messages, repairAttempts = this.options?.repairAttempts ?? 0, repairModel = this.options?.repairModel ?? model, ctx, retryAttempts = this.options?.retryAttempts ?? 0, retryModels = this.options?.retryModels ?? [], ...rest } = params;
166
190
  const request = messages ? {
167
191
  ...rest,
168
192
  model: this.prepareModel(model),
@@ -226,7 +250,26 @@ var AIService = class extends BaseService {
226
250
  }
227
251
  return this.error("PARSE_ERROR", "AI: Agent object failed without text", { cause: error });
228
252
  }
229
- return this.error("BAD_REQUEST", "AI: Provided failed to generate object", { cause: error });
253
+ if (retryAttempts <= 0) return this.error("BAD_REQUEST", "AI: Provider failed to generate object", { cause: error });
254
+ this.logger.warn(`generateObject failed, retrying (${retryAttempts} attempts left)`, {
255
+ model,
256
+ error
257
+ });
258
+ const delay = Math.min(1e3 * 2 ** ((this.options?.retryAttempts ?? 3) - retryAttempts), 1e4);
259
+ await new Promise((resolve) => setTimeout(resolve, delay));
260
+ const nextModel = retryModels?.[0] ?? model;
261
+ const nextRetryModels = retryModels ? [...retryModels.slice(1), model] : void 0;
262
+ return this.generateObject({
263
+ ...rest,
264
+ ...messages ? { messages } : { prompt },
265
+ model: nextModel,
266
+ schema,
267
+ repairAttempts,
268
+ repairModel,
269
+ ctx,
270
+ retryAttempts: retryAttempts - 1,
271
+ retryModels: nextRetryModels
272
+ });
230
273
  }
231
274
  }
232
275
  async generateReplicate(model, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"ai.service.mjs","names":[],"sources":["../../../../src/modules/ai/ai.service.ts"],"sourcesContent":["import { OPENAI_TEXT_EMBEDDING_3_SMALL } from \"@m5kdev/commons/modules/ai/ai.constants\";\r\nimport { arrayToPseudoXML } from \"@m5kdev/commons/modules/ai/ai.utils\";\r\nimport type { Mastra } from \"@mastra/core\";\r\nimport { RequestContext } from \"@mastra/core/request-context\";\r\nimport type { FullOutput, MastraModelOutput } from \"@mastra/core/stream\";\r\nimport { MDocument } from \"@mastra/rag\";\r\nimport type { OpenRouterProvider } from \"@openrouter/ai-sdk-provider\";\r\nimport {\r\n embed,\r\n embedMany,\r\n generateText,\r\n type ModelMessage,\r\n NoObjectGeneratedError,\r\n Output,\r\n} from \"ai\";\r\nimport { jsonrepair } from \"jsonrepair\";\r\nimport { err, ok } from \"neverthrow\";\r\nimport type Replicate from \"replicate\";\r\nimport type { ZodType, z } from \"zod\";\r\nimport type { RequiredServiceActor } from \"../base/base.actor\";\r\nimport type { ServerResultAsync } from \"../base/base.dto\";\r\nimport { BaseService } from \"../base/base.service\";\r\nimport { repairJsonPrompt } from \"./ai.prompts\";\r\nimport type { AiUsageRepository, AiUsageRow } from \"./ai.repository\";\r\nimport type { IdeogramV3GenerateInput, IdeogramV3GenerateOutput } from \"./ideogram/ideogram.dto\";\r\nimport type { IdeogramService } from \"./ideogram/ideogram.service\";\r\n\r\ntype MastraAgent = ReturnType<Mastra[\"getAgent\"]>;\r\ntype MastraAgentGenerateOptions = Parameters<MastraAgent[\"generate\"]>[1];\r\ntype MessageListInput = { role: \"user\" | \"assistant\" | \"system\"; content: string }[];\r\ntype GenerateTextParams = Parameters<typeof generateText>[0];\r\ntype GenerateTextInput =\r\n | { prompt: string | ModelMessage[]; messages?: never }\r\n | { messages: ModelMessage[]; prompt?: never };\r\ntype AIServiceActorContext = { actor: RequiredServiceActor<\"user\"> };\r\ntype AIServiceGenerateTextParams = Omit<GenerateTextParams, \"model\" | \"prompt\" | \"messages\"> &\r\n GenerateTextInput & {\r\n model: string;\r\n removeMDash?: boolean;\r\n ctx?: AIServiceActorContext;\r\n };\r\ntype AIServiceGenerateObjectParams<T extends ZodType> = Omit<\r\n GenerateTextParams,\r\n \"model\" | \"prompt\" | \"messages\" | \"output\"\r\n> &\r\n GenerateTextInput & {\r\n model: string;\r\n schema: T;\r\n repairAttempts?: number;\r\n repairModel?: string;\r\n ctx?: AIServiceActorContext;\r\n };\r\n\r\nexport class AIService<MastraInstance extends Mastra> extends BaseService<\r\n { aiUsage?: AiUsageRepository },\r\n { ideogram?: IdeogramService }\r\n> {\r\n helpers = {\r\n arrayToPseudoXML,\r\n };\r\n\r\n mastra?: MastraInstance;\r\n openrouter?: OpenRouterProvider;\r\n replicate?: Replicate;\r\n\r\n constructor(\r\n repositories: { aiUsage?: AiUsageRepository },\r\n services: { ideogram?: IdeogramService },\r\n libs: { mastra?: MastraInstance; openrouter?: OpenRouterProvider; replicate?: Replicate }\r\n ) {\r\n super(repositories, services);\r\n this.mastra = libs.mastra;\r\n this.openrouter = libs.openrouter;\r\n this.replicate = libs.replicate;\r\n }\r\n\r\n getMastra(): MastraInstance {\r\n if (!this.mastra) {\r\n throw new Error(\"Mastra is not available\");\r\n }\r\n return this.mastra;\r\n }\r\n\r\n prepareModel(model: string): ReturnType<OpenRouterProvider[\"chat\"]> {\r\n if (!this.openrouter) {\r\n throw new Error(\"OpenRouter is not configured\");\r\n }\r\n return this.openrouter.chat(model, {\r\n usage: {\r\n include: true,\r\n },\r\n });\r\n }\r\n\r\n prepareEmbeddingModel(model: string): ReturnType<OpenRouterProvider[\"textEmbeddingModel\"]> {\r\n if (!this.openrouter) {\r\n throw new Error(\"OpenRouter is not configured\");\r\n }\r\n const openrouter = this.openrouter as OpenRouterProvider & {\r\n embeddingModel?: (modelId: string) => unknown;\r\n };\r\n return (openrouter.embeddingModel?.(model) ??\r\n openrouter.textEmbeddingModel(model)) as ReturnType<OpenRouterProvider[\"textEmbeddingModel\"]>;\r\n }\r\n\r\n async agentUse(\r\n agent: string,\r\n options: MastraAgentGenerateOptions & { prompt?: string; messages?: MessageListInput },\r\n ctx?: AIServiceActorContext & { model?: string }\r\n ): ServerResultAsync<Awaited<ReturnType<MastraModelOutput<any>[\"getFullOutput\"]>>> {\r\n return this.throwableAsync(async () => {\r\n this.logger.info(\"AGENT USE\");\r\n const { prompt, messages, ...rest } = options;\r\n const payload = messages || prompt;\r\n if (!payload) return this.error(\"BAD_REQUEST\", \"No prompt or messages provided\");\r\n const requestContext = options.requestContext ?? new RequestContext();\r\n\r\n if (ctx?.actor) {\r\n requestContext.set(\"userId\", ctx.actor.userId);\r\n }\r\n if (ctx?.model) {\r\n requestContext.set(\"model\", ctx.model);\r\n }\r\n const mAgent = this.getMastra().getAgent(agent);\r\n\r\n const result = await mAgent.generate(payload as any, {\r\n ...rest,\r\n requestContext: rest.requestContext ?? requestContext,\r\n });\r\n this.logger.info(\"AGENT USE DONE\");\r\n if (this.repository.aiUsage) {\r\n const createUsageResult = await this.repository.aiUsage.create({\r\n userId: ctx?.actor?.userId,\r\n model: ctx?.model ?? \"unknown\",\r\n provider: \"openrouter\",\r\n feature: agent,\r\n traceId: result.traceId,\r\n inputTokens: result.usage.inputTokens,\r\n outputTokens: result.usage.outputTokens,\r\n totalTokens: result.usage.totalTokens,\r\n cost: (result?.providerMetadata?.openrouter?.usage as any)?.cost ?? 0,\r\n });\r\n if (createUsageResult.isErr()) return err(createUsageResult.error);\r\n }\r\n this.logger.info(\"AGENT USE CREATED USAGE\");\r\n return ok(result);\r\n });\r\n }\r\n\r\n async agentText(\r\n agent: string,\r\n options: MastraAgentGenerateOptions & { prompt?: string; messages?: MessageListInput },\r\n ctx?: AIServiceActorContext & { model?: string }\r\n ): ServerResultAsync<string> {\r\n const result = await this.agentUse(agent, options, ctx);\r\n if (result.isErr())\r\n return this.error(\"SERVICE_UNAVAILABLE\", \"AI: Agent text failed\", { cause: result.error });\r\n return ok(result.value.text);\r\n }\r\n\r\n async agentTextResult(\r\n agent: string,\r\n options: MastraAgentGenerateOptions & { prompt?: string; messages?: MessageListInput },\r\n ctx?: AIServiceActorContext & { model?: string }\r\n ): ServerResultAsync<FullOutput<any>> {\r\n const result = await this.agentUse(agent, options, ctx);\r\n if (result.isErr()) return err(result.error);\r\n return ok(result.value);\r\n }\r\n\r\n async agentObject<T extends ZodType<any>>(\r\n agent: string,\r\n options: MastraAgentGenerateOptions & {\r\n schema: T;\r\n prompt?: string;\r\n messages?: MessageListInput;\r\n },\r\n ctx?: AIServiceActorContext & { model?: string }\r\n ): ServerResultAsync<z.infer<T>> {\r\n const { schema, ...rest } = options;\r\n const result = await this.agentUse(agent, { ...rest, structuredOutput: { schema } }, ctx);\r\n if (result.isErr())\r\n return this.error(\"SERVICE_UNAVAILABLE\", \"AI: Agent object failed\", { cause: result.error });\r\n return ok(result.value.object as z.infer<T>);\r\n }\r\n\r\n async agentObjectResult<T extends ZodType<any>>(\r\n agent: string,\r\n options: MastraAgentGenerateOptions & {\r\n schema: T;\r\n prompt?: string;\r\n messages?: MessageListInput;\r\n },\r\n ctx?: AIServiceActorContext & { model?: string }\r\n ): ServerResultAsync<FullOutput<any> & { object: z.infer<T> }> {\r\n this.logger.info(\"AGENT OBJECT RESULT\");\r\n const { schema, ...rest } = options;\r\n const result = await this.agentUse(agent, { ...rest, structuredOutput: { schema } }, ctx);\r\n if (result.isErr()) return err(result.error);\r\n this.logger.info(\"AGENT OBJECT RESULT DONE\");\r\n return ok({ ...result.value, object: result.value.object as z.infer<T> });\r\n }\r\n\r\n async embedDocument(\r\n value: string,\r\n options?: Parameters<ReturnType<typeof MDocument.fromText>[\"chunk\"]>[0],\r\n type: \"text\" | \"markdown\" | \"html\" | \"json\" = \"text\",\r\n model: string = OPENAI_TEXT_EMBEDDING_3_SMALL\r\n ): ServerResultAsync<{ embeddings: number[][]; chunks: { text: string }[] }> {\r\n return this.throwableAsync(async () => {\r\n if (type === \"text\") {\r\n const doc = MDocument.fromText(value);\r\n const chunks = await doc.chunk(\r\n options ?? {\r\n strategy: \"recursive\",\r\n maxSize: 512,\r\n overlap: 50,\r\n separators: [\"\\n\"],\r\n }\r\n );\r\n const embeddings = await this.embedMany(chunks, model);\r\n if (embeddings.isErr()) return err(embeddings.error);\r\n return ok({ embeddings: embeddings.value.embeddings, chunks });\r\n }\r\n return this.error(\"BAD_REQUEST\", \"Unsupported document type\");\r\n });\r\n }\r\n\r\n async embed(\r\n text: string,\r\n model: string = OPENAI_TEXT_EMBEDDING_3_SMALL\r\n ): ServerResultAsync<{ embedding: number[] }> {\r\n return this.throwableAsync(async () => {\r\n const result = await embed({\r\n model: this.prepareEmbeddingModel(model),\r\n value: text,\r\n });\r\n return ok(result);\r\n });\r\n }\r\n\r\n async embedMany(\r\n chunks: { text: string }[],\r\n model: string = OPENAI_TEXT_EMBEDDING_3_SMALL\r\n ): ServerResultAsync<{ embeddings: number[][] }> {\r\n return this.throwableAsync(async () => {\r\n const result = await embedMany({\r\n model: this.prepareEmbeddingModel(model),\r\n values: chunks.map((chunk) => chunk.text),\r\n });\r\n return ok(result);\r\n });\r\n }\r\n\r\n async generateText(params: AIServiceGenerateTextParams): ServerResultAsync<string> {\r\n return this.throwableAsync(async () => {\r\n const { removeMDash = true, model, prompt, messages, ctx, ...rest } = params;\r\n const request = messages\r\n ? { ...rest, model: this.prepareModel(model), messages }\r\n : { ...rest, model: this.prepareModel(model), prompt };\r\n const result = await generateText(request);\r\n if (this.repository.aiUsage) {\r\n const createUsageResult = await this.repository.aiUsage.create({\r\n userId: ctx?.actor?.userId,\r\n model,\r\n provider: \"openrouter\",\r\n feature: \"generateText\",\r\n traceId: result.providerMetadata?.openrouter?.traceId?.toString(),\r\n inputTokens: result.usage.inputTokens,\r\n outputTokens: result.usage.outputTokens,\r\n totalTokens: result.usage.totalTokens,\r\n cost: (result?.providerMetadata?.openrouter?.usage as any)?.cost ?? 0,\r\n });\r\n if (createUsageResult.isErr()) return err(createUsageResult.error);\r\n }\r\n return ok(removeMDash ? result.text.replace(/\\u2013|\\u2014/g, \"-\") : result.text);\r\n });\r\n }\r\n\r\n async generateObject<T extends ZodType>(\r\n params: AIServiceGenerateObjectParams<T>\r\n ): ServerResultAsync<z.infer<T>> {\r\n const {\r\n model,\r\n schema,\r\n prompt,\r\n messages,\r\n repairAttempts = 0,\r\n repairModel,\r\n ctx,\r\n ...rest\r\n } = params;\r\n const request = messages\r\n ? {\r\n ...rest,\r\n model: this.prepareModel(model),\r\n messages,\r\n output: Output.object({ schema }),\r\n }\r\n : {\r\n ...rest,\r\n model: this.prepareModel(model),\r\n prompt,\r\n output: Output.object({ schema }),\r\n };\r\n try {\r\n const result = await generateText(request);\r\n if (this.repository.aiUsage) {\r\n const createUsageResult = await this.repository.aiUsage.create({\r\n userId: ctx?.actor?.userId,\r\n model,\r\n provider: \"openrouter\",\r\n feature: \"generateObject\",\r\n traceId: result.providerMetadata?.openrouter?.traceId?.toString(),\r\n inputTokens: result.usage.inputTokens,\r\n outputTokens: result.usage.outputTokens,\r\n totalTokens: result.usage.totalTokens,\r\n cost: (result?.providerMetadata?.openrouter?.usage as any)?.cost ?? 0,\r\n });\r\n if (createUsageResult.isErr()) return err(createUsageResult.error);\r\n }\r\n return ok(result.output as z.infer<T>);\r\n } catch (error) {\r\n if (NoObjectGeneratedError.isInstance(error)) {\r\n if (this.repository.aiUsage) {\r\n const createUsageResult = await this.repository.aiUsage.create({\r\n userId: ctx?.actor?.userId,\r\n model,\r\n provider: \"openrouter\",\r\n feature: \"generateObject\",\r\n traceId: null,\r\n inputTokens: error?.usage?.inputTokens,\r\n outputTokens: error?.usage?.outputTokens,\r\n totalTokens: error?.usage?.totalTokens,\r\n cost: 0,\r\n });\r\n if (createUsageResult.isErr()) return err(createUsageResult.error);\r\n }\r\n if (error.text) {\r\n const repairedText = jsonrepair(error.text);\r\n const parsed = schema.safeParse(repairedText);\r\n if (parsed.success) return ok(parsed.data);\r\n\r\n if (repairAttempts === 0)\r\n return this.error(\"PARSE_ERROR\", \"AI: Agent object failed\", { cause: error });\r\n\r\n return this.generateObject({\r\n ...rest,\r\n prompt: repairJsonPrompt.compile({\r\n text: error.text,\r\n error: JSON.stringify(error.cause ?? \"Unknown error\"),\r\n }),\r\n repairAttempts: repairAttempts - 1,\r\n model: repairModel ?? model,\r\n schema,\r\n ctx,\r\n });\r\n }\r\n return this.error(\"PARSE_ERROR\", \"AI: Agent object failed without text\", {\r\n cause: error,\r\n });\r\n }\r\n return this.error(\"BAD_REQUEST\", \"AI: Provided failed to generate object\", { cause: error });\r\n }\r\n }\r\n\r\n async generateReplicate(\r\n model: Parameters<Replicate[\"run\"]>[0],\r\n options: Parameters<Replicate[\"run\"]>[1]\r\n ): ServerResultAsync<object> {\r\n return this.throwableAsync(async () => {\r\n if (!this.replicate) {\r\n return this.error(\"INTERNAL_SERVER_ERROR\", \"Replicate is not configured\");\r\n }\r\n try {\r\n return ok(await this.replicate.run(model, options));\r\n } catch (error) {\r\n return this.error(\"INTERNAL_SERVER_ERROR\", undefined, { cause: error });\r\n }\r\n });\r\n }\r\n\r\n async generateTranscript(\r\n file_url: string\r\n ): ServerResultAsync<{ text: string; metadata: unknown }> {\r\n const output = await this.generateReplicate(\r\n \"thomasmol/whisper-diarization:1495a9cddc83b2203b0d8d3516e38b80fd1572ebc4bc5700ac1da56a9b3ed886\",\r\n {\r\n input: {\r\n file_url,\r\n },\r\n }\r\n );\r\n\r\n if (output.isErr()) return err(output.error);\r\n\r\n try {\r\n const { segments } = output.value as { segments: { text: string }[] };\r\n return ok({ text: segments.map((segment) => segment.text).join(\"\"), metadata: segments });\r\n } catch (error) {\r\n return this.error(\"INTERNAL_SERVER_ERROR\", undefined, { cause: error });\r\n }\r\n }\r\n\r\n async generateIdeogram(\r\n input: IdeogramV3GenerateInput\r\n ): ServerResultAsync<IdeogramV3GenerateOutput> {\r\n if (!this.service.ideogram) {\r\n return this.error(\"INTERNAL_SERVER_ERROR\", \"Ideogram service is not available\");\r\n }\r\n return this.service.ideogram.generate(input);\r\n }\r\n\r\n async getUsage(\r\n userId: string\r\n ): ServerResultAsync<Pick<AiUsageRow, \"inputTokens\" | \"outputTokens\" | \"totalTokens\" | \"cost\">> {\r\n if (!this.repository.aiUsage) {\r\n return this.error(\"INTERNAL_SERVER_ERROR\", \"AI usage repository is not available\");\r\n }\r\n return this.repository.aiUsage.getUsage(userId);\r\n }\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"ai.service.mjs","names":[],"sources":["../../../../src/modules/ai/ai.service.ts"],"sourcesContent":["import { OPENAI_TEXT_EMBEDDING_3_SMALL } from \"@m5kdev/commons/modules/ai/ai.constants\";\r\nimport { arrayToPseudoXML } from \"@m5kdev/commons/modules/ai/ai.utils\";\r\nimport type { Mastra } from \"@mastra/core\";\r\nimport { RequestContext } from \"@mastra/core/request-context\";\r\nimport type { FullOutput, MastraModelOutput } from \"@mastra/core/stream\";\r\nimport { MDocument } from \"@mastra/rag\";\r\nimport type { OpenRouterProvider } from \"@openrouter/ai-sdk-provider\";\r\nimport {\r\n embed,\r\n embedMany,\r\n generateText,\r\n type ModelMessage,\r\n NoObjectGeneratedError,\r\n Output,\r\n} from \"ai\";\r\nimport { jsonrepair } from \"jsonrepair\";\r\nimport { err, ok } from \"neverthrow\";\r\nimport type Replicate from \"replicate\";\r\nimport type { ZodType, z } from \"zod\";\r\nimport type { RequiredServiceActor } from \"../base/base.actor\";\r\nimport type { ServerResultAsync } from \"../base/base.dto\";\r\nimport { BaseService } from \"../base/base.service\";\r\nimport { repairJsonPrompt } from \"./ai.prompts\";\r\nimport type { AiUsageRepository, AiUsageRow } from \"./ai.repository\";\r\nimport type { IdeogramV3GenerateInput, IdeogramV3GenerateOutput } from \"./ideogram/ideogram.dto\";\r\nimport type { IdeogramService } from \"./ideogram/ideogram.service\";\r\n\r\ntype MastraAgent = ReturnType<Mastra[\"getAgent\"]>;\r\ntype MastraAgentGenerateOptions = Parameters<MastraAgent[\"generate\"]>[1];\r\ntype MessageListInput = { role: \"user\" | \"assistant\" | \"system\"; content: string }[];\r\ntype GenerateTextParams = Parameters<typeof generateText>[0];\r\ntype GenerateTextInput =\r\n | { prompt: string | ModelMessage[]; messages?: never }\r\n | { messages: ModelMessage[]; prompt?: never };\r\ntype AIServiceActorContext = { actor: RequiredServiceActor<\"user\"> };\r\ntype AIServiceGenerateTextParams = Omit<GenerateTextParams, \"model\" | \"prompt\" | \"messages\"> &\r\n GenerateTextInput & {\r\n model: string;\r\n removeMDash?: boolean;\r\n ctx?: AIServiceActorContext;\r\n retryAttempts?: number;\r\n retryModels?: string[];\r\n };\r\ntype AIServiceGenerateObjectParams<T extends ZodType> = Omit<\r\n GenerateTextParams,\r\n \"model\" | \"prompt\" | \"messages\" | \"output\"\r\n> &\r\n GenerateTextInput & {\r\n model: string;\r\n schema: T;\r\n repairAttempts?: number;\r\n repairModel?: string;\r\n ctx?: AIServiceActorContext;\r\n retryAttempts?: number;\r\n retryModels?: string[];\r\n };\r\n\r\ntype AIServiceOptions = {\r\n retryAttempts?: number;\r\n retryModels?: string[];\r\n repairAttempts?: number;\r\n repairModel?: string;\r\n removeMDash?: boolean;\r\n};\r\n\r\nexport class AIService<MastraInstance extends Mastra> extends BaseService<\r\n { aiUsage?: AiUsageRepository },\r\n { ideogram?: IdeogramService }\r\n> {\r\n helpers = {\r\n arrayToPseudoXML,\r\n };\r\n\r\n mastra?: MastraInstance;\r\n openrouter?: OpenRouterProvider;\r\n replicate?: Replicate;\r\n options?: AIServiceOptions;\r\n\r\n constructor(\r\n repositories: { aiUsage?: AiUsageRepository },\r\n services: { ideogram?: IdeogramService },\r\n libs: { mastra?: MastraInstance; openrouter?: OpenRouterProvider; replicate?: Replicate },\r\n options?: AIServiceOptions\r\n ) {\r\n super(repositories, services);\r\n this.mastra = libs.mastra;\r\n this.openrouter = libs.openrouter;\r\n this.replicate = libs.replicate;\r\n this.options = options;\r\n }\r\n\r\n getMastra(): MastraInstance {\r\n if (!this.mastra) {\r\n throw new Error(\"Mastra is not available\");\r\n }\r\n return this.mastra;\r\n }\r\n\r\n prepareModel(model: string): ReturnType<OpenRouterProvider[\"chat\"]> {\r\n if (!this.openrouter) {\r\n throw new Error(\"OpenRouter is not configured\");\r\n }\r\n return this.openrouter.chat(model, {\r\n usage: {\r\n include: true,\r\n },\r\n });\r\n }\r\n\r\n prepareEmbeddingModel(model: string): ReturnType<OpenRouterProvider[\"textEmbeddingModel\"]> {\r\n if (!this.openrouter) {\r\n throw new Error(\"OpenRouter is not configured\");\r\n }\r\n const openrouter = this.openrouter as OpenRouterProvider & {\r\n embeddingModel?: (modelId: string) => unknown;\r\n };\r\n return (openrouter.embeddingModel?.(model) ??\r\n openrouter.textEmbeddingModel(model)) as ReturnType<OpenRouterProvider[\"textEmbeddingModel\"]>;\r\n }\r\n\r\n async agentUse(\r\n agent: string,\r\n options: MastraAgentGenerateOptions & { prompt?: string; messages?: MessageListInput },\r\n ctx?: AIServiceActorContext & { model?: string }\r\n ): ServerResultAsync<Awaited<ReturnType<MastraModelOutput<any>[\"getFullOutput\"]>>> {\r\n return this.throwableAsync(async () => {\r\n this.logger.info(\"AGENT USE\");\r\n const { prompt, messages, ...rest } = options;\r\n const payload = messages || prompt;\r\n if (!payload) return this.error(\"BAD_REQUEST\", \"No prompt or messages provided\");\r\n const requestContext = options.requestContext ?? new RequestContext();\r\n\r\n if (ctx?.actor) {\r\n requestContext.set(\"userId\", ctx.actor.userId);\r\n }\r\n if (ctx?.model) {\r\n requestContext.set(\"model\", ctx.model);\r\n }\r\n const mAgent = this.getMastra().getAgent(agent);\r\n\r\n const result = await mAgent.generate(payload as any, {\r\n ...rest,\r\n requestContext: rest.requestContext ?? requestContext,\r\n });\r\n this.logger.info(\"AGENT USE DONE\");\r\n if (this.repository.aiUsage) {\r\n const createUsageResult = await this.repository.aiUsage.create({\r\n userId: ctx?.actor?.userId,\r\n model: ctx?.model ?? \"unknown\",\r\n provider: \"openrouter\",\r\n feature: agent,\r\n traceId: result.traceId,\r\n inputTokens: result.usage.inputTokens,\r\n outputTokens: result.usage.outputTokens,\r\n totalTokens: result.usage.totalTokens,\r\n cost: (result?.providerMetadata?.openrouter?.usage as any)?.cost ?? 0,\r\n });\r\n if (createUsageResult.isErr()) return err(createUsageResult.error);\r\n }\r\n this.logger.info(\"AGENT USE CREATED USAGE\");\r\n return ok(result);\r\n });\r\n }\r\n\r\n async agentText(\r\n agent: string,\r\n options: MastraAgentGenerateOptions & { prompt?: string; messages?: MessageListInput },\r\n ctx?: AIServiceActorContext & { model?: string }\r\n ): ServerResultAsync<string> {\r\n const result = await this.agentUse(agent, options, ctx);\r\n if (result.isErr())\r\n return this.error(\"SERVICE_UNAVAILABLE\", \"AI: Agent text failed\", { cause: result.error });\r\n return ok(result.value.text);\r\n }\r\n\r\n async agentTextResult(\r\n agent: string,\r\n options: MastraAgentGenerateOptions & { prompt?: string; messages?: MessageListInput },\r\n ctx?: AIServiceActorContext & { model?: string }\r\n ): ServerResultAsync<FullOutput<any>> {\r\n const result = await this.agentUse(agent, options, ctx);\r\n if (result.isErr()) return err(result.error);\r\n return ok(result.value);\r\n }\r\n\r\n async agentObject<T extends ZodType<any>>(\r\n agent: string,\r\n options: MastraAgentGenerateOptions & {\r\n schema: T;\r\n prompt?: string;\r\n messages?: MessageListInput;\r\n },\r\n ctx?: AIServiceActorContext & { model?: string }\r\n ): ServerResultAsync<z.infer<T>> {\r\n const { schema, ...rest } = options;\r\n const result = await this.agentUse(agent, { ...rest, structuredOutput: { schema } }, ctx);\r\n if (result.isErr())\r\n return this.error(\"SERVICE_UNAVAILABLE\", \"AI: Agent object failed\", { cause: result.error });\r\n return ok(result.value.object as z.infer<T>);\r\n }\r\n\r\n async agentObjectResult<T extends ZodType<any>>(\r\n agent: string,\r\n options: MastraAgentGenerateOptions & {\r\n schema: T;\r\n prompt?: string;\r\n messages?: MessageListInput;\r\n },\r\n ctx?: AIServiceActorContext & { model?: string }\r\n ): ServerResultAsync<FullOutput<any> & { object: z.infer<T> }> {\r\n this.logger.info(\"AGENT OBJECT RESULT\");\r\n const { schema, ...rest } = options;\r\n const result = await this.agentUse(agent, { ...rest, structuredOutput: { schema } }, ctx);\r\n if (result.isErr()) return err(result.error);\r\n this.logger.info(\"AGENT OBJECT RESULT DONE\");\r\n return ok({ ...result.value, object: result.value.object as z.infer<T> });\r\n }\r\n\r\n async embedDocument(\r\n value: string,\r\n options?: Parameters<ReturnType<typeof MDocument.fromText>[\"chunk\"]>[0],\r\n type: \"text\" | \"markdown\" | \"html\" | \"json\" = \"text\",\r\n model: string = OPENAI_TEXT_EMBEDDING_3_SMALL\r\n ): ServerResultAsync<{ embeddings: number[][]; chunks: { text: string }[] }> {\r\n return this.throwableAsync(async () => {\r\n if (type === \"text\") {\r\n const doc = MDocument.fromText(value);\r\n const chunks = await doc.chunk(\r\n options ?? {\r\n strategy: \"recursive\",\r\n maxSize: 512,\r\n overlap: 50,\r\n separators: [\"\\n\"],\r\n }\r\n );\r\n const embeddings = await this.embedMany(chunks, model);\r\n if (embeddings.isErr()) return err(embeddings.error);\r\n return ok({ embeddings: embeddings.value.embeddings, chunks });\r\n }\r\n return this.error(\"BAD_REQUEST\", \"Unsupported document type\");\r\n });\r\n }\r\n\r\n async embed(\r\n text: string,\r\n model: string = OPENAI_TEXT_EMBEDDING_3_SMALL\r\n ): ServerResultAsync<{ embedding: number[] }> {\r\n return this.throwableAsync(async () => {\r\n const result = await embed({\r\n model: this.prepareEmbeddingModel(model),\r\n value: text,\r\n });\r\n return ok(result);\r\n });\r\n }\r\n\r\n async embedMany(\r\n chunks: { text: string }[],\r\n model: string = OPENAI_TEXT_EMBEDDING_3_SMALL\r\n ): ServerResultAsync<{ embeddings: number[][] }> {\r\n return this.throwableAsync(async () => {\r\n const result = await embedMany({\r\n model: this.prepareEmbeddingModel(model),\r\n values: chunks.map((chunk) => chunk.text),\r\n });\r\n return ok(result);\r\n });\r\n }\r\n\r\n async generateText(params: AIServiceGenerateTextParams): ServerResultAsync<string> {\r\n return this.throwableAsync(async () => {\r\n const {\r\n removeMDash = this.options?.removeMDash ?? true,\r\n model,\r\n prompt,\r\n messages,\r\n ctx,\r\n retryAttempts = this.options?.retryAttempts ?? 0,\r\n retryModels = this.options?.retryModels ?? [],\r\n ...rest\r\n } = params;\r\n const request = messages\r\n ? { ...rest, model: this.prepareModel(model), messages }\r\n : { ...rest, model: this.prepareModel(model), prompt };\r\n try {\r\n const result = await generateText(request);\r\n if (this.repository.aiUsage) {\r\n const createUsageResult = await this.repository.aiUsage.create({\r\n userId: ctx?.actor?.userId,\r\n model,\r\n provider: \"openrouter\",\r\n feature: \"generateText\",\r\n traceId: result.providerMetadata?.openrouter?.traceId?.toString(),\r\n inputTokens: result.usage.inputTokens,\r\n outputTokens: result.usage.outputTokens,\r\n totalTokens: result.usage.totalTokens,\r\n cost: (result?.providerMetadata?.openrouter?.usage as any)?.cost ?? 0,\r\n });\r\n if (createUsageResult.isErr()) return err(createUsageResult.error);\r\n }\r\n return ok(removeMDash ? result.text.replace(/\\u2013|\\u2014/g, \"-\") : result.text);\r\n } catch (error) {\r\n if (retryAttempts <= 0) throw error;\r\n this.logger.warn(`generateText failed, retrying (${retryAttempts} attempts left)`, {\r\n model,\r\n error,\r\n });\r\n // Exponential backoff: wait before retrying\r\n const delay = Math.min(\r\n 1000 * 2 ** ((this.options?.retryAttempts ?? 3) - retryAttempts),\r\n 10000\r\n );\r\n await new Promise<void>((resolve) => setTimeout(resolve, delay));\r\n const nextModel = retryModels?.[0] ?? model;\r\n const nextRetryModels = retryModels ? [...retryModels.slice(1), model] : undefined;\r\n return this.generateText({\r\n ...rest,\r\n ...(messages ? { messages } : { prompt: prompt! }),\r\n model: nextModel,\r\n removeMDash,\r\n ctx,\r\n retryAttempts: retryAttempts - 1,\r\n retryModels: nextRetryModels,\r\n } as AIServiceGenerateTextParams);\r\n }\r\n });\r\n }\r\n\r\n async generateObject<T extends ZodType>(\r\n params: AIServiceGenerateObjectParams<T>\r\n ): ServerResultAsync<z.infer<T>> {\r\n const {\r\n model,\r\n schema,\r\n prompt,\r\n messages,\r\n repairAttempts = this.options?.repairAttempts ?? 0,\r\n repairModel = this.options?.repairModel ?? model,\r\n ctx,\r\n retryAttempts = this.options?.retryAttempts ?? 0,\r\n retryModels = this.options?.retryModels ?? [],\r\n ...rest\r\n } = params;\r\n const request = messages\r\n ? {\r\n ...rest,\r\n model: this.prepareModel(model),\r\n messages,\r\n output: Output.object({ schema }),\r\n }\r\n : {\r\n ...rest,\r\n model: this.prepareModel(model),\r\n prompt,\r\n output: Output.object({ schema }),\r\n };\r\n try {\r\n const result = await generateText(request);\r\n if (this.repository.aiUsage) {\r\n const createUsageResult = await this.repository.aiUsage.create({\r\n userId: ctx?.actor?.userId,\r\n model,\r\n provider: \"openrouter\",\r\n feature: \"generateObject\",\r\n traceId: result.providerMetadata?.openrouter?.traceId?.toString(),\r\n inputTokens: result.usage.inputTokens,\r\n outputTokens: result.usage.outputTokens,\r\n totalTokens: result.usage.totalTokens,\r\n cost: (result?.providerMetadata?.openrouter?.usage as any)?.cost ?? 0,\r\n });\r\n if (createUsageResult.isErr()) return err(createUsageResult.error);\r\n }\r\n return ok(result.output as z.infer<T>);\r\n } catch (error) {\r\n if (NoObjectGeneratedError.isInstance(error)) {\r\n if (this.repository.aiUsage) {\r\n const createUsageResult = await this.repository.aiUsage.create({\r\n userId: ctx?.actor?.userId,\r\n model,\r\n provider: \"openrouter\",\r\n feature: \"generateObject\",\r\n traceId: null,\r\n inputTokens: error?.usage?.inputTokens,\r\n outputTokens: error?.usage?.outputTokens,\r\n totalTokens: error?.usage?.totalTokens,\r\n cost: 0,\r\n });\r\n if (createUsageResult.isErr()) return err(createUsageResult.error);\r\n }\r\n if (error.text) {\r\n const repairedText = jsonrepair(error.text);\r\n const parsed = schema.safeParse(repairedText);\r\n if (parsed.success) return ok(parsed.data);\r\n\r\n if (repairAttempts === 0)\r\n return this.error(\"PARSE_ERROR\", \"AI: Agent object failed\", { cause: error });\r\n\r\n return this.generateObject({\r\n ...rest,\r\n prompt: repairJsonPrompt.compile({\r\n text: error.text,\r\n error: JSON.stringify(error.cause ?? \"Unknown error\"),\r\n }),\r\n repairAttempts: repairAttempts - 1,\r\n model: repairModel ?? model,\r\n schema,\r\n ctx,\r\n });\r\n }\r\n return this.error(\"PARSE_ERROR\", \"AI: Agent object failed without text\", {\r\n cause: error,\r\n });\r\n }\r\n if (retryAttempts <= 0)\r\n return this.error(\"BAD_REQUEST\", \"AI: Provider failed to generate object\", {\r\n cause: error,\r\n });\r\n this.logger.warn(`generateObject failed, retrying (${retryAttempts} attempts left)`, {\r\n model,\r\n error,\r\n });\r\n // Exponential backoff: wait before retrying\r\n const delay = Math.min(\r\n 1000 * 2 ** ((this.options?.retryAttempts ?? 3) - retryAttempts),\r\n 10000\r\n );\r\n await new Promise<void>((resolve) => setTimeout(resolve, delay));\r\n const nextModel = retryModels?.[0] ?? model;\r\n const nextRetryModels = retryModels ? [...retryModels.slice(1), model] : undefined;\r\n return this.generateObject({\r\n ...rest,\r\n ...(messages ? { messages } : { prompt: prompt! }),\r\n model: nextModel,\r\n schema,\r\n repairAttempts,\r\n repairModel,\r\n ctx,\r\n retryAttempts: retryAttempts - 1,\r\n retryModels: nextRetryModels,\r\n } as AIServiceGenerateObjectParams<T>);\r\n }\r\n }\r\n\r\n async generateReplicate(\r\n model: Parameters<Replicate[\"run\"]>[0],\r\n options: Parameters<Replicate[\"run\"]>[1]\r\n ): ServerResultAsync<object> {\r\n return this.throwableAsync(async () => {\r\n if (!this.replicate) {\r\n return this.error(\"INTERNAL_SERVER_ERROR\", \"Replicate is not configured\");\r\n }\r\n try {\r\n return ok(await this.replicate.run(model, options));\r\n } catch (error) {\r\n return this.error(\"INTERNAL_SERVER_ERROR\", undefined, { cause: error });\r\n }\r\n });\r\n }\r\n\r\n async generateTranscript(\r\n file_url: string\r\n ): ServerResultAsync<{ text: string; metadata: unknown }> {\r\n const output = await this.generateReplicate(\r\n \"thomasmol/whisper-diarization:1495a9cddc83b2203b0d8d3516e38b80fd1572ebc4bc5700ac1da56a9b3ed886\",\r\n {\r\n input: {\r\n file_url,\r\n },\r\n }\r\n );\r\n\r\n if (output.isErr()) return err(output.error);\r\n\r\n try {\r\n const { segments } = output.value as { segments: { text: string }[] };\r\n return ok({ text: segments.map((segment) => segment.text).join(\"\"), metadata: segments });\r\n } catch (error) {\r\n return this.error(\"INTERNAL_SERVER_ERROR\", undefined, { cause: error });\r\n }\r\n }\r\n\r\n async generateIdeogram(\r\n input: IdeogramV3GenerateInput\r\n ): ServerResultAsync<IdeogramV3GenerateOutput> {\r\n if (!this.service.ideogram) {\r\n return this.error(\"INTERNAL_SERVER_ERROR\", \"Ideogram service is not available\");\r\n }\r\n return this.service.ideogram.generate(input);\r\n }\r\n\r\n async getUsage(\r\n userId: string\r\n ): ServerResultAsync<Pick<AiUsageRow, \"inputTokens\" | \"outputTokens\" | \"totalTokens\" | \"cost\">> {\r\n if (!this.repository.aiUsage) {\r\n return this.error(\"INTERNAL_SERVER_ERROR\", \"AI usage repository is not available\");\r\n }\r\n return this.repository.aiUsage.getUsage(userId);\r\n }\r\n}\r\n"],"mappings":"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"}
@@ -2,8 +2,8 @@ import { LiteralUnion } from "../../../node_modules/.pnpm/@better-auth_core@1.4.
2
2
  import { BillingService } from "../billing/billing.service.mjs";
3
3
  import { EmailService } from "../email/email.service.mjs";
4
4
  import { sessions, users } from "./auth.db.mjs";
5
- import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
6
5
  import { InferSelectModel } from "drizzle-orm";
6
+ import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
7
7
  import * as _$better_auth0 from "better-auth";
8
8
  import { BetterAuthOptions, betterAuth } from "better-auth";
9
9
  import * as _$better_auth_api0 from "better-auth/api";
@@ -3279,14 +3279,14 @@ declare function createBetterAuth<O extends Orm, S extends Schema, E extends Ema
3279
3279
  $Infer: {
3280
3280
  body: ({
3281
3281
  permission: {
3282
- readonly user?: ("update" | "list" | "delete" | "get" | "set-role" | "create" | "ban" | "impersonate" | "set-password")[] | undefined;
3283
- readonly session?: ("list" | "delete" | "revoke")[] | undefined;
3282
+ readonly user?: ("set-role" | "create" | "update" | "delete" | "list" | "get" | "ban" | "impersonate" | "set-password")[] | undefined;
3283
+ readonly session?: ("delete" | "list" | "revoke")[] | undefined;
3284
3284
  };
3285
3285
  permissions?: never | undefined;
3286
3286
  } | {
3287
3287
  permissions: {
3288
- readonly user?: ("update" | "list" | "delete" | "get" | "set-role" | "create" | "ban" | "impersonate" | "set-password")[] | undefined;
3289
- readonly session?: ("list" | "delete" | "revoke")[] | undefined;
3288
+ readonly user?: ("set-role" | "create" | "update" | "delete" | "list" | "get" | "ban" | "impersonate" | "set-password")[] | undefined;
3289
+ readonly session?: ("delete" | "list" | "revoke")[] | undefined;
3290
3290
  };
3291
3291
  permission?: never | undefined;
3292
3292
  }) & {
@@ -4830,7 +4830,7 @@ declare function createBetterAuth<O extends Orm, S extends Schema, E extends Ema
4830
4830
  } | undefined;
4831
4831
  verification?: {
4832
4832
  modelName?: string;
4833
- fields?: Partial<Record<"createdAt" | "updatedAt" | "expiresAt" | "identifier" | "value", string>>;
4833
+ fields?: Partial<Record<"createdAt" | "updatedAt" | "expiresAt" | "value" | "identifier", string>>;
4834
4834
  additionalFields?: {
4835
4835
  [key: string]: _$better_auth0.DBFieldAttribute;
4836
4836
  };
@@ -1,6 +1,6 @@
1
1
  import { BetterAuth } from "./auth.lib.mjs";
2
- import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
3
2
  import { InferSelectModel } from "drizzle-orm";
3
+ import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
4
4
  import { NextFunction, Request, Response } from "express";
5
5
 
6
6
  //#region src/modules/auth/auth.middleware.d.ts
@@ -1,8 +1,8 @@
1
1
  import { auth_db_exports } from "./auth.db.mjs";
2
2
  import { BaseRepository } from "../base/base.repository.mjs";
3
- import { v4 } from "uuid";
4
3
  import { and, count, desc, eq, gte, ne } from "drizzle-orm";
5
4
  import { ok } from "neverthrow";
5
+ import { v4 } from "uuid";
6
6
  //#region src/modules/auth/auth.repository.ts
7
7
  ({ ...auth_db_exports });
8
8
  function parseOrganizationMetadata(metadata) {
@@ -1,6 +1,6 @@
1
1
  import { auth_db_exports } from "./auth.db.mjs";
2
- import { v4 } from "uuid";
3
2
  import { desc, eq } from "drizzle-orm";
3
+ import { v4 } from "uuid";
4
4
  //#region src/modules/auth/auth.utils.ts
5
5
  ({ ...auth_db_exports });
6
6
  async function getActiveOrganizationAndTeam(orm, schema, userId) {
@@ -1,7 +1,7 @@
1
1
  import { ServerResultAsync, pickColumns } from "./base.dto.mjs";
2
2
  import { Base } from "./base.abstract.mjs";
3
- import { SQLiteColumn, SQLiteTableWithColumns } from "drizzle-orm/sqlite-core";
4
3
  import { InferInsertModel, InferSelectModel, SQL, SelectedFields } from "drizzle-orm";
4
+ import { SQLiteColumn, SQLiteTableWithColumns } from "drizzle-orm/sqlite-core";
5
5
  import { QueryFilters, QueryInput } from "@m5kdev/commons/modules/schemas/query.schema";
6
6
  import { LibSQLDatabase } from "drizzle-orm/libsql";
7
7
 
@@ -1,10 +1,10 @@
1
1
  import { ServerResult, ServerResultAsync } from "../base/base.dto.mjs";
2
2
  import { BaseTableRepository } from "../base/base.repository.mjs";
3
3
  import { BillingSchema } from "@m5kdev/commons/modules/billing/billing.schema";
4
- import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
5
4
  import { InferSelectModel } from "drizzle-orm";
5
+ import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
6
6
  import { LibSQLDatabase } from "drizzle-orm/libsql";
7
- import { Stripe } from "stripe";
7
+ import { Stripe as Stripe$1 } from "stripe";
8
8
  import { StripePlan } from "@m5kdev/commons/modules/billing/billing.types";
9
9
 
10
10
  //#region src/modules/billing/billing.repository.d.ts
@@ -2713,7 +2713,7 @@ declare const schema: {
2713
2713
  type Schema = typeof schema;
2714
2714
  type Orm = LibSQLDatabase<Schema>;
2715
2715
  declare class BillingRepository extends BaseTableRepository<Orm, Schema, Record<string, never>, Schema["subscriptions"]> {
2716
- stripe: Stripe;
2716
+ stripe: Stripe$1;
2717
2717
  plans: StripePlan[];
2718
2718
  trial?: StripePlan;
2719
2719
  constructor(options: {
@@ -2721,7 +2721,7 @@ declare class BillingRepository extends BaseTableRepository<Orm, Schema, Record<
2721
2721
  schema: Schema;
2722
2722
  table: Schema["subscriptions"];
2723
2723
  libs: {
2724
- stripe: Stripe;
2724
+ stripe: Stripe$1;
2725
2725
  };
2726
2726
  config: {
2727
2727
  trial?: StripePlan;
@@ -2730,7 +2730,7 @@ declare class BillingRepository extends BaseTableRepository<Orm, Schema, Record<
2730
2730
  });
2731
2731
  hasTrial(): boolean;
2732
2732
  getPlanByPriceId(priceId: string): StripePlan | undefined;
2733
- getCustomerByEmail(email: string): ServerResultAsync<Stripe.Customer | null>;
2733
+ getCustomerByEmail(email: string): ServerResultAsync<Stripe$1.Customer | null>;
2734
2734
  getUserByCustomerId(customerId: string): ServerResultAsync<InferSelectModel<Schema["users"]> | null>;
2735
2735
  createCustomer({
2736
2736
  email,
@@ -2740,8 +2740,8 @@ declare class BillingRepository extends BaseTableRepository<Orm, Schema, Record<
2740
2740
  email: string;
2741
2741
  name?: string;
2742
2742
  userId: string;
2743
- }): ServerResultAsync<Stripe.Customer>;
2744
- createTrialSubscription(customerId: string): ServerResultAsync<Stripe.Subscription>;
2743
+ }): ServerResultAsync<Stripe$1.Customer>;
2744
+ createTrialSubscription(customerId: string): ServerResultAsync<Stripe$1.Subscription>;
2745
2745
  createSubscription({
2746
2746
  customerId,
2747
2747
  priceId,
@@ -2752,7 +2752,7 @@ declare class BillingRepository extends BaseTableRepository<Orm, Schema, Record<
2752
2752
  priceId: string;
2753
2753
  quantity?: number;
2754
2754
  trialDays?: number;
2755
- }): ServerResultAsync<Stripe.Subscription>;
2755
+ }): ServerResultAsync<Stripe$1.Subscription>;
2756
2756
  updateUserCustomerId({
2757
2757
  userId,
2758
2758
  customerId
@@ -2762,7 +2762,7 @@ declare class BillingRepository extends BaseTableRepository<Orm, Schema, Record<
2762
2762
  }): ServerResultAsync<InferSelectModel<Schema["users"]>>;
2763
2763
  getLatestSubscription(referenceId: string): ServerResultAsync<BillingSchema | null>;
2764
2764
  getActiveSubscription(referenceId: string): ServerResultAsync<BillingSchema | null>;
2765
- listInvoices(customerId: string): ServerResultAsync<Stripe.Invoice[]>;
2765
+ listInvoices(customerId: string): ServerResultAsync<Stripe$1.Invoice[]>;
2766
2766
  createCheckoutSession({
2767
2767
  customerId,
2768
2768
  priceId,
@@ -2771,8 +2771,8 @@ declare class BillingRepository extends BaseTableRepository<Orm, Schema, Record<
2771
2771
  customerId: string;
2772
2772
  priceId: string;
2773
2773
  userId: string;
2774
- }): ServerResultAsync<Stripe.Checkout.Session>;
2775
- createBillingPortalSession(customerId: string): ServerResultAsync<Stripe.BillingPortal.Session>;
2774
+ }): ServerResultAsync<Stripe$1.Checkout.Session>;
2775
+ createBillingPortalSession(customerId: string): ServerResultAsync<Stripe$1.BillingPortal.Session>;
2776
2776
  syncStripeData({
2777
2777
  customerId,
2778
2778
  userId
@@ -2780,7 +2780,7 @@ declare class BillingRepository extends BaseTableRepository<Orm, Schema, Record<
2780
2780
  customerId: string;
2781
2781
  userId: string;
2782
2782
  }): ServerResultAsync<boolean>;
2783
- constructEvent(body: Buffer | string, signature: string, secret: string): ServerResult<Stripe.Event>;
2783
+ constructEvent(body: Buffer | string, signature: string, secret: string): ServerResult<Stripe$1.Event>;
2784
2784
  }
2785
2785
  //#endregion
2786
2786
  export { BillingRepository };
@@ -4,7 +4,7 @@ import { BillingRepository } from "./billing.repository.mjs";
4
4
  import { User } from "../auth/auth.lib.mjs";
5
5
  import { BaseService } from "../base/base.service.mjs";
6
6
  import { BillingSchema } from "@m5kdev/commons/modules/billing/billing.schema";
7
- import Stripe$1 from "stripe";
7
+ import Stripe from "stripe";
8
8
 
9
9
  //#region src/modules/billing/billing.service.d.ts
10
10
  declare class BillingService extends BaseService<{
@@ -18,7 +18,7 @@ declare class BillingService extends BaseService<{
18
18
  email: string;
19
19
  name?: string;
20
20
  };
21
- }): ServerResultAsync<Stripe$1.Customer>;
21
+ }): ServerResultAsync<Stripe.Customer>;
22
22
  createUserHook({
23
23
  user
24
24
  }: {
@@ -29,7 +29,7 @@ declare class BillingService extends BaseService<{
29
29
  };
30
30
  }): ServerResultAsync<boolean>;
31
31
  getActiveSubscription(ctx: Context): ServerResultAsync<BillingSchema | null>;
32
- listInvoices(ctx: Context): ServerResultAsync<Stripe$1.Invoice[]>;
32
+ listInvoices(ctx: Context): ServerResultAsync<Stripe.Invoice[]>;
33
33
  createCheckoutSession({
34
34
  priceId
35
35
  }: {
@@ -38,15 +38,15 @@ declare class BillingService extends BaseService<{
38
38
  user
39
39
  }: {
40
40
  user: User;
41
- }): ServerResultAsync<Stripe$1.Checkout.Session>;
41
+ }): ServerResultAsync<Stripe.Checkout.Session>;
42
42
  createBillingPortalSession({
43
43
  user
44
44
  }: {
45
45
  user: User;
46
- }): ServerResultAsync<Stripe$1.BillingPortal.Session>;
47
- constructEvent(body: Buffer | string, signature: string): ServerResult<Stripe$1.Event>;
46
+ }): ServerResultAsync<Stripe.BillingPortal.Session>;
47
+ constructEvent(body: Buffer | string, signature: string): ServerResult<Stripe.Event>;
48
48
  syncStripeData(customerId: string, eventType?: string): ServerResultAsync<boolean>;
49
- processEvent(event: Stripe$1.Event): ServerResultAsync<boolean>;
49
+ processEvent(event: Stripe.Event): ServerResultAsync<boolean>;
50
50
  }
51
51
  //#endregion
52
52
  export { BillingService };
@@ -1,8 +1,8 @@
1
1
  import { ServerResult } from "../base/base.dto.mjs";
2
2
  import { BaseTableRepository } from "../base/base.repository.mjs";
3
3
  import { ConnectListInputSchema } from "./connect.dto.mjs";
4
- import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
5
4
  import { InferInsertModel, InferSelectModel } from "drizzle-orm";
5
+ import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
6
6
  import { LibSQLDatabase } from "drizzle-orm/libsql";
7
7
 
8
8
  //#region src/modules/connect/connect.repository.d.ts
@@ -1,6 +1,6 @@
1
1
  import { BaseService } from "../base/base.service.mjs";
2
- import { v4 } from "uuid";
3
2
  import { err, ok } from "neverthrow";
3
+ import { v4 } from "uuid";
4
4
  import path, { dirname } from "node:path";
5
5
  import { fileTypes } from "@m5kdev/commons/modules/file/file.constants";
6
6
  import { createWriteStream } from "node:fs";
@@ -1,7 +1,7 @@
1
1
  import { ServerResultAsync } from "../base/base.dto.mjs";
2
2
  import { BaseTableRepository } from "../base/base.repository.mjs";
3
- import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
4
3
  import { InferInsertModel, InferSelectModel } from "drizzle-orm";
4
+ import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
5
5
  import { LibSQLDatabase } from "drizzle-orm/libsql";
6
6
 
7
7
  //#region src/modules/recurrence/recurrence.repository.d.ts
@@ -18,7 +18,7 @@ declare class RecurrenceService extends BaseService<{
18
18
  filters?: {
19
19
  columnId: string;
20
20
  type: "string" | "number" | "boolean" | "date" | "enum";
21
- method: "intersect" | "on" | "contains" | "starts_with" | "ends_with" | "equals" | "greater_than" | "less_than" | "between" | "before" | "after" | "oneOf" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
21
+ method: "contains" | "equals" | "starts_with" | "ends_with" | "greater_than" | "less_than" | "on" | "between" | "before" | "after" | "oneOf" | "intersect" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
22
22
  value: string | number | boolean | string[];
23
23
  valueTo?: string | undefined;
24
24
  endColumnId?: string | undefined;
@@ -21,7 +21,7 @@ declare function createRecurrenceTRPC({
21
21
  filters?: {
22
22
  columnId: string;
23
23
  type: "string" | "number" | "boolean" | "date" | "enum";
24
- method: "intersect" | "on" | "contains" | "starts_with" | "ends_with" | "equals" | "greater_than" | "less_than" | "between" | "before" | "after" | "oneOf" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
24
+ method: "contains" | "equals" | "starts_with" | "ends_with" | "greater_than" | "less_than" | "on" | "between" | "before" | "after" | "oneOf" | "intersect" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
25
25
  value: string | number | boolean | string[];
26
26
  valueTo?: string | undefined;
27
27
  endColumnId?: string | undefined;
@@ -1,7 +1,7 @@
1
1
  import { ServerError } from "../../utils/errors.mjs";
2
2
  import { z } from "zod";
3
- import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
4
3
  import { Result } from "neverthrow";
4
+ import * as _$drizzle_orm_sqlite_core0 from "drizzle-orm/sqlite-core";
5
5
  import * as _$drizzle_zod0 from "drizzle-zod";
6
6
 
7
7
  //#region src/modules/tag/tag.dto.d.ts
@@ -21,7 +21,7 @@ declare function createTagTRPC({
21
21
  filters?: {
22
22
  columnId: string;
23
23
  type: "string" | "number" | "boolean" | "date" | "enum";
24
- method: "intersect" | "on" | "contains" | "starts_with" | "ends_with" | "equals" | "greater_than" | "less_than" | "between" | "before" | "after" | "oneOf" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
24
+ method: "contains" | "equals" | "starts_with" | "ends_with" | "greater_than" | "less_than" | "on" | "between" | "before" | "after" | "oneOf" | "intersect" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
25
25
  value: string | number | boolean | string[];
26
26
  valueTo?: string | undefined;
27
27
  endColumnId?: string | undefined;
@@ -54,7 +54,7 @@ declare function createTagTRPC({
54
54
  resourceIds?: {
55
55
  columnId: string;
56
56
  type: "string" | "number" | "boolean" | "date" | "enum";
57
- method: "intersect" | "on" | "contains" | "starts_with" | "ends_with" | "equals" | "greater_than" | "less_than" | "between" | "before" | "after" | "oneOf" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
57
+ method: "contains" | "equals" | "starts_with" | "ends_with" | "greater_than" | "less_than" | "on" | "between" | "before" | "after" | "oneOf" | "intersect" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
58
58
  value: string | number | boolean | string[];
59
59
  valueTo?: string | undefined;
60
60
  endColumnId?: string | undefined;
@@ -1,6 +1,6 @@
1
1
  import { BaseService } from "../base/base.service.mjs";
2
- import { v4 } from "uuid";
3
2
  import { err, ok } from "neverthrow";
3
+ import { v4 } from "uuid";
4
4
  import path from "node:path";
5
5
  import { closeSync, existsSync, mkdirSync, openSync } from "node:fs";
6
6
  import ffbin from "ffmpeg-ffprobe-static";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m5kdev/backend",
3
- "version": "0.8.4",
3
+ "version": "0.8.6",
4
4
  "description": "Composable Express server stack with Drizzle ORM and tRPC.",
5
5
  "license": "GPL-3.0-only",
6
6
  "repository": {
@@ -59,8 +59,8 @@
59
59
  "trpc-to-openapi": "2.3.0",
60
60
  "uuid": "11.0.5",
61
61
  "zod": "4.2.1",
62
- "@m5kdev/commons": "0.8.4",
63
- "@m5kdev/config": "0.8.4"
62
+ "@m5kdev/commons": "0.8.6",
63
+ "@m5kdev/config": "0.8.6"
64
64
  },
65
65
  "devDependencies": {
66
66
  "@jest/globals": "30.2.0",