{"_id":"@cristianglezm/live-commentary-widget","_rev":"4-11b9cacfb3c35c1b6be8b4ac0bef0c22","name":"@cristianglezm/live-commentary-widget","dist-tags":{"latest":"1.2.1"},"versions":{"1.0.0":{"name":"@cristianglezm/live-commentary-widget","version":"1.0.0","keywords":["AI","live AI commentary","react","widget","chat","overlay"],"author":{"name":"Cristian Gonzalez","email":"cristian.glez.m@gmail.com"},"license":"MIT","_id":"@cristianglezm/live-commentary-widget@1.0.0","maintainers":[{"name":"cristianglezm","email":"cristianglezm@gmail.com"}],"homepage":"https://github.com/cristianglezm/live-commentary-widget","bugs":{"url":"https://github.com/cristianglezm/live-commentary-widget/issues"},"dist":{"shasum":"e99ff73095f9d63da22153200a2ff3dbab0535da","tarball":"https://registry.npmjs.org/@cristianglezm/live-commentary-widget/-/live-commentary-widget-1.0.0.tgz","fileCount":64,"integrity":"sha512-4Fq7ulkOpSUrGGMDR3pUXQomhgHtESWHHj0/wMASmKqgnuKsdouE2q6IaR3wyMkItV9rGHHztIsVZp30ol1nJA==","signatures":[{"sig":"MEUCIHgnYiMu9wMM2O5mb0aqWA9VXlyMjuR63vVSm2tt7sjPAiEA3IeKJU/YwGd+nIQncfB3tezqYwwVn1UCzCeaVnTM0+Y=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":365009},"main":"./dist/index.umd.cjs","type":"module","style":"./dist/live-commentary-widget.css","types":"./dist/types/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/index.js","require":"./dist/index.umd.cjs"},"./style.css":"./dist/live-commentary-widget.css"},"gitHead":"1a282b599ffa1c2ebc4b137b52405b0b8a859ea2","scripts":{"test":"vitest run","build":"vite build && tsc --emitDeclarationOnly","test:ui":"vitest --ui","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"cristianglezm","email":"cristianglezm@gmail.com"},"repository":{"url":"git+https://github.com/cristianglezm/live-commentary-widget.git","type":"git"},"_npmVersion":"10.9.4","description":"A React component that provides a Twitch-chat-like widget for live AI commentary on screen / canvas content.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"22.21.1","_hasShrinkwrap":false,"devDependencies":{"vite":"^7.2.4","jsdom":"^27.2.0","vitest":"^4.0.8","@vitest/ui":"^4.0.14","typescript":"^5.9.3","@types/node":"^24.10.1","tailwindcss":"^4.1.17","@types/react":"^19.2.7","@playwright/test":"^1.57.0","@types/react-dom":"^19.2.3","@tailwindcss/vite":"^4.1.17","@vitejs/plugin-react":"^5.1.1","@testing-library/react":"^16.0.0","@testing-library/jest-dom":"^6.9.1"},"peerDependencies":{"react":"^18.0.0 || ^19.0.0","react-dom":"^18.0.0 || ^19.0.0"},"_npmOperationalInternal":{"tmp":"tmp/live-commentary-widget_1.0.0_1764255940816_0.4313753590462821","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@cristianglezm/live-commentary-widget","version":"1.1.0","keywords":["AI","live AI commentary","react","widget","chat","overlay"],"author":{"name":"Cristian Gonzalez","email":"cristian.glez.m@gmail.com"},"license":"MIT","_id":"@cristianglezm/live-commentary-widget@1.1.0","maintainers":[{"name":"cristianglezm","email":"cristianglezm@gmail.com"}],"homepage":"https://github.com/cristianglezm/live-commentary-widget","bugs":{"url":"https://github.com/cristianglezm/live-commentary-widget/issues"},"dist":{"shasum":"1690d9305598931df7548fe4f829a71ad87b8855","tarball":"https://registry.npmjs.org/@cristianglezm/live-commentary-widget/-/live-commentary-widget-1.1.0.tgz","fileCount":64,"integrity":"sha512-vAL+ILjEWzhFdSr8R/ULGoGBjcgV4a+e9mBKfUaiR1sYb7lDJBHR5AyN8Es3ihGXu6KZyAp4NUCg7Iqty0NRkw==","signatures":[{"sig":"MEUCIFxEyPBeYTPJFU9EZLeCstpwo0bq0aPiIb5RsZNNY+lcAiEAnMCREYTkjL1sy3OdxAtNLAcgFa9WTgwU/PQJvjbXpPM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":375472},"main":"./dist/index.umd.cjs","type":"module","style":"./dist/live-commentary-widget.css","types":"./dist/types/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/index.js","require":"./dist/index.umd.cjs"},"./style.css":"./dist/live-commentary-widget.css"},"gitHead":"4d5d01abcb59b7245cf027b235b0814e7afdba2e","scripts":{"test":"vitest run","build":"vite build && tsc --emitDeclarationOnly","test:ui":"vitest --ui","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"cristianglezm","email":"cristianglezm@gmail.com"},"repository":{"url":"git+https://github.com/cristianglezm/live-commentary-widget.git","type":"git"},"_npmVersion":"10.9.4","description":"A React component that provides a Twitch-chat-like widget for live AI commentary on screen / canvas content.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"22.21.1","_hasShrinkwrap":false,"devDependencies":{"vite":"^7.2.4","jsdom":"^27.2.0","vitest":"^4.0.8","@vitest/ui":"^4.0.14","typescript":"^5.9.3","@types/node":"^24.10.1","tailwindcss":"^4.1.17","@types/react":"^19.2.7","@playwright/test":"^1.57.0","@types/react-dom":"^19.2.3","@tailwindcss/vite":"^4.1.17","@vitejs/plugin-react":"^5.1.1","@testing-library/react":"^16.0.0","@testing-library/jest-dom":"^6.9.1"},"peerDependencies":{"react":"^18.0.0 || ^19.0.0","react-dom":"^18.0.0 || ^19.0.0"},"_npmOperationalInternal":{"tmp":"tmp/live-commentary-widget_1.1.0_1764594268336_0.20297130048835688","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@cristianglezm/live-commentary-widget","version":"1.2.0","keywords":["AI","live AI commentary","react","widget","chat","overlay"],"author":{"name":"Cristian Gonzalez","email":"cristian.glez.m@gmail.com"},"license":"MIT","_id":"@cristianglezm/live-commentary-widget@1.2.0","maintainers":[{"name":"cristianglezm","email":"cristianglezm@gmail.com"}],"homepage":"https://github.com/cristianglezm/live-commentary-widget","bugs":{"url":"https://github.com/cristianglezm/live-commentary-widget/issues"},"dist":{"shasum":"c7bf72f456a20572b8166a3986c70d8f0a8f8584","tarball":"https://registry.npmjs.org/@cristianglezm/live-commentary-widget/-/live-commentary-widget-1.2.0.tgz","fileCount":64,"integrity":"sha512-9y4dnDjQJ+5xwJscWIkljnsrUa5fm3KP8gZoPFzneN4wXgIKzscquJ0dyOIavr+o+OTWwEj9cmhBGBvaJgoVvA==","signatures":[{"sig":"MEUCIQD/9zbUAM1TFRpn/tTRFcR6Ln951lazOsHUD87mXHavvgIgdoDoomz+r/Mb/vP+ykLpawUbHKflQwgaSkDkVByewr0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":379352},"main":"./dist/index.umd.cjs","type":"module","style":"./dist/live-commentary-widget.css","types":"./dist/types/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/index.js","require":"./dist/index.umd.cjs"},"./style.css":"./dist/live-commentary-widget.css"},"gitHead":"bf7d446acc3a82a7282a40a86318930e8ba1bba6","scripts":{"test":"vitest run","build":"vite build && tsc --emitDeclarationOnly","test:ui":"vitest --ui","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"cristianglezm","email":"cristianglezm@gmail.com"},"repository":{"url":"git+https://github.com/cristianglezm/live-commentary-widget.git","type":"git"},"_npmVersion":"10.9.4","description":"A React component that provides a Twitch-chat-like widget for live AI commentary on screen / canvas content.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"22.21.1","_hasShrinkwrap":false,"devDependencies":{"vite":"^7.2.4","jsdom":"^27.2.0","vitest":"^4.0.8","@vitest/ui":"^4.0.14","typescript":"^5.9.3","@types/node":"^24.10.1","tailwindcss":"^4.1.17","@types/react":"^19.2.7","@playwright/test":"^1.57.0","@types/react-dom":"^19.2.3","@tailwindcss/vite":"^4.1.17","@vitejs/plugin-react":"^5.1.1","@testing-library/react":"^16.0.0","@testing-library/jest-dom":"^6.9.1"},"peerDependencies":{"react":"^18.0.0 || ^19.0.0","react-dom":"^18.0.0 || ^19.0.0"},"_npmOperationalInternal":{"tmp":"tmp/live-commentary-widget_1.2.0_1764807794421_0.9958561300412019","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"_id":"@cristianglezm/live-commentary-widget@1.2.1","bugs":{"url":"https://github.com/cristianglezm/live-commentary-widget/issues"},"dist":{"shasum":"91631ba41b6a1648ddc449023608d642388b33d8","tarball":"https://registry.npmjs.org/@cristianglezm/live-commentary-widget/-/live-commentary-widget-1.2.1.tgz","fileCount":65,"integrity":"sha512-aW1vjU5iZznijIIlovoGhHmChCsN0USK2/LsmJhu224tXPrniOICjBXH8+yPepoL6Z0/khYoxpKC+mSYzfA2Pw==","signatures":[{"sig":"MEQCIFFnnB7psmOs7O5YoxzRKnL+Z7JrRQrvlur8q9SxUizsAiALpygHn/6HSOwvgPBGjysQ4fM3G0s7jf67ukUruzKukg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC7hrMNVDTJ7XQ9NSg1xgJSGu3LCIA0sjNGCBNqVkoQAQIhAI17yrQeBdP1TBr7TycGQWVOxRWbz+8FZuiZxvCEf03Y"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cristianglezm%2flive-commentary-widget@1.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":398208},"main":"./dist/index.umd.cjs","name":"@cristianglezm/live-commentary-widget","type":"module","style":"./dist/live-commentary-widget.css","types":"./dist/types/index.d.ts","author":{"name":"Cristian Gonzalez","email":"cristian.glez.m@gmail.com"},"module":"./dist/index.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/index.js","require":"./dist/index.umd.cjs"},"./style.css":"./dist/live-commentary-widget.css"},"gitHead":"458c67de048fd6443e2c200dfcbdda5309e123e5","license":"MIT","scripts":{"test":"vitest run","build":"vite build && tsc --emitDeclarationOnly","test:ui":"vitest --ui","test:watch":"vitest","type-check":"tsc --noEmit"},"version":"1.2.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5a7fc4f0-a01c-4ee8-a23e-042087e32b0d"}},"homepage":"https://github.com/cristianglezm/live-commentary-widget","keywords":["AI","live AI commentary","react","widget","chat","overlay"],"repository":{"url":"git+https://github.com/cristianglezm/live-commentary-widget.git","type":"git"},"_npmVersion":"12.0.2","description":"A React component that provides a Twitch-chat-like widget for live AI commentary on screen / canvas content.","directories":{},"maintainers":[{"name":"cristianglezm","email":"cristianglezm@gmail.com"}],"sideEffects":["*.css"],"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^8.3.0","jsdom":"^30.0.1","vitest":"^5.0.0","@vitest/ui":"^5.0.0","typescript":"^7.0.2","@types/node":"^26.5.1","tailwindcss":"^4.3.3","@types/react":"^19.3.0","@playwright/test":"^1.63.0","@types/react-dom":"^19.3.0","@tailwindcss/vite":"^4.3.3","@vitejs/plugin-react":"^6.1.1","@testing-library/react":"^16.3.3","@testing-library/jest-dom":"^7.0.1"},"peerDependencies":{"react":"^18.0.0 || ^19.0.0","react-dom":"^18.0.0 || ^19.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/live-commentary-widget_1.2.1_1789400703200_0.7819008817234825"}}},"time":{"created":"2025-11-27T15:05:40.738Z","modified":"2026-09-14T15:45:03.573Z","1.0.0":"2025-11-27T15:05:40.996Z","1.1.0":"2025-12-01T13:04:28.509Z","1.2.0":"2025-12-04T00:23:14.592Z","1.2.1":"2026-09-14T15:45:03.278Z"},"bugs":{"url":"https://github.com/cristianglezm/live-commentary-widget/issues"},"author":{"name":"Cristian Gonzalez","email":"cristian.glez.m@gmail.com"},"license":"MIT","homepage":"https://github.com/cristianglezm/live-commentary-widget","keywords":["AI","live AI commentary","react","widget","chat","overlay"],"repository":{"url":"git+https://github.com/cristianglezm/live-commentary-widget.git","type":"git"},"description":"A React component that provides a Twitch-chat-like widget for live AI commentary on screen / canvas content.","maintainers":[{"name":"cristianglezm","email":"cristianglezm@gmail.com"}],"readme":"# @cristianglezm/live-commentary-widget\n\n[![npm](https://img.shields.io/npm/v/@cristianglezm/live-commentary-widget.svg)](https://www.npmjs.com/package/@cristianglezm/live-commentary-widget)\n![License](https://img.shields.io/npm/l/@cristianglezm/live-commentary-widget)\n\nA React component library that adds a \"Twitch-style\" live chat overlay to your application. It uses AI Vision models to \"watch\" the screen (or a specific canvas) and generate humor, context-aware commentary, or useful insights in real-time.\n\n\n## ✨ Features\n\n*   **Plug & Play**: Drop `<LiveCommentary />` into any React app.\n*   **Visual Context**: Users can toggle \"Show Context\" on comments to verify exactly what the AI saw at that moment.\n*   **Headless Hooks**: Use `useLiveCommentary` and `useScreenCapture` to build your own custom UI.\n*   **AI Middleware**: Intercept raw AI responses to handle your own parsing, username assignment, or state management.\n*   **AI Powered**: Compatible with OpenAI's Vision API (`gpt-4o`) and local alternatives (e.g., `llama.cpp` server).\n*   **Screen & Canvas Support**: Capture the entire screen via the browser API or hook directly into a `<canvas>` for games.\n*   **Sticky Scroll**: Chat widget automatically scrolls to new messages but pauses when you scroll up.\n\n## 📦 Installation\n\n```bash\nnpm install @cristianglezm/live-commentary-widget\n```\n\n## 💻 Usage\n\n### 1. Basic Usage (The \"Easy\" Way)\nThe `LiveCommentary` component wraps the logic and the UI into one standard widget.\n\n```tsx\nimport { LiveCommentary } from '@cristianglezm/live-commentary-widget';\nimport '@cristianglezm/live-commentary-widget/style.css';\n\nfunction App() {\n  return (\n    <div>\n      <LiveCommentary \n        config={{\n          model: 'gpt-4o',\n          apiKey: 'not_required', \n        }} \n      />\n    </div>\n  );\n}\n```\n\n### 2. Middleware (Controlled Mode)\nWant to control exactly who says what? Use `responseTransform` to intercept the raw text from the LLM and return your own message objects.\n\n**Pro Tip:** You also receive the `capturedImage` snapshot, so you can attach it to your custom messages to enable the \"Show Context\" feature.\n\n```tsx\nimport { LiveCommentary, createChatMessage } from '@cristianglezm/live-commentary-widget';\n\n<LiveCommentary \n  responseTransform={(rawText, capturedImage) => {\n    // rawText: The raw string response from the AI\n    // capturedImage: The base64 image used for this analysis\n    \n    // You can parse JSON, XML, or just return a hardcoded user\n    return [\n      // createChatMessage(text, username, color, customUsernamesList, attachment)\n      createChatMessage(rawText, \"MyCustomBot\", \"#ff0000\", undefined, capturedImage)\n    ];\n  }}\n/>\n```\n\n### 3. Headless Mode (Custom UI)\nBuild your own UI entirely using the hooks.\n\n```tsx\nimport { useLiveCommentary, useScreenCapture, ChatWidget } from '@cristianglezm/live-commentary-widget';\n\nfunction MyCustomPage() {\n  const { isCapturing, startCapture, captureFrame } = useScreenCapture({ mode: 'screen-capture' });\n  \n  const { messages, triggerEvaluation } = useLiveCommentary({\n     isCapturing,\n     captureFrame,\n     config: { apiKey: '...' }\n  });\n\n  return (\n    <div>\n      <button onClick={startCapture}>Start Recording</button>\n      <button onClick={() => triggerEvaluation()}>Force Comment</button>\n      \n      {/* You can use our widget or render your own list */}\n      <div className=\"my-custom-chat-container\">\n        {messages.map(msg => (\n            <div key={msg.id}>\n                <b>{msg.username}:</b> {msg.text}\n                {/* Access the visual context image via msg.attachment */}\n                {msg.attachment && <img src={`data:image/jpeg;base64,${msg.attachment}`} />}\n            </div>\n        ))}\n      </div>\n    </div>\n  );\n}\n```\n\n## 📸 Visual Context\n\nThe widget automatically attaches a snapshot of the screen to every AI-generated comment. This allows users to understand *why* the AI said something.\n\n1.  **Hover/Look** at a message in the chat.\n2.  Click the **\"Show Context\"** button (small eye icon).\n3.  The image frame analyzed by the AI will appear below the text.\n\nThis is particularly useful for:\n*   **Debugging prompts**: See if the model is hallucinating or just saw something you missed.\n*   **Verification**: Proving the commentary is \"live\" and reacting to the actual video feed.\n\n## ⚙️ Configuration Props (`LiveCommentary`)\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `config` | `Partial<VlmSettings>` | | Override API settings (url, key, model, temp). |\n| `mode` | `'screen-capture' \\| 'external'` | `'screen-capture'` | Use `'external'` for direct canvas/video hook. |\n| `responseTransform` | `(raw: string, img?: string) => ChatMessage[]` | | **New:** Middleware to handle raw AI text yourself. |\n| `captureSource` | `() => string \\| null` | | Required if mode is `external`. Returns base64 image string. |\n| `prompts` | `CommentaryPrompts` | | Customize the system instructions and triggers. |\n| `contextData` | `object` | | Arbitrary JSON data sent to the AI for context. |\n| `usernames` | `string[]` | `undefined` | Custom list of usernames for random assignment. |\n| `showBadges` | `boolean` | `true` | Show Twitch-style badges (Broadcaster, Prime, etc). |\n| `title` | `string` | `\"Live Commentary\"` | Header title of the widget. |\n| `overlay` | `boolean` | `true` | If `true`, fixed positioning. If `false`, fills parent. |\n\n## 🎨 Customization\n\nThe widget uses CSS variables for theming. Import the CSS and override variables in your `:root`.\n\n```css\nimport '@cristianglezm/live-commentary-widget/style.css';\n\n:root {\n  --color-lc-bg: #18181b;\n  --color-lc-accent: #9147ff;\n}\n```\n\n## 📄 License\n\nMIT © Cristian Gonzalez\n","readmeFilename":"README.md"}