@gnar-engine/cli 1.0.2 → 1.0.4
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/bootstrap/deploy.localdev.yml +18 -31
- package/bootstrap/secrets.localdev.yml +7 -12
- package/bootstrap/services/user/Dockerfile +1 -1
- package/install.sh +32 -0
- package/package.json +1 -1
- package/src/config.js +2 -1
- package/src/dev/dev.service.js +44 -16
- package/src/scaffolder/commands.js +11 -4
- package/src/scaffolder/scaffolder.handler.js +228 -55
- package/templates/service/Dockerfile.hbs +4 -1
- package/templates/service/package.json.hbs +14 -16
- package/templates/service/{app.js.hbs → src/app.js.hbs} +8 -4
- package/templates/service/{commands → src/commands}/{{serviceName}}.handler.js.hbs +1 -2
- package/{bootstrap/services/agent/src/config.js → templates/service/src/mongodb.config.js.hbs} +11 -18
- package/templates/service/{config.js.hbs → src/mysql.config.js.hbs} +6 -0
- package/{bootstrap/services/agent/src/schema/Agent.schema.js → templates/service/src/schema/{{serviceName}}.schema.js.hbs} +3 -3
- package/templates/service/src/services/mongodb.{{serviceName}}.service.js.hbs +70 -0
- package/bootstrap/services/agent/Dockerfile +0 -23
- package/bootstrap/services/agent/notes.md +0 -28
- package/bootstrap/services/agent/package.json +0 -16
- package/bootstrap/services/agent/src/app.js +0 -52
- package/bootstrap/services/agent/src/commands/agent.handler.js +0 -104
- package/bootstrap/services/agent/src/controllers/http.controller.js +0 -44
- package/bootstrap/services/agent/src/controllers/message.controller.js +0 -51
- package/bootstrap/services/agent/src/db/migrations/01-init.js +0 -50
- package/bootstrap/services/agent/src/db/migrations/02-agent-service-init.js +0 -36
- package/bootstrap/services/agent/src/policies/agent.policy.js +0 -13
- package/bootstrap/services/agent/src/services/agent.service.js +0 -259
- package/bootstrap/services/agent/src/services/chatgpt.service.js +0 -46
- package/bootstrap/services/agent/src/services/manifest.service.js +0 -21
- package/bootstrap/services/portal/Dockerfile +0 -23
- package/bootstrap/services/portal/Dockerfile.remote +0 -40
- package/bootstrap/services/portal/README.md +0 -22
- package/bootstrap/services/portal/nginx.conf +0 -12
- package/bootstrap/services/portal/package.json +0 -59
- package/bootstrap/services/portal/public/favicon.ico +0 -0
- package/bootstrap/services/portal/public/gnar-white.png +0 -0
- package/bootstrap/services/portal/public/gnarengine-logo-black.png +0 -0
- package/bootstrap/services/portal/public/index.html +0 -43
- package/bootstrap/services/portal/public/logo192.png +0 -0
- package/bootstrap/services/portal/public/logo512.png +0 -0
- package/bootstrap/services/portal/public/manifest.json +0 -25
- package/bootstrap/services/portal/public/robots.txt +0 -3
- package/bootstrap/services/portal/src/App.js +0 -56
- package/bootstrap/services/portal/src/assets/Logo_Anchord_Black.svg +0 -1
- package/bootstrap/services/portal/src/assets/Logo_Anchord_Black_Green.svg +0 -1
- package/bootstrap/services/portal/src/assets/Logo_Anchord_White_Green.svg +0 -1
- package/bootstrap/services/portal/src/assets/activity.svg +0 -3
- package/bootstrap/services/portal/src/assets/arrow.svg +0 -3
- package/bootstrap/services/portal/src/assets/bin-white.svg +0 -3
- package/bootstrap/services/portal/src/assets/bin.svg +0 -3
- package/bootstrap/services/portal/src/assets/check.svg +0 -3
- package/bootstrap/services/portal/src/assets/chevron.svg +0 -3
- package/bootstrap/services/portal/src/assets/contact.svg +0 -3
- package/bootstrap/services/portal/src/assets/dots-vertical.svg +0 -5
- package/bootstrap/services/portal/src/assets/eye-off.svg +0 -3
- package/bootstrap/services/portal/src/assets/eye.svg +0 -4
- package/bootstrap/services/portal/src/assets/gnar-engine-black.svg +0 -47
- package/bootstrap/services/portal/src/assets/gnar-engine-white.svg +0 -47
- package/bootstrap/services/portal/src/assets/gnar_engine.svg +0 -3
- package/bootstrap/services/portal/src/assets/gnarengine-logo-black.png +0 -0
- package/bootstrap/services/portal/src/assets/home.svg +0 -3
- package/bootstrap/services/portal/src/assets/link.svg +0 -3
- package/bootstrap/services/portal/src/assets/lock.svg +0 -3
- package/bootstrap/services/portal/src/assets/package.svg +0 -4
- package/bootstrap/services/portal/src/assets/raffle.svg +0 -3
- package/bootstrap/services/portal/src/assets/settings.svg +0 -4
- package/bootstrap/services/portal/src/assets/shopping-bag.svg +0 -3
- package/bootstrap/services/portal/src/assets/user-black.svg +0 -3
- package/bootstrap/services/portal/src/assets/user.svg +0 -3
- package/bootstrap/services/portal/src/assets/users.svg +0 -3
- package/bootstrap/services/portal/src/assets/wallet.svg +0 -3
- package/bootstrap/services/portal/src/css/style.css +0 -1007
- package/bootstrap/services/portal/src/data/data.js +0 -70
- package/bootstrap/services/portal/src/features/attributeFormRow/AttributeFormRow.jsx +0 -32
- package/bootstrap/services/portal/src/features/billingShipping/BillingShipping.jsx +0 -160
- package/bootstrap/services/portal/src/features/crud/crudEdit.less +0 -230
- package/bootstrap/services/portal/src/features/crud/crudList.less +0 -134
- package/bootstrap/services/portal/src/features/crud/crudPage.less +0 -31
- package/bootstrap/services/portal/src/features/crudContact/CrudContactList.jsx +0 -108
- package/bootstrap/services/portal/src/features/crudContact/CrudContactSingle.jsx +0 -243
- package/bootstrap/services/portal/src/features/crudOrder/CrudOrderList.jsx +0 -109
- package/bootstrap/services/portal/src/features/crudOrder/CrudOrderSingle.jsx +0 -315
- package/bootstrap/services/portal/src/features/crudProducts/CrudProductList.jsx +0 -104
- package/bootstrap/services/portal/src/features/crudProducts/CrudProductSingle.jsx +0 -388
- package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesList.jsx +0 -104
- package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesSingle.jsx +0 -208
- package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionList.jsx +0 -110
- package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionSingle.jsx +0 -261
- package/bootstrap/services/portal/src/features/crudUser/CrudUserList.jsx +0 -107
- package/bootstrap/services/portal/src/features/crudUser/CrudUserSingle.jsx +0 -402
- package/bootstrap/services/portal/src/features/inventoryFormRow/InventoryFormRow.jsx +0 -30
- package/bootstrap/services/portal/src/features/lineItems/LineItems.jsx +0 -113
- package/bootstrap/services/portal/src/features/loginForm/LoginForm.jsx +0 -56
- package/bootstrap/services/portal/src/features/loginForm/loginForm.less +0 -56
- package/bootstrap/services/portal/src/features/notes/Notes.jsx +0 -18
- package/bootstrap/services/portal/src/features/passwordReset/PasswordResetForm.jsx +0 -96
- package/bootstrap/services/portal/src/features/passwordReset/PasswordResetRequestForm.jsx +0 -74
- package/bootstrap/services/portal/src/features/priceFormRow/PriceFormRow.jsx +0 -102
- package/bootstrap/services/portal/src/features/priceFormRow/priceFormRow.less +0 -24
- package/bootstrap/services/portal/src/features/raffleEntriesList/RaffleEntriesList.jsx +0 -99
- package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx +0 -46
- package/bootstrap/services/portal/src/features/sidebar/Sidebar.jsx +0 -64
- package/bootstrap/services/portal/src/features/sidebar/sidebar.less +0 -49
- package/bootstrap/services/portal/src/features/skus/Skus.jsx +0 -109
- package/bootstrap/services/portal/src/features/subscriptionSchedule/SubscriptionSchedule.jsx +0 -44
- package/bootstrap/services/portal/src/features/taxonomyFormRow/TaxonomyFormRow.jsx +0 -32
- package/bootstrap/services/portal/src/features/user/User.jsx +0 -54
- package/bootstrap/services/portal/src/features/user/user.less +0 -57
- package/bootstrap/services/portal/src/includes/utilities.js +0 -259
- package/bootstrap/services/portal/src/index.js +0 -14
- package/bootstrap/services/portal/src/layouts/CrudLayout.jsx +0 -50
- package/bootstrap/services/portal/src/layouts/LoginLayout.jsx +0 -17
- package/bootstrap/services/portal/src/layouts/PortalLayout.jsx +0 -48
- package/bootstrap/services/portal/src/layouts/loginLayout.less +0 -33
- package/bootstrap/services/portal/src/layouts/portalLayout.less +0 -67
- package/bootstrap/services/portal/src/pages/contacts/Contacts.jsx +0 -199
- package/bootstrap/services/portal/src/pages/dashboard/Dashboard.jsx +0 -17
- package/bootstrap/services/portal/src/pages/integrations/Integrations.jsx +0 -10
- package/bootstrap/services/portal/src/pages/login/Login.jsx +0 -15
- package/bootstrap/services/portal/src/pages/login/login.less +0 -10
- package/bootstrap/services/portal/src/pages/orders/Orders.jsx +0 -199
- package/bootstrap/services/portal/src/pages/passwordReset/PasswordResetPage.jsx +0 -15
- package/bootstrap/services/portal/src/pages/passwordResetRequest/PasswordResetRequestPage.jsx +0 -15
- package/bootstrap/services/portal/src/pages/payments/Payments.jsx +0 -10
- package/bootstrap/services/portal/src/pages/portal/Portal.jsx +0 -43
- package/bootstrap/services/portal/src/pages/products/Products.jsx +0 -212
- package/bootstrap/services/portal/src/pages/raffleEntries/RaffleEntries.jsx +0 -124
- package/bootstrap/services/portal/src/pages/raffles/Raffles.jsx +0 -186
- package/bootstrap/services/portal/src/pages/reports/Reports.jsx +0 -10
- package/bootstrap/services/portal/src/pages/settings/Settings.jsx +0 -10
- package/bootstrap/services/portal/src/pages/subscriptions/Subscriptions.jsx +0 -199
- package/bootstrap/services/portal/src/pages/users/Users.jsx +0 -193
- package/bootstrap/services/portal/src/pages/users/users.less +0 -25
- package/bootstrap/services/portal/src/slices/authSlice.js +0 -71
- package/bootstrap/services/portal/src/store/configureStore.js +0 -12
- package/bootstrap/services/portal/src/styles/global.less +0 -159
- package/bootstrap/services/portal/src/styles/inputs.less +0 -157
- package/bootstrap/services/portal/src/styles/main.less +0 -26
- package/bootstrap/services/portal/src/ui/collapsible/Collapsible.jsx +0 -97
- package/bootstrap/services/portal/src/ui/collapsible/collapsible.less +0 -23
- package/bootstrap/services/portal/src/ui/customCheckbox/CustomCheckbox.jsx +0 -17
- package/bootstrap/services/portal/src/ui/customCheckbox/customCheckbox.less +0 -42
- package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelect.jsx +0 -63
- package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelectPeriod.jsx +0 -63
- package/bootstrap/services/portal/src/ui/customSelect/CustomSelect.jsx +0 -63
- package/bootstrap/services/portal/src/ui/customSelect/customSelect.less +0 -92
- package/bootstrap/services/portal/src/ui/goBack/GoBack.jsx +0 -19
- package/bootstrap/services/portal/src/ui/loader/Loader.jsx +0 -12
- package/bootstrap/services/portal/src/ui/pagination/Pagination.jsx +0 -23
- package/bootstrap/services/portal/src/ui/repeater/Repeater.jsx +0 -29
- package/bootstrap/services/portal/src/ui/saveButton/SaveButton.jsx +0 -69
- package/bootstrap/services/portal/src/ui/saveButton/saveButton.less +0 -0
- package/bootstrap/services/user/src/db/seeders/development/02-portal-admin-user.js +0 -27
- package/templates/service/schema/{{serviceName}}.schema.js.hbs +0 -14
- /package/templates/service/{controllers → src/controllers}/http.controller.js.hbs +0 -0
- /package/templates/service/{controllers → src/controllers}/message.controller.js.hbs +0 -0
- /package/templates/service/{db → src/mysql.db}/migrations/01-init.js.hbs +0 -0
- /package/templates/service/{db → src/mysql.db}/migrations/02-{{lowerCase serviceName}}-service-init.js.hbs +0 -0
- /package/templates/service/{policies → src/policies}/{{serviceName}}.policy.js.hbs +0 -0
- /package/templates/service/{services/{{serviceName}}.service.js.hbs → src/services/mysql.{{serviceName}}.service.js.hbs} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { message, http, logger, db } from '@gnar-engine/core';
|
|
2
2
|
import { config } from './config.js';
|
|
3
3
|
import { messageHandlers } from './controllers/message.controller.js';
|
|
4
|
-
import { httpController as {{
|
|
4
|
+
import { httpController as {{lowerCase serviceName}}PlatformHttpController } from './controllers/http.controller.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Initialise service
|
|
@@ -9,11 +9,15 @@ import { httpController as {{pascalCase serviceName}}PlatformHttpController } fr
|
|
|
9
9
|
export const initService = async () => {
|
|
10
10
|
|
|
11
11
|
// Run migrations
|
|
12
|
-
|
|
12
|
+
if (config.db.type == 'mysql') {
|
|
13
|
+
db.migrations.runMigrations({config});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Run seeders
|
|
13
17
|
db.seeders.runSeeders({config});
|
|
14
18
|
|
|
15
19
|
// Import command handlers after the command bus is initialised
|
|
16
|
-
await import('./commands/{{
|
|
20
|
+
await import('./commands/{{lowerCase serviceName}}.handler.js');
|
|
17
21
|
// Add more handlers as needed
|
|
18
22
|
|
|
19
23
|
// Initialise and register message handlers
|
|
@@ -25,7 +29,7 @@ export const initService = async () => {
|
|
|
25
29
|
// Register http routes
|
|
26
30
|
await http.registerRoutes({
|
|
27
31
|
controllers: [
|
|
28
|
-
{{
|
|
32
|
+
{{lowerCase serviceName}}PlatformHttpController,
|
|
29
33
|
]
|
|
30
34
|
});
|
|
31
35
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { commands, logger, error } from '@gnar-engine/core';
|
|
2
|
-
import { auth } from '../services/authentication.service.js';
|
|
3
2
|
import { {{serviceName}} } from '../services/{{serviceName}}.service.js';
|
|
4
3
|
import { config } from '../config.js';
|
|
5
|
-
import { validate{{pascalCase serviceName}}
|
|
4
|
+
import { validate{{pascalCase serviceName}} } from '../schema/{{serviceName}}.schema.js';
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
/**
|
package/{bootstrap/services/agent/src/config.js → templates/service/src/mongodb.config.js.hbs}
RENAMED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const config = {
|
|
5
5
|
// service name
|
|
6
|
-
serviceName: '
|
|
6
|
+
serviceName: '{{serviceName}}Service',
|
|
7
7
|
|
|
8
8
|
// microservice | modular-monolith
|
|
9
9
|
architecture: process.env.GLOBAL_ARCHITECTURE || 'microservice',
|
|
@@ -14,39 +14,32 @@ export const config = {
|
|
|
14
14
|
allowedMethods: ['GET', 'POST', 'PUT', 'DELETE'],
|
|
15
15
|
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
16
16
|
rateLimiting: {
|
|
17
|
-
max:
|
|
18
|
-
timeWindow: '1
|
|
17
|
+
max: 5,
|
|
18
|
+
timeWindow: '1 minute',
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
|
|
22
22
|
// database
|
|
23
23
|
db: {
|
|
24
24
|
// type: mongodb | mysql
|
|
25
|
-
type: '
|
|
25
|
+
type: 'mongodb',
|
|
26
26
|
|
|
27
27
|
// MongoDB
|
|
28
|
-
connectionUrl: process.env.
|
|
28
|
+
connectionUrl: process.env.{{upperCase serviceName}}_MONGO_URL,
|
|
29
29
|
connectionArgs: {},
|
|
30
|
-
|
|
31
|
-
// MySQL
|
|
32
|
-
host: process.env.AGENT_MYSQL_HOST,
|
|
33
|
-
user: process.env.AGENT_MYSQL_USER,
|
|
34
|
-
password: process.env.AGENT_MYSQL_PASSWORD,
|
|
35
|
-
database: process.env.AGENT_MYSQL_DATABASE,
|
|
36
|
-
connectionLimit: 10,
|
|
37
|
-
queueLimit: 20,
|
|
38
|
-
maxRetries: 5
|
|
39
30
|
},
|
|
40
31
|
|
|
41
32
|
// message broker
|
|
42
33
|
message: {
|
|
43
34
|
url: process.env.RABBITMQ_URL,
|
|
44
|
-
queueName: '
|
|
35
|
+
queueName: '{{serviceName}}ServiceQueue',
|
|
45
36
|
prefetch: 20
|
|
46
37
|
},
|
|
47
38
|
|
|
48
|
-
|
|
39
|
+
webSockets: {
|
|
40
|
+
reconnectInterval: 5000,
|
|
41
|
+
maxInitialConnectionAttempts: 5
|
|
42
|
+
},
|
|
49
43
|
|
|
50
|
-
|
|
51
|
-
agent: 'chatgpt'
|
|
44
|
+
hashNameSpace: '{{uuid}}',
|
|
52
45
|
}
|
|
@@ -40,9 +40,15 @@ export const config = {
|
|
|
40
40
|
|
|
41
41
|
// message broker
|
|
42
42
|
message: {
|
|
43
|
+
url: process.env.RABBITMQ_URL,
|
|
43
44
|
queueName: '{{serviceName}}ServiceQueue',
|
|
44
45
|
prefetch: 20
|
|
45
46
|
},
|
|
46
47
|
|
|
48
|
+
webSockets: {
|
|
49
|
+
reconnectInterval: 5000,
|
|
50
|
+
maxInitialConnectionAttempts: 5
|
|
51
|
+
},
|
|
52
|
+
|
|
47
53
|
hashNameSpace: '{{uuid}}',
|
|
48
54
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { schema } from '@gnar-engine/core';
|
|
2
2
|
import { config } from '../config.js';
|
|
3
3
|
|
|
4
|
-
export const
|
|
5
|
-
schemaName: '
|
|
4
|
+
export const {{serviceName}}Schema = {
|
|
5
|
+
schemaName: '{{serviceName}}Service.{{serviceName}}Schema',
|
|
6
6
|
schema: {
|
|
7
7
|
type: 'object',
|
|
8
8
|
properties: {
|
|
@@ -14,4 +14,4 @@ export const AgentSchema = {
|
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
export const
|
|
17
|
+
export const validate{{pascalCase serviceName}} = schema.compile({{serviceName}}Schema);
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { db, logger } from '@gnar-engine/core';
|
|
2
|
+
import { ObjectId } from 'mongodb';
|
|
3
|
+
|
|
4
|
+
export const {{serviceName}} = {
|
|
5
|
+
|
|
6
|
+
// Get all {{lowerCasePlural serviceName}}
|
|
7
|
+
getAll: async () => {
|
|
8
|
+
try {
|
|
9
|
+
const items = await db.collection('{{lowerCasePlural serviceName}}').find().toArray();
|
|
10
|
+
return items;
|
|
11
|
+
} catch (error) {
|
|
12
|
+
logger.error("Error fetching {{lowerCasePlural serviceName}}:", error);
|
|
13
|
+
throw error;
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
// Create a {{lowerCase serviceName}}
|
|
18
|
+
create: async (data) => {
|
|
19
|
+
try {
|
|
20
|
+
const collection = db.collection('{{lowerCasePlural serviceName}}');
|
|
21
|
+
const result = await collection.insertOne(data);
|
|
22
|
+
return await collection.findOne({ _id: result.insertedId });
|
|
23
|
+
} catch (error) {
|
|
24
|
+
logger.error("Error creating {{lowerCase serviceName}}:", error);
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
// Get a {{lowerCase serviceName}} by ID
|
|
30
|
+
getById: async ({ id }) => {
|
|
31
|
+
try {
|
|
32
|
+
const collection = db.collection('{{lowerCasePlural serviceName}}');
|
|
33
|
+
const objectId = new ObjectId(id);
|
|
34
|
+
const item = await collection.findOne({ _id: objectId });
|
|
35
|
+
return item;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
logger.error("Error fetching {{lowerCase serviceName}}:", error);
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
// Update a {{lowerCase serviceName}}
|
|
43
|
+
update: async ({ id, updatedData }) => {
|
|
44
|
+
try {
|
|
45
|
+
const collection = db.collection('{{lowerCasePlural serviceName}}');
|
|
46
|
+
const objectId = new ObjectId(id);
|
|
47
|
+
const result = await collection.updateOne(
|
|
48
|
+
{ _id: objectId },
|
|
49
|
+
{ $set: updatedData }
|
|
50
|
+
);
|
|
51
|
+
return result.modifiedCount > 0;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
logger.error("Error updating {{lowerCase serviceName}}:", error);
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
// Delete a {{lowerCase serviceName}}
|
|
59
|
+
delete: async ({ id }) => {
|
|
60
|
+
try {
|
|
61
|
+
const collection = db.collection('{{lowerCasePlural serviceName}}');
|
|
62
|
+
const objectId = new ObjectId(id);
|
|
63
|
+
const result = await collection.deleteOne({ _id: objectId });
|
|
64
|
+
return result.deletedCount > 0;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
logger.error("Error deleting {{lowerCase serviceName}}:", error);
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# Dockerfile for Agent Service
|
|
2
|
-
FROM node:20-alpine
|
|
3
|
-
|
|
4
|
-
# Set the working directory
|
|
5
|
-
WORKDIR /usr/gnar_engine/app
|
|
6
|
-
|
|
7
|
-
# Define a global env var
|
|
8
|
-
ENV GLOBAL_SERVICE_BASE_DIR=/usr/gnar_engine/app/src/
|
|
9
|
-
|
|
10
|
-
# Copy package.json and package-lock.json
|
|
11
|
-
COPY ./services/agent/package*.json ./
|
|
12
|
-
|
|
13
|
-
# Install nodemon
|
|
14
|
-
RUN npm install -g nodemon
|
|
15
|
-
|
|
16
|
-
# Install app dependencies
|
|
17
|
-
RUN npm install
|
|
18
|
-
|
|
19
|
-
# Expose the port the service will run on
|
|
20
|
-
EXPOSE 3000
|
|
21
|
-
|
|
22
|
-
# Start the application
|
|
23
|
-
CMD ["nodemon", "--watch", "./gnar_engine", "./gnar_engine/app.js"]
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# Gnar MCP Notes
|
|
2
|
-
|
|
3
|
-
### Aims
|
|
4
|
-
|
|
5
|
-
- We don't want to provide all command implementations (with payload information) until we know what commands are required.
|
|
6
|
-
|
|
7
|
-
Step 1: Gather Facts
|
|
8
|
-
|
|
9
|
-
- All first prompts (no chatId provided) are 'gather facts'.
|
|
10
|
-
- This prompt will be augmented with the all service/model schemas and a list of all available commands e.g. userService.create, userService.update.
|
|
11
|
-
- From the client input the model should generate an action plan with an ordered list of the commands required, and also request the exact data required from the user to carry out the plan (based on the schemas provided in the augmented prompt).
|
|
12
|
-
|
|
13
|
-
Step 2: Confirm plan
|
|
14
|
-
|
|
15
|
-
- All further prompts (chatId provided) that do not have a 'confirmed plan' are 'confirm plan'.
|
|
16
|
-
- This prompt will be augmented with the all service/model schemas, a list of all available commands, a manifest containing the command implementations (including payload information) for each command in the most recently proposed action plan, the most recently proposed action plan itself, and a list of all previous user inputs and response texts.
|
|
17
|
-
- The model should determine from the resources provided if the action plan is accurate and if we have enough information, request conmfirmation from the user to action the request. If not we should request further information from the user until all information is provided. Should reassess the proposed plan based on user input and the command implementations provided in the prompt augmentation. If the plan is suitable, we have all the required information, and the user has confirmed that we can action the request, the model should include - actionPlanGoAhead = true in the response, and also the first command execution payload in the actionPlan.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// should we postback before actioning?
|
|
21
|
-
Step 3: Action plan loop
|
|
22
|
-
- Before returning back to the client - if the agent response has 'actionPlanGoAhead' = true, we should initalise the action plan execution loop
|
|
23
|
-
- Action Plan Execution Loop (foreach action plan command):
|
|
24
|
-
- The command will be triggered with the included payload.
|
|
25
|
-
- The result of the first command will be passed back to the agent with the system prompt, action plan, all messages, schemas, relevant command implementations.
|
|
26
|
-
- This prompt should confirm the payload for the next command in the action Plan.
|
|
27
|
-
|
|
28
|
-
- Upon the last command being executed, the model will be prompted to provide a text output to confirm the result of the action plan.
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "agent-service",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "LLM Agent microservice for Gnar Engine",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"start": "node ./src/app.js",
|
|
8
|
-
"start:dev": "nodemon --watch ./src ./src/app.js"
|
|
9
|
-
},
|
|
10
|
-
"dependencies": {
|
|
11
|
-
"@gnar-engine/core": "^1.0.1",
|
|
12
|
-
"openai": "5.13.1"
|
|
13
|
-
},
|
|
14
|
-
"author": "Gnar Software",
|
|
15
|
-
"license": "MIT"
|
|
16
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { message, http, logger, db, registerService } from '@gnar-engine/core';
|
|
2
|
-
import { config } from './config.js';
|
|
3
|
-
import { messageHandlers } from './controllers/message.controller.js';
|
|
4
|
-
import { httpController as AgentPlatformHttpController } from './controllers/http.controller.js';
|
|
5
|
-
import { manifestService } from './services/manifest.service.js';
|
|
6
|
-
import { Agent } from './services/agent.service.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Initialise service
|
|
10
|
-
*/
|
|
11
|
-
export const initService = async () => {
|
|
12
|
-
|
|
13
|
-
// Run migrations
|
|
14
|
-
db.migrations.runMigrations({config});
|
|
15
|
-
db.seeders.runSeeders({config});
|
|
16
|
-
|
|
17
|
-
// Import command handlers after the command bus is initialised
|
|
18
|
-
await import('./commands/agent.handler.js');
|
|
19
|
-
// Add more handlers as needed
|
|
20
|
-
|
|
21
|
-
// Initialise and register message handlers
|
|
22
|
-
await message.init({
|
|
23
|
-
config: config.message,
|
|
24
|
-
handlers: messageHandlers
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
// Register http routes
|
|
28
|
-
await http.registerRoutes({
|
|
29
|
-
controllers: [
|
|
30
|
-
AgentPlatformHttpController,
|
|
31
|
-
]
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
// Initialise agent client
|
|
35
|
-
await Agent.init();
|
|
36
|
-
|
|
37
|
-
// Start the HTTP server
|
|
38
|
-
await http.start();
|
|
39
|
-
|
|
40
|
-
// Register service with control service
|
|
41
|
-
await registerService();
|
|
42
|
-
|
|
43
|
-
// Start manifest generation poll
|
|
44
|
-
//setInterval(() => {
|
|
45
|
-
manifestService.generateServiceManifests();
|
|
46
|
-
//}, 3600);
|
|
47
|
-
|
|
48
|
-
logger.info('G n a r E n g i n e | Agent Service initialised successfully.');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
initService();
|
|
52
|
-
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { commands, logger } from '@gnar-engine/core';
|
|
2
|
-
import { Agent } from '../services/agent.service.js';
|
|
3
|
-
import { config } from '../config.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Prompt the LLM agent
|
|
8
|
-
*/
|
|
9
|
-
commands.register('agentService.prompt', async ({input, chatId, authUser}) => {
|
|
10
|
-
try {
|
|
11
|
-
logger.info('recieved input' + JSON.stringify(input));
|
|
12
|
-
let chatContextToStore = {};
|
|
13
|
-
|
|
14
|
-
const [manifests, resolvedChatId, chat] = await Promise.all([
|
|
15
|
-
// Get the manifests
|
|
16
|
-
commands.execute('controlService.getManifests'),
|
|
17
|
-
|
|
18
|
-
// Create a new chat if chatId is not provided
|
|
19
|
-
(async () => {
|
|
20
|
-
if (!chatId) {
|
|
21
|
-
return await Agent.createChat({
|
|
22
|
-
userId: '',
|
|
23
|
-
title: input.substring(0, 50),
|
|
24
|
-
sessionKey: input.sessionKey
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return chatId
|
|
29
|
-
})(),
|
|
30
|
-
|
|
31
|
-
// Retrieve existing chat if chatId is provided
|
|
32
|
-
(async () => {
|
|
33
|
-
if (chatId) {
|
|
34
|
-
return await Agent.getChat({chatId});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return null;
|
|
38
|
-
})()
|
|
39
|
-
]);
|
|
40
|
-
|
|
41
|
-
let preparedInput;
|
|
42
|
-
|
|
43
|
-
// Gather facts
|
|
44
|
-
if (!chatId) {
|
|
45
|
-
preparedInput = await Agent.prepareGatherFactsPrompt({inputText: input, manifests: manifests});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Prepare Plan
|
|
49
|
-
else if (chat) {
|
|
50
|
-
await logger.info('GOT HERE WITH CHAT: ' + JSON.stringify(chat));
|
|
51
|
-
preparedInput = await Agent.preparePlanPrompt({inputText: input, manifests: manifests, chat: chat});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Infer
|
|
55
|
-
let agentResponse = await Agent.infer({preparedInput});
|
|
56
|
-
logger.info('Agent response: ' + agentResponse);
|
|
57
|
-
agentResponse = JSON.parse(agentResponse);
|
|
58
|
-
|
|
59
|
-
// Collect context from response
|
|
60
|
-
chatContextToStore.actionPlan = agentResponse.actionPlan || null;
|
|
61
|
-
chatContextToStore.input = input;
|
|
62
|
-
chatContextToStore.responseText = agentResponse.responseText || null;
|
|
63
|
-
|
|
64
|
-
// Collect required command implementations from manifests to store for next time
|
|
65
|
-
if (agentResponse.commandsRequired) {
|
|
66
|
-
chatContextToStore.commandsManifest = [];
|
|
67
|
-
|
|
68
|
-
agentResponse.commandsRequired.forEach((commandRequired) => {
|
|
69
|
-
manifests.manifests.forEach((manifest) => {
|
|
70
|
-
//logger.info('got here ' + commandRequired + ' ' + JSON.stringify(manifest.manifest) );
|
|
71
|
-
if (manifest.manifest?.commandImplementations?.[commandRequired]) {
|
|
72
|
-
chatContextToStore.commandsManifest.push(manifest.manifest.commandImplementations[commandRequired]);
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
logger.info('Chat context to store: ' + JSON.stringify(chatContextToStore));
|
|
79
|
-
|
|
80
|
-
// Store chat messages
|
|
81
|
-
chatId = resolvedChatId;
|
|
82
|
-
Agent.createChatMessage({
|
|
83
|
-
chatId: chatId,
|
|
84
|
-
userName: authUser.username,
|
|
85
|
-
context: chatContextToStore
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// Plan execution loop
|
|
89
|
-
if (agentResponse.actionPlan) {
|
|
90
|
-
logger.info('Executing plan: ' + agentResponse.actionPlan);
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
let response = {
|
|
95
|
-
structuredResponse: agentResponse,
|
|
96
|
-
chatId: chatId
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
return response;
|
|
100
|
-
} catch (err) {
|
|
101
|
-
logger.error("Error handling LLM agent prompt: " + err);
|
|
102
|
-
throw err;
|
|
103
|
-
}
|
|
104
|
-
});
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { commands, logger } from '@gnar-engine/core';
|
|
2
|
-
import { authorise } from '../policies/agent.policy.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* HTTP controller
|
|
6
|
-
*/
|
|
7
|
-
export const httpController = {
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Prompt the agent
|
|
11
|
-
*/
|
|
12
|
-
agentPrompt: {
|
|
13
|
-
method: 'POST',
|
|
14
|
-
url: '/agent/prompt',
|
|
15
|
-
preHandler: async (request, reply) => authorise.agentPrompt(request, reply),
|
|
16
|
-
handler: async (request, reply) => {
|
|
17
|
-
logger.info('Received agent prompt request' + JSON.stringify(request.body));
|
|
18
|
-
const params = {
|
|
19
|
-
input: request.body.textInput,
|
|
20
|
-
chatId: request.body.chatId || '',
|
|
21
|
-
authUser: request.user
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
// Sanitize input (remove all JSON delimiters)
|
|
25
|
-
params.input = params.input.replace(/[\{\}\[\]\"\'\:\,]/g, '');
|
|
26
|
-
|
|
27
|
-
// execute
|
|
28
|
-
let response;
|
|
29
|
-
logger.info('params' + JSON.stringify(params));
|
|
30
|
-
try {
|
|
31
|
-
response = await commands.execute('prompt', params);
|
|
32
|
-
} catch (error) {
|
|
33
|
-
logger.error(error.message);
|
|
34
|
-
return reply.code(500).send({ error: error.message});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
logger.info('response is: ' + JSON.stringify(response));
|
|
38
|
-
|
|
39
|
-
// handle response
|
|
40
|
-
reply.code(200).send(response);
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { commands } from '@gnar-engine/core';
|
|
2
|
-
|
|
3
|
-
export const messageHandlers = {
|
|
4
|
-
|
|
5
|
-
getAgent: async (payload) => {
|
|
6
|
-
let result;
|
|
7
|
-
if (payload.data?.id) {
|
|
8
|
-
result = await commands.execute('getSingleAgent', {
|
|
9
|
-
id: payload.data.id
|
|
10
|
-
});
|
|
11
|
-
} else if (payload.data?.email) {
|
|
12
|
-
result = await commands.execute('getSingleAgent', {
|
|
13
|
-
email: payload.data.email
|
|
14
|
-
});
|
|
15
|
-
} else {
|
|
16
|
-
throw new Error('No Agent ID or email provided');
|
|
17
|
-
}
|
|
18
|
-
if (!result) {
|
|
19
|
-
throw new Error('Agent not found');
|
|
20
|
-
}
|
|
21
|
-
return { Agent: result };
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
getManyAgents: async (payload) => {
|
|
25
|
-
const results = await commands.execute('getManyAgents', {});
|
|
26
|
-
return { agents: results };
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
createAgent: async (payload) => {
|
|
30
|
-
const results = await commands.execute('createAgents', {
|
|
31
|
-
agents: [payload.data.Agent]
|
|
32
|
-
});
|
|
33
|
-
return { agents: results };
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
updateAgent: async (payload) => {
|
|
37
|
-
const result = await commands.execute('updateAgent', {
|
|
38
|
-
id: payload.data.id,
|
|
39
|
-
newAgentData: payload.data
|
|
40
|
-
});
|
|
41
|
-
return { Agent: result };
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
deleteAgent: async (payload) => {
|
|
45
|
-
await commands.execute('deleteAgent', {
|
|
46
|
-
id: payload.data.id
|
|
47
|
-
});
|
|
48
|
-
return { message: 'Agent deleted' };
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
};
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { logger, db } from '@gnar-engine/core';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Up
|
|
5
|
-
*/
|
|
6
|
-
export const up = async () => {
|
|
7
|
-
await initDatabaseTables();
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Down
|
|
12
|
-
*/
|
|
13
|
-
export const down = async () => {
|
|
14
|
-
await dropDatabaseTables();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Create all tables
|
|
19
|
-
*/
|
|
20
|
-
export const initDatabaseTables = async () => {
|
|
21
|
-
|
|
22
|
-
// Migrations table
|
|
23
|
-
logger.info("Creating migrations table");
|
|
24
|
-
const createMigrationsTableQuery = `
|
|
25
|
-
CREATE TABLE migrations (
|
|
26
|
-
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
27
|
-
name VARCHAR(255) NOT NULL UNIQUE,
|
|
28
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
29
|
-
)`;
|
|
30
|
-
await db.query(createMigrationsTableQuery);
|
|
31
|
-
|
|
32
|
-
// Seeders table
|
|
33
|
-
logger.info("Creating seeders table");
|
|
34
|
-
const createSeedersTableQuery = `
|
|
35
|
-
CREATE TABLE seeders (
|
|
36
|
-
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
37
|
-
name VARCHAR(255) NOT NULL UNIQUE,
|
|
38
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
39
|
-
)`;
|
|
40
|
-
await db.query(createSeedersTableQuery);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Drop all tables
|
|
45
|
-
*/
|
|
46
|
-
export const dropDatabaseTables = async () => {
|
|
47
|
-
logger.info('Dropping tables');
|
|
48
|
-
await db.query('DROP TABLE IF EXISTS migrations');
|
|
49
|
-
await db.query('DROP TABLE IF EXISTS seeders');
|
|
50
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { logger, db } from '@gnar-engine/core';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Up
|
|
5
|
-
*/
|
|
6
|
-
export const up = async () => {
|
|
7
|
-
logger.info('Creating table: agent-chats');
|
|
8
|
-
await db.query(`
|
|
9
|
-
CREATE TABLE agent_chats (
|
|
10
|
-
id CHAR(36) PRIMARY KEY,
|
|
11
|
-
user_id CHAR(36) NOT NULL,
|
|
12
|
-
title VARCHAR(255) NOT NULL,
|
|
13
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
14
|
-
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
15
|
-
)
|
|
16
|
-
`);
|
|
17
|
-
|
|
18
|
-
logger.info('Creating table: agent-chat-messages');
|
|
19
|
-
await db.query(`
|
|
20
|
-
CREATE TABLE agent_chat_messages (
|
|
21
|
-
id CHAR(36) PRIMARY KEY,
|
|
22
|
-
chat_id CHAR(36) NOT NULL,
|
|
23
|
-
user_name VARCHAR(255) NOT NULL,
|
|
24
|
-
context MEDIUMTEXT NOT NULL,
|
|
25
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
26
|
-
)
|
|
27
|
-
`);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Down
|
|
32
|
-
*/
|
|
33
|
-
export const down = async () => {
|
|
34
|
-
logger.info('Dropping table: agents');
|
|
35
|
-
await db.query('DROP TABLE IF EXISTS agents');
|
|
36
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { config } from '../config.js';
|
|
2
|
-
|
|
3
|
-
export const authorise = {
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Authorise agent prompt
|
|
7
|
-
*/
|
|
8
|
-
agentPrompt: async (request, reply) => {
|
|
9
|
-
if (!request.user || request.user.role !== 'service_admin') {
|
|
10
|
-
reply.code(403).send({error: 'not authorised'});
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
}
|