json-object-editor 0.10.653 → 0.10.657
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 +47 -1
- package/_www/mcp-test.html +287 -276
- package/css/joe-ai.css +1 -1
- package/css/joe-styles.css +56 -1
- package/css/joe.css +57 -2
- package/css/joe.min.css +1 -1
- package/js/JsonObjectEditor.jquery.craydent.js +152 -17
- package/js/joe-ai.js +2075 -1825
- package/js/joe.js +153 -18
- package/js/joe.min.js +1 -1
- package/package.json +1 -1
- package/readme.md +74 -4
- package/server/fields/core.js +54 -6
- package/server/modules/MCP.js +1364 -1237
- package/server/modules/Sites.js +79 -0
- package/server/modules/Storage.js +28 -1
- package/server/modules/ThoughtPipeline.js +6 -0
- package/server/plugins/awsConnect.js +31 -1
- package/server/plugins/chatgpt.js +1732 -1339
- package/server/schemas/ai_prompt.js +389 -322
- package/server/schemas/ai_response.js +414 -365
- package/server/schemas/status.js +12 -2
- package/server/schemas/task.js +9 -3
|
@@ -168,6 +168,27 @@ function JsonObjectEditor(specs){
|
|
|
168
168
|
}});
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
};
|
|
172
|
+
this.uploaderSetFileRole = function(uploader_id, filename, role){
|
|
173
|
+
try{
|
|
174
|
+
var joe_uploader = self.uploaders && self.uploaders[uploader_id];
|
|
175
|
+
if (!joe_uploader || !Array.isArray(joe_uploader.files)) { return; }
|
|
176
|
+
var file = joe_uploader.files.where({filename:filename})[0];
|
|
177
|
+
if (!file) { return; }
|
|
178
|
+
if (role) {
|
|
179
|
+
file.file_role = role;
|
|
180
|
+
} else {
|
|
181
|
+
delete file.file_role;
|
|
182
|
+
}
|
|
183
|
+
if (joe_uploader.preview) {
|
|
184
|
+
$(joe_uploader.preview).html(_renderUploaderFilePreviews(joe_uploader.files, joe_uploader.cuid));
|
|
185
|
+
}
|
|
186
|
+
if (typeof self.updateObject === 'function') {
|
|
187
|
+
self.updateObject(null, null, true);
|
|
188
|
+
}
|
|
189
|
+
}catch(e){
|
|
190
|
+
console.warn('uploaderSetFileRole error', e && e.message || e);
|
|
191
|
+
}
|
|
171
192
|
};
|
|
172
193
|
window._joes.push(this);
|
|
173
194
|
|
|
@@ -5329,6 +5350,19 @@ this.renderHTMLContent = function(specs){
|
|
|
5329
5350
|
if(files && !$c.isArray(files)){
|
|
5330
5351
|
files = [files];
|
|
5331
5352
|
}
|
|
5353
|
+
|
|
5354
|
+
// Register uploader object (including optional file_roles) BEFORE we render
|
|
5355
|
+
// previews so that _renderUploaderFilePreviews can access role metadata.
|
|
5356
|
+
var uploader_obj = {
|
|
5357
|
+
cuid: uploader_id,
|
|
5358
|
+
prop: prop.name,
|
|
5359
|
+
files: files,
|
|
5360
|
+
max: prop.max || 0,
|
|
5361
|
+
// Optional file role configuration from schema (e.g. [{value,label,default}])
|
|
5362
|
+
roles: prop.file_roles || []
|
|
5363
|
+
};
|
|
5364
|
+
self.uploaders[uploader_id] = uploader_obj;
|
|
5365
|
+
|
|
5332
5366
|
if(prop.field && self.current.object[prop.field]){
|
|
5333
5367
|
var kfield = self.getField(prop.field);
|
|
5334
5368
|
var preview = self.current.object[prop.field]
|
|
@@ -5351,18 +5385,11 @@ this.renderHTMLContent = function(specs){
|
|
|
5351
5385
|
'<div class="joe-uploader-preview">'+dz_message+'</div>'+
|
|
5352
5386
|
'</div>'+
|
|
5353
5387
|
'<div class="joe-uploader-message">add a file</div>'+
|
|
5354
|
-
'<div class="joe-button joe-green-button joe-upload-cofirm-button hidden" onclick="_joe.uploaderConfirm(\''+uploader_id+'\',\''+prop.name+'\');">Upload File</div>'+__clearDiv__+
|
|
5388
|
+
'<div class="joe-button joe-green-button joe-upload-cofirm-button ui-helper-hidden hidden" onclick="_joe.uploaderConfirm(\''+uploader_id+'\',\''+prop.name+'\');">Upload File</div>'+__clearDiv__+
|
|
5355
5389
|
'</div>'
|
|
5356
5390
|
;
|
|
5357
5391
|
//var idprop = prop.idprop || '_id';
|
|
5358
5392
|
//html+= __clearDiv__;
|
|
5359
|
-
var uploader_obj = {
|
|
5360
|
-
cuid:uploader_id,
|
|
5361
|
-
prop:prop.name,
|
|
5362
|
-
files:files,
|
|
5363
|
-
max:prop.max || 0
|
|
5364
|
-
}
|
|
5365
|
-
self.uploaders[uploader_id] = uploader_obj;
|
|
5366
5393
|
return html;
|
|
5367
5394
|
};
|
|
5368
5395
|
function _removeUploaderFile(id,filename){
|
|
@@ -5378,9 +5405,10 @@ this.renderHTMLContent = function(specs){
|
|
|
5378
5405
|
var jup_template,html= '';
|
|
5379
5406
|
var alink ="<a href='${url}${base64}' class='file-link' target='_blank'></a>";
|
|
5380
5407
|
var delete_btn = '<joe-uploader-file-delete-btn class="svg-shadow" onclick="_joe.Fields.uploader.remove(\''+cuid+'\',\'${filename}\');">'+self.SVG.icon.close+'</joe-uploader-delete-btn>';
|
|
5381
|
-
var label = '
|
|
5382
|
-
|
|
5383
|
-
|
|
5408
|
+
var label = '';
|
|
5409
|
+
var uploader = self.uploaders && self.uploaders[cuid];
|
|
5410
|
+
var roles = uploader && uploader.roles;
|
|
5411
|
+
|
|
5384
5412
|
files.map(function(file){
|
|
5385
5413
|
var filesize = '<joe-uploader-file-label>${filename}</joe-uploader-file-label>';
|
|
5386
5414
|
if(file.size){
|
|
@@ -5403,18 +5431,49 @@ this.renderHTMLContent = function(specs){
|
|
|
5403
5431
|
|
|
5404
5432
|
|
|
5405
5433
|
|
|
5434
|
+
// Build the label with filename and optional OpenAI file id on a new line
|
|
5435
|
+
label = '<joe-uploader-file-label>'+(file.filename || '')+'</joe-uploader-file-label>';
|
|
5436
|
+
if(file.openai_file_id){
|
|
5437
|
+
label += '<joe-uploader-file-oaid >'+file.openai_file_id+'</joe-uploader-file-oaid>';
|
|
5438
|
+
}
|
|
5439
|
+
|
|
5440
|
+
// Optional file role selector when roles are configured on this uploader
|
|
5441
|
+
var roleSelect = '';
|
|
5442
|
+
if (roles && roles.length) {
|
|
5443
|
+
var currentRole = file.file_role || '';
|
|
5444
|
+
var safeFilename = String(file.filename || '').replace(/'/g, "\\'");
|
|
5445
|
+
var optsHtml = '<option value=""></option>';
|
|
5446
|
+
roles.forEach(function(r){
|
|
5447
|
+
if (!r || !r.value) { return; }
|
|
5448
|
+
var lbl = r.label || r.value;
|
|
5449
|
+
var sel = (currentRole === r.value) ? ' selected' : '';
|
|
5450
|
+
optsHtml += '<option value="'+r.value.replace(/\"/g,'"')+'"'+sel+'>'+lbl.replace(/</g,'<').replace(/>/g,'>')+'</option>';
|
|
5451
|
+
});
|
|
5452
|
+
var onchange = "_joe.uploaderSetFileRole('"+cuid+"','"+safeFilename+"', this.value)";
|
|
5453
|
+
roleSelect = '<div class=\"joe-uploader-file-role\"><select onchange=\"'+onchange+'\">'+optsHtml+'</select></div>';
|
|
5454
|
+
}
|
|
5455
|
+
|
|
5406
5456
|
if((file.type && file.type.contains('image')) || (!file.type && (file.url||file.base64).split('.').contains(['jpg','jpeg','png','gif','svg']))){
|
|
5407
|
-
jup_template = '<joe-uploader-file class="'+(file.uploaded && 'uploaded'||'')+'" style="background-image:url(${url}${base64})">'+alink+label+filesize+delete_btn+'</joe-uploader-file>';
|
|
5457
|
+
jup_template = '<joe-uploader-file class="'+(file.uploaded && 'uploaded'||'')+'" style="background-image:url(${url}${base64})">'+alink+label+roleSelect+filesize+delete_btn+'</joe-uploader-file>';
|
|
5408
5458
|
}else if (docTypes.includes((file.url || file.base64).split('.').pop())) {
|
|
5409
5459
|
jup_template = '<joe-uploader-file class="'+(file.uploaded && 'uploaded'||'')+'">'+
|
|
5410
5460
|
'<joe-uploader-file-extension >.'+(file.type.split('/')[1] || 'docx')+'</joe-uploader-file-extension>'+
|
|
5411
|
-
alink+label+filesize+delete_btn+'</joe-uploader-file>';
|
|
5461
|
+
alink+label+roleSelect+filesize+delete_btn+'</joe-uploader-file>';
|
|
5412
5462
|
}else{
|
|
5413
5463
|
jup_template = '<joe-uploader-file class="'+(file.uploaded && 'uploaded'||'')+'">'+
|
|
5414
5464
|
'<joe-uploader-file-extension >.'+(file.type.split('/')[1] || '???')+'</joe-uploader-file-extension>'+
|
|
5415
|
-
alink+label+filesize+delete_btn+'</joe-uploader-file>';
|
|
5465
|
+
alink+label+roleSelect+filesize+delete_btn+'</joe-uploader-file>';
|
|
5416
5466
|
}
|
|
5417
|
-
|
|
5467
|
+
// Build optional OpenAI retry/upload button
|
|
5468
|
+
var openaiBtn = '';
|
|
5469
|
+
var needRetry = (!file.openai_file_id || file.openai_status == 'error');
|
|
5470
|
+
var hasUrl = !!file.url;
|
|
5471
|
+
if(hasUrl && needRetry){
|
|
5472
|
+
var openaiLabel = (file.openai_status == 'error') ? 'Retry OpenAI' : 'Upload to OpenAI';
|
|
5473
|
+
var safeFilename = (file.filename || '').replace(/'/g,"\\'");
|
|
5474
|
+
openaiBtn = '<joe-uploader-openai-btn class="joe-button" style="margin-left:6px;" onclick="_joe.SERVER.Plugins.openaiRetryFromUrl(\''+cuid+'\',\''+safeFilename+'\');">'+openaiLabel+'</joe-uploader-openai-btn>';
|
|
5475
|
+
}
|
|
5476
|
+
html += fillTemplate(jup_template,file) + openaiBtn;
|
|
5418
5477
|
})
|
|
5419
5478
|
return html+'<div class="clear"></div>';
|
|
5420
5479
|
}
|
|
@@ -5431,7 +5490,7 @@ this.renderHTMLContent = function(specs){
|
|
|
5431
5490
|
$(joe_uploader.dropzone).find('img,div').replaceWith('<img src="' + base64 + '">')
|
|
5432
5491
|
//joe_uploader.dropzone.html('<img src="' + base64 + '">');
|
|
5433
5492
|
joe_uploader.message.html('<b>'+file.name+'</b> selected');
|
|
5434
|
-
joe_uploader.confirmBtn.removeClass('hidden');
|
|
5493
|
+
joe_uploader.confirmBtn.removeClass('ui-helper-hidden hidden');
|
|
5435
5494
|
}else {
|
|
5436
5495
|
results.innerHTML = 'Nothing to upload.';
|
|
5437
5496
|
}
|
|
@@ -5462,7 +5521,7 @@ this.renderHTMLContent = function(specs){
|
|
|
5462
5521
|
}
|
|
5463
5522
|
joe_uploader.files.push(temp_file);
|
|
5464
5523
|
$(joe_uploader.preview).html(_renderUploaderFilePreviews(joe_uploader.files,joe_uploader.cuid));
|
|
5465
|
-
joe_uploader.confirmBtn.removeClass('hidden');
|
|
5524
|
+
joe_uploader.confirmBtn.removeClass('ui-helper-hidden hidden');
|
|
5466
5525
|
}else {
|
|
5467
5526
|
results.innerHTML = 'Nothing to upload.';
|
|
5468
5527
|
}
|
|
@@ -5530,6 +5589,20 @@ this.renderHTMLContent = function(specs){
|
|
|
5530
5589
|
var fileobj = joe_uploader.files.where({filename:filename})[0];
|
|
5531
5590
|
fileobj.uploaded = new Date();
|
|
5532
5591
|
fileobj.url = url;
|
|
5592
|
+
// Apply captured OpenAI info if present
|
|
5593
|
+
var key = self.current.object._id + '/' + filename;
|
|
5594
|
+
var oi = _joe._lastOpenAI && _joe._lastOpenAI[key];
|
|
5595
|
+
fileobj.openai_purpose = 'assistants';
|
|
5596
|
+
if(oi){
|
|
5597
|
+
fileobj.openai_file_id = oi.openai_file_id || null;
|
|
5598
|
+
fileobj.openai_status = (oi.openai_file_id && 'ok') || (oi.openai_error && 'error') || 'not_uploaded';
|
|
5599
|
+
fileobj.openai_error = oi.openai_error || null;
|
|
5600
|
+
if(oi.openai_error){
|
|
5601
|
+
joe_uploader.message.append('<div>OpenAI error: '+oi.openai_error+'</div>');
|
|
5602
|
+
}
|
|
5603
|
+
}else{
|
|
5604
|
+
fileobj.openai_status = fileobj.openai_status || 'not_uploaded';
|
|
5605
|
+
}
|
|
5533
5606
|
delete fileobj.base64;
|
|
5534
5607
|
}
|
|
5535
5608
|
|
|
@@ -5600,6 +5673,14 @@ this.renderHTMLContent = function(specs){
|
|
|
5600
5673
|
self.uploaders[id].dropzone = $(this).find('.joe-uploader-dropzone');
|
|
5601
5674
|
self.uploaders[id].confirmBtn = $(this).find('.joe-upload-cofirm-button');
|
|
5602
5675
|
|
|
5676
|
+
// If there are pending files (not uploaded or missing url), show the confirm button
|
|
5677
|
+
var pending = (self.uploaders[id].files || []).some(function(file){
|
|
5678
|
+
return $c.isObject(file) && (!file.uploaded || !file.url);
|
|
5679
|
+
});
|
|
5680
|
+
if(pending){
|
|
5681
|
+
self.uploaders[id].confirmBtn.removeClass('ui-helper-hidden hidden');
|
|
5682
|
+
}
|
|
5683
|
+
|
|
5603
5684
|
});
|
|
5604
5685
|
};
|
|
5605
5686
|
encapsulateFieldType('uploader',self.renderUploaderField,
|
|
@@ -9936,6 +10017,13 @@ logit(intent)
|
|
|
9936
10017
|
url = prefix+response.Key;
|
|
9937
10018
|
}
|
|
9938
10019
|
var filename = response.Key.replace(self.current.object._id+'/','');
|
|
10020
|
+
// Stash OpenAI info for use during finalization
|
|
10021
|
+
_joe._lastOpenAI = _joe._lastOpenAI || {};
|
|
10022
|
+
_joe._lastOpenAI[response.Key] = {
|
|
10023
|
+
openai_file_id: response.openai_file_id,
|
|
10024
|
+
openai_purpose: response.openai_purpose,
|
|
10025
|
+
openai_error: response.openai_error
|
|
10026
|
+
};
|
|
9939
10027
|
if(field.url_field){
|
|
9940
10028
|
var nprop = {};
|
|
9941
10029
|
_joe.current.object[field.url_field] = url;
|
|
@@ -9960,6 +10048,53 @@ logit(intent)
|
|
|
9960
10048
|
file: { base64:data.base64, extension:data.extension, type:data.contentType, filename: (_joe.current.object._id+data.extension), name: (_joe.current.object._id+data.extension) },
|
|
9961
10049
|
field: data.field
|
|
9962
10050
|
}, callback);
|
|
10051
|
+
},
|
|
10052
|
+
// Retry uploading a specific file to OpenAI using its URL.
|
|
10053
|
+
// Invoked by the uploader row action.
|
|
10054
|
+
openaiRetryFromUrl:function(uploader_id, filename){
|
|
10055
|
+
try{
|
|
10056
|
+
var joe_uploader = self.uploaders[uploader_id];
|
|
10057
|
+
if(!joe_uploader){ return alert('Uploader not found'); }
|
|
10058
|
+
var file = joe_uploader.files.where({filename:filename})[0];
|
|
10059
|
+
if(!file){ return alert('File not found'); }
|
|
10060
|
+
if(!file.url){ return alert('No URL to upload to OpenAI'); }
|
|
10061
|
+
var btn = $(joe_uploader.preview).find("joe-uploader-openai-btn:contains('"+filename+"')");
|
|
10062
|
+
joe_uploader.message.append('<div>Uploading to OpenAI...</div>');
|
|
10063
|
+
$.ajax({
|
|
10064
|
+
url: (location.port && '//'+__jsc.hostname+':'+__jsc.port+'/API/plugin/chatgpt/filesRetryFromUrl/') || '//'+__jsc.hostname+'/API/plugin/chatgpt/filesRetryFromUrl/',
|
|
10065
|
+
type:'POST',
|
|
10066
|
+
data:{
|
|
10067
|
+
url:file.url,
|
|
10068
|
+
filename:file.filename,
|
|
10069
|
+
contentType:file.type
|
|
10070
|
+
},
|
|
10071
|
+
success:function(resp){
|
|
10072
|
+
if(resp && resp.success && resp.openai_file_id){
|
|
10073
|
+
file.openai_file_id = resp.openai_file_id;
|
|
10074
|
+
file.openai_purpose = resp.openai_purpose || 'assistants';
|
|
10075
|
+
file.openai_status = 'ok';
|
|
10076
|
+
file.openai_error = null;
|
|
10077
|
+
joe_uploader.message.append('<div>OpenAI file attached</div>');
|
|
10078
|
+
}else{
|
|
10079
|
+
file.openai_status = 'error';
|
|
10080
|
+
file.openai_error = (resp && resp.error) || 'Upload failed';
|
|
10081
|
+
joe_uploader.message.append('<div>OpenAI error: '+(file.openai_error)+'</div>');
|
|
10082
|
+
}
|
|
10083
|
+
// Refresh preview to reflect new status/button
|
|
10084
|
+
$(joe_uploader.preview).html(_renderUploaderFilePreviews(joe_uploader.files,joe_uploader.cuid));
|
|
10085
|
+
// Save object so file metadata is persisted
|
|
10086
|
+
self.updateObject(null, null, true);
|
|
10087
|
+
},
|
|
10088
|
+
error:function(xhr,status,err){
|
|
10089
|
+
var message = (xhr && (xhr.responseJSON && (xhr.responseJSON.error || xhr.responseJSON.code) || xhr.responseText)) || err || status || 'Retry failed';
|
|
10090
|
+
file.openai_status = 'error';
|
|
10091
|
+
file.openai_error = message;
|
|
10092
|
+
joe_uploader.message.append('<div>OpenAI error: '+message+'</div>');
|
|
10093
|
+
}
|
|
10094
|
+
});
|
|
10095
|
+
}catch(e){
|
|
10096
|
+
alert(e && e.message || e);
|
|
10097
|
+
}
|
|
9963
10098
|
}
|
|
9964
10099
|
},
|
|
9965
10100
|
ready:{
|