mirror of
https://github.com/multipleof4/.sune.git
synced 2026-01-14 07:57:55 +00:00
29 lines
17 KiB
Plaintext
29 lines
17 KiB
Plaintext
[
|
|
{
|
|
"id": "er71va2",
|
|
"name": "Gemini Code",
|
|
"pinned": true,
|
|
"avatar": "data:image/webp;base64,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",
|
|
"url": "gh://multipleof4/.sune@main/gemgirl.sune",
|
|
"updatedAt": 1757036000606,
|
|
"settings": {
|
|
"model": "or:google/gemini-2.5-pro",
|
|
"temperature": 1,
|
|
"top_p": 0.96,
|
|
"top_k": 0,
|
|
"frequency_penalty": 0,
|
|
"presence_penalty": 0,
|
|
"repetition_penalty": 1,
|
|
"min_p": 0,
|
|
"top_a": 0,
|
|
"max_tokens": 0,
|
|
"verbosity": "high",
|
|
"reasoning_effort": "default",
|
|
"system_prompt": "You deliver production-ready code. Don't break existing behavior. Apply Code Golfing practices; 1 liners. When asked a question, only answer the question; no code.",
|
|
"html": "<!-- Sune: GitHub Blob Fetch -->\n<!-- Version: 1.1.0 -->\n<div id=\"ghFetchSune\" class=\"p-2 border-b border-gray-200\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center gap-2\">\n <i data-lucide=\"github\" class=\"h-4 w-4\"></i>\n <span class=\"text-xs font-medium\">GitHub Fetch</span>\n <span class=\"text-[10px] text-gray-400\">v1.1.0</span>\n </div>\n <div class=\"flex items-center gap-1\">\n <button id=\"ghFetchAllBtn\" type=\"button\" class=\"rounded-lg px-2 py-1 text-xs bg-black text-white hover:bg-black/90 active:scale-95 transition-transform\">\n Fetch All\n </button>\n <button type=\"button\" id=\"ghAddRowBtn\" class=\"h-8 w-8 rounded-lg bg-gray-100 hover:bg-gray-200 flex items-center justify-center active:scale-95 transition-transform\" title=\"Add another URL\">\n <i data-lucide=\"plus\" class=\"h-4 w-4\"></i>\n </button>\n <button type=\"button\" id=\"ghHelpBtn\" class=\"h-8 px-2 rounded-lg bg-gray-100 hover:bg-gray-200 flex items-center justify-center active:scale-95 transition-transform\">\n <i data-lucide=\"help-circle\" class=\"h-4 w-4\"></i>\n </button>\n </div>\n </div>\n\n <div id=\"ghRows\" class=\"mt-2 space-y-1\"></div>\n <div id=\"ghStatus\" class=\"mt-2 text-[11px] text-gray-600 min-h-[1em]\"></div>\n</div>\n\n<script>\n(() => {\n const root = document.getElementById('ghFetchSune');\n if (!root) return;\n\n const $ = (sel, ctx = root) => ctx.querySelector(sel);\n const $$ = (sel, ctx = root) => Array.from(ctx.querySelectorAll(sel));\n\n const els = {\n rows: $('#ghRows'),\n addBtn: $('#ghAddRowBtn'),\n fetchAllBtn: $('#ghFetchAllBtn'),\n helpBtn: $('#ghHelpBtn'),\n status: $('#ghStatus'),\n };\n\n const icons = () => { try { window.lucide && window.lucide.createIcons({ attrs: { 'aria-hidden': 'true' } }); } catch (e) { console.error(\"Lucide error:\", e); } };\n\n function storageKeyBase() {\n // Use the active Sune's unique ID for robust, non-conflicting storage.\n const suneId = window.SUNE?.id;\n if (suneId) {\n return `gh_fetch_sune_${suneId}`;\n }\n // Fallback for safety, though SUNE.id should always exist.\n const name = (window.SUNE?.name || 'default').toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '');\n return `gh_fetch_${name}`;\n }\n \n const getUrlsKey = () => storageKeyBase() + '_urls_v2';\n\n function loadUrls() {\n try {\n const multi = window.localStorage.getItem(getUrlsKey());\n if (multi) {\n const arr = JSON.parse(multi);\n return Array.isArray(arr) ? arr.map(x => String(x || '')) : [''];\n }\n } catch {}\n return [''];\n }\n\n function saveUrls(urls) {\n try {\n window.localStorage.setItem(getUrlsKey(), JSON.stringify(urls.map(u => String(u || '').trim())));\n } catch {}\n }\n\n function setGlobalStatus(msg, kind = 'info') {\n els.status.textContent = msg || '';\n const colorClass = kind === 'error' ? 'text-red-600' : kind === 'ok' ? 'text-green-600' : 'text-gray-600';\n els.status.className = `mt-2 text-[11px] min-h-[1em] ${colorClass}`;\n }\n\n function spinnerSvg(cls='h-3 w-3') {\n return `<svg class=\"animate-spin ${cls}\" viewBox=\"0 0 24 24\"><circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\" fill=\"none\"></circle><path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8v4A4 4 0 004 12z\"></path></svg>`;\n }\n\n function parseGitHubUrl(u) {\n try {\n const url = new URL(u);\n let owner, repo, ref, path, raw, blob, lines = null;\n\n if (url.hash && /#L\\d+/i.test(url.hash)) {\n const m = url.hash.match(/#L(\\d+)(?:-L(\\d+))?/i);\n if (m) lines = { start: Math.max(1, +m[1] || 1), end: Math.max(+m[1] || 1, +m[2] || +m[1] || 1) };\n }\n\n if (url.hostname === 'github.com') {\n const parts = url.pathname.split('/').filter(Boolean);\n if (parts.length >= 4 && (parts[2] === 'blob' || parts[2] === 'raw')) {\n owner = parts[0]; repo = parts[1]; ref = parts[3];\n path = parts.slice(4).join('/');\n raw = `https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${path}`;\n blob = `https://github.com/${owner}/${repo}/blob/${ref}/${path}${url.hash || ''}`;\n return { raw, blob, owner, repo, ref, path, lines };\n }\n } else if (url.hostname === 'raw.githubusercontent.com') {\n const parts = url.pathname.split('/').filter(Boolean);\n if (parts.length >= 4) {\n owner = parts[0]; repo = parts[1]; ref = parts[2];\n path = parts.slice(3).join('/');\n raw = url.href;\n blob = `https://github.com/${owner}/${repo}/blob/${ref}/${path}${url.hash || ''}`;\n return { raw, blob, owner, repo, ref, path, lines };\n }\n }\n return null;\n } catch { return null; }\n }\n \n function guessLangFromPath(p = '') {\n const ext = (p.split('.').pop() || '').toLowerCase();\n if (!ext) return '';\n const map = { js: 'javascript', ts: 'typescript', py: 'python', rb: 'ruby', go: 'go', rs: 'rust', java: 'java', kt: 'kotlin', cs: 'csharp', php: 'php', sh: 'bash', ps1: 'powershell', sql: 'sql', html: 'html', css: 'css', scss: 'scss', md: 'markdown', json: 'json', yml: 'yaml', yaml: 'yaml', toml: 'toml', Dockerfile: 'dockerfile' };\n return map[ext] || '';\n }\n\n async function fetchOne(rawInput) {\n const input = (rawInput || '').trim();\n if (!input) throw new Error('Empty URL');\n const parsed = parseGitHubUrl(input);\n if (!parsed) throw new Error('Invalid GitHub URL. Use blob/raw format.');\n\n const fetchOptions = { cache: 'no-store' };\n const ghToken = window.globalStore?.ghToken;\n if (ghToken) {\n fetchOptions.headers = { 'Authorization': `Bearer ${ghToken}` };\n }\n\n const res = await fetch(parsed.raw, fetchOptions);\n if (!res.ok) throw new Error(`Fetch failed: HTTP ${res.status}`);\n \n let content = await res.text();\n if (parsed.lines) {\n const lines = content.replace(/\\r\\n/g, '\\n').split('\\n');\n const s = parsed.lines.start - 1, e = parsed.lines.end;\n content = lines.slice(s, e).join('\\n');\n }\n\n const lang = guessLangFromPath(parsed.path);\n const header = `From: ${parsed.blob}`;\n const md = `${header}\\n\\n\\`\\`\\`${lang}\\n${content}\\n\\`\\`\\``;\n return { md, blob: parsed.blob };\n }\n\n let urls = loadUrls();\n\n function rowTpl(idx, value = '') {\n return `\n <div class=\"rounded-lg border border-gray-200 bg-white p-2\">\n <div class=\"flex items-stretch gap-2\">\n <input\n data-role=\"url\" data-index=\"${idx}\" type=\"url\" inputmode=\"url\"\n placeholder=\"GitHub blob or raw URL...\"\n class=\"flex-1 min-w-0 rounded-md border border-gray-300 px-2 py-1 text-xs focus:ring-2 focus:ring-black/20 focus:border-black transition\"\n aria-label=\"GitHub URL\" value=\"${value.replace(/\"/g, '"')}\"\n />\n <button data-role=\"paste\" data-index=\"${idx}\" type=\"button\" class=\"shrink-0 rounded-md border px-2 text-xs bg-white hover:bg-gray-50 active:scale-95 transition-transform\" title=\"Paste\">\n <i data-lucide=\"clipboard\" class=\"h-4 w-4\"></i>\n </button>\n <button data-role=\"fetch-one\" data-index=\"${idx}\" type=\"button\" class=\"shrink-0 rounded-md px-2 text-xs bg-black text-white hover:bg-black/90 active:scale-95 transition-transform\">\n Fetch\n </button>\n <button data-role=\"remove\" data-index=\"${idx}\" type=\"button\" class=\"shrink-0 rounded-md border p-2 text-xs text-gray-500 bg-white hover:bg-gray-50 hover:text-red-600 active:scale-95 transition-transform\" title=\"Remove\">\n <i data-lucide=\"trash-2\" class=\"h-4 w-4\"></i>\n </button>\n </div>\n <div data-role=\"row-status\" data-index=\"${idx}\" class=\"mt-1 text-[11px] text-gray-500 min-h-[1em]\"></div>\n </div>\n `;\n }\n\n function renderRows() {\n if (!urls.length) urls = [''];\n els.rows.innerHTML = urls.map((u, i) => rowTpl(i, u)).join('');\n icons();\n }\n \n function setRowStatus(index, msg, kind='info') {\n const node = els.rows.querySelector(`[data-role=\"row-status\"][data-index=\"${index}\"]`);\n if (!node) return;\n node.textContent = msg || '';\n const colorClass = kind === 'error' ? 'text-red-600' : kind === 'ok' ? 'text-green-600' : 'text-gray-500';\n node.className = `mt-1 text-[11px] min-h-[1em] ${colorClass}`;\n }\n\n async function postToChat(md) {\n if (window.USER && typeof window.USER.log === 'function') {\n await window.USER.log(md);\n } else {\n throw new Error('Chat injection function (USER.log) not found.');\n }\n }\n\n async function fetchRow(index) {\n const input = els.rows.querySelector(`input[data-role=\"url\"][data-index=\"${index}\"]`);\n const fetchBtn = els.rows.querySelector(`button[data-role=\"fetch-one\"][data-index=\"${index}\"]`);\n if (!input || !fetchBtn) return;\n\n setRowStatus(index, '');\n const url = (input.value || '').trim();\n if (!url) {\n setRowStatus(index, 'Please enter a GitHub URL.', 'error');\n return false;\n }\n\n const prevHTML = fetchBtn.innerHTML;\n fetchBtn.innerHTML = spinnerSvg();\n fetchBtn.disabled = true;\n input.disabled = true;\n\n try {\n const { md, blob } = await fetchOne(url);\n await postToChat(md);\n input.value = blob; // Store canonical blob URL\n urls[index] = blob;\n saveUrls(urls);\n setRowStatus(index, 'Added to chat.', 'ok');\n return true;\n } catch (err) {\n setRowStatus(index, err.message || String(err), 'error');\n return false;\n } finally {\n fetchBtn.innerHTML = prevHTML;\n fetchBtn.disabled = false;\n input.disabled = false;\n }\n }\n\n els.rows.addEventListener('click', async (e) => {\n const btn = e.target.closest('button[data-role]');\n if (!btn) return;\n const role = btn.dataset.role;\n const index = +btn.dataset.index;\n if (Number.isNaN(index)) return;\n\n if (role === 'paste') {\n try {\n const text = await navigator.clipboard.readText();\n const input = els.rows.querySelector(`input[data-index=\"${index}\"]`);\n if (input && text) {\n input.value = text.trim();\n urls[index] = input.value;\n saveUrls(urls);\n setRowStatus(index, 'Pasted.', 'ok');\n }\n } catch {\n setRowStatus(index, 'Clipboard read failed.', 'error');\n }\n } else if (role === 'fetch-one') {\n await fetchRow(index);\n } else if (role === 'remove') {\n urls.length > 1 ? urls.splice(index, 1) : (urls[0] = '');\n saveUrls(urls);\n renderRows();\n }\n });\n\n els.rows.addEventListener('input', (e) => {\n const input = e.target.closest('input[data-role=\"url\"]');\n if (!input) return;\n urls[+input.dataset.index] = input.value;\n saveUrls(urls);\n });\n \n els.rows.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' && e.target.matches('input[data-role=\"url\"]')) {\n e.preventDefault();\n fetchRow(+e.target.dataset.index);\n }\n });\n\n els.addBtn.addEventListener('click', () => {\n urls.push('');\n saveUrls(urls);\n renderRows();\n els.rows.querySelector(`input[data-index=\"${urls.length - 1}\"]`)?.focus();\n });\n\n els.fetchAllBtn.addEventListener('click', async () => {\n const list = urls.map((url, i) => ({ url: url.trim(), i })).filter(item => item.url);\n if (!list.length) {\n setGlobalStatus('No URLs to fetch. Add one with the + button.', 'error');\n return;\n }\n\n const prevHTML = els.fetchAllBtn.innerHTML;\n els.fetchAllBtn.innerHTML = spinnerSvg('h-4 w-4');\n els.fetchAllBtn.disabled = true;\n setGlobalStatus(`Fetching ${list.length} item(s)...`);\n\n let success = 0, failed = 0;\n for (const item of list) {\n const ok = await fetchRow(item.i);\n ok ? success++ : failed++;\n }\n\n els.fetchAllBtn.innerHTML = prevHTML;\n els.fetchAllBtn.disabled = false;\n \n if (failed === 0) {\n setGlobalStatus(`Fetched ${success} item(s) successfully.`, 'ok');\n } else {\n setGlobalStatus(`Completed: ${success} succeeded, ${failed} failed.`, 'error');\n }\n });\n\n els.helpBtn.addEventListener('click', () => {\n alert([\n 'GitHub Fetch Sune - Help',\n '',\n '• Use the + button to add URL fields.',\n '• Paste a GitHub \"blob\" or \"raw\" URL into a field.',\n '• Example: https://github.com/owner/repo/blob/main/path/file.js#L10-L20',\n '• The #L... part is optional and selects specific lines.',\n '• Click \"Fetch\" on a row, or \"Fetch All\" for all fields.',\n '',\n 'Pro Tip: Go to Account Settings and add your GitHub Token to fetch from private repos and avoid rate limits.',\n ].join('\\n'));\n });\n\n renderRows();\n})();\n</script>\n",
|
|
"extension_html": "<!-- <sune src='https://raw.githubusercontent.com/sune-org/store/refs/heads/main/titles.sune' private></sune>-->\n\n<sune src='https://raw.githubusercontent.com/sune-org/store/refs/heads/main/sync.sune' private></sune>",
|
|
"script": ""
|
|
},
|
|
"storage": {}
|
|
}
|
|
] |