{"_id":"@bump-sh/agent-widget","name":"@bump-sh/agent-widget","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@bump-sh/agent-widget","version":"0.1.0","description":"Embeddable, themeable chat widget for Bump.sh agents — a Web Component you drop in with 3 lines.","type":"module","license":"MIT","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","unpkg":"./dist/browser.js","jsdelivr":"./dist/browser.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"engines":{"node":">=18"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/bump-sh/agent-client.git","directory":"packages/agent-widget"},"homepage":"https://bump-sh.github.io/agent-client/","bugs":{"url":"https://github.com/bump-sh/agent-client/issues"},"scripts":{"build":"tsup","test":"vitest run","test:watch":"vitest","check":"biome check src test","format":"biome format --write src test","prepublishOnly":"npm run build"},"keywords":["bump.sh","agent","chat","widget","web-component","ui"],"dependencies":{"@bump-sh/agent-conversation":"^0.1.0"},"_id":"@bump-sh/agent-widget@0.1.0","gitHead":"bb61054d3f5035080ddc9d6e2df8dfb9a11682d6","_nodeVersion":"22.22.0","_npmVersion":"10.9.4","dist":{"integrity":"sha512-Oa0bbZ31jNRZpFzkykIBwiNxKRLf9Zz3ffbZRsSKkYrizS/zACVDH/GPeU26KO+EO5fdu4u7w1gF2rxHnqYSUA==","shasum":"6cbf1b0a6d9f666dadddce7112153f2f8003d726","tarball":"https://registry.npmjs.org/@bump-sh/agent-widget/-/agent-widget-0.1.0.tgz","fileCount":10,"unpackedSize":264091,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDieeeu4weXJX/9M4XK6TE5zmNd/E4ZNu3v6ZR5hV87UQIgHhZ0W1emM3mdgQPpn4IwKw313r6+org9aK9t747uiXo="}]},"_npmUser":{"name":"scharrier","email":"sebastien@bump.sh"},"directories":{},"maintainers":[{"name":"paulrbr","email":"paul@bonaud.fr"},{"name":"scharrier","email":"sebastien@bump.sh"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/agent-widget_0.1.0_1786711384121_0.7037622888506319"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-14T12:43:03.966Z","0.1.0":"2026-08-14T12:43:04.258Z","modified":"2026-08-14T12:43:04.499Z"},"maintainers":[{"name":"paulrbr","email":"paul@bonaud.fr"},{"name":"scharrier","email":"sebastien@bump.sh"}],"description":"Embeddable, themeable chat widget for Bump.sh agents — a Web Component you drop in with 3 lines.","homepage":"https://bump-sh.github.io/agent-client/","keywords":["bump.sh","agent","chat","widget","web-component","ui"],"repository":{"type":"git","url":"git+https://github.com/bump-sh/agent-client.git","directory":"packages/agent-widget"},"bugs":{"url":"https://github.com/bump-sh/agent-client/issues"},"license":"MIT","readme":"# @bump-sh/agent-widget\n\nEmbeddable, themeable chat widget for [Bump.sh](https://bump.sh) agents. A Web\nComponent you drop in with 3 lines — fully isolated (Shadow DOM), fully\ncustomizable.\n\n- **3-line path** — `new Widget({ endpoint })` and you have a chat box.\n- **3 display modes** — `modal` (default), `sidebar`, `inline`.\n- **Isolated** — Shadow DOM: the host page's CSS can't leak in, and vice versa.\n- **Customizable** — CSS tokens, `::part()`, slots, and options.\n- **BYO conversation** — pass your own\n  [`@bump-sh/agent-conversation`](../agent-conversation) `Conversation`.\n\n## Install\n\n```sh\nnpm install @bump-sh/agent-widget\n```\n\nRequires a modern browser with Web Components and native `<dialog>` support\n(all evergreen browsers). The only dependency is\n[`@bump-sh/agent-conversation`](../agent-conversation).\n\n## Quickstart\n\n```ts\nimport { Widget } from \"@bump-sh/agent-widget\"\n\nnew Widget({ endpoint: \"https://your-host/demo/weather/agent\" })\n```\n\nThat mounts a floating launcher + modal. Or declaratively:\n\n```html\n<agent-widget endpoint=\"https://…/agent\" mode=\"sidebar\"></agent-widget>\n<script type=\"module\" src=\"https://unpkg.com/@bump-sh/agent-widget\"></script>\n```\n\nImporting the package auto-registers the `<agent-widget>` element.\n\n## Playground\n\nExplore every option interactively — live preview plus the code to copy — with\nthe [playground](../agent-playground):\n\n```sh\nnpm run playground              # from the repo root\n```\n\n## Options\n\n```ts\nconst widget = new Widget({\n  endpoint,                         // OR conversation: myConversation  (bring your own)\n  token,                            // auth: string | () => string | Promise<string>\n  config,                           // agent config → Config-<Key> headers (map or per-request callback)\n  headers,                          // extra request headers (map or per-request callback)\n  mode: \"modal\",                    // \"modal\" | \"sidebar\" | \"inline\"\n  launcher: true,                   // floating launcher button (modal/sidebar); false to open it yourself\n  target: \"#app\",                   // inline container (selector or element); modal/sidebar → <body>\n  open: false,                      // start opened (inline is always open)\n  theme: { accent: \"#0a0a0a\" },     // → CSS custom properties, see Theming\n  title: \"Assistant\",\n  subtitle: \"AI Agent\",             // small line under the title\n  placeholder: \"Ask anything…\",\n  greeting: \"Hi! How can I help?\",  // optional first assistant message (visual only, not sent to the agent)\n  suggestions: [\"What can you do?\"], // clickable example prompts, shown until the first message\n                                    // (clicking one sends it)\n  avatar: \"https://…/logo.png\",     // image URL or inline emoji/HTML\n  launcherIcon: \"✨\",               // launcher button icon: image URL or inline emoji/HTML\n                                    // (defaults to an AI sparkle)\n  disclaimer: \"AI can make mistakes…\", // footer under the composer (\"\" to hide)\n  labels: { send: \"Send\", close: \"Close\", launch: \"Open chat\", today: \"Today\" },\n                                    // a11y labels + the date divider — override to localize\n  renderMarkdown: (text) => \"…\",    // replace the built-in safe renderer\n})\n```\n\nThe instance is the handle:\n\n```ts\nwidget.open(); widget.close(); widget.toggle()\nwidget.destroy()      // remove the element from the page\nwidget.conversation   // the underlying Conversation (history, events, reset)\nwidget.element        // the <agent-widget> DOM element\n```\n\n### HTML attributes\n\nFor declarative use, these attributes are observed and reactive — change one\nand the widget updates:\n\n| attribute     | maps to        | notes                                          |\n| ------------- | -------------- | ---------------------------------------------- |\n| `endpoint`    | `endpoint`     | Changing it resets the built-in conversation.  |\n| `mode`        | `mode`         | `modal` \\| `sidebar` \\| `inline`.              |\n| `open`        | `open()`/`close()` | Present = open. Toggle it to drive the panel. |\n| `title`       | `title`        |                                                |\n| `subtitle`    | `subtitle`     |                                                |\n| `placeholder` | `placeholder`  | Also the empty-state hint.                     |\n\nEverything else (`token`, `config`, `theme`, callbacks…) is JS-only: pass it\nto `new Widget(options)`, or call `element.configure(options)` before\nattaching a hand-created element.\n\n### Authentication\n\nPass a `token` — it's sent to the endpoint as `Authorization: Bearer <token>`.\nUse a callback for short-lived tokens; it's re-evaluated on every request, so\nthe token refreshes without remounting the widget:\n\n```ts\nnew Widget({\n  endpoint,\n  token: async () => (await fetch(\"/agent-token\")).text(),\n})\n```\n\nThe token lives in the browser, so **mint a user-scoped, short-lived token\nserver-side** — where the page already knows who the logged-in user is — and\nnever expose a raw or tenant-wide API key. In your workflow file, the token is\navailable as `$current_user.token`.\n\n### Agent configuration & custom headers\n\n`config` keys are sent as `Config-<Key>` request headers and are available in\nyour workflow file as `$config.<key>` (`config: { locale: \"fr\" }` →\n`$config.locale`); `headers` adds any other header. Key matching is\ncase-insensitive and treats `-` and `_` as equivalent — prefer dash-separated\nkeys. Both accept a map, or a callback re-evaluated on every request:\n\n```ts\nnew Widget({\n  endpoint,\n  config: { locale: \"fr\" },\n  headers: () => ({ \"X-Request-Id\": crypto.randomUUID() }),\n})\n```\n\n### Markdown rendering\n\nThe built-in renderer is intentionally tiny and dependency-free: it escapes all\nHTML first, then re-introduces a fixed, safe subset — bold, italic, inline code,\ncode blocks, headings, lists, blockquotes, tables, horizontal rules, and links\nrestricted to `http(s)`/`mailto`/relative schemes. It keeps the bundle small —\nno `javascript:`/`data:` links, no raw HTML passthrough.\n\nNeed full CommonMark/GFM? Swap in a specialized renderer via `renderMarkdown`.\nAlways pair the parser with a sanitizer — do not trust model output:\n\n```ts\nimport { marked } from \"marked\"\nimport DOMPurify from \"dompurify\"\n\nnew Widget({\n  endpoint,\n  renderMarkdown: (text) => DOMPurify.sanitize(marked.parse(text) as string),\n})\n```\n\n## Bring your own conversation\n\nBuild the `Conversation` yourself when you need direct access to it — history,\n`on()` events, `reset()` — or to share it with other parts of your app:\n\n```ts\nimport { Conversation } from \"@bump-sh/agent-conversation\"\nimport { Widget } from \"@bump-sh/agent-widget\"\n\nconst conversation = new Conversation({ endpoint: \"https://…/agent\", token: \"…\" })\nnew Widget({ conversation })\n```\n\nAnything with a `send(content): AsyncIterable<AgentEvent>` works\n(`ConversationLike`), so you can also wrap or mock it.\n\n## Theming\n\nSet CSS custom properties — they pierce the Shadow DOM:\n\n```css\nagent-widget {\n  --agent-accent: #e11d48;\n  --agent-font: \"Inter\", sans-serif;\n  --agent-radius: 12px;\n  --agent-width: 360px; /* sidebar */\n}\n```\n\n| token                 | default                 | what it styles                          |\n| --------------------- | ----------------------- | --------------------------------------- |\n| `--agent-accent`      | `#0a0a0a`               | Accents: links, and buttons by default  |\n| `--agent-button-bg`   | `var(--agent-accent)`   | Launcher & send button — override to decouple them from the accent |\n| `--agent-button-fg`   | `#fff`                  | Launcher & send button icon             |\n| `--agent-bg`          | `#ffffff`               | Panel background                        |\n| `--agent-text`        | `#0d0d0d`               | Text                                    |\n| `--agent-muted`       | `#8a8a8f`               | Secondary text (subtitle, status…)      |\n| `--agent-user-bg`     | `#f4f4f5`               | User message bubble                     |\n| `--agent-input-bg`    | `#f7f7f8`               | Composer input                          |\n| `--agent-border`      | `#ececee`               | Borders                                 |\n| `--agent-code-bg`     | `#f4f4f6`               | Code blocks & table headers             |\n| `--agent-avatar-bg`   | `var(--agent-user-bg)`  | Avatar background                       |\n| `--agent-avatar-size` | `28px`                  | Avatar box                              |\n| `--agent-font`        | system sans stack       | Font family                             |\n| `--agent-mono`        | system mono stack       | Code font family                        |\n| `--agent-radius`      | `20px`                  | Corner radius (user bubble, composer, modal panel) |\n| `--agent-width`       | `26vw`                  | Sidebar width                           |\n| `--agent-gutter`      | `18px`                  | Horizontal padding                      |\n| `--agent-column`      | `760px`                 | Max conversation width (inline)         |\n| `--agent-z`           | `2147483000`            | Stacking order                          |\n\nThe `theme` option is a JS shortcut for the most common ones — `accent`,\n`buttonBg`, `buttonFg`, `bg`, `text`, `muted`, `userBg`, `inputBg`, `border`,\n`codeBg`, `font`, `radius`, `width`, `z` — set the rest directly in CSS as\nabove.\n\nStyle internal structure with `::part()`:\n\n```css\nagent-widget::part(send) { border-radius: 6px; }\nagent-widget::part(message-user) { background: #eef; }\n```\n\nParts: `launcher`, `panel`, `header`, `title`, `subtitle`, `close`, `thread`,\n`message`, `message-user`, `message-assistant`, `avatar`, `composer`,\n`input`, `send`, `status`, `disclaimer`.\n\nReplace whole regions with slots: `title`, `empty` (empty-thread state),\n`composer-actions` (left of the send button).\n\n```html\n<agent-widget endpoint=\"https://…/agent\">\n  <span slot=\"title\">Ask our docs</span>\n</agent-widget>\n```\n\n## Interaction & accessibility\n\n- **Enter** sends, **Shift+Enter** inserts a newline.\n- Modal and sidebar are native `<dialog>`s shown top-layer: **Escape** closes,\n  focus is trapped, and clicking the backdrop dismisses.\n- Launcher, close, and send buttons carry `aria-label`s — localize them via\n  `labels`.\n- While a reply streams, sending is disabled and a status line shows the\n  tools the agent is running.\n\n## Exports\n\n- `Widget` — the one-line façade (create, mount, handle).\n- `AgentWidget` — the custom element class, for hand-rolled setups.\n- `defineAgentWidget(tag?)` — register the element, optionally under a custom\n  tag name (idempotent; called automatically on import).\n- `renderMarkdown` — the built-in safe renderer, reusable on its own.\n- Types: `WidgetOptions`, `ConversationLike`, `Labels`, `Mode`, `Theme`.\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-28a9d8c50a775c6e9747b17062ce9009"}