@mongoosejs/studio 0.2.6 → 0.2.8

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.
@@ -11,7 +11,7 @@ const ExecuteScriptParams = new Archetype({
11
11
  },
12
12
  chatMessageId: {
13
13
  $type: mongoose.Types.ObjectId,
14
- $required: true,
14
+ $required: true
15
15
  },
16
16
  script: {
17
17
  $type: 'string'
@@ -0,0 +1,54 @@
1
+ 'use strict';
2
+
3
+ const Archetype = require('archetype');
4
+ const authorize = require('../../authorize');
5
+ const callLLM = require('../../integrations/callLLM');
6
+ const getModelDescriptions = require('../../helpers/getModelDescriptions');
7
+
8
+ const CreateChatMessageParams = new Archetype({
9
+ model: {
10
+ $type: 'string',
11
+ $required: true
12
+ },
13
+ content: {
14
+ $type: 'string',
15
+ $required: true
16
+ },
17
+ documentData: {
18
+ $type: 'string'
19
+ },
20
+ roles: {
21
+ $type: ['string']
22
+ }
23
+ }).compile('CreateChatMessageParams');
24
+
25
+ module.exports = ({ db, options }) => async function createChatMessage(params) {
26
+ const { model, content, documentData, roles } = new CreateChatMessageParams(params);
27
+
28
+ await authorize('Model.createChatMessage', roles);
29
+
30
+ const Model = db.models[model];
31
+ if (Model == null) {
32
+ throw new Error(`Model ${model} not found`);
33
+ }
34
+
35
+ const modelDescriptions = getModelDescriptions({ models: { [Model.modelName]: Model } });
36
+ const context = [
37
+ modelDescriptions,
38
+ 'Current draft document:\n' + (documentData || '')
39
+ ].join('\n\n');
40
+ const system = systemPrompt + '\n\n' + context + (options?.context ? '\n\n' + options.context : '');
41
+
42
+ const llmMessages = [{ role: 'user', content: [{ type: 'text', text: content }] }];
43
+ const res = await callLLM(llmMessages, system, options);
44
+
45
+ return { text: res.text };
46
+ };
47
+
48
+ const systemPrompt = `
49
+ You are a helpful assistant that drafts MongoDB documents for the user.
50
+
51
+ Use the model description and the current draft document to refine the user's intent.
52
+
53
+ Return only the updated document body as a JavaScript object literal. Do not use Markdown or code fences.
54
+ `.trim();
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  exports.addField = require('./addField');
4
+ exports.createChatMessage = require('./createChatMessage');
4
5
  exports.createDocument = require('./createDocument');
5
6
  exports.deleteDocument = require('./deleteDocument');
6
7
  exports.deleteDocuments = require('./deleteDocuments');
@@ -12,5 +13,6 @@ exports.getDocumentsStream = require('./getDocumentsStream');
12
13
  exports.getCollectionInfo = require('./getCollectionInfo');
13
14
  exports.getIndexes = require('./getIndexes');
14
15
  exports.listModels = require('./listModels');
16
+ exports.streamChatMessage = require('./streamChatMessage');
15
17
  exports.updateDocument = require('./updateDocument');
16
18
  exports.updateDocuments = require('./updateDocuments');
@@ -0,0 +1,58 @@
1
+ 'use strict';
2
+
3
+ const Archetype = require('archetype');
4
+ const authorize = require('../../authorize');
5
+ const streamLLM = require('../../integrations/streamLLM');
6
+ const getModelDescriptions = require('../../helpers/getModelDescriptions');
7
+
8
+ const StreamChatMessageParams = new Archetype({
9
+ model: {
10
+ $type: 'string',
11
+ $required: true
12
+ },
13
+ content: {
14
+ $type: 'string',
15
+ $required: true
16
+ },
17
+ documentData: {
18
+ $type: 'string'
19
+ },
20
+ roles: {
21
+ $type: ['string']
22
+ }
23
+ }).compile('StreamChatMessageParams');
24
+
25
+ module.exports = ({ db, options }) => async function* streamChatMessage(params) {
26
+ const { model, content, documentData, roles } = new StreamChatMessageParams(params);
27
+
28
+ await authorize('Model.streamChatMessage', roles);
29
+
30
+ const Model = db.models[model];
31
+ if (Model == null) {
32
+ throw new Error(`Model ${model} not found`);
33
+ }
34
+
35
+ const modelDescriptions = getModelDescriptions({ models: { [Model.modelName]: Model } });
36
+ const context = [
37
+ modelDescriptions,
38
+ 'Current draft document:\n' + (documentData || '')
39
+ ].join('\n\n');
40
+ const system = systemPrompt + '\n\n' + context + (options?.context ? '\n\n' + options.context : '');
41
+
42
+ const llmMessages = [{ role: 'user', content: [{ type: 'text', text: content }] }];
43
+ const textStream = streamLLM(llmMessages, system, options);
44
+
45
+ for await (const textPart of textStream) {
46
+ yield { textPart };
47
+ }
48
+
49
+ return {};
50
+ };
51
+
52
+ const systemPrompt = `
53
+ You are a helpful assistant that drafts MongoDB documents for the user.
54
+
55
+ Use the model description and the current draft document to refine the user's intent.
56
+
57
+ Return only the updated document body as a JavaScript object literal. Do not use Markdown or code fences.
58
+ `.trim();
@@ -23,6 +23,7 @@ const actionsToRequiredRoles = {
23
23
  'Model.getDocumentsStream': ['owner', 'admin', 'member', 'readonly'],
24
24
  'Model.getIndexes': ['owner', 'admin', 'member', 'readonly'],
25
25
  'Model.listModels': ['owner', 'admin', 'member', 'readonly'],
26
+ 'Model.streamChatMessage': ['owner', 'admin', 'member', 'readonly'],
26
27
  'Model.updateDocuments': ['owner', 'admin', 'member']
27
28
  };
28
29
 
@@ -17,8 +17,16 @@ const formatSchemaTypeInstance = schemaType => {
17
17
  return schemaType.instance;
18
18
  };
19
19
 
20
+ const formatEnum = schemaType => {
21
+ if (!schemaType.options?.enum) {
22
+ return '';
23
+ }
24
+ return ` (enum: ${JSON.stringify(schemaType.options.enum)})`;
25
+ };
26
+
20
27
  const formatSchemaPath = (path, schemaType) => `- ${path}: ${formatSchemaTypeInstance(schemaType)}` +
21
28
  formatRef(schemaType) +
29
+ formatEnum(schemaType) +
22
30
  (schemaType.schema ? formatNestedSchema(schemaType) : '');
23
31
 
24
32
  const listModelPaths = Model => [