json-object-editor 0.10.425 → 0.10.430

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.
@@ -28,7 +28,7 @@ var apps = function(){
28
28
  var default_schemas = JOE.webconfig.default_schemas;
29
29
  return{
30
30
  joe:{
31
- title:'Platform',
31
+ title:'JOE Platform',
32
32
  info:'This is the master Data Model Management System (DMMS) admin page. It has access to all of your schemas and datasets.',
33
33
  description:'JOE is the Json Object Editor. The Platform app has access to all your schemas and datasets.',
34
34
  plugins:['auth.js','formBuilder.js','reportbuilder.js','callbackTester.js','memberRegistry.js','awsConnect.js','notifier.js','calendar.js','inventory.js','money.js'],
package/server/init.js CHANGED
@@ -62,7 +62,7 @@ var app = function(config){
62
62
 
63
63
  });
64
64
  }
65
- ['Apps','Schemas','Mongo','MySQL','Comments'].map(function(m){
65
+ ['Apps','Schemas','Mongo','MySQL','Comments','Utils'].map(function(m){
66
66
  initializeModule(m);
67
67
  });
68
68
  //initializeModule('Apps');
@@ -495,7 +495,8 @@ function Apps(){
495
495
  return app;
496
496
  }
497
497
  this.loadPlugin = function(p){
498
- logit(moduleName+'loading plugin '+p);
498
+ //logit(moduleName+'loading plugin '+p);
499
+ console.log(JOE.Utils.color('[plugin]', 'plugin'), 'loaded: '+p);
499
500
  var plugin;
500
501
  if(p.indexOf('.js') == -1){p+= '.js';}
501
502
  try{
@@ -16,6 +16,9 @@ var os = require('os');
16
16
  const $J = require('./UniversalShorthand');
17
17
  var rd = require('renderizer')({templatesDir:path.resolve(JOE.joedir,JOE.webconfig.templatesDir)});
18
18
 
19
+ function coloredLog(message) {
20
+ console.log(JOE.Utils.color('[server]', 'module'), message);
21
+ }
19
22
  var authBool = JOE.isAuthorized = function(req,res){
20
23
  var users = (JOE.Data && JOE.Data.user) || [];
21
24
 
@@ -140,7 +143,23 @@ server.get(['/API/user/:method'],auth,function(req,res,next){
140
143
  res.jsonp({logout:true});
141
144
  return next();
142
145
  break;
143
-
146
+ case 'apps':
147
+ logit('getting apps for '+req.User.name);
148
+ userApps = [];
149
+ if (req.User.apps && req.User.apps.length) {
150
+ req.User.apps.map(function (app) {
151
+ if (JOE.Apps.cache[app]) {
152
+ userApps.push({
153
+ name: app,
154
+ title: JOE.Apps.cache[app].title,
155
+ description: JOE.Apps.cache[app].description
156
+ });
157
+ }
158
+ });
159
+ }
160
+ res.jsonp({userApps});
161
+ return;//return next();
162
+ break;
144
163
  }
145
164
  }
146
165
 
@@ -711,12 +730,17 @@ server.get(['/JOE/','/JOE/:appname'],auth,function(req,res,next){
711
730
  }
712
731
 
713
732
  //var collections = [];
714
-
733
+ let uappsObj = [];
734
+ USER.apps.map(a=>{
735
+ let aa = Apps[a]||{};
736
+ uappsObj.push({name:a,title:aa.title,description:aa.description});
737
+ });
715
738
  var payload = {
716
739
  APPNAME:currentApp.title || appname,
717
740
  APPINFO:JSON.stringify(stringFunctions(currentApp)),
718
741
  APPS:apps.join(','),
719
742
  USERAPPS:(USER.apps||apps||[]).join(','),
743
+ USERAPPSOBJ:JSON.stringify(uappsObj),
720
744
  webconfig:JOE.webconfig,
721
745
  settings:settings,
722
746
  JOEPATH:JOE.webconfig.joepath,
@@ -761,21 +785,21 @@ server.get(['/RENDER/:contentType/:templateName'],function(req,res){
761
785
 
762
786
  JOE.webDir = webDir = JOE.appDir+'/'+JOE.webconfig.webDir+'/';
763
787
  JOE.Utils.setupFileFolder(webDir,'web');
764
-
788
+ coloredLog('listening on '+JOE.webconfig.port);
765
789
 
766
790
 
767
791
  server.use('/',express.static(JOE.webDir));
768
792
 
769
793
  http.listen(JOE.webconfig.port,function(){
770
794
  //console.log('joe listening on '+JOE.webconfig.port);
771
- console.log(JOE.Utils.color('[server]','module')+' on '+JOE.webconfig.port);
795
+ coloredLog('using webDir: '+JOE.webDir);
772
796
  });
773
797
  JOE.httpServer = http;
774
798
  var httpsPort = JOE.webconfig.httpsPort;
775
799
  if(httpsPort){
776
800
  var httpsServer = https.Server({key: JOE.Pem.serviceKey, cert: JOE.Pem.certificate}, server);
777
801
  httpsServer.listen(httpsPort);
778
- console.log(JOE.Utils.color('[server]','module')+' https on '+httpsPort);
802
+ coloredLog(' https on '+httpsPort);
779
803
  JOE.httpsServer = httpsServer;
780
804
  // pem.createCertificate({selfSigned:true}, function(err, keys){
781
805
  // if(err){
@@ -21,8 +21,7 @@ function UniversalShorthand(){
21
21
  if(items){
22
22
  callback && callback(items);
23
23
  return items;
24
- }
25
-
24
+ }
26
25
  }
27
26
  this.schema = function(schemaname,callback){
28
27
  self._usages.schema++;
@@ -174,6 +174,68 @@ var utils = function(){
174
174
  }
175
175
  return finalItems;
176
176
  }
177
+ this.flattenObject = function(id, options = {}) {
178
+ const { recursive = true, depth = 1, visited = new Set() } = options;
179
+
180
+ let object = null;
181
+
182
+ if (id) {
183
+ object = $J.get(id);
184
+ }
185
+
186
+ if (!object) return null;
187
+
188
+ const flattened = {};
189
+ const currentId = object._id || object.id;
190
+ if (currentId) visited.add(currentId);
191
+
192
+ for (const [field, val] of Object.entries(object)) {
193
+ if (val === undefined || val === null) continue;
194
+ if (field == '_id'){
195
+ flattened[field] = val;
196
+ continue;
197
+ }
198
+ if(field == 'password'){
199
+ flattened[field] = '********';
200
+ continue;
201
+
202
+ }
203
+ if(field =="status"){
204
+ flattened[field] = $J.get(val);
205
+ continue
206
+ }
207
+ if (typeof val === 'string' && $c.isCuid(val) && recursive && depth > 0) {
208
+ if (!visited.has(val)) {
209
+ const expanded = JOE.Utils.flattenObject(val, {
210
+ recursive,
211
+ depth: depth - 1,
212
+ visited: new Set(visited)
213
+ });
214
+ flattened[field] = expanded || val;
215
+ } else {
216
+ flattened[field] = val;
217
+ }
218
+ }
219
+ else if (Array.isArray(val) && val.every(v => typeof v === 'string' && $c.isCuid(v)) && recursive && depth > 0) {
220
+ flattened[field] = val.map(refId => {
221
+ if (!visited.has(refId)) {
222
+ const expanded = JOE.Utils.flattenObject(refId, {
223
+ recursive,
224
+ depth: depth - 1,
225
+ visited: new Set(visited)
226
+ });
227
+ return expanded || refId;
228
+ }
229
+ return refId;
230
+ });
231
+ }
232
+ else {
233
+ flattened[field] = val;
234
+ }
235
+ }
236
+
237
+ return flattened;
238
+ };
177
239
 
178
240
  return this;
179
241
  };
@@ -1,5 +1,6 @@
1
1
  var schema = {
2
2
  title: "Ai Conversation | ${name}",
3
+ display:'Ai Convo',
3
4
  info: "Tracks AI conversations across users, assistants, and external members, storing only summaries for performance.",
4
5
  methods:{
5
6
  chatSpawner:async function(object_id){
@@ -13,11 +14,22 @@ var schema = {
13
14
  "info",
14
15
 
15
16
  { section_start: "participants", display: "Participants", collapsed: false },
16
- { name: "user", type: "objectReference", values: "user", display: "JOE User" },
17
+ { name: "user", type: "select", values: "user", display: "JOE User", comment: "Select the JOE user who initiated this conversation.",width:'50%'},
18
+
19
+ {name:'assistant',type:"select",values:'ai_assistant',display:'AI Assistant',width:'50%',
20
+ comment:'Select the AI assistant to use for this conversation.',default:function(){
21
+ try{
22
+ var defAi = Ai.getDefaultAssistant();
23
+ return defAi._id;
24
+ }catch(e){
25
+ console.log('Error getting default assistant',e);
26
+ }
27
+ },
28
+ },
17
29
  { name: "members", type: "objectReference", values: "members", display: "External Members"},
18
- { name: "assistants", type: "group", cssClass:"ai-options", template:function(ass,curObj){
19
- return `${ass.name} || ${curObj.name}`;
20
- }, values: function() { return _joe.getDataset('ai_assistant'); }, display: "Assistants", cols:2 },
30
+ // { name: "assistants", type: "group", cssClass:"ai-options", template:function(ass,curObj){
31
+ // return `${ass.name} || ${curObj.name}`;
32
+ // }, values: function() { return _joe.getDataset('ai_assistant'); }, display: "Assistants", cols:2 },
21
33
  { section_end: "participants" },
22
34
 
23
35
  { section_start: "thread", display: "Thread", collapsed: true },
@@ -28,18 +40,11 @@ var schema = {
28
40
  { name: "summary", type: "wysiwyg", display: "Conversation Summary", height: "300px", comment: "Auto-generated after key points or closing." },
29
41
  { section_end: "summary" },
30
42
 
31
- { section_start: "linked", display: "Linked Objects", collapsed: true },
32
- { name: "linked_objects", type: "objectlist", display: "Linked Objects", fields: [
33
- { name: "schema", type: "text", display: "Schema" },
34
- { name: "object_id", type: "text", display: "Object ID" }
35
- ]
36
- },
37
- { section_end: "linked" },
38
43
 
39
44
  { section_start: "system", collapsed: true },
40
45
  "_id",
41
46
  "created",
42
- "updated",
47
+ "joeUpdated",
43
48
  "itemtype",
44
49
  { section_end: "system" },
45
50
 
@@ -49,7 +54,7 @@ var schema = {
49
54
  {
50
55
  name: "openChat",
51
56
  type: "button",
52
- display: "Open Chat",
57
+ display: "Continue Conversation",
53
58
  icon:"ai_assistant",
54
59
  onclick2:function(object){
55
60
  if (!object || !object._id) return '';
@@ -59,14 +64,18 @@ var schema = {
59
64
  if (!object || !object._id) return '';
60
65
  return `_joe.schemas.ai_conversation.methods.chatSpawner('${object._id}');`;
61
66
  },
67
+
62
68
  },
69
+ {name:'context_objects',type:"objectReference", locked:true,values:function(obj,prop){
70
+ return JOE.getData();
71
+ }},
63
72
  { sidebar_end: "right" },
64
73
 
65
74
  ];
66
75
  },
67
76
 
68
77
  idprop: "_id",
69
- sorter: ["-created"],
78
+ sorter: ["!created"],
70
79
  };
71
80
 
72
81
  module.exports = schema;
@@ -0,0 +1,84 @@
1
+ // Joe AI Tool Schema
2
+ // This schema defines reusable tools for OpenAI Assistants and Chat Completions.
3
+ // Each tool includes a JSON schema for function calling and an executable code block.
4
+
5
+ var schema = {
6
+ title: "Ai Tool | ${name}",
7
+ display: "Ai Tool",
8
+ info: "Reusable Ai tool function for OpenAI tool calling and local execution.",
9
+ //menuicon: `<svg viewBox="0 0 24 24"><path d="M3 6h18M3 12h18M3 18h18"/></svg>`,
10
+
11
+ listView: {
12
+ title: '<joe-title>${name}</joe-title><joe-subtitle>${info}</joe-subtitle>',
13
+ listWindowTitle: 'Ai Tools'
14
+ },
15
+ methods:{
16
+ updateToolProperties:function(propObj){
17
+ //get the current tool properties as json
18
+ // set the tool_properties.name to the passed current objects tool_id
19
+ let rawProps = _jco(true).tool_properties ||"{}";
20
+ var toolProperties = eval('('+rawProps+')')||{};
21
+ toolProperties.name = propObj.name;
22
+ _joe.Fields.set('tool_properties',JSON.stringify(toolProperties,'\n','\t'));
23
+
24
+ }
25
+ },
26
+ fields: function() {
27
+ return [
28
+ "name",
29
+ "info", // Unique identifier
30
+ "description", // Short tool description
31
+ {name:'tool_id', type:'text', display:'Tool ID', comment:'Unique identifier for the tool. Used in OpenAI function calling.',onblur:"_joe.schemas.ai_tool.methods.updateToolProperties({name:this.value});"},
32
+ { section_start: "schema", display: "OpenAI Tool Schema" },
33
+ {
34
+ name: "tool_properties",
35
+ type: "code",
36
+ display: "Tool Properties (OpenAI format)",
37
+ height: "300px",
38
+ comment:
39
+ `<div>Define the tool funcitonal properties as used in OpenAI tool calling.</div>
40
+ <pre>{
41
+ "type": "function",
42
+ "name": "get_weather",
43
+ "description": "Get current temperature for provided coordinates in celsius.",
44
+ "parameters": {
45
+ "type": "object",
46
+ "properties": {
47
+ "latitude": { "type": "number" },
48
+ "longitude": { "type": "number" }
49
+ },
50
+ "required": ["latitude", "longitude"],
51
+ "additionalProperties": false
52
+ },
53
+ "strict": true
54
+ }</pre>`
55
+ },
56
+ { section_end: "schema" },
57
+
58
+ { section_start: "execution", display: "Server Execution" },
59
+ {
60
+ name: "server_code",
61
+ type: "code",
62
+ display: "Code to Execute (Node.js async)",
63
+ height: "300px",
64
+ comment: "Use `args` as input. Return a string, object, or promise.<br/>e.g. <code>return await joe.search(args.dataset, args.query);</code>"
65
+ },
66
+ { section_end: "execution" },
67
+
68
+ { section_start: "meta", collapsed: true },
69
+ "tags",
70
+ "datasets",
71
+ { section_end: "meta" },
72
+
73
+ { section_start: "system", collapsed: true },
74
+ "_id",
75
+ "created",
76
+ "itemtype",
77
+ { section_end: "system" }
78
+ ];
79
+ },
80
+
81
+ idprop: "_id"
82
+ };
83
+
84
+ module.exports = schema;