{"id":50675173,"url":"https://github.com/ziuus/synapsejs","last_synced_at":"2026-06-08T15:02:28.486Z","repository":{"id":341905483,"uuid":"1171970939","full_name":"ziuus/SynapseJS","owner":"ziuus","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-12T16:02:08.000Z","size":30994,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-12T16:12:51.848Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ziuus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-03T20:10:09.000Z","updated_at":"2026-03-12T16:02:14.000Z","dependencies_parsed_at":null,"dependency_job_id":"fc918069-59f0-444d-bf48-0c4bc5cf53cd","html_url":"https://github.com/ziuus/SynapseJS","commit_stats":null,"previous_names":["ziuus/axonjs","ziuus/synapsejs"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ziuus/SynapseJS","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziuus%2FSynapseJS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziuus%2FSynapseJS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziuus%2FSynapseJS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziuus%2FSynapseJS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ziuus","download_url":"https://codeload.github.com/ziuus/SynapseJS/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziuus%2FSynapseJS/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34067353,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-08T15:02:27.178Z","updated_at":"2026-06-08T15:02:28.476Z","avatar_url":"https://github.com/ziuus.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003e⚡ SynapseJS\u003c/h1\u003e\n  \u003cp\u003e\u003cstrong\u003eThe AI Runtime Layer for Frontend Applications\u003c/strong\u003e\u003c/p\u003e\n  \u003cp\u003e\n    \u003ca href=\"https://www.npmjs.com/package/@synapsenodes/core\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@synapsenodes/core?color=6366f1\u0026label=npm\" alt=\"npm version\"\u003e\u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/badge/tools-20_built--in-emerald?color=10b981\" alt=\"20 built-in tools\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/providers-Groq%20%7C%20Gemini%20%7C%20OpenAI-8b5cf6\" alt=\"providers\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/TypeScript-5.x-3178c6\" alt=\"TypeScript\"\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n---\n\n**SynapseJS** lets any LLM see, click, scroll, fill, navigate, and control your web UI — with one line of setup and zero extra infrastructure. Drop it into any React / Next.js project and your AI agent gains 20 production-ready capabilities instantly.\n\n```ts\nconst agent = new Agent({\n  llmProvider: \"groq\",\n  apiKey: process.env.GROQ_API_KEY,\n});\nconst result = await agent.run([\n  { role: \"user\", content: \"Switch to dark mode\" },\n]);\n// The AI calls interactWithScreen → clicks your theme toggle automatically\n```\n\n---\n\n## Table of Contents\n\n1. [Quick Start](#quick-start)\n2. [Providers](#providers)\n3. [Built-in Tools (20)](#built-in-tools)\n4. [Custom Tools](#custom-tools)\n5. [Frontend Integration](#frontend-integration)\n   - [useSynapseDOM](#useagentdom)\n   - [useSynapseSignals](#useaxonsignals)\n6. [3D Scene Integration](#3d-scene-integration)\n7. [API Reference](#api-reference)\n8. [TypeScript Types](#typescript-types)\n9. [FAQ](#faq)\n\n---\n\n## Quick Start\n\n### 1. Install\n\n```bash\nnpm install @synapsenodes/core\n# or\npnpm add @synapsenodes/core\n```\n\n### 2. Create an Agent (backend — Next.js API route)\n\n```ts\n// app/api/chat/route.ts\nimport { Agent } from \"@synapsenodes/core\";\n\nexport async function POST(req: Request) {\n  const { messages, domElements } = await req.json();\n\n  const agent = new Agent({\n    llmProvider: \"groq\",\n    apiKey: process.env.GROQ_API_KEY,\n    model: \"llama-3.3-70b-versatile\", // optional\n    maxSteps: 5, // optional loop limit\n  });\n\n  // Register your own custom tools (optional)\n  agent.tools.register({\n    name: \"getWeather\",\n    description: \"Get the current weather for a city\",\n    schema: z.object({ city: z.string() }),\n    execute: async ({ city }) =\u003e\n      fetch(`/api/weather?city=${city}`).then((r) =\u003e r.json()),\n  });\n\n  const result = await agent.run(messages, domElements);\n  return Response.json(result);\n}\n```\n\n### 3. Connect the frontend\n\n```tsx\n// app/page.tsx\n\"use client\";\nimport { useSynapseDOM, useSynapseSignals } from \"@synapsenodes/core/client\";\n\nexport default function Page() {\n  const domElements = useSynapseDOM(); // auto-scans interactive elements\n  const { processSignals } = useSynapseSignals({\n    // handle AI actions\n    SHOW_NOTIFICATION: ({ message, type }) =\u003e toast(message, type),\n    NAVIGATE: ({ url }) =\u003e router.push(url),\n    SET_THEME: ({ theme }) =\u003e (document.documentElement.dataset.theme = theme),\n    HIGHLIGHT_ELEMENT: ({ elementId }) =\u003e highlight(elementId),\n    // ... handle whichever signals you need\n  });\n\n  const handleSubmit = async (message: string) =\u003e {\n    const res = await fetch(\"/api/chat\", {\n      method: \"POST\",\n      body: JSON.stringify({ messages, domElements }),\n    });\n    const data = await res.json();\n    processSignals(data.messages.flatMap((m: any) =\u003e m.toolCalls ?? []));\n  };\n}\n```\n\n---\n\n## Providers\n\n| Provider               | Env Variable     | Recommended Model         |\n| ---------------------- | ---------------- | ------------------------- |\n| **Groq** (recommended) | `GROQ_API_KEY`   | `llama-3.3-70b-versatile` |\n| **Gemini**             | `GEMINI_API_KEY` | `gemini-2.0-flash-exp`    |\n| **OpenAI**             | `OPENAI_API_KEY` | `gpt-4o`                  |\n\n---\n\n## Built-in Tools\n\nSynapseJS ships **20 tools** that are registered automatically — no configuration needed. The LLM selects the right tool based on the user's intent.\n\n### Wave 1 — Core UI Automation\n\n| Tool                 | Signal              | Purpose                                             |\n| -------------------- | ------------------- | --------------------------------------------------- |\n| `interactWithScreen` | `UI_INTERACTION`    | Click any element or type into inputs               |\n| `readScreenText`     | `READ_ELEMENT`      | Read the current text / value of any element        |\n| `observeState`       | `OBSERVE_STATE`     | Read any DOM property (`value`, `checked`, `href`…) |\n| `fillForm`           | `FILL_FORM`         | Batch-fill multiple form fields at once             |\n| `navigateTo`         | `NAVIGATE`          | Navigate the browser to any URL or route            |\n| `showNotification`   | `SHOW_NOTIFICATION` | Display a toast notification                        |\n\n### Wave 2 — Enhanced Interactions\n\n| Tool               | Signal              | Purpose                                  |\n| ------------------ | ------------------- | ---------------------------------------- |\n| `scrollTo`         | `SCROLL_TO`         | Scroll to an element or pixel offset     |\n| `copyToClipboard`  | `COPY_TO_CLIPBOARD` | Copy text to the user's clipboard        |\n| `toggleElement`    | `TOGGLE_ELEMENT`    | Show or hide any element                 |\n| `selectDropdown`   | `SELECT_DROPDOWN`   | Set a `\u003cselect\u003e` to any option           |\n| `highlightElement` | `HIGHLIGHT_ELEMENT` | Draw an attention ring around an element |\n\n### Wave 3 — Power Features\n\n| Tool             | Signal             | Purpose                           |\n| ---------------- | ------------------ | --------------------------------- |\n| `waitForElement` | `WAIT_FOR_ELEMENT` | Poll DOM until an element appears |\n| `getPageUrl`     | `GET_PAGE_URL`     | Return `window.location.href`     |\n| `setPageTitle`   | `SET_PAGE_TITLE`   | Update `document.title`           |\n| `openModal`      | `OPEN_MODAL`       | Open or close a modal/dialog      |\n| `downloadFile`   | `DOWNLOAD_FILE`    | Trigger a file download           |\n| `submitForm`     | `SUBMIT_FORM`      | Submit a `\u003cform\u003e` element         |\n| `checkboxToggle` | `CHECKBOX_TOGGLE`  | Check/uncheck a checkbox          |\n| `setTheme`       | `SET_THEME`        | Set `data-theme` on `\u003chtml\u003e`      |\n\n### 3D Scene Control\n\n| Tool                  | Signal           | Purpose                                           |\n| --------------------- | ---------------- | ------------------------------------------------- |\n| `interactWith3DScene` | `3D_INTERACTION` | Emit events or set variables on a Spline 3D scene |\n\n---\n\n## Custom Tools\n\nRegister any tool that runs your own business logic:\n\n```ts\nimport { Agent } from \"@synapsenodes/core\";\nimport { z } from \"zod\";\n\nconst agent = new Agent({ llmProvider: \"groq\", apiKey: \"...\" });\n\nagent.tools.register({\n  name: \"sendEmail\",\n  description:\n    'Send an email to a recipient. Requires \"to\", \"subject\", and \"body\".',\n  schema: z.object({\n    to: z.string().email(),\n    subject: z.string(),\n    body: z.string(),\n  }),\n  execute: async ({ to, subject, body }) =\u003e {\n    await mailer.send({ to, subject, body });\n    return { sent: true };\n  },\n});\n\nconst result = await agent.run([\n  {\n    role: \"user\",\n    content: \"Email john@example.com about the meeting tomorrow\",\n  },\n]);\n```\n\n### Tool Registry API\n\n```ts\nagent.tools.register(tool); // Register a new tool\nagent.tools.unregister(name); // Remove a tool   → boolean\nagent.tools.has(name); // Check existence  → boolean\nagent.tools.list(); // Get all names    → string[]\nagent.tools.getTool(name); // Get a tool       → Tool | undefined\nagent.tools.getAllTools(); // Get all tools    → Tool[]\nagent.tools.execute(name, args); // Run a tool      → Promise\u003cany\u003e\n```\n\n---\n\n## Frontend Integration\n\n### useSynapseDOM\n\nAutomatically scans the DOM and returns a simplified JSON snapshot the LLM uses to understand your UI:\n\n```tsx\nimport { useSynapseDOM } from \"@synapsenodes/core/client\";\n\nconst domElements = useSynapseDOM();\n// Returns: [{ id: 'submit-btn', type: 'button', text: 'Submit', actionable: true }, ...]\n```\n\nTag any element for AI visibility:\n\n```html\n\u003c!-- Make a static element readable by the AI --\u003e\n\u003cdiv id=\"cart-count\" data-synapse-read=\"true\"\u003e3 items\u003c/div\u003e\n\n\u003c!-- Register a 3D canvas with controllable events --\u003e\n\u003cdiv\n  id=\"hero-scene\"\n  data-synapse-3d=\"true\"\n  data-3d-events=\"mouseHover, mouseDown\"\n  data-3d-variables=\"score, speed\"\n\u003e\u003c/div\u003e\n```\n\n### useSynapseSignals\n\nThe zero-boilerplate way to handle any signal the AI emits:\n\n```tsx\nimport { useSynapseSignals } from \"@synapsenodes/core/client\";\n\nconst { processSignals } = useSynapseSignals({\n  UI_INTERACTION: ({ elementId, action, value }) =\u003e {\n    const el = document.getElementById(elementId);\n    if (action === \"click\") el?.click();\n    if (action === \"type\") (el as HTMLInputElement).value = value;\n  },\n  SHOW_NOTIFICATION: ({ message, type, durationMs }) =\u003e {\n    showToast(message, type, durationMs);\n  },\n  NAVIGATE: ({ url, newTab }) =\u003e {\n    if (newTab) window.open(url, \"_blank\");\n    else window.location.href = url;\n  },\n  SET_THEME: ({ theme }) =\u003e {\n    document.documentElement.dataset.theme = theme;\n  },\n  // Handle only what you need — rest are silently ignored\n});\n\n// In your message handler:\nconst allToolCalls = data.messages.flatMap((m) =\u003e m.toolCalls ?? []);\nprocessSignals(allToolCalls);\n```\n\n---\n\n## 3D Scene Integration\n\n```bash\nnpm install @splinetool/react-spline\n```\n\n```tsx\n'use client';\nimport { useEffect } from 'react';\nimport type { Application } from '@splinetool/runtime';\n\ndeclare global {\n  interface Window { SynapseSplineInterop?: { emitEvent: ..., setVariable: ... } }\n}\n\nfunction SplineScene() {\n  function onLoad(app: Application) {\n    window.SynapseSplineInterop = {\n      emitEvent: (action, target) =\u003e app.emitEvent(action as any, target),\n      setVariable: (name, value) =\u003e app.setVariable(name, value as any),\n    };\n  }\n  return (\n    \u003cdiv id=\"hero-3d-scene\" data-synapse-3d=\"true\" data-3d-events=\"mouseHover, mouseDown\"\u003e\n      \u003cSpline scene=\"your-scene.splinecode\" onLoad={onLoad} /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nThen wire the signal:\n\n```tsx\nconst { processSignals } = useSynapseSignals({\n  \"3D_INTERACTION\": ({ actionType, target, value }) =\u003e {\n    if (actionType === \"emitEvent\")\n      window.SynapseSplineInterop?.emitEvent(\"mouseHover\", target);\n    if (actionType === \"setVariable\")\n      window.SynapseSplineInterop?.setVariable(target, value);\n  },\n});\n```\n\n---\n\n## API Reference\n\n### `new Agent(config: AgentConfig)`\n\n| Property       | Type                                       | Default          | Description                   |\n| -------------- | ------------------------------------------ | ---------------- | ----------------------------- |\n| `llmProvider`  | `'groq' \\| 'gemini' \\| 'openai' \\| 'mock'` | required         | LLM backend to use            |\n| `apiKey`       | `string`                                   | —                | Provider API key              |\n| `model`        | `string`                                   | provider default | Override the default model    |\n| `systemPrompt` | `string`                                   | SynapseJS default   | Custom system instructions    |\n| `maxSteps`     | `number`                                   | `5`              | Max reasoning loop iterations |\n| `memory`       | `'session' \\| 'none'`                      | `'none'`         | Conversation memory mode      |\n\n### `agent.run(messages, domElements?)`\n\nRun the reasoning loop and return the full message history including all tool calls.\n\n```ts\nconst result = await agent.run(\n  [{ role: \"user\", content: \"Submit the form\" }],\n  [{ id: \"contact-form\", type: \"unknown\", actionable: true }],\n);\n// result.messages — full history\n// result.text     — final assistant text\n```\n\n---\n\n## TypeScript Types\n\n```ts\nimport type {\n  AgentConfig,\n  AgentResponse,\n  SynapseSignalType,\n  SynapseSignal,\n  AgentSignalHandler,\n  SynapseToolName,\n  Tool,\n  CoreMessage,\n} from \"@synapsenodes/core\";\n```\n\n---\n\n## FAQ\n\n**Q: How does the AI know what's on the screen?**  \nA: `useSynapseDOM()` scans for all `button`, `input`, `a`, and `data-synapse-read`/`data-synapse-3d` tagged elements and produces a JSON snapshot sent with every request.\n\n**Q: Do I need to configure anything to get the 20 tools?**  \nA: No. All tools are pre-registered in the constructor. Just create an `Agent` and they're available.\n\n**Q: Can I remove a built-in tool I don't want?**  \nA: Yes: `agent.tools.unregister('setTheme')`.\n\n**Q: How do I add my own tools?**  \nA: `agent.tools.register({ name, description, schema, execute })`. See [Custom Tools](#custom-tools).\n\n**Q: Does this work with Next.js App Router?**  \nA: Yes. The `Agent` class runs only on the server (API routes). `useSynapseDOM` and `useSynapseSignals` are client components.\n\n**Q: What if I'm not using React?**  \nA: The `Agent` class and `ToolRegistry` are framework-agnostic. Build your own signal dispatch layer for Vue, Svelte, or vanilla JS.\n\n---\n\n## License\n\nMIT © SynapseJS Contributors\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fziuus%2Fsynapsejs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fziuus%2Fsynapsejs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fziuus%2Fsynapsejs/lists"}