ai-model-bazaar / script.js
johko's picture
Can you fix the code so I actually see models?
c7516ef verified
// script.js – Shared logic
// Utilities
const $ = (sel) => document.querySelector(sel);
const $$ = (sel) => [...document.querySelectorAll(sel)];
// Router
function showPage(id) {
$$('.page').forEach(p => p.classList.add('hidden'));
$(`#${id}`).classList.remove('hidden');
}
window.showPage = showPage;
// Mock Model Registry
export const MODELS = [
{
id: 1,
name: "HuggingFace BERT",
type: "language",
description: "Pre-trained transformer for NLP tasks like classification or Q&A.",
endpoint: "https://api.mock/bert",
tags: ["text", "classification", "embedding", "transformer"]
},
{
id: 2,
name: "Facebook Prophet",
type: "time-series",
description: "Forecasting tool for seasonal and trend time-series data.",
endpoint: "https://api.mock/prophet",
tags: ["forecast", "timeseries", "seasonality", "trend"]
},
{
id: 3,
name: "YOLOv8",
type: "vision",
description: "State-of-the-art object detection and segmentation model.",
endpoint: "https://api.mock/yolo",
tags: ["image", "detection", "objects", "realtime"]
},
{
id: 4,
name: "Stable Diffusion",
type: "generative",
description: "Generate high-quality images from text prompts.",
endpoint: "https://api.mock/sd",
tags: ["image", "generation", "text2img", "diffusion"]
}
];
// Knowledge Graph
export const TASK_KEYWORDS = {
"forecast": ["time-series"],
"sales": ["time-series"],
"image": ["vision", "generative"],
"generate": ["generative"],
"text": ["language"],
"detect": ["vision"],
"report": ["language"],
"trend": ["time-series"]
};
// Simple state
window.workflowModels = [];
// Render Marketplace
function renderModels(filter = "") {
const grid = $("#model-grid");
grid.innerHTML = "";
const typeFilter = $(".tag-btn.active")?.dataset.type || "";
MODELS.filter(m => {
if (typeFilter && m.type !== typeFilter) return false;
if (filter && !m.name.toLowerCase().includes(filter.toLowerCase()) && !m.tags.some(t => t.toLowerCase().includes(filter.toLowerCase()))) return false;
return true;
}).forEach(m => {
const card = document.createElement("model-card");
card.setAttribute("data-id", m.id);
card.setAttribute("data-name", m.name);
card.setAttribute("data-type", m.type);
card.setAttribute("data-desc", m.description);
card.setAttribute("data-tags", JSON.stringify(m.tags));
grid.appendChild(card);
});
feather.replace();
}
window.renderModels = renderModels;
// Planner Agent
function planWorkflow(task) {
const logs = [];
logs.push(`πŸ” Planner received task: "${task}"`);
const words = task.toLowerCase().split(/\W+/);
const matchedTypes = new Set();
words.forEach(w => {
if (TASK_KEYWORDS[w]) {
TASK_KEYWORDS[w].forEach(t => matchedTypes.add(t));
}
});
logs.push(`πŸ“Š Matched types: ${[...matchedTypes].join(", ")}`);
const suggested = MODELS.filter(m => matchedTypes.has(m.type));
logs.push(`βœ… Suggested models: ${suggested.map(m => m.name).join(", ")}`);
const panel = $("#workflow-suggestion");
panel.innerHTML = `<div class="mb-4"><strong>Suggested Workflow:</strong></div>
<div class="flex flex-col gap-3">
${suggested.map(m => `
<div class="p-3 rounded-lg bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 flex items-center justify-between">
<div>
<div class="font-semibold">${m.name}</div>
<div class="text-sm text-gray-500 dark:text-gray-400">${m.description}</div>
</div>
<button class="px-3 py-1 rounded-md bg-indigo-600 hover:bg-indigo-700 text-white text-sm add-to-workflow-btn" data-id="${m.id}">Add</button>
</div>
`).join("")}
</div>`;
// Log Panel Update
const logPanel = document.querySelector("log-panel");
if (logPanel) logPanel.logs = logs;
// Bind add buttons
$$(".add-to-workflow-btn").forEach(btn => {
btn.onclick = () => {
const id = Number(btn.dataset.id);
if (!window.workflowModels.find(m => m.id === id)) {
window.workflowModels.push(MODELS.find(m => m.id === id));
renderWorkflowStudio();
}
};
});
}
// Workflow Studio
function renderWorkflowStudio() {
const studio = $("#workflow-studio");
if (!window.workflowModels.length) {
studio.innerHTML = `<div class="text-gray-500 dark:text-gray-400 text-center py-10">No models added yet. Visit Marketplace or Agents to add.</div>`;
return;
}
studio.innerHTML = `
<div id="workflow-list" class="mb-4 flex flex-col gap-3">
${window.workflowModels.map((m, idx) => `
<div class="p-4 rounded-lg bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 flex items-center justify-between cursor-move" draggable="true" data-index="${idx}">
<div class="flex items-center gap-3">
<i data-feather="menu" class="w-4 h-4 text-gray-400"></i>
<div>
<div class="font-semibold">${m.name}</div>
<div class="text-sm text-gray-500 dark:text-gray-400">${m.type} β€’ ${m.description}</div>
</div>
</div>
<button class="px-3 py-1 rounded-md bg-red-500 hover:bg-red-600 text-white text-sm remove-model-btn" data-index="${idx}">Remove</button>
</div>
`).join("")}
</div>
<button id="run-workflow-btn" class="px-4 py-2 rounded-lg bg-green-600 hover:bg-green-700 text-white font-medium">Run Workflow</button>
<div id="workflow-results" class="mt-6"></div>
`;
feather.replace();
bindReorder();
$$(".remove-model-btn").forEach(btn => {
btn.onclick = () => {
const idx = Number(btn.dataset.index);
window.workflowModels.splice(idx, 1);
renderWorkflowStudio();
};
};
$("#run-workflow-btn").onclick = runWorkflow;
}
// Drag Reorder
function bindReorder() {
const list = $("#workflow-list");
let dragged = null;
list.querySelectorAll("[draggable=true]").forEach(el => {
el.ondragstart = (e) => { dragged = e.target.closest("[data-index]"); };
el.ondragover = (e) => e.preventDefault();
el.ondrop = (e) => {
e.preventDefault();
const target = e.target.closest("[data-index]");
if (!target || target === dragged) return;
const from = Number(dragged.dataset.index);
const to = Number(target.dataset.index);
const temp = window.workflowModels[from];
window.workflowModels[from] = window.workflowModels[to];
window.workflowModels[to] = temp;
renderWorkflowStudio();
};
});
}
// Run Workflow
async function runWorkflow() {
const results = $("#workflow-results");
results.innerHTML = `<div class="text-gray-500 dark:text-gray-400">Running...</div>`;
const logs = [];
const outputs = [];
for (const m of window.workflowModels) {
logs.push(`πŸš€ Calling ${m.name} at ${m.endpoint}`);
await new Promise(r => setTimeout(r, 600)); // mock latency
let out = `[Mock Output] ${m.name}: `;
if (m.type === "language") out += "Generated text summary.";
if (m.type === "time-series") out += "Sales forecast chart data.";
if (m.type === "vision") out += "Detected 5 objects.";
if (m.type === "generative") out += `<img src="https://static.photos/abstract/640x360/${m.id}" alt="generated image" class="rounded-lg mt-2 max-w-full"/>`;
outputs.push(out);
logs.push(`βœ… ${m.name} responded`);
}
logs.push("✨ Workflow complete");
const logPanel = document.querySelector("log-panel");
if (logPanel) logPanel.logs = logs;
results.innerHTML = `
<div class="mb-2 font-semibold">Results:</div>
<div class="flex flex-col gap-3">
${outputs.map(o => `<div class="p-3 rounded-lg bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700">${o}</div>`).join("")}
</div>
`;
}
// Init
document.addEventListener("DOMContentLoaded", () => {
renderModels();
// Search
$("#search-input").addEventListener("input", e => renderModels(e.target.value));
// Type Filter
$(".tag-btn").forEach(btn => {
btn.onclick = () => {
$(".tag-btn").forEach(b => b.classList.remove("active"));
btn.classList.add("active");
renderModels();
};
});
// Planner
$("#plan-btn").onclick = () => {
const task = $("#task-input").value.trim();
if (!task) return;
planWorkflow(task);
};
// Workflow Studio
window.renderWorkflowStudio = renderWorkflowStudio;
renderWorkflowStudio();
});