json-object-editor 0.10.633 → 0.10.636

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-object-editor",
3
- "version": "0.10.633",
3
+ "version": "0.10.636",
4
4
  "description": "JOE the Json Object Editor | Platform Edition",
5
5
  "main": "app.js",
6
6
  "scripts": {
@@ -580,16 +580,21 @@ function shrinkUnderstandObjectMessagesForTokens(messages) {
580
580
  }
581
581
 
582
582
  // Normalize model output that should contain JSON. Models often wrap JSON
583
- // in markdown fences (```json ... ```); this helper strips fences and
584
- // attempts to isolate the first well-formed JSON object substring.
583
+ // in markdown fences (```json ... ```), and may prepend/append prose. This
584
+ // helper strips fences and tries to isolate the first well-formed JSON
585
+ // object/array substring so JSON.parse has the best chance of succeeding.
585
586
  function extractJsonText(raw) {
586
587
  if (!raw) { return ''; }
587
588
  let t = String(raw).trim();
588
- // Strip leading ```... fence
589
- if (t.startsWith('```')) {
590
- const firstNewline = t.indexOf('\n');
589
+ // If there is any ```...``` fenced block, prefer its contents.
590
+ const fenceIdx = t.indexOf('```json') !== -1 ? t.indexOf('```json') : t.indexOf('```');
591
+ if (fenceIdx !== -1) {
592
+ let start = fenceIdx;
593
+ const firstNewline = t.indexOf('\n', start);
591
594
  if (firstNewline !== -1) {
592
595
  t = t.substring(firstNewline + 1);
596
+ } else {
597
+ t = t.substring(start + 3);
593
598
  }
594
599
  const lastFence = t.lastIndexOf('```');
595
600
  if (lastFence !== -1) {
@@ -597,12 +602,17 @@ function shrinkUnderstandObjectMessagesForTokens(messages) {
597
602
  }
598
603
  t = t.trim();
599
604
  }
600
- // If there's extra prose around the JSON, slice from first { to last }
601
- if (t[0] !== '{') {
605
+ // If there's extra prose around the JSON, slice from first {/[ to last }/]
606
+ if (t[0] !== '{' && t[0] !== '[') {
602
607
  const firstBrace = t.indexOf('{');
603
- const lastBrace = t.lastIndexOf('}');
604
- if (firstBrace !== -1 && lastBrace !== -1 && lastBrace > firstBrace) {
605
- t = t.slice(firstBrace, lastBrace + 1);
608
+ const firstBracket = t.indexOf('[');
609
+ let first = -1;
610
+ if (firstBrace === -1) { first = firstBracket; }
611
+ else if (firstBracket === -1) { first = firstBrace; }
612
+ else { first = Math.min(firstBrace, firstBracket); }
613
+ const lastBrace = Math.max(t.lastIndexOf('}'), t.lastIndexOf(']'));
614
+ if (first !== -1 && lastBrace !== -1 && lastBrace > first) {
615
+ t = t.slice(first, lastBrace + 1);
606
616
  }
607
617
  }
608
618
  return t.trim();
@@ -656,7 +666,7 @@ function shrinkUnderstandObjectMessagesForTokens(messages) {
656
666
  }, null, ' ');
657
667
 
658
668
  const openai = newClient();
659
- const model = body.model || 'gpt-4o-mini';
669
+ const model = body.model || 'gpt-4o-mini';////'gpt-5-nano';
660
670
 
661
671
  // For simplicity and robustness, use plain text output and instruct the
662
672
  // model to return a strict JSON object. We previously attempted the
@@ -667,6 +677,14 @@ function shrinkUnderstandObjectMessagesForTokens(messages) {
667
677
  instructions: systemText,
668
678
  input: userInput
669
679
  };
680
+ // Optional web_search tool: if the caller sets allow_web truthy, expose
681
+ // the built-in web_search capability and let the model decide when to
682
+ // call it.
683
+ if (body.allow_web) {
684
+ coloredLog("allowing web search");
685
+ requestBase.tools = [{ type: 'web_search' }];
686
+ requestBase.tool_choice = 'auto';
687
+ }
670
688
 
671
689
  let response;
672
690
  if (assistantId) {
@@ -706,6 +724,13 @@ function shrinkUnderstandObjectMessagesForTokens(messages) {
706
724
  filteredPatch[f] = patch[f];
707
725
  }
708
726
  });
727
+ // If we got no fields back on the first attempt, retry once before
728
+ // giving up. Avoid infinite loops by marking a retry flag.
729
+ if (!Object.keys(filteredPatch).length && !body._retry) {
730
+ coloredLog('[autofill] empty patch, retrying once');
731
+ const retryBody = Object.assign({}, body, { _retry: true });
732
+ return await self.autofill(retryBody, req, res);
733
+ }
709
734
 
710
735
  // Optional save
711
736
  let savedItem = null;
@@ -25,7 +25,7 @@ var form ={
25
25
  {section_start:'Content'},
26
26
  {name:'sections',type:'objectList',properties:['name','id'],comment:'name will be displayed, id is for css and js'},
27
27
  // {name:'questions',type:'objectReference',values:'question'},
28
- {name:'questions',type:'buckets',values:'question',
28
+ {name:'questions',type:'buckets',values:'question',reloadable:true,
29
29
  comment:'Drag questions to the section of the form they belong in. <joe-button onclick="_joe.Fields.rerender(\'questions\');" class="joe-reload-button joe-button joe-iconed-button">reload form sections</joe-button>',
30
30
  bucketCount:function(item){
31
31
  return (item.sections && item.sections.length) || 1;
@@ -37,12 +37,15 @@ var form ={
37
37
  })
38
38
  return names;
39
39
  },
40
- template:'<joe-subtext>${question_type}</joe-subtext><joe-title>${name}</joe-title><joe-subtitle>${fieldname}</joe-subtitle>'
41
-
40
+ template:function(f,q){
41
+ return `<joe-subtext>${q.question_type}</joe-subtext>
42
+ <joe-title>${q.name}</joe-title>
43
+ <joe-subtitle>${q.title || ''}</joe-subtitle>
44
+ <joe-subtitle>${q.fieldname||''}</joe-subtitle>`;
45
+ }
42
46
  },
43
47
  {section_end:'Content'},
44
- {section_start:'Submission'},
45
- {label:'Submit Action'},
48
+ {section_start:'Functions',collapsed:true},
46
49
 
47
50
  {label:'On Client'},
48
51
  {name:'validate',type:'code',language:'javascript',
@@ -53,7 +56,7 @@ var form ={
53
56
  {label:'On Server'},
54
57
  {name:'server_action',type:'code',language:'javascript',
55
58
  comment:'function called on server, function(submission,form_info,request)'},
56
- {section_end:'Submission'},
59
+ {section_end:'Functions'},
57
60
  {sidebar_start:'right'},
58
61
  'updated',
59
62
  {section_start:'Preview'},
@@ -71,7 +74,7 @@ var form ={
71
74
  },
72
75
  {section_end:'Preview'},
73
76
  {section_start:'Adv'},
74
- 'form_button_label',
77
+ {name:'form_button_label',display:'form button label',type:'text',comment:'label for the form submit button'},
75
78
  {name:'hostname',comment:'joe hostname'},
76
79
  {name:'save_submission', type:'boolean', display:'save submission',comment:"use standard submission object"},
77
80
  {name:'upsert_submission', type:'boolean', display:'upsert submission',
@@ -1,6 +1,23 @@
1
1
  var question ={
2
2
  title: 'Q | ${name}',
3
3
  info:"The question panel is where you can manage the questions used to build a form.",
4
+ subsets:function(){
5
+ return [{name:'Required',filter:{required:true},stripeColor:'#ff9999'}
6
+
7
+ ].concat(_joe.Filter.Options.getDatasetPropertyValues(
8
+ 'question',
9
+ 'question_type',
10
+ { group: 'fieldtype', collapsed: false } // optional grouping
11
+ ));
12
+ },
13
+ stripeColor:function(item){
14
+ if(item.required){
15
+ return {
16
+ title:'Required',
17
+ color:'#ff9999'
18
+ };
19
+ }
20
+ },
4
21
  filters:function(item){
5
22
  return _joe.Filter.Options.tags({group:true,untagged:true,collapsed:true});
6
23
  },
@@ -20,12 +37,12 @@ var question ={
20
37
  return (['multiple','select'].indexOf(item.question_type) == -1);
21
38
  }
22
39
  },
23
- {name:'option_template',width:'33%',
40
+ {name:'option_template',width:'33%',display:'option template',comment:'template for each option, use ${property} to display the property value.',
24
41
  hidden:function(item){
25
42
  return (['multiple','select'].indexOf(item.question_type) == -1);
26
43
  }
27
44
  },
28
- {name:'value_template',width:'33%',
45
+ {name:'value_template',width:'33%',display:'value template',comment:'defaults to _id',
29
46
  hidden:function(item){
30
47
  return (['multiple','select'].indexOf(item.question_type) == -1);
31
48
  }