json-object-editor 0.10.633 → 0.10.638
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 +10 -0
- package/_www/matrix.html +126 -0
- package/_www/mcp-nav.js +6 -0
- package/_www/mcp-prompt.html +116 -116
- package/_www/mcp-schemas.html +32 -2
- package/css/joe-styles.css +6 -2
- package/css/joe.css +6 -3
- package/css/joe.min.css +1 -1
- package/docs/JOE_AI_Overview.md +330 -0
- package/favicon-dev.png +0 -0
- package/js/JsonObjectEditor.jquery.craydent.js +8 -2
- package/js/favicon-env.js +50 -0
- package/js/joe-ai.js +9 -4
- package/js/joe.js +9 -3
- package/js/joe.min.js +1 -1
- package/package.json +1 -1
- package/pages/joe.html +6 -4
- package/pages/template.html +5 -4
- package/pages/template_ie.html +5 -4
- package/readme.md +8 -4
- package/server/app-config.js +2 -0
- package/server/modules/Apps.js +3 -0
- package/server/plugins/chatgpt.js +36 -11
- package/server/schemas/ai_widget_conversation.js +229 -229
- package/server/schemas/form.js +51 -7
- package/server/schemas/location.js +24 -0
- package/server/schemas/member.js +35 -0
- package/server/schemas/question.js +55 -2
- package/server/schemas/submission.js +30 -0
- package/web-components/joe-matrix.css +480 -0
- package/web-components/joe-matrix.js +1065 -0
package/package.json
CHANGED
package/pages/joe.html
CHANGED
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name='viewport' content='initial-scale=1.0, user-scalable=no' />
|
|
6
6
|
<title>${this.webconfig.name} JOE</title>
|
|
7
|
-
<link rel="shortcut icon" href="/JsonObjectEditor/favicon.ico" type="image/x-icon">
|
|
8
|
-
<link rel="icon" href="/JsonObjectEditor/favicon.ico" type="image/x-icon">
|
|
9
|
-
<link rel="icon" sizes="192x192" href="/JsonObjectEditor/img/ico/android-icon-192x192.png">
|
|
10
|
-
<link rel="apple-touch-icon" sizes="144x144" href="/JsonObjectEditor/img/ico/android-icon-144x144.png" />
|
|
7
|
+
<link rel="shortcut icon" href="/JsonObjectEditor/favicon.ico" type="image/x-icon" id="favicon-shortcut">
|
|
8
|
+
<link rel="icon" href="/JsonObjectEditor/favicon.ico" type="image/x-icon" id="favicon-icon">
|
|
9
|
+
<link rel="icon" sizes="192x192" href="/JsonObjectEditor/img/ico/android-icon-192x192.png" id="favicon-192">
|
|
10
|
+
<link rel="apple-touch-icon" sizes="144x144" href="/JsonObjectEditor/img/ico/android-icon-144x144.png" id="favicon-apple" />
|
|
11
|
+
<script src="/JsonObjectEditor/js/favicon-env.js"></script>
|
|
12
|
+
|
|
11
13
|
<meta name="joe-notes" content="joe.html template" >
|
|
12
14
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
13
15
|
<meta name="mobile-web-app-capable" content="yes">
|
package/pages/template.html
CHANGED
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
<meta name='viewport' content='initial-scale=1.0, user-scalable=no' >
|
|
7
7
|
<title> ${this.webconfig.name} > ${APPNAME} </title>
|
|
8
8
|
<script src="/JsonObjectEditor/js/libs/adapter-latest.js"></script>
|
|
9
|
-
<link rel="shortcut icon" href="/JsonObjectEditor/favicon.ico" type="image/x-icon">
|
|
10
|
-
<link rel="icon" href="/JsonObjectEditor/favicon.ico" type="image/x-icon">
|
|
11
|
-
<link rel="icon" sizes="192x192" href="/JsonObjectEditor/img/ico/android-icon-192x192.png">
|
|
12
|
-
<link rel="apple-touch-icon" sizes="144x144" href="/JsonObjectEditor/img/ico/android-icon-144x144.png" />
|
|
9
|
+
<link rel="shortcut icon" href="/JsonObjectEditor/favicon.ico" type="image/x-icon" id="favicon-shortcut">
|
|
10
|
+
<link rel="icon" href="/JsonObjectEditor/favicon.ico" type="image/x-icon" id="favicon-icon">
|
|
11
|
+
<link rel="icon" sizes="192x192" href="/JsonObjectEditor/img/ico/android-icon-192x192.png" id="favicon-192">
|
|
12
|
+
<link rel="apple-touch-icon" sizes="144x144" href="/JsonObjectEditor/img/ico/android-icon-144x144.png" id="favicon-apple" />
|
|
13
|
+
<script src="/JsonObjectEditor/js/favicon-env.js"></script>
|
|
13
14
|
|
|
14
15
|
<meta name="joe-notes" content="template.html template" >
|
|
15
16
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
package/pages/template_ie.html
CHANGED
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
<meta name='viewport' content='initial-scale=1.0, user-scalable=no' >
|
|
9
9
|
<title> ${this.webconfig.name} > ${APPNAME} </title>
|
|
10
10
|
<script src="/JsonObjectEditor/js/libs/adapter-latest.js"></script>
|
|
11
|
-
<link rel="shortcut icon" href="/JsonObjectEditor/favicon.ico" type="image/x-icon">
|
|
12
|
-
<link rel="icon" href="/JsonObjectEditor/favicon.ico" type="image/x-icon">
|
|
13
|
-
<link rel="icon" sizes="192x192" href="/JsonObjectEditor/img/ico/android-icon-192x192.png">
|
|
14
|
-
<link rel="apple-touch-icon" sizes="144x144" href="/JsonObjectEditor/img/ico/android-icon-144x144.png" />
|
|
11
|
+
<link rel="shortcut icon" href="/JsonObjectEditor/favicon.ico" type="image/x-icon" id="favicon-shortcut">
|
|
12
|
+
<link rel="icon" href="/JsonObjectEditor/favicon.ico" type="image/x-icon" id="favicon-icon">
|
|
13
|
+
<link rel="icon" sizes="192x192" href="/JsonObjectEditor/img/ico/android-icon-192x192.png" id="favicon-192">
|
|
14
|
+
<link rel="apple-touch-icon" sizes="144x144" href="/JsonObjectEditor/img/ico/android-icon-144x144.png" id="favicon-apple" />
|
|
15
|
+
<script src="/JsonObjectEditor/js/favicon-env.js"></script>
|
|
15
16
|
|
|
16
17
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
17
18
|
<meta name="mobile-web-app-capable" content="yes">
|
package/readme.md
CHANGED
|
@@ -37,10 +37,14 @@ JOE is software that allows you to manage data models via JSON objects. There ar
|
|
|
37
37
|
- Auth
|
|
38
38
|
- If users exist, `POST /mcp` requires cookie or Basic Auth (same as other APIs). If no users configured, it is effectively open.
|
|
39
39
|
|
|
40
|
-
- Test
|
|
41
|
-
- JOE ships
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
- Test pages
|
|
41
|
+
- JOE ships several debug/test pages in `/_www/`:
|
|
42
|
+
- `mcp-test.html` - Simple MCP tool tester
|
|
43
|
+
- `mcp-schemas.html` - Schema health and summary viewer
|
|
44
|
+
- `mcp-prompt.html` - MCP prompt/instructions viewer
|
|
45
|
+
- `matrix.html` - Interactive schema relationship visualization with D3.js force-directed graph
|
|
46
|
+
- Access via JOE path: `http://localhost:<PORT>/JsonObjectEditor/_www/<page>.html`
|
|
47
|
+
- If your host app serves its own `_www`, pages can also be available at the root (fallback) if running with the updated server that mounts JOE’s `_www` as a secondary static directory. Then: `http://localhost:<PORT>/<page>.html`
|
|
44
48
|
|
|
45
49
|
- Tools
|
|
46
50
|
- `listSchemas(name?)`, `getSchema(name)`
|
package/server/app-config.js
CHANGED
|
@@ -17,6 +17,8 @@ var apps = function(){
|
|
|
17
17
|
(_joe.search({}).length)+ ' objects';
|
|
18
18
|
if(_joe.User && _joe.User.role == 'super'){
|
|
19
19
|
message+='<br/><br/><joe-button onclick="_joe.SERVER.Cache.reload()" class="joe-button joe-iconed-button joe-grey-button joe-red-button joe-reload-button"> reload cache </joe-button>';
|
|
20
|
+
//add horizontal rule then text links to schems page and matrix page
|
|
21
|
+
message+=`<hr/> <a href="/schemas.html">schemas</a> <a href="/matrix.html">matrix</a>`;
|
|
20
22
|
}
|
|
21
23
|
return message;
|
|
22
24
|
},
|
package/server/modules/Apps.js
CHANGED
|
@@ -39,6 +39,7 @@ function Apps(){
|
|
|
39
39
|
title:specs.title||'<small>JOE Platform v'+JOE.VERSION+'</small>',
|
|
40
40
|
cssclass:'w2 h1',
|
|
41
41
|
content:function(){
|
|
42
|
+
var app = APPINFO || {};
|
|
42
43
|
if(!_joe.Data || !_joe.Data.user){return 'loading data';}
|
|
43
44
|
//console.log(_joe.Data.user);
|
|
44
45
|
|
|
@@ -74,6 +75,8 @@ function Apps(){
|
|
|
74
75
|
message+='<joe-button onclick="_joe.SERVER.Cache.reload()" class="joe-button joe-iconed-button joe-grey-button joe-red-button joe-reload-button"> re-cache </joe-button>';
|
|
75
76
|
}
|
|
76
77
|
+'</div><joe-clear></joe-clear>';
|
|
78
|
+
//add horizontal rule then text links to schems page and matrix page
|
|
79
|
+
message+='<a href="/mcp-schemas.html?app='+app.title.toLowerCase()+'" target="mcp_schemas_win">schemas</a> <a href="/matrix.html?app='+app.title.toLowerCase()+'" target="matrix_win">matrix</a>';
|
|
77
80
|
return message;
|
|
78
81
|
}
|
|
79
82
|
|
|
@@ -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 ... ```)
|
|
584
|
-
//
|
|
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
|
-
//
|
|
589
|
-
|
|
590
|
-
|
|
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
|
|
604
|
-
|
|
605
|
-
|
|
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;
|