UNPKG

json-object-editor

Version:

JOE the Json Object Editor | Platform Edition

117 lines (107 loc) 4.54 kB
<!doctype html> <html> <head> <meta charset="utf-8"> <title>JOE MCP Prompt</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif;margin:20px;} textarea{width:100%;height:360px;font-family:ui-monospace,Menlo,Consolas,monospace} .small{font-size:12px;color:#666} </style> </head> <body> <div id="mcp-nav"></div> <script src="/JsonObjectEditor/_www/mcp-nav.js"></script> <h1>Starter Agent Instructions</h1> <div class="small">Copy into your Custom GPT or Assistant system prompt. This text is loaded from docs/joe_agent_custom_gpt_instructions_v_2.md (source of truth).</div> <h3>Downloads</h3> <div class="small">Quickly export JSON helpful for agent setup and offline review.</div> <div class="row" style="display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin:8px 0 16px;"> <label for="base" style="margin:0">Base URL</label> <input id="base" value="" placeholder="http://localhost:2025" style="min-width:280px"/> <button id="downloadApps">Download apps.json</button> <button id="downloadHydrate">Download hydrate-<date>.json</button> <span id="dlStatus" class="small"></span> </div> <textarea readonly id="prompt" placeholder="Loading instructions from docs…"></textarea> <script> (function(){ var $ = function(id){ return document.getElementById(id); }; var base = $('base'); var dlBtn = $('downloadApps'); var dlHydrateBtn = $('downloadHydrate'); var dlStatus = $('dlStatus'); var promptBox = $('prompt'); base.value = base.value || location.origin; function setStatus(msg, ok){ dlStatus.textContent = msg||''; dlStatus.className = 'small ' + (ok===true?'good': ok===false?'bad':''); } async function fetchJSON(url, opts){ const res = await fetch(url, opts); const ct = res.headers.get('content-type')||''; const isJSON = ct.indexOf('application/json') >= 0; if(!res.ok){ let detail = isJSON ? await res.json().catch(function(){return {};}) : await res.text(); throw new Error('HTTP '+res.status+': '+(isJSON?JSON.stringify(detail):detail)); } return isJSON ? res.json() : res.text(); } async function callMCP(method, params){ const url = base.value.replace(/\/$/,'') + '/mcp'; const body = { jsonrpc: '2.0', id: String(Date.now()), method: method, params: params||{} }; return fetchJSON(url, { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(body) }); } dlBtn.onclick = async function(){ setStatus('Fetching apps...', null); try{ const resp = await callMCP('listApps', {}); const data = (resp && (resp.result||resp)) || {}; const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'apps.json'; document.body.appendChild(a); a.click(); setTimeout(function(){ URL.revokeObjectURL(url); a.remove(); }, 0); setStatus('Downloaded', true); } catch(e){ setStatus(e.message||String(e), false); } }; // Load system instructions from docs (source of truth) (function loadDocs(){ var path = '/JsonObjectEditor/docs/joe_agent_custom_gpt_instructions_v_3.md'; fetch(path).then(function(r){ if(!r.ok) throw new Error('HTTP '+r.status); return r.text(); }) .then(function(text){ promptBox.value = text; }) .catch(function(e){ promptBox.value = 'Failed to load instructions: '+(e.message||String(e)); }); })(); dlHydrateBtn.onclick = async function(){ setStatus('Fetching hydrate...', null); try{ const resp = await callMCP('hydrate', {}); const data = (resp && (resp.result||resp)) || {}; const now = new Date(); const yyyy = now.getFullYear(); const mm = String(now.getMonth()+1).padStart(2,'0'); const dd = String(now.getDate()).padStart(2,'0'); const fname = `hydrate_${yyyy}-${mm}-${dd}.json`; const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = fname; document.body.appendChild(a); a.click(); setTimeout(function(){ URL.revokeObjectURL(url); a.remove(); }, 0); setStatus('Downloaded', true); } catch(e){ setStatus(e.message||String(e), false); } }; })(); </script> </body> </html>