json-object-editor 0.10.623 → 0.10.625
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 +9 -0
- package/_www/mcp-export.html +5 -5
- package/_www/mcp-prompt.html +1 -1
- package/_www/mcp-test.html +4 -4
- package/docs/joe_agent_custom_gpt_instructions_v_3.md +123 -0
- package/js/JsonObjectEditor.jquery.craydent.js +2 -2
- package/js/joe.js +20 -20
- package/js/joe.min.js +1 -1
- package/package.json +1 -1
- package/readme.md +9 -9
- package/server/modules/MCP.js +30 -24
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -44,12 +44,12 @@ JOE is software that allows you to manage data models via JSON objects. There ar
|
|
|
44
44
|
|
|
45
45
|
- Tools
|
|
46
46
|
- `listSchemas(name?)`, `getSchema(name)`
|
|
47
|
-
- `getObject(_id,
|
|
47
|
+
- `getObject(_id, itemtype?)` (supports optional `flatten` and `depth`)
|
|
48
48
|
- `search` (exact): unified tool for cache and storage
|
|
49
|
-
- Params: `{
|
|
50
|
-
- Defaults to cache across all collections; add `
|
|
49
|
+
- Params: `{ itemtype?, query?, ids?, source?: 'cache'|'storage', limit?, flatten?, depth? }`
|
|
50
|
+
- Defaults to cache across all collections; add `itemtype` to filter; set `source:"storage"` to query a specific collection in the DB. Runtime accepts legacy alias `schema` (maps to `itemtype`). Use `fuzzySearch` for typo-tolerant free text.
|
|
51
51
|
- `fuzzySearch` (typo-tolerant free text across weighted fields)
|
|
52
|
-
- Params: `{
|
|
52
|
+
- Params: `{ itemtype?, q, filters?, fields?, threshold?, limit?, offset?, highlight?, minQueryLength? }`
|
|
53
53
|
- Defaults: `fields` resolved from schema `searchables` (plural) if present; otherwise weights `name:0.6, info:0.3, description:0.1`. `threshold:0.5`, `limit:50`, `minQueryLength:2`.
|
|
54
54
|
- Returns: `{ items, count }`. Each item may include `_score` (0..1) and `_matches` when `highlight` is true.
|
|
55
55
|
- `saveObject({ object })`
|
|
@@ -86,17 +86,17 @@ JOE is software that allows you to manage data models via JSON objects. There ar
|
|
|
86
86
|
```
|
|
87
87
|
- fuzzySearch (cache):
|
|
88
88
|
```powershell
|
|
89
|
-
$body = @{ jsonrpc="2.0"; id="6"; method="fuzzySearch"; params=@{
|
|
89
|
+
$body = @{ jsonrpc="2.0"; id="6"; method="fuzzySearch"; params=@{ itemtype="<schemaName>"; q="st paal"; threshold=0.35; limit=10 } } | ConvertTo-Json -Depth 10
|
|
90
90
|
Invoke-RestMethod -Method Post -Uri "$base/mcp" -Headers $h -Body $body
|
|
91
91
|
```
|
|
92
92
|
- search (storage):
|
|
93
93
|
```powershell
|
|
94
|
-
$body = @{ jsonrpc="2.0"; id="4"; method="search"; params=@{
|
|
94
|
+
$body = @{ jsonrpc="2.0"; id="4"; method="search"; params=@{ itemtype="<schemaName>"; source="storage"; query=@{ }; limit=10 } } | ConvertTo-Json -Depth 10
|
|
95
95
|
Invoke-RestMethod -Method Post -Uri "$base/mcp" -Headers $h -Body $body
|
|
96
96
|
```
|
|
97
97
|
- search (ids + flatten):
|
|
98
98
|
```powershell
|
|
99
|
-
$body = @{ jsonrpc="2.0"; id="5"; method="search"; params=@{
|
|
99
|
+
$body = @{ jsonrpc="2.0"; id="5"; method="search"; params=@{ itemtype="<schemaName>"; ids=@("<id1>","<id2>"); flatten=$true; depth=2 } } | ConvertTo-Json -Depth 10
|
|
100
100
|
Invoke-RestMethod -Method Post -Uri "$base/mcp" -Headers $h -Body $body
|
|
101
101
|
```
|
|
102
102
|
- saveObject:
|
|
@@ -131,13 +131,13 @@ JOE is software that allows you to manage data models via JSON objects. There ar
|
|
|
131
131
|
```bash
|
|
132
132
|
curl -s -X POST http://localhost:<PORT>/mcp \
|
|
133
133
|
-H 'Content-Type: application/json' \
|
|
134
|
-
-d '{"jsonrpc":"2.0","id":"6","method":"fuzzySearch","params":{"
|
|
134
|
+
-d '{"jsonrpc":"2.0","id":"6","method":"fuzzySearch","params":{"itemtype":"<schemaName>","q":"st paal","threshold":0.35,"limit":10}}' | jq
|
|
135
135
|
```
|
|
136
136
|
- search (storage):
|
|
137
137
|
```bash
|
|
138
138
|
curl -s -X POST http://localhost:<PORT>/mcp \
|
|
139
139
|
-H 'Content-Type: application/json' \
|
|
140
|
-
-d '{"jsonrpc":"2.0","id":"4","method":"search","params":{"
|
|
140
|
+
-d '{"jsonrpc":"2.0","id":"4","method":"search","params":{"itemtype":"<schemaName>","source":"storage","query":{},"limit":10}}' | jq
|
|
141
141
|
```
|
|
142
142
|
```bash
|
|
143
143
|
curl -s -X POST http://localhost:<PORT>/mcp \
|
package/server/modules/MCP.js
CHANGED
|
@@ -125,19 +125,21 @@ MCP.tools = {
|
|
|
125
125
|
}
|
|
126
126
|
},
|
|
127
127
|
|
|
128
|
-
// Convenience: fetch a single object by _id (
|
|
129
|
-
|
|
128
|
+
// Convenience: fetch a single object by _id (itemtype optional). Prefer cache; fallback to storage.
|
|
129
|
+
// Accepts legacy alias 'schema' for itemtype.
|
|
130
|
+
getObject: async ({ _id, itemtype, schema, flatten = false, depth = 1 }, _ctx) => {
|
|
130
131
|
if (!_id) throw new Error("Missing required param '_id'");
|
|
132
|
+
itemtype = itemtype || schema; // legacy alias
|
|
131
133
|
// Fast path via global lookup
|
|
132
134
|
let obj = (JOE && JOE.Cache && JOE.Cache.findByID) ? (JOE.Cache.findByID(_id) || null) : null;
|
|
133
|
-
if (!obj &&
|
|
134
|
-
const results = await loadFromStorage(
|
|
135
|
+
if (!obj && itemtype) {
|
|
136
|
+
const results = await loadFromStorage(itemtype, { _id });
|
|
135
137
|
obj = (results && results[0]) || null;
|
|
136
138
|
}
|
|
137
|
-
if (!obj &&
|
|
138
|
-
obj = JOE.Cache.findByID(
|
|
139
|
+
if (!obj && itemtype && JOE && JOE.Cache && JOE.Cache.findByID) {
|
|
140
|
+
obj = JOE.Cache.findByID(itemtype, _id) || null;
|
|
139
141
|
}
|
|
140
|
-
if (!obj) throw new Error(`Object not found${
|
|
142
|
+
if (!obj) throw new Error(`Object not found${itemtype?(' in '+itemtype):''} with _id: ${_id}`);
|
|
141
143
|
if (flatten && JOE && JOE.Utils && JOE.Utils.flattenObject) {
|
|
142
144
|
try { return sanitizeItems(JOE.Utils.flattenObject(_id, { recursive: true, depth }))[0]; } catch(e) {}
|
|
143
145
|
}
|
|
@@ -153,23 +155,25 @@ MCP.tools = {
|
|
|
153
155
|
searchCache: async () => { throw new Error('Use search instead'); },
|
|
154
156
|
*/
|
|
155
157
|
|
|
156
|
-
// Unified search: defaults to cache; set source="storage" to query DB for a
|
|
157
|
-
|
|
158
|
+
// Unified search: defaults to cache; set source="storage" to query DB for a given itemtype
|
|
159
|
+
// Accepts legacy alias 'schema' for itemtype.
|
|
160
|
+
search: async ({ itemtype, schema, query = {}, ids, source = 'cache', limit = 50, offset = 0, flatten = false, depth = 1, countOnly = false, withCount = false, sortBy, sortDir = 'desc', slim = false }, _ctx) => {
|
|
161
|
+
itemtype = itemtype || schema; // legacy alias
|
|
158
162
|
const useCache = !source || source === 'cache';
|
|
159
163
|
const useStorage = source === 'storage';
|
|
160
164
|
|
|
161
165
|
if (ids && !Array.isArray(ids)) throw new Error("'ids' must be an array if provided");
|
|
162
166
|
|
|
163
|
-
// When ids are provided and
|
|
164
|
-
if (Array.isArray(ids) &&
|
|
167
|
+
// When ids are provided and an itemtype is known, prefer cache for safety/speed
|
|
168
|
+
if (Array.isArray(ids) && itemtype) {
|
|
165
169
|
let items = [];
|
|
166
170
|
if (JOE && JOE.Cache && JOE.Cache.findByID) {
|
|
167
|
-
const found = JOE.Cache.findByID(
|
|
171
|
+
const found = JOE.Cache.findByID(itemtype, ids.join(',')) || [];
|
|
168
172
|
items = Array.isArray(found) ? found : (found ? [found] : []);
|
|
169
173
|
}
|
|
170
174
|
if (useStorage && (!items || items.length === 0)) {
|
|
171
175
|
try {
|
|
172
|
-
const fromStorage = await loadFromStorage(
|
|
176
|
+
const fromStorage = await loadFromStorage(itemtype, { _id: { $in: ids } });
|
|
173
177
|
items = fromStorage || [];
|
|
174
178
|
} catch (e) { /* ignore storage errors here */ }
|
|
175
179
|
}
|
|
@@ -192,7 +196,7 @@ MCP.tools = {
|
|
|
192
196
|
if (useCache) {
|
|
193
197
|
if (!JOE || !JOE.Cache || !JOE.Cache.search) throw new Error('Cache not initialized');
|
|
194
198
|
let results = JOE.Cache.search(query || {});
|
|
195
|
-
if (
|
|
199
|
+
if (itemtype) results = (results || []).filter(i => i && i.itemtype === itemtype);
|
|
196
200
|
results = sortItems(results, sortBy, sortDir);
|
|
197
201
|
if (countOnly) {
|
|
198
202
|
return { count: (results || []).length };
|
|
@@ -206,8 +210,8 @@ MCP.tools = {
|
|
|
206
210
|
}
|
|
207
211
|
|
|
208
212
|
if (useStorage) {
|
|
209
|
-
if (!
|
|
210
|
-
const results = await loadFromStorage(
|
|
213
|
+
if (!itemtype) throw new Error("'itemtype' is required when source=storage");
|
|
214
|
+
const results = await loadFromStorage(itemtype, query || {});
|
|
211
215
|
let sorted = sortItems(results, sortBy, sortDir);
|
|
212
216
|
if (countOnly) {
|
|
213
217
|
return { count: (sorted || []).length };
|
|
@@ -227,7 +231,9 @@ MCP.tools = {
|
|
|
227
231
|
},
|
|
228
232
|
|
|
229
233
|
// Fuzzy, typo-tolerant search over cache with weighted fields
|
|
230
|
-
|
|
234
|
+
// Accepts legacy alias 'schema' for itemtype.
|
|
235
|
+
fuzzySearch: async ({ itemtype, schema, q, filters = {}, fields, threshold = 0.35, limit = 50, offset = 0, highlight = false, minQueryLength = 2 }, _ctx) => {
|
|
236
|
+
itemtype = itemtype || schema; // legacy alias
|
|
231
237
|
if (!q || (q+'').length < (minQueryLength||2)) {
|
|
232
238
|
return { items: [] };
|
|
233
239
|
}
|
|
@@ -235,7 +241,7 @@ MCP.tools = {
|
|
|
235
241
|
var query = Object.assign({}, filters || {});
|
|
236
242
|
query.$fuzzy = { q, fields, threshold, limit, offset, highlight, minQueryLength };
|
|
237
243
|
var results = JOE.Cache.search(query) || [];
|
|
238
|
-
if (
|
|
244
|
+
if (itemtype) { results = results.filter(function(i){ return i && i.itemtype === itemtype; }); }
|
|
239
245
|
var total = (typeof results.count === 'number') ? results.count : results.length;
|
|
240
246
|
if (typeof limit === 'number' && limit > 0) { results = results.slice(0, limit); }
|
|
241
247
|
return { items: sanitizeItems(results), count: total };
|
|
@@ -372,12 +378,12 @@ MCP.descriptions = {
|
|
|
372
378
|
listSchemas: "List all available JOE schema names.",
|
|
373
379
|
getSchema: "Retrieve schema by name. Set summaryOnly=true for normalized summary instead of full schema.",
|
|
374
380
|
getSchemas: "Retrieve multiple schemas. With summaryOnly=true, returns summaries; if names omitted, returns all.",
|
|
375
|
-
getObject: "Fetch a single object by _id (
|
|
381
|
+
getObject: "Fetch a single object by _id (itemtype optional). Supports optional flatten. Accepts legacy alias 'schema' for itemtype.",
|
|
376
382
|
// getObjectsByIds: "Deprecated - use 'search' with ids.",
|
|
377
383
|
// queryObjects: "Deprecated - use 'search'.",
|
|
378
384
|
// searchCache: "Deprecated - use 'search'.",
|
|
379
|
-
search: "Exact search. Defaults to cache; set source=storage to query DB. Supports sortBy/sortDir, offset/limit paging, withCount, and slim response for {_id,itemtype,name,info,joeUpdated,created}. Use fuzzySearch for typo-tolerant free text.",
|
|
380
|
-
fuzzySearch: "Fuzzy free‑text search. Candidates are prefiltered by 'filters' (e.g., { itemtype: 'user' }) and then scored. If 'fields' are omitted, the schema's searchables (strings) are used with best-field scoring; provide 'fields' (strings or {path,weight}) to use weighted sums. Examples: { q: 'corey hadden', filters: { itemtype: 'user' } } or { q: 'backyard', filters: { itemtype: 'house' } }.",
|
|
385
|
+
search: "Exact search. Defaults to cache; set source=storage to query DB. Supports sortBy/sortDir, offset/limit paging, withCount, and slim response for {_id,itemtype,name,info,joeUpdated,created}. Accepts legacy alias 'schema' for itemtype. Use fuzzySearch for typo-tolerant free text.",
|
|
386
|
+
fuzzySearch: "Fuzzy free‑text search. Candidates are prefiltered by 'filters' (e.g., { itemtype: 'user' }) and then scored. Accepts legacy alias 'schema' for itemtype. If 'fields' are omitted, the schema's searchables (strings) are used with best-field scoring; provide 'fields' (strings or {path,weight}) to use weighted sums. Examples: { q: 'corey hadden', filters: { itemtype: 'user' } } or { q: 'backyard', filters: { itemtype: 'house' } }.",
|
|
381
387
|
saveObject: "Create/update an object; triggers events/history.",
|
|
382
388
|
saveObjects: "Batch save objects with bounded concurrency; per-item history/events preserved.",
|
|
383
389
|
hydrate: "Loads and merges the full JOE context, including core and organization-specific schemas, relationships, universal fields (tags and statuses), and datasets. Returns a single unified object describing the active environment for use by agents, UIs, and plugins.",
|
|
@@ -406,7 +412,7 @@ MCP.params = {
|
|
|
406
412
|
type: "object",
|
|
407
413
|
properties: {
|
|
408
414
|
_id: { type: "string" },
|
|
409
|
-
|
|
415
|
+
itemtype: { type: "string" },
|
|
410
416
|
flatten: { type: "boolean" },
|
|
411
417
|
depth: { type: "integer" }
|
|
412
418
|
},
|
|
@@ -418,7 +424,7 @@ MCP.params = {
|
|
|
418
424
|
search: {
|
|
419
425
|
type: "object",
|
|
420
426
|
properties: {
|
|
421
|
-
|
|
427
|
+
itemtype: { type: "string" },
|
|
422
428
|
query: { type: "object" },
|
|
423
429
|
ids: { type: "array", items: { type: "string" } },
|
|
424
430
|
source: { type: "string", enum: ["cache","storage"] },
|
|
@@ -437,7 +443,7 @@ MCP.params = {
|
|
|
437
443
|
fuzzySearch: {
|
|
438
444
|
type: "object",
|
|
439
445
|
properties: {
|
|
440
|
-
|
|
446
|
+
itemtype: { type: "string" },
|
|
441
447
|
q: { type: "string" },
|
|
442
448
|
filters: { type: "object" },
|
|
443
449
|
fields: {
|