@dnax/core 0.13.3 → 0.13.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.
package/app/hono.ts CHANGED
@@ -227,6 +227,7 @@ function HonoInstance(): typeof app {
227
227
  col?.access?.hasOwnProperty(action) ||
228
228
  getPermission(session.get()?.role, tenant_id) ||
229
229
  null;
230
+
230
231
  let nextLifecyle: any = false;
231
232
 
232
233
  // Middleware for apis
@@ -237,7 +238,7 @@ function HonoInstance(): typeof app {
237
238
  action: action,
238
239
  c: c,
239
240
  isAuth: c.var?._v?.isAuth || false,
240
- rest: new useRest({ tenant_id: tenant_id }),
241
+ rest: new useRest({ tenant_id: tenant_id, c: c }),
241
242
  session: session as any,
242
243
  });
243
244
  }
@@ -263,10 +264,9 @@ function HonoInstance(): typeof app {
263
264
  return await next();
264
265
  }
265
266
 
266
- let performFromStudio = c.var["isStudio"] || false;
267
-
268
- if (col && col?.access?.allAction) {
269
- nextLifecyle = await col?.access?.allAction({
267
+ if (col && (col?.access?.allAction || col?.access?.hasOwnProperty("*"))) {
268
+ let accesFx = col?.access?.allAction || col?.access?.["*"];
269
+ nextLifecyle = await accesFx({
270
270
  token: c.var["token"] || null,
271
271
  action: action,
272
272
  c: c,
@@ -305,7 +305,7 @@ function HonoInstance(): typeof app {
305
305
  }
306
306
  }
307
307
 
308
- if (nextLifecyle || performFromStudio) {
308
+ if (nextLifecyle) {
309
309
  return await next();
310
310
  } else {
311
311
  c.status(403);
@@ -353,6 +353,7 @@ function HonoInstance(): typeof app {
353
353
 
354
354
  const rest = new useRest({
355
355
  tenant_id: c.var["tenant-id"],
356
+ c: c,
356
357
  });
357
358
 
358
359
  // Controlle action
@@ -363,14 +364,20 @@ function HonoInstance(): typeof app {
363
364
  // Exec service
364
365
  if (action == "execService") {
365
366
  if (!service) return fn.error("Service not found", 404);
366
- response = await service.fx({
367
- io: Cfg.io,
368
- data: body?.data || {},
369
- rest: rest,
370
- error: fn.error,
371
- session: sessionStorage(),
372
- isAuth: c.var?._v?.isAuth || false,
373
- });
367
+ let fx = service.exec || service.fx;
368
+ if (fx) {
369
+ response = await fx({
370
+ io: Cfg.io,
371
+ data: body?.data || {},
372
+ rest: rest,
373
+ error: fn.error,
374
+ session: sessionStorage(),
375
+ isAuth: c.var?._v?.isAuth || false,
376
+ });
377
+ } else {
378
+ c?.status(404);
379
+ return c.json({ message: "Service's function not found" });
380
+ }
374
381
 
375
382
  return c.json(response);
376
383
  }
@@ -555,6 +555,8 @@ class useRest {
555
555
  })
556
556
  .toArray();
557
557
 
558
+ result.docs = toJson(result.docs);
559
+
558
560
  if (col?.hooks?.afterFind && useHook) {
559
561
  await col.hooks.afterFind({
560
562
  sharedData: sharedData,
@@ -572,8 +574,9 @@ class useRest {
572
574
  });
573
575
  }
574
576
 
575
- let resultDocs = toJson(result.docs);
576
- if (typeof options?.elementAt == "number") {
577
+ let resultDocs = toJson([...(result?.docs || [])]);
578
+
579
+ if (typeof options?.elementAt == "number" && options?.elementAt) {
577
580
  resultDocs = resultDocs[options?.elementAt] ?? null;
578
581
  }
579
582
  return resolve(resultDocs);
package/index.ts CHANGED
@@ -4,10 +4,11 @@ import { toBson } from "./driver/mongo/utils";
4
4
  import { runApp } from "./app";
5
5
  import Joi from "joi";
6
6
  import define from "./define";
7
- import moment from "moment";
8
7
  import * as utils from "./utils";
9
8
  import { searchEngine } from "./lib/orama";
10
9
  import { dataCache } from "./lib/bento";
10
+ import { ai } from "./lib/ai";
11
+ import { crypt } from "./lib/crypto";
11
12
 
12
13
  /**
13
14
  * v is internal data validation and based of Joi validation.
@@ -16,4 +17,4 @@ import { dataCache } from "./lib/bento";
16
17
  */
17
18
  const v = Joi;
18
19
 
19
- export { runApp, define, utils, useRest, v, searchEngine, dataCache };
20
+ export { runApp, define, utils, useRest, v, dataCache, ai, crypt };
@@ -0,0 +1,21 @@
1
+ import { Ollama } from "./provider/ollama";
2
+ import { CohereClient } from "./provider/cohere";
3
+ import { Mistral } from "./provider/mistral";
4
+ import { OpenAI } from "./provider/openai";
5
+ import { Groq } from "./provider/groq";
6
+ import { Agent } from "./lib/Agent";
7
+ import { Space } from "./lib/Space";
8
+ import { Task } from "./lib/Task";
9
+
10
+ const ai = {
11
+ Ollama,
12
+ CohereClient,
13
+ Mistral,
14
+ OpenAI,
15
+ Groq,
16
+ Agent,
17
+ Space,
18
+ Task,
19
+ };
20
+
21
+ export { ai };
@@ -0,0 +1,159 @@
1
+ import { Groq } from "groq-sdk";
2
+ import { CohereClient } from "../provider/cohere";
3
+ import { OpenAI } from "../provider/openai";
4
+ import { Mistral } from "../provider/mistral";
5
+ type outputFunction = (content: any) => Promise<any>;
6
+
7
+ type AgentOptions = {
8
+ config: {
9
+ provider: "groq" | "cohere" | "openai" | "mistral";
10
+ model: string;
11
+ apiKey: string;
12
+ token?: string;
13
+ };
14
+ name?: string;
15
+ role: string;
16
+ goal: string;
17
+ backstory: string;
18
+ tools?: any[];
19
+ temperature?: number;
20
+ max_tokens?: number;
21
+ output_format?: "string" | "json";
22
+ fn: (
23
+ ctx: {
24
+ instruction: string;
25
+ data: object | any;
26
+ chat_history: any[];
27
+ activities: any[];
28
+ },
29
+ ai?: {
30
+ groq?: InstanceType<typeof Groq>;
31
+ cohere?: InstanceType<typeof CohereClient>;
32
+ openai?: InstanceType<typeof OpenAI>;
33
+ mistral?: InstanceType<typeof Mistral>;
34
+ }
35
+ ) => Promise<any>;
36
+ };
37
+
38
+ export type AgentType = InstanceType<typeof Agent>;
39
+
40
+ class Agent {
41
+ public cfg: AgentOptions;
42
+ #groq?: InstanceType<typeof Groq>;
43
+ #cohere?: InstanceType<typeof CohereClient>;
44
+ #openai?: InstanceType<typeof OpenAI>;
45
+ #mistral?: InstanceType<typeof Mistral>;
46
+ constructor(cfg: AgentOptions) {
47
+ this.cfg = cfg;
48
+
49
+ // Init default value
50
+ if (!this.cfg.temperature) this.cfg.temperature = 0.5;
51
+
52
+ // set groq client
53
+ if (cfg.config.provider === "groq") {
54
+ this.#groq = new Groq({
55
+ apiKey: cfg.config.apiKey,
56
+ });
57
+ }
58
+
59
+ // set cohere client
60
+ if (cfg.config.provider === "cohere") {
61
+ this.#cohere = new CohereClient({
62
+ token: cfg.config.apiKey || cfg.config.token,
63
+ });
64
+ }
65
+
66
+ // set openai client
67
+ if (cfg.config.provider === "openai") {
68
+ this.#openai = new OpenAI({
69
+ apiKey: cfg.config.apiKey,
70
+ });
71
+ }
72
+
73
+ // set mistral client
74
+ if (cfg.config.provider === "mistral") {
75
+ this.#mistral = new Mistral({
76
+ apiKey: cfg.config.apiKey,
77
+ });
78
+ }
79
+ }
80
+
81
+ async exec(
82
+ instruction: string,
83
+ data?: object
84
+ ): Promise<string | object | null | Array<any>> {
85
+ const messages: any = [];
86
+ var response: any = null;
87
+
88
+ return new Promise(async (resolve, reject) => {
89
+ try {
90
+ // Groq AI
91
+ if (this.#groq) {
92
+ response = await this.#groq.chat.completions.create({
93
+ messages: messages,
94
+ model: this.cfg.config.model,
95
+
96
+ temperature: Number(this?.cfg?.temperature),
97
+ tools: this.cfg?.tools || [],
98
+ response_format: {
99
+ type: this.cfg.output_format == "json" ? "json_object" : "text",
100
+ },
101
+ });
102
+ }
103
+
104
+ // Cohere AI
105
+ if (this.#cohere) {
106
+ response = await this.#cohere.chat({
107
+ chatHistory: messages,
108
+ message: instruction,
109
+ model: this.cfg.config.model,
110
+ temperature: Number(this?.cfg?.temperature),
111
+ preamble: this.cfg?.backstory || "",
112
+ maxTokens: Number(this?.cfg?.max_tokens),
113
+
114
+ tools: this.cfg?.tools || [],
115
+ responseFormat: {
116
+ type: this.cfg.output_format == "json" ? "json_object" : "text",
117
+ },
118
+ });
119
+ }
120
+
121
+ // OpenAI AI
122
+ if (this.#openai) {
123
+ response = await this.#openai.chat.completions.create({
124
+ max_tokens: Number(this?.cfg?.max_tokens),
125
+ messages: messages,
126
+ model: this.cfg.config.model,
127
+ temperature: Number(this?.cfg?.temperature),
128
+ tools: this.cfg?.tools || [],
129
+
130
+ response_format: {
131
+ type: this.cfg.output_format == "json" ? "json_object" : "text",
132
+ },
133
+ });
134
+ }
135
+
136
+ // Mistral AI
137
+ if (this.#mistral) {
138
+ response = await this.#mistral.chat.complete({
139
+ messages: messages,
140
+ model: this.cfg.config.model,
141
+ temperature: Number(this?.cfg?.temperature),
142
+ tools: this.cfg?.tools || [],
143
+ maxTokens: Number(this?.cfg?.max_tokens),
144
+ responseFormat: {
145
+ type: this.cfg.output_format == "json" ? "json_object" : "text",
146
+ },
147
+ });
148
+ }
149
+
150
+ resolve(response);
151
+ } catch (error) {
152
+ console?.error(error);
153
+ reject(error);
154
+ }
155
+ });
156
+ }
157
+ }
158
+
159
+ export { Agent };
@@ -0,0 +1,34 @@
1
+ import type { TaskType } from "./Task";
2
+ import type { AgentType } from "./Agent";
3
+ type SpaceOptions = {
4
+ name: string;
5
+ tasks: TaskType[];
6
+ agents: AgentType[];
7
+ arbitrator?: AgentType;
8
+ evaluators?: AgentType[];
9
+ summarizers?: AgentType[];
10
+ };
11
+
12
+ type responseType = {
13
+ task_name: string;
14
+ response: string;
15
+ };
16
+
17
+ class Space {
18
+ #tasks: TaskType[];
19
+ #agents: AgentType[];
20
+ #summarizers?: AgentType[];
21
+ #evaluator?: AgentType;
22
+ #arbitrator?: AgentType;
23
+ #activities?: any[];
24
+ constructor(cfg: SpaceOptions) {
25
+ this.#tasks = cfg.tasks;
26
+ this.#agents = cfg.agents;
27
+ this.#summarizers = cfg.summarizers;
28
+ this.#evaluator = cfg.evaluator;
29
+ this.#arbitrator = cfg.arbitrator;
30
+ }
31
+ run(content: string, data?: object) {}
32
+ }
33
+
34
+ export { Space };
@@ -0,0 +1,19 @@
1
+ import type { AgentType } from "./Agent";
2
+ export type TaskType = InstanceType<typeof Task>;
3
+ type TaskOptions = {
4
+ title?: string;
5
+ description: string;
6
+ expected_output: string;
7
+ output_format: "string" | "json" | boolean;
8
+ tools?: any[];
9
+ agent?: AgentType;
10
+ };
11
+ class Task {
12
+ public cfg: TaskOptions;
13
+ constructor(cfg: TaskOptions) {
14
+ this.cfg = cfg;
15
+ }
16
+ exec(instruction: string, data?: object) {}
17
+ }
18
+
19
+ export { Task };
@@ -0,0 +1,3 @@
1
+ import { CohereClient } from "cohere-ai";
2
+
3
+ export { CohereClient };
@@ -0,0 +1,3 @@
1
+ import { Groq } from "groq-sdk";
2
+
3
+ export { Groq };
@@ -0,0 +1,3 @@
1
+ import { Mistral } from "@mistralai/mistralai";
2
+
3
+ export { Mistral };
@@ -0,0 +1,3 @@
1
+ import { Ollama } from "ollama";
2
+
3
+ export { Ollama };
@@ -0,0 +1,3 @@
1
+ import OpenAI from "openai";
2
+
3
+ export { OpenAI };
@@ -69,6 +69,7 @@ const sessionStorage = () => ({
69
69
  if (input?.generateToken) {
70
70
  localSession.set(input?.id, data);
71
71
  }
72
+
72
73
  store.set(key, data);
73
74
  return {
74
75
  state: input.state,
package/lib/crypto.ts ADDED
@@ -0,0 +1,68 @@
1
+ import crypto from "node:crypto";
2
+
3
+ class AES {
4
+ #key;
5
+ constructor(
6
+ options: {
7
+ secretKey: string;
8
+ } = {
9
+ secretKey: "",
10
+ }
11
+ ) {
12
+ // Crée une clé de 256 bits (32 octets) en utilisant un hachage SHA-256 de la clé secrète fournie
13
+ this.#key = crypto.createHash("sha256").update(options.secretKey).digest();
14
+ }
15
+
16
+ // Fonction de chiffrement
17
+ encrypt(data: string | object) {
18
+ let dataEncoding = JSON.stringify(data);
19
+ const iv = crypto.randomBytes(12); // Génère un IV de 12 octets pour AES-GCM
20
+
21
+ // Crée un objet de chiffrement avec AES-256-GCM, la clé et l'IV
22
+ const cipher = crypto.createCipheriv("aes-256-gcm", this.#key, iv);
23
+
24
+ // Chiffre le message et convertit le texte chiffré en hexadécimal
25
+ let encrypted = cipher.update(dataEncoding, "utf8", "hex");
26
+ encrypted += cipher.final("hex");
27
+
28
+ // Récupère l'authTag pour l'intégrité
29
+ const authTag = cipher.getAuthTag().toString("hex");
30
+
31
+ // Retourne l'IV, l'authTag et le texte chiffré en format hexadécimal
32
+ return iv.toString("hex") + ":" + authTag + ":" + encrypted;
33
+ }
34
+
35
+ // Fonction de déchiffrement
36
+ decrypt(data: string) {
37
+ let encryptedData = data;
38
+ const [iv, authTag, ciphertext] = encryptedData.split(":");
39
+
40
+ /* const iv = Buffer.from(encryptedData.slice(0, 24), "hex");
41
+ const authTag = Buffer.from(encryptedData.slice(24, 56), "hex");
42
+ const ciphertext = encryptedData.slice(56); // Extrait les données chiffrées
43
+ */
44
+ // Crée un objet de déchiffrement avec AES-256-GCM, la clé et l'IV
45
+ const decipher = crypto.createDecipheriv(
46
+ "aes-256-gcm",
47
+ this.#key,
48
+ Buffer.from(iv, "hex")
49
+ );
50
+
51
+ // Définit l'authTag pour vérifier l'intégrité
52
+ decipher.setAuthTag(Buffer.from(authTag, "hex"));
53
+
54
+ // Déchiffre le texte chiffré et convertit en UTF-8
55
+ let decrypted = decipher.update(ciphertext, "hex", "utf8");
56
+ decrypted += decipher.final("utf8");
57
+
58
+ return JSON.parse(decrypted); // Retourne le message déchiffré
59
+ }
60
+ }
61
+
62
+ const message = "Bonjour, comment ça va ?";
63
+
64
+ const crypt = {
65
+ AES,
66
+ };
67
+
68
+ export { crypt };
@@ -17,10 +17,12 @@ async function loadPermissions() {
17
17
  for await (let t of Cfg.tenants) {
18
18
  let tenantPath = `${t.dir}/permissions/**/**.rabc.{ts,js}`;
19
19
  const glob = new Glob(tenantPath);
20
+
20
21
  for await (let file of glob.scan({
21
22
  cwd: Cfg.cwd,
22
23
  })) {
23
24
  let fullPathFile = path.join(Cfg.cwd || "", file);
25
+
24
26
  await import(fullPathFile)
25
27
  .then((inject) => {
26
28
  permissions.push({
@@ -44,7 +46,7 @@ function getPermission(
44
46
  ): permissionSchema | undefined | null {
45
47
  if (Cfg?.permissions?.length) {
46
48
  return Cfg.permissions.find((col: permissionSchema) => {
47
- return col.role === role && col.tenant_id === tenant_id;
49
+ return col?.role === role && col?.tenant_id === tenant_id;
48
50
  });
49
51
  }
50
52
  return null;
@@ -77,8 +79,11 @@ function checkPermission(
77
79
  let findCollection = perm?.access?.find((c) =>
78
80
  c?.collections?.includes(collection)
79
81
  );
82
+
80
83
  if (findCollection) {
81
- let actionsOnCollection = findCollection.actions.find((a) => a === action);
84
+ let actionsOnCollection = findCollection.actions.find(
85
+ (a) => a === action || a == "*"
86
+ );
82
87
  actionsOnCollection ? (approved = true) : (approved = false);
83
88
  }
84
89
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dnax/core",
3
- "version": "0.13.3",
3
+ "version": "0.13.6",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,6 +20,7 @@
20
20
  "@clack/prompts": "^0.7.0",
21
21
  "@colors/colors": "^1.6.0",
22
22
  "@lukeed/ms": "^2.0.2",
23
+ "@mistralai/mistralai": "^1.3.0",
23
24
  "@orama/orama": "^2.0.23",
24
25
  "@types/dot-object": "^2.1.6",
25
26
  "@types/jsonwebtoken": "^9.0.6",
@@ -27,6 +28,7 @@
27
28
  "boxen": "^7.1.1",
28
29
  "chokidar": "^3.6.0",
29
30
  "clean-deep": "^3.4.0",
31
+ "cohere-ai": "^7.14.0",
30
32
  "collect.js": "^4.36.1",
31
33
  "consola": "^3.2.3",
32
34
  "cookie": "^0.6.0",
@@ -35,6 +37,7 @@
35
37
  "find-open-port": "^2.0.3",
36
38
  "fs-extra": "^11.2.0",
37
39
  "generate-unique-id": "^2.0.3",
40
+ "groq-sdk": "^0.7.0",
38
41
  "hono": "^4.6.3",
39
42
  "joi": "^17.13.3",
40
43
  "json-joy": "^16.8.0",
@@ -44,6 +47,8 @@
44
47
  "moment": "^2.30.1",
45
48
  "mongodb": "^6.8.0",
46
49
  "nodemailer": "^6.9.14",
50
+ "ollama": "^0.5.9",
51
+ "openai": "^4.71.1",
47
52
  "radash": "^12.1.0",
48
53
  "sharp": "^0.33.5",
49
54
  "signaldb": "^0.18.0",
package/tsconfig.json CHANGED
@@ -1,27 +1,27 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  // Enable latest features
4
- "lib": ["ESNext", "DOM"],
4
+ "lib": [
5
+ "ESNext",
6
+ "DOM"
7
+ ],
5
8
  "target": "ESNext",
6
9
  "module": "ESNext",
7
10
  "moduleDetection": "force",
8
11
  "jsx": "react-jsx",
9
12
  "allowJs": true,
10
-
11
13
  // Bundler mode
12
14
  "moduleResolution": "bundler",
13
15
  "allowImportingTsExtensions": true,
14
16
  "verbatimModuleSyntax": true,
15
17
  "noEmit": true,
16
-
17
18
  // Best practices
18
19
  "strict": true,
19
20
  "skipLibCheck": true,
20
21
  "noFallthroughCasesInSwitch": true,
21
-
22
22
  // Some stricter flags (disabled by default)
23
23
  "noUnusedLocals": false,
24
24
  "noUnusedParameters": false,
25
25
  "noPropertyAccessFromIndexSignature": false
26
26
  }
27
- }
27
+ }
package/types/index.ts CHANGED
@@ -185,7 +185,6 @@ export type hooksCtx = (ctx: {
185
185
  update?: updateParams;
186
186
  pipeline?: Array<object>;
187
187
  sharedData?: any;
188
- store?: any;
189
188
  action?: Actions;
190
189
  c?: Context;
191
190
  rest: InstanceType<typeof useRest>;
@@ -270,6 +269,7 @@ export type Collection = {
270
269
  afterAggregate?: hooksCtx;
271
270
  };
272
271
  access?: {
272
+ "*"?: accessCtx;
273
273
  beforeAction?: accessCtx;
274
274
  allAction?: accessCtx;
275
275
  find?: accessCtx;
@@ -469,6 +469,7 @@ export type Endpoint = endpointCtx;
469
469
 
470
470
  export type Service = {
471
471
  /**
472
+ * @internal
472
473
  * Dont touch it automatically generated
473
474
  */
474
475
  tenant_id?: string;
@@ -481,7 +482,27 @@ export type Service = {
481
482
  * @param ctx
482
483
  * @returns
483
484
  */
484
- fx: (ctx: {
485
+ fx?: (ctx: {
486
+ /**
487
+ * Incomming data [payload]
488
+ */
489
+ data: object;
490
+ /**
491
+ * Local rest linked to current tenant
492
+ */
493
+ rest: InstanceType<typeof useRest>;
494
+ error: typeof fn.error;
495
+ /**
496
+ * Session of request
497
+ */
498
+ session: sessionCtx;
499
+ /**
500
+ * authenticated user or no
501
+ */
502
+ isAuth: boolean;
503
+ io: Io;
504
+ }) => any;
505
+ exec?: (ctx: {
485
506
  /**
486
507
  * Incomming data [payload]
487
508
  */
@@ -545,7 +566,6 @@ export type accessType = {
545
566
  handler: AccessFunctionType;
546
567
  }
547
568
  | "*"
548
- | "allAction"
549
569
  | "aggregate"
550
570
  | "find"
551
571
  | "findOne"