json-object-editor 0.10.610 → 0.10.623
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/CHANGELOG.md +8 -0
- package/_www/mcp-nav.js +1 -0
- package/app.js +26 -2
- package/css/joe-styles.css +1 -0
- package/css/joe.css +2 -1
- package/css/joe.min.css +1 -1
- package/js/JsonObjectEditor.jquery.craydent.js +27 -53
- package/js/joe-ai.js +399 -0
- package/js/joe.js +28 -54
- package/js/joe.min.js +1 -1
- package/package.json +2 -2
- package/readme.md +663 -526
- package/server/app-config.js +2 -1
- package/server/fields/core.js +35 -17
- package/server/modules/Server.js +50 -0
- package/server/modules/Storage.js +7 -1
- package/server/modules/Utils.js +2 -1
- package/server/plugins/awsConnect.js +32 -6
- package/server/plugins/chatgpt-assistants.js +3 -3
- package/server/plugins/chatgpt-responses.js +45 -0
- package/server/plugins/chatgpt.js +729 -0
- package/server/schemas/ai_assistant.js +255 -0
- package/server/schemas/ai_conversation.js +34 -0
- package/server/schemas/ai_prompt.js +323 -0
- package/server/schemas/ai_response.js +217 -0
- package/server/schemas/ai_tool.js +30 -0
- package/server/schemas/ai_widget_conversation.js +110 -0
- package/server/schemas/task.js +783 -778
- package/server/webconfig.js +3 -1
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
// Joe AI Assistant Schema
|
|
2
|
+
// This schema is used to manage AI Assistants within Joe, including syncing with OpenAI.
|
|
3
|
+
|
|
4
|
+
var schema = {
|
|
5
|
+
title: "Ai Assistant | ${name}",
|
|
6
|
+
display: "Ai Assist",
|
|
7
|
+
info: "An AI Assistant configuration linked to OpenAI, managed within Joe.",
|
|
8
|
+
// Curated summary for agents and tools
|
|
9
|
+
summary:{
|
|
10
|
+
description:'Configuration record for an AI assistant connected to OpenAI.',
|
|
11
|
+
purpose:'Use to store instructions, default model, tools, and file attachments for assistants used by JOE chat UIs and widgets. One ai_assistant typically maps to a single OpenAI assistant_id.',
|
|
12
|
+
labelField:'name',
|
|
13
|
+
defaultSort:{ field:'joeUpdated', dir:'desc' },
|
|
14
|
+
searchableFields:['name','info','assistant_id','ai_model','tags','datasets'],
|
|
15
|
+
allowedSorts:['joeUpdated','created','name','last_synced'],
|
|
16
|
+
relationships:{
|
|
17
|
+
outbound:[
|
|
18
|
+
{ field:'status', targetSchema:'status', cardinality:'one' },
|
|
19
|
+
{ field:'datasets', targetSchema:'<schemaName>', cardinality:'many' },
|
|
20
|
+
{ field:'files', targetSchema:'file', cardinality:'many' }
|
|
21
|
+
],
|
|
22
|
+
inbound:{ graphRef:'server/relationships.graph.json' }
|
|
23
|
+
},
|
|
24
|
+
joeManagedFields:['created','joeUpdated'],
|
|
25
|
+
fields:[
|
|
26
|
+
{ name:'_id', type:'string', required:true },
|
|
27
|
+
{ name:'itemtype', type:'string', required:true, const:'ai_assistant' },
|
|
28
|
+
{ name:'name', type:'string', required:true },
|
|
29
|
+
{ name:'info', type:'string' },
|
|
30
|
+
{ name:'ai_model', type:'string' },
|
|
31
|
+
{ name:'assistant_id', type:'string' },
|
|
32
|
+
{ name:'openai_assistant_version', type:'string' },
|
|
33
|
+
{ name:'file_search_enabled', type:'boolean' },
|
|
34
|
+
{ name:'code_interpreter_enabled', type:'boolean' },
|
|
35
|
+
{ name:'assistant_thinking_text', type:'string' },
|
|
36
|
+
{ name:'instructions', type:'string' },
|
|
37
|
+
{ name:'tools', type:'string' },
|
|
38
|
+
{ name:'files', type:'string', isArray:true, isReference:true, targetSchema:'file' },
|
|
39
|
+
{ name:'file_ids', type:'string', isArray:true },
|
|
40
|
+
{ name:'datasets', type:'string', isArray:true },
|
|
41
|
+
{ name:'tags', type:'string', isArray:true, isReference:true, targetSchema:'tag' },
|
|
42
|
+
{ name:'status', type:'string', isReference:true, targetSchema:'status' },
|
|
43
|
+
{ name:'last_synced', type:'string', format:'date-time' },
|
|
44
|
+
{ name:'joeUpdated', type:'string', format:'date-time' },
|
|
45
|
+
{ name:'created', type:'string', format:'date-time' }
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
menuicon: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
|
|
49
|
+
<path d="M294.49 618.18v64.49c0 22.42.95 35.46 2.84 39.12 2.4 4.94 6.93 8.52 12.29 9.71 9.18 2.13 18.6 3.01 28.02 2.64h17.31c18.81 0 28.22 6.04 28.22 18.11 0 13.96-9.93 22.51-29.8 25.64-24.41 2.74-48.98 3.87-73.55 3.37-29.87 0-51.01-5.79-63.44-17.38-12.42-11.59-18.66-31.41-18.7-59.47v-81.08c.85-11.33-1.15-22.68-5.81-33.04-5.69-7.66-14.07-12.88-23.46-14.6-11.09-2.78-18.54-13.19-17.58-24.58-1.07-11.43 6.42-21.9 17.58-24.58 9.41-1.95 17.77-7.32 23.46-15.07 4.7-10.35 6.7-21.71 5.81-33.04v-80.88c0-27.62 6.21-47.22 18.63-58.81 12.42-11.59 33.57-17.36 63.44-17.31 26.13-.73 52.27.66 78.17 4.16 6.92 1.05 13.37 4.16 18.5 8.92 4.27 4.08 6.66 9.75 6.61 15.66 0 12.07-9.41 18.11-28.22 18.11h-17.84c-16.04 0-27.05 1.72-33.04 5.15-5.92 3.96-9.36 10.72-9.05 17.84v92.71c-.35 31.23-8.72 52.03-25.11 62.38-1.29.88-2.06 2.34-2.05 3.9 0 2.42 2.93 6.06 8.79 10.9 6.54 5.96 11.3 13.63 13.74 22.14 3.19 11.34 4.62 23.11 4.23 34.89Zm435.01-134.4v-64.23c0-22.42-.95-35.46-2.84-39.12-2.4-4.94-6.93-8.52-12.29-9.71-9.18-2.13-18.6-3.01-28.02-2.64h-17.18c-18.81 0-28.22-6.04-28.22-18.11 0-13.96 9.93-22.42 29.8-25.37 24.42-2.73 48.98-3.86 73.55-3.37 29.87 0 51.01 5.79 63.44 17.38 12.42 11.59 18.63 31.19 18.63 58.81v81.28c-.88 11.33 1.12 22.69 5.81 33.04 5.75 7.62 14.1 12.87 23.46 14.74 11.16 2.71 18.62 13.22 17.51 24.65.74 9.18-4.03 17.93-12.16 22.27-4.09 1.86-8.33 3.34-12.69 4.43-8.51 2.69-15.35 9.08-18.63 17.38-2.71 9.15-3.85 18.69-3.37 28.22v81.01c0 27.8-6.21 47.47-18.63 59.01-12.42 11.54-33.57 17.33-63.44 17.38-26.13.74-52.27-.65-78.17-4.16-6.92-1.05-13.37-4.16-18.5-8.92-4.31-4.17-6.7-9.93-6.61-15.93 0-12.07 9.41-18.11 28.22-18.11 2.25 0 8.19.18 17.84.53 11.25.56 22.5-1.19 33.04-5.15 4.1-2.12 7.02-5.98 7.93-10.51 1.33-11.91 1.82-23.9 1.45-35.88v-64.49c-.51-12.88 1.38-25.74 5.55-37.93 4.19-9.77 11.07-18.15 19.82-24.18 1.29-.88 2.06-2.34 2.05-3.9 0-2.42-2.93-6.06-8.79-10.9-6.55-5.96-11.31-13.63-13.74-22.14-3.43-11.46-5.05-23.39-4.82-35.35Z"/>
|
|
50
|
+
<rect width="74.5" height="189" x="409.75" y="456.75" rx="33.94" ry="33.94"/>
|
|
51
|
+
<rect width="74.5" height="189" x="539.75" y="456.75" rx="33.94" ry="33.94"/>
|
|
52
|
+
</svg>`,
|
|
53
|
+
listView:{
|
|
54
|
+
title: '<joe-title>${name}</joe-title><joe-subtitle>${info}</joe-subtitle><joe-subtitle>${assistant_id}</joe-subtitle>',
|
|
55
|
+
listWindowTitle: 'Ai Assistants'
|
|
56
|
+
},
|
|
57
|
+
subsets:function(){
|
|
58
|
+
var schemas = [];
|
|
59
|
+
var subs = [];
|
|
60
|
+
_joe.current.list.map(function(asst){
|
|
61
|
+
schemas = schemas.concat(asst.datasets||[]);
|
|
62
|
+
});
|
|
63
|
+
(new Set(schemas)).map(function(schema){
|
|
64
|
+
subs.push({name:schema,filter:{datasets:{$in:[schema]}}})
|
|
65
|
+
});
|
|
66
|
+
return subs;
|
|
67
|
+
},
|
|
68
|
+
stripeColor: function(ai_assistant) {
|
|
69
|
+
//use the stripe color from ai_assistant status object if it has one
|
|
70
|
+
if (ai_assistant.status){
|
|
71
|
+
var status = _joe.Cache.get(ai_assistant.status);
|
|
72
|
+
if (status && status.color) {
|
|
73
|
+
return {color:status.color,title:status.name};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
bgColor: function(ai_assistant) {
|
|
78
|
+
//if it's the default assistant, use goldenrod color
|
|
79
|
+
let def_id = _joe.Data.setting.where({name:'DEFAULT_AI_ASSISTANT'})[0]||false;
|
|
80
|
+
if (def_id && def_id.value == ai_assistant._id) {
|
|
81
|
+
return {color:'#DAA520'};
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
methods: {
|
|
85
|
+
syncAssistantToOpenAI: function(currentObject, event) {
|
|
86
|
+
var $button = $(event.target).closest('joe-button');
|
|
87
|
+
var originalHTML = $button.html();
|
|
88
|
+
|
|
89
|
+
if (!currentObject || !currentObject._id) {
|
|
90
|
+
alert("No valid record to sync.");
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const url = `/API/plugin/chatgpt-assistants/syncAssistantToOpenAI?_id=${currentObject._id}`;
|
|
95
|
+
|
|
96
|
+
// Disable button and show spinner
|
|
97
|
+
$button.prop('disabled', true);
|
|
98
|
+
$button.html(`<svg class="joe-loading-spinner" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg"><circle class="path" cx="25" cy="25" r="20" fill="none" stroke-width="5"/></svg> Syncing...`);
|
|
99
|
+
|
|
100
|
+
fetch(url)
|
|
101
|
+
.then(response => response.json())
|
|
102
|
+
.then(response => {
|
|
103
|
+
if (response && response.success) {
|
|
104
|
+
console.log("Assistant synced successfully:", response);
|
|
105
|
+
|
|
106
|
+
// 🔄 Refresh the object after sync
|
|
107
|
+
_joe.Object.getFromServer(currentObject._id, { goto: true }, function(success) {
|
|
108
|
+
if (success) {
|
|
109
|
+
console.log("Assistant reloaded into Joe UI.");
|
|
110
|
+
//_joe.updateObject(null,null,true);
|
|
111
|
+
} else {
|
|
112
|
+
console.warn("Failed to reload Assistant object.");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
$button.prop('disabled', false);
|
|
116
|
+
$button.html(originalHTML);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
} else {
|
|
120
|
+
alert("Sync failed. See console for details.");
|
|
121
|
+
console.error(response);
|
|
122
|
+
$button.prop('disabled', false);
|
|
123
|
+
$button.html(originalHTML);
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
.catch(err => {
|
|
127
|
+
alert("Error syncing Assistant. See console.");
|
|
128
|
+
console.error(err);
|
|
129
|
+
$button.prop('disabled', false);
|
|
130
|
+
$button.html(originalHTML);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
fields: function() {
|
|
135
|
+
return [
|
|
136
|
+
"name:text:40%", // Assistant Name
|
|
137
|
+
"info:text:60%", // Assistant Subtitle (optional)
|
|
138
|
+
|
|
139
|
+
{ section_start: "openai_config", display: "OpenAI" },
|
|
140
|
+
'ai_model',
|
|
141
|
+
|
|
142
|
+
{ name: "assistant_id", type: "text", display: "OpenAI Assistant ID", locked: true,
|
|
143
|
+
comment: function(ai_assistant) {
|
|
144
|
+
if (!ai_assistant.assistant_id) {
|
|
145
|
+
return 'No Assistant created yet. Save to generate a Playground link.';
|
|
146
|
+
}
|
|
147
|
+
return `<a href="https://platform.openai.com/playground/assistants?assistant=${ai_assistant.assistant_id}" target="_blank" style="color: #3498db;">View this Assistant in OpenAI Playground</a>`;
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
{ name: "openai_assistant_version", type: "text", default: "v1", hidden: true },
|
|
151
|
+
{
|
|
152
|
+
name: "file_search_enabled",
|
|
153
|
+
type: "boolean",
|
|
154
|
+
display: "Enable File Search",
|
|
155
|
+
default: false,
|
|
156
|
+
width:"50%"
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: "code_interpreter_enabled",
|
|
160
|
+
type: "boolean",
|
|
161
|
+
display: "Enable Code Interpreter",
|
|
162
|
+
default: false,
|
|
163
|
+
width:"50%"
|
|
164
|
+
},
|
|
165
|
+
{ section_end: "openai_config" },
|
|
166
|
+
{ section_start: "instructions", display: "instructions" },
|
|
167
|
+
{
|
|
168
|
+
name: "assistant_thinking_text",
|
|
169
|
+
type: "text",
|
|
170
|
+
display: "Assistant Thinking Text",
|
|
171
|
+
info: "What the user should see while the Assistant is thinking.",
|
|
172
|
+
placeholder: "e.g. 'Assistant is preparing a response...'"
|
|
173
|
+
},
|
|
174
|
+
{ name: "instructions", type: "wysiwyg" }, // Full TinyMCE editor
|
|
175
|
+
{ section_end: "instructions" },
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
{ section_start: "tools", display: "Function Tools",
|
|
180
|
+
collapsed:function(asst) { return !asst.tools; }
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: "tools",
|
|
184
|
+
type: "code",
|
|
185
|
+
display: "Tool Definitions (JSON)",
|
|
186
|
+
comment: '<div>Paste or edit full JSON function definitions here:</div><div><a href="https://platform.openai.com/docs/assistants/tools/function-calling" target="_blank" style="color: #3498db;">View OpenAI Function Calling Documentation</a></div><pre>{<br/> "type": "function",<br/> "function": {<br/> "name": "your_function",<br/> "description": "Describe what your function does.",<br/> "parameters": {<br/> "type": "object",<br/> "properties": {<br/> "theme": {<br/> "type": "string",<br/> "description": "The theme to suggest (e.g., hope, perseverance)."<br/> }<br/> }<br/> }<br/> }<br/>}</pre><br/>'
|
|
187
|
+
,
|
|
188
|
+
|
|
189
|
+
height: "300px"
|
|
190
|
+
},
|
|
191
|
+
{ section_end: "tools" },
|
|
192
|
+
|
|
193
|
+
{ section_start: "files" },
|
|
194
|
+
{
|
|
195
|
+
name: "files",
|
|
196
|
+
type: "group",
|
|
197
|
+
display: "Attached Files",
|
|
198
|
+
values: function() {
|
|
199
|
+
return _joe.getDataset("file");
|
|
200
|
+
},
|
|
201
|
+
template: "${name}",
|
|
202
|
+
idprop: "_id"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: "file_ids",
|
|
206
|
+
type: "content",
|
|
207
|
+
display: "File IDs (auto populated on sync)",
|
|
208
|
+
comment: "Auto-managed list of OpenAI file_ids attached to this Assistant."
|
|
209
|
+
},
|
|
210
|
+
{ section_end: "files" },
|
|
211
|
+
{section_start:'categorization',collapsed:true},
|
|
212
|
+
'datasets',
|
|
213
|
+
{section_end:'categorization'},
|
|
214
|
+
{ section_start: "system", collapsed: true },
|
|
215
|
+
"_id",
|
|
216
|
+
"created",
|
|
217
|
+
"itemtype",
|
|
218
|
+
{ section_end: "system" },
|
|
219
|
+
{ sidebar_start: "right", collapsed: false },
|
|
220
|
+
"tags",
|
|
221
|
+
"status",
|
|
222
|
+
{
|
|
223
|
+
name: "last_synced",
|
|
224
|
+
type: "date",
|
|
225
|
+
display: "Last Synced",
|
|
226
|
+
locked:true,
|
|
227
|
+
comment: "Last time this Assistant was updated at OpenAI."
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
name: "sync_button",
|
|
231
|
+
type: "button",
|
|
232
|
+
display: "Sync to OpenAI",
|
|
233
|
+
method: "syncAssistantToOpenAI",
|
|
234
|
+
color: "green",
|
|
235
|
+
title: "Sync this Assistant with OpenAI"
|
|
236
|
+
},
|
|
237
|
+
// {
|
|
238
|
+
// name: "test_button",
|
|
239
|
+
// type: "button",
|
|
240
|
+
// display: "Test Button",
|
|
241
|
+
// method: "testButtonClick", // <- the method name you want to call
|
|
242
|
+
// color: "orange", // <- Joe color class (joe-orange-button)
|
|
243
|
+
// title: "Click to test button functionality",
|
|
244
|
+
// schema: "ai_assistant" // <- schema to pull the method from (optional for now, we lock it anyway)
|
|
245
|
+
// },
|
|
246
|
+
{ sidebar_end: "right" },
|
|
247
|
+
|
|
248
|
+
];
|
|
249
|
+
},
|
|
250
|
+
|
|
251
|
+
idprop: "_id"
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
module.exports = schema;
|
|
255
|
+
|
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
var schema = {
|
|
2
2
|
title: "Ai Conversation | ${name}",
|
|
3
3
|
display:'Ai Convo',
|
|
4
|
+
summary:{
|
|
5
|
+
description:'Metadata record for an AI conversation between a user, optional external members, and one or more assistants.',
|
|
6
|
+
purpose:'Use ai_conversation to track which user and assistant are involved in a chat, the OpenAI thread_id, high-level status, tags, and a summary. Full message history is fetched from OpenAI at runtime rather than stored in Joe.',
|
|
7
|
+
labelField:'name',
|
|
8
|
+
defaultSort:{ field:'created', dir:'desc' },
|
|
9
|
+
searchableFields:['name','info','summary','thread_id','tags','_id'],
|
|
10
|
+
allowedSorts:['created','joeUpdated','name'],
|
|
11
|
+
relationships:{
|
|
12
|
+
outbound:[
|
|
13
|
+
{ field:'user', targetSchema:'user', cardinality:'one' },
|
|
14
|
+
{ field:'assistant', targetSchema:'ai_assistant', cardinality:'one' },
|
|
15
|
+
{ field:'members', targetSchema:'members', cardinality:'many' },
|
|
16
|
+
{ field:'status', targetSchema:'status', cardinality:'one' },
|
|
17
|
+
{ field:'tags', targetSchema:'tag', cardinality:'many' }
|
|
18
|
+
],
|
|
19
|
+
inbound:{ graphRef:'server/relationships.graph.json' }
|
|
20
|
+
},
|
|
21
|
+
joeManagedFields:['created','joeUpdated'],
|
|
22
|
+
fields:[
|
|
23
|
+
{ name:'_id', type:'string', required:true },
|
|
24
|
+
{ name:'itemtype', type:'string', required:true, const:'ai_conversation' },
|
|
25
|
+
{ name:'name', type:'string', required:true },
|
|
26
|
+
{ name:'info', type:'string' },
|
|
27
|
+
{ name:'user', type:'string', isReference:true, targetSchema:'user' },
|
|
28
|
+
{ name:'assistant', type:'string', isReference:true, targetSchema:'ai_assistant' },
|
|
29
|
+
{ name:'members', type:'string', isArray:true, isReference:true, targetSchema:'members' },
|
|
30
|
+
{ name:'thread_id', type:'string' },
|
|
31
|
+
{ name:'summary', type:'string' },
|
|
32
|
+
{ name:'status', type:'string', isReference:true, targetSchema:'status' },
|
|
33
|
+
{ name:'tags', type:'string', isArray:true, isReference:true, targetSchema:'tag' },
|
|
34
|
+
{ name:'joeUpdated', type:'string', format:'date-time' },
|
|
35
|
+
{ name:'created', type:'string', format:'date-time' }
|
|
36
|
+
]
|
|
37
|
+
},
|
|
4
38
|
info: "Tracks AI conversations across users, assistants, and external members, storing only summaries for performance.",
|
|
5
39
|
methods:{
|
|
6
40
|
chatSpawner:async function(object_id){
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
var schema = {
|
|
2
|
+
display:'Ai Prompt',
|
|
3
|
+
title : 'Ai Prompt | ${name}',
|
|
4
|
+
info:"An ai prompt that can be sent to openAi, etc",
|
|
5
|
+
summary:{
|
|
6
|
+
description:'Reusable AI prompt definition that describes how to call the chatgpt plugin or Responses API.',
|
|
7
|
+
purpose:'Use ai_prompt to define prompt methods, helper functions, and instructions for generating structured AI responses or content. Prompts can be tagged, scoped to datasets, and linked to ai_response records.',
|
|
8
|
+
labelField:'name',
|
|
9
|
+
defaultSort:{ field:'joeUpdated', dir:'desc' },
|
|
10
|
+
searchableFields:['name','info','prompt_method','ai_model','tags','datasets'],
|
|
11
|
+
allowedSorts:['joeUpdated','created','name','ai_model'],
|
|
12
|
+
relationships:{
|
|
13
|
+
outbound:[
|
|
14
|
+
{ field:'status', targetSchema:'status', cardinality:'one' },
|
|
15
|
+
{ field:'tags', targetSchema:'tag', cardinality:'many' },
|
|
16
|
+
{ field:'datasets', targetSchema:'<schemaName>', cardinality:'many' }
|
|
17
|
+
],
|
|
18
|
+
inbound:{ graphRef:'server/relationships.graph.json' }
|
|
19
|
+
},
|
|
20
|
+
joeManagedFields:['created','joeUpdated'],
|
|
21
|
+
fields:[
|
|
22
|
+
{ name:'_id', type:'string', required:true },
|
|
23
|
+
{ name:'itemtype', type:'string', required:true, const:'ai_prompt' },
|
|
24
|
+
{ name:'name', type:'string', required:true },
|
|
25
|
+
{ name:'info', type:'string' },
|
|
26
|
+
{ name:'prompt_method', type:'string' },
|
|
27
|
+
{ name:'content_items', type:'objectList' },
|
|
28
|
+
{ name:'functions', type:'string' },
|
|
29
|
+
{ name:'instructions_format', type:'string' },
|
|
30
|
+
{ name:'instructions', type:'string' },
|
|
31
|
+
{ name:'user_prompt', type:'string' },
|
|
32
|
+
{ name:'status', type:'string', isReference:true, targetSchema:'status' },
|
|
33
|
+
{ name:'tags', type:'string', isArray:true, isReference:true, targetSchema:'tag' },
|
|
34
|
+
{ name:'ai_model', type:'string' },
|
|
35
|
+
{ name:'temperature', type:'number' },
|
|
36
|
+
{ name:'datasets', type:'string', isArray:true },
|
|
37
|
+
{ name:'joeUpdated', type:'string', format:'date-time' },
|
|
38
|
+
{ name:'created', type:'string', format:'date-time' }
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
menuicon:`<svg xmlns="http://www.w3.org/2000/svg" viewBox="-128 -128 1280 1280">
|
|
42
|
+
<path d="M356.52 692.84v31.84c0 11.07.47 17.51 1.4 19.31 1.19 2.44 3.42 4.2 6.07 4.8 4.53 1.05 9.18 1.49 13.83 1.31h8.55c9.29 0 13.93 2.98 13.93 8.94 0 6.89-4.9 11.11-14.71 12.66-12.05 1.35-24.18 1.91-36.31 1.66-14.75 0-25.19-2.86-31.32-8.58-6.13-5.72-9.21-15.51-9.23-29.36v-40.03c.42-5.59-.57-11.2-2.87-16.31-2.81-3.78-6.95-6.36-11.58-7.21-5.48-1.37-9.15-6.51-8.68-12.14-.53-5.64 3.17-10.81 8.68-12.14 4.65-.96 8.77-3.61 11.58-7.44 2.32-5.11 3.31-10.72 2.87-16.31v-39.93c0-13.64 3.07-23.32 9.2-29.04 6.13-5.72 16.57-8.57 31.32-8.55 12.9-.36 25.81.33 38.6 2.06 3.42.52 6.6 2.05 9.14 4.4 2.11 2.02 3.29 4.82 3.26 7.73 0 5.96-4.64 8.94-13.93 8.94h-8.81c-7.92 0-13.35.85-16.31 2.54-2.92 1.96-4.62 5.29-4.47 8.81v45.77c-.17 15.42-4.31 25.69-12.4 30.8-.64.43-1.02 1.16-1.01 1.92 0 1.2 1.45 2.99 4.34 5.38 3.23 2.94 5.58 6.73 6.79 10.93 1.58 5.6 2.28 11.41 2.09 17.23Zm90.28-100.23c16.42.07 29.72 13.37 29.79 29.79.25 8.33-3.05 16.37-9.07 22.12-11.82 11.24-30.37 11.24-42.18 0-6.02-5.75-9.32-13.79-9.07-22.12-.18-7.36 2.58-14.49 7.67-19.8 5.8-6.5 14.16-10.15 22.87-9.98Zm0 73.9c16.42.07 29.72 13.37 29.79 29.79.25 8.34-3.06 16.4-9.1 22.15-11.82 11.24-30.37 11.24-42.18 0-6.02-5.75-9.32-13.79-9.07-22.12-.18-7.36 2.58-14.49 7.67-19.8 5.8-6.52 14.17-10.18 22.9-10.02Zm89.36-40.03v-31.71c0-11.07-.47-17.51-1.4-19.31-1.19-2.44-3.42-4.2-6.07-4.8-4.53-1.05-9.18-1.49-13.83-1.31h-8.48c-9.29 0-13.93-2.98-13.93-8.94 0-6.89 4.9-11.07 14.71-12.53 12.05-1.35 24.18-1.9 36.31-1.66 14.75 0 25.19 2.86 31.32 8.58 6.13 5.72 9.2 15.4 9.2 29.04v40.13c-.44 5.59.55 11.2 2.87 16.31 2.84 3.76 6.96 6.35 11.58 7.28 5.51 1.34 9.2 6.53 8.65 12.17.37 4.53-1.99 8.85-6 10.99-2.02.92-4.11 1.65-6.26 2.19-4.2 1.33-7.58 4.48-9.2 8.58-1.34 4.52-1.9 9.23-1.66 13.93v40c0 13.72-3.07 23.44-9.2 29.13-6.13 5.7-16.57 8.56-31.32 8.58-12.9.36-25.81-.32-38.6-2.06-3.42-.52-6.6-2.05-9.14-4.4-2.13-2.06-3.31-4.9-3.26-7.86 0-5.96 4.64-8.94 13.93-8.94 1.11 0 4.05.09 8.81.26 5.55.28 11.11-.59 16.31-2.54 2.02-1.05 3.47-2.95 3.92-5.19.66-5.88.9-11.8.72-17.72v-31.84c-.25-6.36.68-12.71 2.74-18.73 2.07-4.82 5.46-8.96 9.79-11.94.64-.43 1.02-1.16 1.01-1.92 0-1.2-1.45-2.99-4.34-5.38-3.23-2.94-5.58-6.73-6.79-10.93-1.69-5.66-2.5-11.55-2.38-17.45Zm164.47-327.03 197.56 40.87-197.56 40.86-40.86 197.57-40.87-197.57-197.56-40.86 197.56-40.87 40.87-197.56 40.86 197.56z"/>
|
|
43
|
+
<path d="m516.05 158.53 81.14 16.79-81.14 16.78-16.78 81.15-16.79-81.15-81.14-16.78 81.14-16.79 16.79-81.14 16.78 81.14zm43.7 281.88 41.02 8.48-41.02 8.48-8.48 41.02-8.49-41.02-41.01-8.48 41.01-8.48 8.49-41.02 8.48 41.02z"/>
|
|
44
|
+
<path d="M698.87 563.96c16.22 26.17 25.29 55.26 25.29 85.9 0 117.09-105.49 205.38-245.39 205.38-3.01 0-6.03-.04-9.07-.12-13.15-.34-27.52-2.1-42.74-3.96-16.83-2.06-34.23-4.19-52.19-4.67l-8.81-.24-8.65 1.71-138.94 27.52 12.32-30.18 18.2-44.57-32.74-35.61c-22.03-23.96-48.3-63.4-48.3-115.27 0-113.76 124.78-206.3 278.15-206.3 10.26 0 20.38.43 30.35 1.23l-48.12-48.12C259.65 403.99 125.8 514.97 125.8 650.82c0 56.11 22.89 107.94 61.57 150.01l-59.5 145.77 252.16-49.95c26.34.7 55.86 6.99 85.42 7.76 3.35.09 6.69.13 10.01.13 171.44 0 290.73-115.81 290.73-253.72 0-42.53-13.14-82.62-36.34-117.86l-30.99 30.99Z"/>
|
|
45
|
+
</svg>`,
|
|
46
|
+
listView:{
|
|
47
|
+
title: function(aip){
|
|
48
|
+
return `
|
|
49
|
+
<joe-title>${aip.name}</joe-title>
|
|
50
|
+
<joe-subtitle>${aip.info}</joe-subtitle><br/>
|
|
51
|
+
|
|
52
|
+
<joe-subtext class="fright"><div><b>${aip.ai_model}</b></div>${aip.prompt_method}</joe-subtext>
|
|
53
|
+
<joe-subtext>${aip.content_items.map(i=>{
|
|
54
|
+
return `<b>${i.itemtype}</b>: ${i.reference}`;
|
|
55
|
+
}).join('')}</joe-subtext>
|
|
56
|
+
${_joe.schemas.tag.methods.renderTags(aip.tags,'fleft')}
|
|
57
|
+
`;
|
|
58
|
+
},
|
|
59
|
+
listWindowTitle: 'Ai Prompts'
|
|
60
|
+
},
|
|
61
|
+
subsets:function(i){
|
|
62
|
+
|
|
63
|
+
return _joe.Filter.Options.status();
|
|
64
|
+
},
|
|
65
|
+
filters:function(i){
|
|
66
|
+
|
|
67
|
+
return _joe.Filter.Options.tags();
|
|
68
|
+
},
|
|
69
|
+
stripeColor: function(item) {
|
|
70
|
+
//use the stripe color from ai_assistant status object if it has one
|
|
71
|
+
if (item.status){
|
|
72
|
+
var status = _joe.Cache.get(item.status);
|
|
73
|
+
if (status && status.color) {
|
|
74
|
+
return {color:status.color,title:status.name};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
onload:function(dataset){
|
|
79
|
+
//replace the blank instructions field with the populated template field && the blank instrctions format field with the populated template type field
|
|
80
|
+
dataset.map(function(item){
|
|
81
|
+
if(item.template){
|
|
82
|
+
item.instructions = item.template;
|
|
83
|
+
delete item.template;
|
|
84
|
+
}
|
|
85
|
+
if(item.template_type){
|
|
86
|
+
item.instructions_format = item.template_type;
|
|
87
|
+
delete item.template_type;
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
},
|
|
91
|
+
fields:[
|
|
92
|
+
'name',
|
|
93
|
+
'info',
|
|
94
|
+
{name:"prompt_method",placeholder:"name of method to call in plugin", comment:'use executeJOEAiPrompt to use the JOE ui here for all smarts', default:"executeJOEAiPrompt",display:"Prompt Plugin Method",type:'text'},
|
|
95
|
+
{name:'content_items',type:'objectList',
|
|
96
|
+
properties:['itemtype','reference']
|
|
97
|
+
},
|
|
98
|
+
{section_start:'Input'},
|
|
99
|
+
{name: 'functions', type: 'code', display: 'Helper Functions', language:'javascript',comment: `
|
|
100
|
+
<div>AI Prompt Helper Function
|
|
101
|
+
|
|
102
|
+
<h4>Usage:</h4>
|
|
103
|
+
<ul>
|
|
104
|
+
<li>Must export an async function.</li>
|
|
105
|
+
<li>Receives: { instructions, params, ai_prompt } as a single argument.</li>
|
|
106
|
+
<li>Must return a final modified instructions string.</li>
|
|
107
|
+
</ul>
|
|
108
|
+
|
|
109
|
+
<h4>Example:</h4>
|
|
110
|
+
<div class="pad10">
|
|
111
|
+
<pre>
|
|
112
|
+
module.exports = async function({ instructions, params, ai_prompt })
|
|
113
|
+
// Your code here to modify the instructions based off params
|
|
114
|
+
const object = $J.get(params.idToLookup);
|
|
115
|
+
|
|
116
|
+
trackObject(params.idToLookup); // Tell parent we used this
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
instructions: "Updated system-level instructions string",
|
|
120
|
+
input: "Specific input text (URL, query, etc)"
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
};
|
|
124
|
+
</pre>
|
|
125
|
+
</div>
|
|
126
|
+
</div>`},
|
|
127
|
+
{section_end:'Input'},
|
|
128
|
+
{section_start:'Instruct'},
|
|
129
|
+
{label:'Instructions'},
|
|
130
|
+
"instructions_format",
|
|
131
|
+
"instructions",
|
|
132
|
+
{name:"user_prompt",display:'User Prompt',type:'rendering',comment:'speciific input to the prompt if any, such as campaign intent'},
|
|
133
|
+
|
|
134
|
+
// 'template_type',
|
|
135
|
+
// {extend:'template',specs:{comment:'legacy field, use instructions instead',
|
|
136
|
+
// // comment:`<div>use $\\{this.AI_PROMPT.name\\} $\\{this.CONTENT\\} <br/></div><div>for <b>module</b>: export function(data) that returns an html string.
|
|
137
|
+
// // data.request, data.REPORT,
|
|
138
|
+
// // <br/>shorthand: $J.get(itemid) $J.schema(schemaname)</div>`,
|
|
139
|
+
// language:function(item){
|
|
140
|
+
// switch(item.template_type){
|
|
141
|
+
// case 'module':
|
|
142
|
+
// return 'javascript';
|
|
143
|
+
// break;
|
|
144
|
+
// default:
|
|
145
|
+
// return '';
|
|
146
|
+
// }
|
|
147
|
+
|
|
148
|
+
// }
|
|
149
|
+
// }},
|
|
150
|
+
{section_end:'Instruct'},
|
|
151
|
+
|
|
152
|
+
{section_start:'system',collapsed:true},
|
|
153
|
+
'_id','created','itemtype',
|
|
154
|
+
{section_end:'system'},
|
|
155
|
+
{sidebar_start:'right',collapsed:true},
|
|
156
|
+
{section_start:'workflow'},
|
|
157
|
+
'status',
|
|
158
|
+
'tags',
|
|
159
|
+
// {name:'merge_status',comment:'status to add when this data is merged in', allowMultiple:false,type:"objectReference",display:'Merge Status',values:function(){
|
|
160
|
+
// return _joe.getDataset('status');
|
|
161
|
+
// }},
|
|
162
|
+
{section_end:'workflow'},
|
|
163
|
+
{section_start:'openAi',collapsed:true},
|
|
164
|
+
'ai_model',
|
|
165
|
+
{name:'temperature', type:'number',display:'Temperature', default:.7, step:"0.1",comment:'0-1, 0 is deterministic, 1 is random'},
|
|
166
|
+
//{name:'max_tokens', type:'number',display:'Max Tokens',comment:'max tokens to return',default:4096},
|
|
167
|
+
{section_end:'openAi'},
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
{section_start:'examples',collapsed:true},
|
|
171
|
+
{name:'examples', display:'prompt examples', comment:'runs the prompt to create a response',type:'content', reloadable:true,run:function(item){
|
|
172
|
+
return $J.schema('ai_prompt').methods.listExamples(item);
|
|
173
|
+
} },
|
|
174
|
+
{section_end:'examples'},
|
|
175
|
+
|
|
176
|
+
{sidebar_end:'right'},
|
|
177
|
+
{sidebar_start:'left',collapsed:function(aip){
|
|
178
|
+
return aip.datasets.length != 0;
|
|
179
|
+
}},
|
|
180
|
+
{section_start:'categorization',collapsed:false},
|
|
181
|
+
'datasets',
|
|
182
|
+
{section_end:'categorization'},
|
|
183
|
+
{sidebar_end:'left'},
|
|
184
|
+
],
|
|
185
|
+
idprop : "_id",
|
|
186
|
+
sorter:['name','!joeUpdated'],
|
|
187
|
+
methods:{
|
|
188
|
+
buildURL: function(prompt, items = []) {
|
|
189
|
+
const method = prompt.prompt_method || '';
|
|
190
|
+
let url = `/API/plugin/chatgpt/${method}?ai_prompt=${prompt._id}`;
|
|
191
|
+
|
|
192
|
+
if (!Array.isArray(items)) {
|
|
193
|
+
console.warn('Expected items to be an array.');
|
|
194
|
+
return url;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (prompt.content_items) {
|
|
198
|
+
prompt.content_items.forEach(ci => {
|
|
199
|
+
const matchingItem = items.find(it => it.itemtype === ci.itemtype );
|
|
200
|
+
if (matchingItem) {
|
|
201
|
+
url += `&${ci.reference}=${matchingItem._id}`;
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return url;
|
|
207
|
+
},
|
|
208
|
+
// listItemClickHandler:function(itemid,promptid){
|
|
209
|
+
// var item = $J.get(itemid);
|
|
210
|
+
// var prompt;
|
|
211
|
+
// if(promptid){
|
|
212
|
+
// prompt = $J.get(promptid);
|
|
213
|
+
// }else{
|
|
214
|
+
// prompt = _jco();
|
|
215
|
+
// }
|
|
216
|
+
// window.open(this.buildURL(prompt,[item]));
|
|
217
|
+
// },
|
|
218
|
+
listItemClickHandler: function (itemMap, promptId) {
|
|
219
|
+
const prompt = promptId ? $J.get(promptId,'ai_prompt') : _jco();
|
|
220
|
+
const items = [];
|
|
221
|
+
|
|
222
|
+
for (const [itemtype, id] of Object.entries(itemMap)) {
|
|
223
|
+
const obj = $J.get(id,itemtype);
|
|
224
|
+
if (obj) {
|
|
225
|
+
items.push(obj);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
window.open(this.buildURL(prompt, items));
|
|
230
|
+
},
|
|
231
|
+
listExamples:function(prompt){
|
|
232
|
+
var examples = [];
|
|
233
|
+
var html ='';
|
|
234
|
+
var ref0;
|
|
235
|
+
var it0;
|
|
236
|
+
if(!prompt.content_items){
|
|
237
|
+
return 'select content items to send with this prompt';
|
|
238
|
+
}
|
|
239
|
+
prompt.content_items.map(function(ci){
|
|
240
|
+
if(_joe.Data[ci.itemtype]){
|
|
241
|
+
examples = examples.concat(_joe.Data[ci.itemtype]);
|
|
242
|
+
it0 = ci.itemtype;
|
|
243
|
+
ref0 = ci.reference;
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
var finalExamples = [];
|
|
247
|
+
|
|
248
|
+
while(finalExamples.length < 5 && finalExamples.length < examples.length){
|
|
249
|
+
let ci = examples[Math.floor(Math.random()*examples.length)];
|
|
250
|
+
if(finalExamples.indexOf(ci) == -1){
|
|
251
|
+
finalExamples.push(ci);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
var rep_url;
|
|
255
|
+
var method =
|
|
256
|
+
finalExamples.map(function(ex){
|
|
257
|
+
//rep_url = '/API/plugin/chatgpt'+'?ai_prompt='+prompt._id+'&'+ref0+'='+ex._id;
|
|
258
|
+
html += _joe.renderFieldListItem(ex,
|
|
259
|
+
'<joe-subtext>'+it0+'</joe-subtext>'+
|
|
260
|
+
'<joe-title>${name} ${date}</joe-title>\
|
|
261
|
+
<joe-subtext>${website}</joe-subtext>',
|
|
262
|
+
it0,
|
|
263
|
+
{
|
|
264
|
+
//action:'onclick="window.open(\''+rep_url+'\');"',
|
|
265
|
+
action:`onclick="_joe.schemas.ai_prompt.methods.listItemClickHandler('${ex._id}');"`,
|
|
266
|
+
icon:'ai_prompt'
|
|
267
|
+
}
|
|
268
|
+
);
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
return html;
|
|
272
|
+
},
|
|
273
|
+
listPrompts: function (objectMap) {
|
|
274
|
+
if (!objectMap || typeof objectMap !== 'object') return '';
|
|
275
|
+
|
|
276
|
+
const activeStatuses = _joe.getDataset('status')
|
|
277
|
+
.filter(f => f.datasets.includes('ai_prompt') && f.active)
|
|
278
|
+
.map(f => f._id);
|
|
279
|
+
|
|
280
|
+
const prompts = _joe.getDataset('ai_prompt').filter(prompt =>
|
|
281
|
+
activeStatuses.includes(prompt.status)
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
const context_items = {}
|
|
285
|
+
// Inline helper: reduce objects to { itemtype: _id }
|
|
286
|
+
const extractIds = map => {
|
|
287
|
+
const idMap = {};
|
|
288
|
+
for (const [type, obj] of Object.entries(map)) {
|
|
289
|
+
if (obj && obj._id) idMap[type] = obj._id;
|
|
290
|
+
}
|
|
291
|
+
return idMap;
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const objectIdMap = extractIds(objectMap);
|
|
295
|
+
const paramStr = JSON.stringify(objectIdMap).replace(/"/g, '"');
|
|
296
|
+
|
|
297
|
+
let html = '';
|
|
298
|
+
const temp = '<joe-title>${name}</joe-title>';
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
let itemtype = _joe.current.object.itemtype;
|
|
302
|
+
const matchingPrompts = prompts.filter(prompt =>
|
|
303
|
+
(prompt.content_items || []).some(ci => ci.itemtype === itemtype)
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
matchingPrompts.forEach(prompt => {
|
|
307
|
+
html += _joe.renderFieldListItem(prompt, temp, 'ai_prompt', {
|
|
308
|
+
icon: 'ai_prompt',
|
|
309
|
+
action: `onclick="(function(){ _joe.schemas.ai_prompt.methods.listItemClickHandler(${paramStr}, '${prompt._id}'); })()"`
|
|
310
|
+
|
|
311
|
+
//action: `onclick="_joe.schemas.ai_prompt.methods.listItemClickHandler(${paramStr}, "${prompt._id}");"`
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
return html;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
module.exports = schema;
|