json-object-editor 0.10.650 → 0.10.654

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.
@@ -1,5 +1,6 @@
1
1
  var schema = {
2
2
  title : 'Ai Response | ${name}',
3
+ display:'AI Response',
3
4
  info:"An ai response from openai etc",
4
5
  summary:{
5
6
  description:'Stored AI response objects generated from ai_prompt and the chatgpt plugin.',
@@ -29,9 +30,13 @@ var schema = {
29
30
  { name:'model_used', type:'string' },
30
31
  { name:'response_type', type:'string' },
31
32
  { name:'response', type:'string' },
33
+ { name:'response_json', type:'object' },
32
34
  { name:'response_keys', type:'string', isArray:true },
33
35
  { name:'response_id', type:'string' },
34
36
  { name:'usage', type:'object' },
37
+ { name:'used_openai_file_ids', type:'string', isArray:true },
38
+ // { name:'creator_type', type:'string', enumValues:['user','ai_assistant'] },
39
+ // { name:'creator_id', type:'string' },
35
40
  { name:'tags', type:'string', isArray:true, isReference:true, targetSchema:'tag' },
36
41
  { name:'joeUpdated', type:'string', format:'date-time' },
37
42
  { name:'created', type:'string', format:'date-time' }
@@ -61,18 +66,131 @@ var schema = {
61
66
  },
62
67
  listWindowTitle: 'Ai Responses'
63
68
  },
64
- subsets: function(){
65
- return _joe.Filter.Options.tags({group:true,collapsed:false}).concat(_joe.getDataset('ai_prompt').map(prompt => {
66
- var color = prompt.status && $J.get(prompt.status,'status').color;
67
- return {
68
- name: prompt.name,
69
- id: prompt._id,
70
- filter: { ai_prompt: prompt._id },
71
- stripecolor: color || null // optional
72
- };
73
- }))
74
- },
69
+ subsets: function(a,b,c){
70
+ var subsets = [];
71
+ // Base subsets: tag-based and by ai_prompt
72
+ var subsets = subsets.concat(
73
+ _joe.getDataset('ai_prompt').map(function(prompt){
74
+ var color = prompt.status && $J.get(prompt.status,'status').color;
75
+ return {
76
+ name: prompt.name,
77
+ id: prompt._id,
78
+ filter: { ai_prompt: prompt._id },
79
+ stripecolor: color || null // optional
80
+ };
81
+ })
82
+ );
75
83
 
84
+ // Additional subset: "Generated Thoughts" – detect from raw JSON
85
+ // We look inside response_json for proposed_thoughts / thoughts arrays.
86
+ try{
87
+ var ds = _joe.getDataset('ai_response') || [];
88
+ var ids = [];
89
+ ds.map(function(r){
90
+ var j = r && r.response_json;
91
+ if (!j) { return; }
92
+ if (Array.isArray(j.proposed_thoughts) && j.proposed_thoughts.length) {
93
+ ids.push(r._id);
94
+ return;
95
+ }
96
+ if (Array.isArray(j.thoughts) && j.thoughts.length) {
97
+ ids.push(r._id);
98
+ }
99
+ });
100
+ if (ids.length) {
101
+ subsets.push({
102
+ name: 'Generated Thoughts',
103
+ id: 'generated_thoughts',
104
+ filter: { _id: { $in: ids } },
105
+ stripecolor: _joe.Colors.ai
106
+ });
107
+ }
108
+ }catch(_e){ }
109
+ //add status subsets
110
+ subsets = subsets.concat(_joe.Filter.Options.status({group:'status'}));
111
+ return subsets;
112
+ },
113
+ stripeColor:function(air){
114
+ if(air.response_json && air.response_json.proposed_thoughts){
115
+ return {color:_joe.Colors.ai,title:'Proposed '+air.response_json.proposed_thoughts.length+' Thoughts'};
116
+ }
117
+ return null;
118
+ },
119
+ bgColor:function(air){//status color
120
+ if(air.status){
121
+ var status = _joe.getDataItem(air.status,'status');
122
+ if(status && status.color){
123
+ return {color:status.color,title:status.name};
124
+ }
125
+ }
126
+ return null;
127
+ },
128
+ filters:function(){
129
+ var filters = [];
130
+ // Tag filters
131
+ filters = filters.concat(
132
+ _joe.Filter.Options.tags({group:'tags',untagged:true,collapsed:true})
133
+ );
134
+ // creator_type simple value grouping
135
+ // try{
136
+ // filters = filters.concat(
137
+ // _joe.Filter.Options.getDatasetPropertyValues('ai_response','creator_type',{ group: 'creator_type', collapsed: true })
138
+ // );
139
+ // }catch(_e){}
140
+ // // creator_id filters with human-readable names
141
+ // try{
142
+ // var dataset = _joe.getDataset('ai_response') || [];
143
+ // var byCreator = {};
144
+ // dataset.map(function(r){
145
+ // if(!r.creator_id){ return; }
146
+ // var key = r.creator_type+':'+r.creator_id;
147
+ // if(!byCreator[key]){
148
+ // var name = r.creator_id;
149
+ // if(r.creator_type === 'user' && _joe.Data.user){
150
+ // var u = _joe.Data.user.find(function(x){ return x && x._id === r.creator_id; });
151
+ // if(u){ name = u.fullname || u.name || u.email || u._id; }
152
+ // }else if(r.creator_type === 'ai_assistant' && _joe.Data.ai_assistant){
153
+ // var a = _joe.Data.ai_assistant.find(function(x){ return x && x._id === r.creator_id; });
154
+ // if(a){ name = a.name || a._id; }
155
+ // }
156
+ // byCreator[key] = {
157
+ // name: name,
158
+ // filter: { creator_type: r.creator_type, creator_id: r.creator_id }
159
+ // };
160
+ // }
161
+ // });
162
+ // var keys = Object.keys(byCreator);
163
+ // if(keys.length){
164
+ // filters.push({ group_start:'creator', collapsed:true });
165
+ // keys.sort(function(a,b){
166
+ // var na = byCreator[a].name.toLowerCase();
167
+ // var nb = byCreator[b].name.toLowerCase();
168
+ // if(na>nb) return 1;
169
+ // if(na<nb) return -1;
170
+ // return 0;
171
+ // }).map(function(k){
172
+ // filters.push({
173
+ // name: byCreator[k].name,
174
+ // filter: byCreator[k].filter
175
+ // });
176
+ // });
177
+ // filters.push({ group_end:'creator' });
178
+ // }
179
+ // }catch(_e){}
180
+ return filters;
181
+ },
182
+ itemExpander:function(air){
183
+ if(air.response_json && air.response_json.proposed_thoughts){
184
+ //list proposed thoughts in html with header "Proposed Thoughts"
185
+ var html = `<joe-card><joe-title>Proposed Thoughts</joe-title>`;
186
+ air.response_json.proposed_thoughts.map(thought=>{
187
+ html += `<joe-subtitle>${thought.statement}</joe-subtitle><br/>`;
188
+ });
189
+ html += `</joe-card>`;
190
+ return html;
191
+ }
192
+ return _joe.schemas.thought.methods.listThoughts(air);
193
+ },
76
194
  sorter:['!created','name'],
77
195
  checkChanges:false,
78
196
  fields:[
@@ -83,7 +201,7 @@ var schema = {
83
201
  return $J.search({_id:{$in:air.referenced_objects}});
84
202
  },display:'Referenced Objects',locked:true},
85
203
  {name:'generated_thoughts',type:'objectReference',width:'50%',values:function(air,orList){
86
- return $J.search({_id:{$in:air.generated_thoughts||[]},itemtype:'thought'});
204
+ return $J.search({source_ai_response:air._id,itemtype:'thought'});
87
205
  },display:'Generated Thoughts',locked:true},
88
206
  {name:'user_prompt', display:'Sent User Prompt',comment:"The input sent by the user after all processing",locked:true,type:'rendering'},
89
207
 
@@ -98,17 +216,53 @@ var schema = {
98
216
 
99
217
  //{name:'params', type:'rendering', locked:true},
100
218
  {section_start:'response',collapsed:false},
101
- {name:'response_type',type:'text',display:'Response Type',
102
- placeholder:'(a code for the responsetype)',locked:true,width:'50%',condition:function(v){
219
+ {
220
+ name:'response_type',
221
+ type:'text',
222
+ display:'Response Type',
223
+ placeholder:'(a code for the responsetype)',
224
+ locked:true,
225
+ width:'50%',
226
+ condition:function(v){
103
227
  return v.length > 0;
104
- }},
105
-
106
- {name:'response', type:'rendering', locked:true,height:'500px'},
228
+ }
229
+ },
230
+ {name:'response', type:'rendering', locked:true, height:'500px'},
231
+ {
232
+ name:'response_json',
233
+ type:'content',
234
+ display:'Parsed Response (JSON)',
235
+ locked:true,
236
+ run:function(air){
237
+ if (!air || !air.response_json) { return ''; }
238
+ try{
239
+ var json = JSON.stringify(air.response_json, null, 2);
240
+ // basic HTML escape for safety
241
+ json = String(json)
242
+ .replace(/&/g,'&amp;')
243
+ .replace(/</g,'&lt;')
244
+ .replace(/>/g,'&gt;');
245
+ return '<pre style="white-space:pre-wrap; max-height:260px; overflow:auto;">'+json+'</pre>';
246
+ }catch(e){
247
+ return '<pre>'+String(air.response_json)+'</pre>';
248
+ }
249
+ }
250
+ },
107
251
  {name:'response_keys', type:'text', locked:true,display:'Response Keys'},
108
252
  {name:'response_id', type:'text', display:'openAI response ID',locked:true},
253
+ {name:'used_openai_file_ids', type:'content', display:'OpenAI File IDs (Used)', locked:true, run:function(air){
254
+ var ids = air && air.used_openai_file_ids;
255
+ if(!ids || !ids.length){ return '<joe-subtext>None</joe-subtext>'; }
256
+ return ids.map(function(id){ return '<joe-subtext>'+id+'</joe-subtext>'; }).join('');
257
+ }},
258
+
109
259
  {section_end:'response'},
110
260
  {sidebar_start:'right', collapsed:false},
261
+ // {section_start:'creator'},
262
+ // 'creator_type','creator_id',
263
+ // {section_end:'creator'},
111
264
  {section_start:'workflow'},
265
+ 'status',
112
266
  'tags',
113
267
  {section_end:'workflow'},
114
268
  {section_start:'tokens'},
@@ -67,7 +67,15 @@ var schema = {
67
67
  return false;
68
68
 
69
69
  },
70
- subsets:function(){
70
+ subsets:function(){//active, inactive, terminal, default
71
+ return [
72
+ {name:'active',filter:{active:true}},
73
+ {name:'inactive',filter:{inactive:true}},
74
+ {name:'terminal',filter:{terminal:true}},
75
+ {name:'default',filter:{default:true}}
76
+ ];
77
+ },
78
+ filters:function(){
71
79
  var schemas = [];
72
80
  var subs = [];
73
81
  _joe.current.list.map(function(status){
@@ -83,7 +91,9 @@ var schema = {
83
91
  'name',
84
92
  'info',
85
93
  'description',
86
- 'color:color',
94
+ {name:'color',type:'color',comment:'hex or html color code',reloadable:true,
95
+ ai:{prompt:'generate a hex color code for this status. prioritise the name and info fields for context. Override with a color name is one is set.'}
96
+ },
87
97
  { name: "index", type: "number", display: "Ordering Index", comment: "Optional manual ordering index for lists and workflows. Lower values appear first.", width:'50%' },
88
98
 
89
99
  { name: "code", type: "text", display: "System Code", comment: "Machine-usable, human-readable identifier for database/API use. Use lowercase with underscores.", width:'50%' },
@@ -178,12 +178,16 @@ var task = function(){return{
178
178
  fields:function(){
179
179
  var fields = [
180
180
  {sidebar_start:'left'},
181
- {section_start:'JAI',display:'JOE Ai'},
181
+ {section_start:'ai_chat', anchor:'AiChat'},
182
182
  "objectChat",
183
183
  "listConversations",
184
+ {section_end:'ai_chat'},
185
+ {section_start:'ai_thoughts', anchor:'AiThoughts'},
184
186
  'proposeThought',
187
+ {section_end:'ai_thoughts'},
188
+ {section_start:'ai_responses', anchor:'AiResponses',collapsed:true},
185
189
  'ai_responses',
186
- {section_end:'JAI'},
190
+ {section_end:'ai_responses'},
187
191
  {sidebar_end:'left'},
188
192
  {section_start:'overview'},
189
193
  'name',
@@ -250,7 +254,9 @@ var task = function(){return{
250
254
  {section_start:'acceptance',collapsed:function(item){
251
255
  return !(item.scceptance_criteria && item.scceptance_criteria.length);
252
256
  }},
253
- {name:'scceptance_criteria',display:'acceptance criteria',type:'objectList',label:false,
257
+ {name:'acceptance_criteria',display:'acceptance criteria',type:'objectList',label:false,value:function(item){
258
+ return item.scceptance_criteria || [];
259
+ },
254
260
  template:function(obj,subobj){
255
261
  var done = (subobj.sub_complete)?'joe-strike':'';
256
262
  return '<joe-title class="'+done+'">${criteria}</joe-title>' ;
@@ -1,6 +1,8 @@
1
+ const { methods } = require("./ai_prompt");
2
+
1
3
  var thought = {
2
4
  display:'Thought',
3
- title: 'Thought | ${thought_type}: ${statement}',
5
+ title: 'Thought | ${name}',
4
6
  info: "Persistent reasoning artifact (hypothesis, synthesis, or link) used to build an auditable world model in JOE.",
5
7
  menuicon:`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
6
8
  <path d="M418.79 152.21c54.1-4.68 106.11 14.11 145.57 50.7 179.88-61.28 357.82 94.91 322.09 281.77-17.7 92.57-93.99 170.46-185.58 191.53-7.83 1.8-34.03 4.23-38 6.47-2.3 1.29-14.64 18.32-18.65 22.27-82.76 81.43-218.9 67.72-286.83-24.62l-35.16 3.37c-205.89-4.36-263.08-280.1-74.73-364.78 10.05-87.72 83.39-159.08 171.29-166.69Zm-39.41 491.05c4.96 4.51 11.22 16.94 16.69 23.33 46.94 54.84 121.44 70.23 186.17 36.84 26.3-13.56 42.96-35.52 62.34-56.84 75.92-4.51 145.19-42.32 182.22-109.5 88.11-159.86-57.37-346.63-233.69-303.07-9.81 2.43-27.09 11.14-35.93 10.11-8.59-1-28.84-22.68-38.58-29.14-86.51-57.47-207.06-11.17-229.88 89.98-3.02 13.37-1.37 36.64-13.02 43.9-16.07 10.02-32.75 13.56-49.51 26.98-116.69 93.45-38.49 282 110.22 268.53 13.11-1.19 31.88-11.21 42.98-1.12Z"/>
@@ -12,7 +14,7 @@ var thought = {
12
14
  purpose: 'Use thoughts to store inspectable reasoning: hypotheses to be vetted, syntheses that compress many objects, and binary links (A↔B) with receipts. Thoughts are reusable as context in pipelines and agent runs.',
13
15
  labelField: 'name',
14
16
  defaultSort: { field: 'joeUpdated', dir: 'desc' },
15
- searchableFields: ['name', 'statement', 'info', 'thought_type', 'status', 'relationship_type', 'tags', '_id'],
17
+ searchableFields: ['name', 'statement', 'info', 'thought_type', 'status', 'relationship_type', 'created_by', 'creator_type', 'creator_id', 'tags', '_id'],
16
18
  allowedSorts: ['joeUpdated', 'created', 'thought_type', 'status', 'certainty'],
17
19
  relationships: {
18
20
  outbound: [
@@ -47,9 +49,11 @@ var thought = {
47
49
  { name: 'b', type: 'object' },
48
50
  { name: 'relationship_type', type: 'string' },
49
51
  { name: 'rationale', type: 'string' },
50
- // Lineage / provenance (ai_response_id, created_by, reviewed_by, etc.)
52
+ // Lineage / provenance (ai_response_id, created_by/creator, reviewed_by, etc.)
51
53
  { name: 'source_ai_response', type: 'string', isReference: true, targetSchema: 'ai_response' },
52
54
  { name: 'created_by', type: 'string' },
55
+ { name: 'creator_type', type: 'string', enumValues: ['user','agent'] },
56
+ { name: 'creator_id', type: 'string' },
53
57
  { name: 'lineage', type: 'object' },
54
58
  { name: 'joeUpdated', type: 'string', format: 'date-time', required: true },
55
59
  { name: 'created', type: 'string', format: 'date-time', required: true }
@@ -68,9 +72,54 @@ var thought = {
68
72
  var filters = [];
69
73
  // Tag-based filters are the main cross-cutting dimension for Thoughts
70
74
  filters = filters.concat(
71
- _joe.Filter.Options.tags({ group: 'tags', untagged: true, collapsed: true })
75
+ _joe.Filter.Options.tags({ group: 'tags', untagged: true, collapsed: true }),
76
+ _joe.Filter.Options.getDatasetPropertyValues('thought','created_by',{ group: 'created_by', collapsed: true }),
77
+ _joe.Filter.Options.getDatasetPropertyValues('thought','creator_type',{ group: 'creator_type', collapsed: true })
78
+
72
79
  );
73
80
 
81
+ // Creator_id filters with human-readable labels
82
+ try{
83
+ var dataset = _joe.getDataset('thought') || [];
84
+ var byCreator = {};
85
+ dataset.map(function(t){
86
+ if(!t.creator_id){ return; }
87
+ var key = t.creator_type+':'+t.creator_id;
88
+ if(!byCreator[key]){
89
+ // Try to resolve a nice display name
90
+ var name = t.creator_id;
91
+ if(t.creator_type === 'user' && _joe.Data.user){
92
+ var u = _joe.Data.user.find(function(x){ return x && x._id === t.creator_id; });
93
+ if(u){ name = u.fullname || u.name || u.email || u._id; }
94
+ }else if(t.creator_type === 'agent'){
95
+ // For agents we only have logical ids like thought_agent_default
96
+ name = t.creator_id;
97
+ }
98
+ byCreator[key] = {
99
+ name: name,
100
+ filter: { creator_type: t.creator_type, creator_id: t.creator_id }
101
+ };
102
+ }
103
+ });
104
+ var keys = Object.keys(byCreator);
105
+ if(keys.length){
106
+ filters.push({ group_start:'creator', collapsed:true });
107
+ keys.sort(function(a,b){
108
+ var na = byCreator[a].name.toLowerCase();
109
+ var nb = byCreator[b].name.toLowerCase();
110
+ if(na>nb) return 1;
111
+ if(na<nb) return -1;
112
+ return 0;
113
+ }).map(function(k){
114
+ filters.push({
115
+ name: byCreator[k].name,
116
+ filter: byCreator[k].filter
117
+ });
118
+ });
119
+ filters.push({ group_end:'creator' });
120
+ }
121
+ }catch(_e){}
122
+
74
123
  // Group thoughts by what they are about (about[].itemtype).
75
124
  // We build filters manually so that each itemtype gets its own filter
76
125
  // on the nested path "about.itemtype". JOE's search engine treats this
@@ -104,7 +153,7 @@ var thought = {
104
153
  },
105
154
  listView: {
106
155
  title: function (th) {
107
- var html = `<joe-subtext>${_joe.Utils.prettyPrintDTS(th.created)}</joe-subtext><joe-title>${th.name}</joe-title>`;
156
+ var html = `<joe-subtext>${th.created_by} - ${_joe.Utils.prettyPrintDTS(th.created)}</joe-subtext><joe-title>${th.name}</joe-title>`;
108
157
  html += `<joe-subtitle>${th.statement}</joe-subtitle>`;
109
158
 
110
159
  return html;
@@ -237,6 +286,8 @@ var thought = {
237
286
  locked: true
238
287
  },
239
288
  { name: 'created_by', type: 'string', locked: true },
289
+ { name: 'creator_type', type: 'select', values:['user','agent'], locked: true },
290
+ { name: 'creator_id', type: 'string', locked: true },
240
291
  {
241
292
  name: 'lineage',
242
293
  type: 'rendering',
@@ -272,6 +323,7 @@ var thought = {
272
323
  }
273
324
  });
274
325
  },
326
+ methods:{},
275
327
  idprop: '_id'
276
328
  };
277
329
 
@@ -21,7 +21,7 @@ var joewebconfig = {
21
21
  templatesDir:'_templates',
22
22
  //httpsPort:2100,
23
23
  default_schemas:['user','group','goal','initiative','event','report','tag','status','workflow','list','notification','note','include','instance','setting',
24
- 'ai_assistant','ai_conversation','ai_response','ai_tool','ai_prompt','ai_widget_conversation','thought'
24
+ 'ai_assistant','ai_conversation','ai_response','ai_tool','ai_prompt','ai_widget_conversation','ai_pipeline','thought'
25
25
  ]
26
26
  };
27
27