Skip to content
Open
5 changes: 4 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@ docs

# exclude aux files
.git
.idea
.idea

# exclude database dumps
db_dumps
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ backend/sessions
backend/node_modules
backend/logs
backend/coverage

logs/
# ignore build files
dist/
frontend/node_modules
Expand Down
1 change: 1 addition & 0 deletions backend/db/.sequelizerc
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is that needed?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was added so that when we run npx sequelize-cli db:migrate, the CLI loads the .env file and has access to environment variables like POSTGRES_HOST, POSTGRES_CAREDB, etc. Without it, the config.js can't resolve process.env.POSTGRES_CAREDB and the migration fails.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dennis-zyska do we need that file though?

Copy link
Copy Markdown
Collaborator

@dennis-zyska dennis-zyska Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we usually don't use the command without the make file, so usually the envs are set. I wonder if it would always overwrite the current one with the .env (because we have multiple .env files), and the others would not work anymore

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '..', '..', '.env') });

module.exports = {
'config': path.resolve('./config', 'config.js'),
Expand Down
1 change: 1 addition & 0 deletions backend/db/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*
* @author Nils Dycke
*/

module.exports = {
development: {
username: 'postgres',
Expand Down
82 changes: 82 additions & 0 deletions backend/db/migrations/20260331100000-create-api_key.js
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do all migration files have just a counter 00000 .... 00001 etc. usually it is the time when the file is created

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
'use strict';

module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.sequelize.query('CREATE EXTENSION IF NOT EXISTS pgcrypto;');

await queryInterface.createTable('ai_api_key', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
userId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'user',
key: 'id',
},
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
},
provider: {
type: Sequelize.STRING,
allowNull: false,
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
apiEndpoint: {
type: Sequelize.STRING,
allowNull: true,
defaultValue: null,
},
encryptedKey: {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this here? We should encrypted the columns from the postgres table itself

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if is resolved, I can't see a change in the code, please reference to the commit if comments are resolved or explain why it is resolved

type: Sequelize.BLOB,
allowNull: false,
},
enabled: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: true,
},
usageLimitMonthly: {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to be discussed how to limit the API keys and models (please set it on the agenda of the team meetings)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I have set this point as one of the points to be discussed in our gradient meeting

type: Sequelize.INTEGER,
allowNull: true,
defaultValue: null,
},
lastUsedAt: {
type: Sequelize.DATE,
allowNull: true,
defaultValue: null,
},
deleted: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false,
},
deletedAt: {
type: Sequelize.DATE,
allowNull: true,
defaultValue: null,
},
createdAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.fn('NOW'),
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.fn('NOW'),
},
});
},

async down(queryInterface, Sequelize) {
await queryInterface.dropTable('ai_api_key');
},
};
55 changes: 55 additions & 0 deletions backend/db/migrations/20260331100001-create-llm_provider.js
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sharing option should be represented in the model table. We should be able to share the model to a user or a group of users (we have the definition of roles in the database). You can ask @karimouf for some pointer on how to share it between different roles of users. This might need additional db tables, as we want to also define the limits for that sharing.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use strict';

module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('ai_model', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
modelPath: {
type: Sequelize.STRING,
allowNull: false,
},
apiBaseUrl: {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please discuss with @akash9676 what parameters are needed for a model

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay @dennis-zyska. I have added this point in our internal meeting with @akash9676

type: Sequelize.STRING,
allowNull: false,
},
enabled: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: true,
},
deleted: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false,
},
deletedAt: {
type: Sequelize.DATE,
allowNull: true,
defaultValue: null,
},
createdAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.fn('NOW'),
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.fn('NOW'),
},
});
},

async down(queryInterface, Sequelize) {
await queryInterface.dropTable('ai_model');
},
};
117 changes: 117 additions & 0 deletions backend/db/migrations/20260331100002-create-llm_log.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
'use strict';

module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('ai_log', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
userId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'user',
key: 'id',
},
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
},
apiKeyId: {
type: Sequelize.INTEGER,
allowNull: true,
defaultValue: null,
references: {
model: 'ai_api_key',
key: 'id',
},
onDelete: 'SET NULL',
onUpdate: 'CASCADE',
},
modelId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'ai_model',
key: 'id',
},
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
},
documentId: {
type: Sequelize.INTEGER,
allowNull: true,
defaultValue: null,
},
studySessionId: {
type: Sequelize.INTEGER,
allowNull: true,
defaultValue: null,
},
studyStepId: {
type: Sequelize.INTEGER,
allowNull: true,
defaultValue: null,
},
input: {
type: Sequelize.JSONB,
allowNull: true,
},
output: {
type: Sequelize.JSONB,
allowNull: true,
},
inputTokens: {
type: Sequelize.INTEGER,
allowNull: true,
defaultValue: null,
},
outputTokens: {
type: Sequelize.INTEGER,
allowNull: true,
defaultValue: null,
},
estimatedCost: {
type: Sequelize.FLOAT,
allowNull: true,
defaultValue: null,
},
latencyMs: {
type: Sequelize.INTEGER,
allowNull: true,
defaultValue: null,
},
status: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: 'success',
},
deleted: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false,
},
deletedAt: {
type: Sequelize.DATE,
allowNull: true,
defaultValue: null,
},
createdAt: {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here the default columns are missing deletedAt, etc.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is resoveld, I can see the deletedAt now.

type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.fn('NOW'),
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.fn('NOW'),
},
});
},

async down(queryInterface, Sequelize) {
await queryInterface.dropTable('ai_log');
},
};
96 changes: 96 additions & 0 deletions backend/db/migrations/20260331100003-create-prompt_template.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
'use strict';

module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('prompt_template', {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prompt templates are handled by our template integration, please ask @mohammadsherif0 how to use it in detail (we need to add another type of template for it, two types, one usual Prompt template and one that can be used in studies). so this table is probably not needed

id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
userId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'user',
key: 'id',
},
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
description: {
type: Sequelize.TEXT,
allowNull: true,
defaultValue: null,
},
provider: {
type: Sequelize.STRING,
allowNull: true,
defaultValue: null,
},
model: {
type: Sequelize.STRING,
allowNull: true,
defaultValue: null,
},
promptText: {
type: Sequelize.TEXT,
allowNull: false,
},
inputMapping: {
type: Sequelize.JSONB,
allowNull: true,
defaultValue: {},
},
defaultOutputMapping: {
type: Sequelize.JSONB,
allowNull: true,
defaultValue: {},
},
shared: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false,
},
sharedScope: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: 'none',
},
sharedTargetId: {
type: Sequelize.INTEGER,
allowNull: true,
defaultValue: null,
},
deleted: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false,
},
deletedAt: {
type: Sequelize.DATE,
allowNull: true,
defaultValue: null,
},
createdAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.fn('NOW'),
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.fn('NOW'),
},
});
},

async down(queryInterface, Sequelize) {
await queryInterface.dropTable('prompt_template');
},
};
10 changes: 10 additions & 0 deletions backend/db/migrations/20260331100004-seed-llm_provider.js
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed, this is coming from the LiteLLM and brokerIO integration

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just delete the whole file

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';

module.exports = {
async up(queryInterface, Sequelize) {
// Models are populated dynamically via LiteLLM and BrokerIO integration
},

async down(queryInterface, Sequelize) {
},
};
Loading
Loading