@aiden-voice/widget 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -102,6 +102,7 @@ throws synchronously, at call time, if you pass both or neither.
102
102
  | `inkColor` | Body text color (chat title and replies). Darkened automatically if needed to stay readable. Overrides the color configured in whoo-aiden; omit it to use that one. | whoo-aiden's, else `'#111111'` |
103
103
  | `accentColor` | Link color in replies. Darkened automatically if needed to stay readable. Overrides the color configured in whoo-aiden; omit it to use that one. | whoo-aiden's, else `'#0000ee'` |
104
104
  | `name` | Agent name for the panel header and the dialog's screen-reader label ("Chat with {name}"). Overrides the name configured in whoo-aiden; omit it to use that one. | whoo-aiden's, else `'Aiden'` |
105
+ | `title` | Full panel title, used for the header heading and the dialog's screen-reader label. Replaces the whole "Chat with {name}" string (e.g. `'Ask our concierge'`), with surrounding whitespace trimmed; the agent's messages are still labelled with its name. A blank value is ignored. | `'Chat with {name}'` |
105
106
  | `greeting` | Welcome text shown in the panel before the first message. | none |
106
107
  | `launcherIconUrl` | Image shown on the launcher bubble instead of the default chat icon. `https:` or `data:image/` only. Until it loads, and permanently if it fails, the default icon shows. Alias of `theme.launcher.iconUrl`. | none (default icon) |
107
108
  | `theme` | Colors, font and launcher icons. See [Theming](#theming). | defaults |
@@ -250,26 +251,34 @@ version it needs exists — don't pre-embed `/v1/` in anticipation of a `1.0.0`
250
251
 
251
252
  ## Releasing
252
253
 
253
- Releases are tag-driven via `.github/workflows/release.yml` (the `Release`
254
- workflow), running in the `release` GitHub environment. It has two jobs:
255
- `cdn` (build, archive upload, alias rewrite, Static Web App deploy) and
256
- `publish` (npm), with `publish` gated on `cdn` succeeding first.
254
+ Releases start from the version bump itself, via `.github/workflows/release.yml`
255
+ (the `Release` workflow), running in the `release` GitHub environment. It has
256
+ three jobs: `tag` (creates the version tag), `cdn` (build, archive upload,
257
+ alias rewrite, Static Web App deploy) and `publish` (npm), with `publish`
258
+ gated on `cdn` succeeding first.
257
259
 
258
260
  1. Bump `version` in **both** `package.json` and `src/version.ts`'s
259
- `WIDGET_VERSION` (a normal PR — `tests/version.test.ts` asserts the two
260
- stay in sync), and merge it to `main`.
261
- 2. Tag the merge commit and push the tag:
262
-
263
- ```sh
264
- git tag v<version> && git push origin v<version>
265
- ```
266
-
267
- The tag must match `package.json`'s `version` exactly, for a stable
268
- release (e.g. `v1.3.0` ↔ `1.3.0`) and for a prerelease alike (e.g.
269
- `v1.3.0-rc.1` ↔ `1.3.0-rc.1`) — the workflow refuses a mismatch.
270
- Prereleases use a `-rc.N` suffix.
271
-
272
- Pushing a `v*` tag runs the workflow. The `cdn` job:
261
+ `WIDGET_VERSION` in a normal PR. `tests/version.test.ts` fails the PR's
262
+ required `quality` check unless the two agree, so a mismatched bump can't
263
+ be merged.
264
+ 2. Merge it to `main`. That is the whole release step: merging is the
265
+ approval, and there is no tag to push.
266
+
267
+ When a push to `main` changes `package.json` or `src/version.ts`, the
268
+ workflow runs and `tag` looks for `v<version>`. If the tag doesn't exist yet,
269
+ `tag` creates it on the pushed commit (a lightweight tag, via the API) and
270
+ `cdn` then `publish` run in that same run. If it does exist, the change
271
+ wasn't a version bump (e.g. a dependency edit in `package.json`), so
272
+ `cdn`/`publish` are skipped. A version that isn't plain SemVer is refused
273
+ before any tag is created. Stable releases and prereleases alike are named
274
+ from the version: `1.3.0` → `v1.3.0`, `1.3.0-rc.1` → `v1.3.0-rc.1`
275
+ (prereleases use a `-rc.N` suffix).
276
+
277
+ Pushing a `v*` tag by hand still starts the workflow too (it skips `tag`),
278
+ and then the tag must match `package.json`'s `version` exactly or the
279
+ workflow refuses.
280
+
281
+ The `cdn` job:
273
282
 
274
283
  - Builds and re-runs the full quality gate (lint, typecheck, unit tests,
275
284
  build) against the tagged commit.
@@ -348,11 +357,14 @@ for a failed `cdn` job.
348
357
 
349
358
  ### Recovering a failed release
350
359
 
351
- If the `cdn` job fails partway through — after the version folder was
352
- already uploaded to the archive — simply re-pushing the same tag will not
353
- work: `scripts/release-plan.mjs plan` refuses a version that already
354
- exists in the archive, since versions are immutable by design. To recover,
355
- delete that version's folder from the archive first, then re-push the tag.
360
+ If the `cdn` job fails before it uploads anything (a flaky test, an Azure
361
+ login), use **Re-run failed jobs** on that run: `tag` already succeeded and
362
+ is not repeated. If it fails partway through — after the version folder was
363
+ already uploaded to the archive — re-running will not work:
364
+ `scripts/release-plan.mjs plan` refuses a version that already exists in the
365
+ archive, since versions are immutable by design. To recover, delete that
366
+ version's folder from the archive first, then re-run the failed `cdn` job (or,
367
+ if you deleted the tag too, re-push it as below).
356
368
  Run this as an operator, not the workflow's identity — the release
357
369
  identity is the only principal with a data-plane role on the container, so
358
370
  an operator's own `az storage blob` command needs `--auth-mode key`
@@ -362,7 +374,9 @@ key for that):
362
374
  ```sh
363
375
  az storage blob delete-batch --account-name <acct> --source widget-releases \
364
376
  --pattern "vX.Y.Z/*" --auth-mode key
365
- git push origin :refs/tags/vX.Y.Z # delete the remote tag
377
+ # Only if you'd rather start a fresh run than re-run the failed job: delete the remote
378
+ # tag and push it again by hand (a manual tag push skips the `tag` job).
379
+ git push origin :refs/tags/vX.Y.Z
366
380
  git tag -d vX.Y.Z && git tag vX.Y.Z && git push origin vX.Y.Z
367
381
  ```
368
382
 
package/dist/types.d.ts CHANGED
@@ -89,6 +89,7 @@ export interface WidgetConfig {
89
89
  */
90
90
  accentColor?: string;
91
91
  name?: string;
92
+ title?: string;
92
93
  greeting?: string;
93
94
  /** Image shown on the launcher bubble instead of the default chat icon. Alias of `theme.launcher.iconUrl`, which wins if both are set. */
94
95
  launcherIconUrl?: string;
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const WIDGET_VERSION = "0.6.0";
1
+ export declare const WIDGET_VERSION = "0.7.0";
@@ -2,7 +2,7 @@ var whooAidenWidget=(function(e){Object.defineProperty(e,Symbol.toStringTag,{val
2
2
  `)&&(xt.lastIndex=n,xt.exec(e))){i(n),t.push({type:`text`,value:`• `,start:n,end:xt.lastIndex}),n=xt.lastIndex,r=n;continue}if(e[n]===`!`&&n+1<e.length&&e[n+1]===`[`){let t=/!\[([^\]]*)\]\(([^)]*)\)/y;t.lastIndex=n;let r=t.exec(e);if(r){n+=r[0].length;continue}}if(e[n-1]!==`!`){_t.lastIndex=n;let a=_t.exec(e);if(a){i(n),t.push({type:`link`,text:a[1],url:a[2],start:n,end:_t.lastIndex}),n=_t.lastIndex,r=n;continue}}vt.lastIndex=n;let a=vt.exec(e);if(a){i(n),t.push({type:`bold`,value:a[1],start:n,end:vt.lastIndex}),n=vt.lastIndex,r=n;continue}yt.lastIndex=n;let o=yt.exec(e);if(o){i(n),t.push({type:`italic`,value:o[1],start:n,end:yt.lastIndex}),n=yt.lastIndex,r=n;continue}bt.lastIndex=n;let s=bt.exec(e);if(s){i(n),t.push({type:`italic`,value:s[1],start:n,end:bt.lastIndex}),n=bt.lastIndex,r=n;continue}St.lastIndex=n;let c=St.exec(e);if(c){let e=c[0].match(Ct),a=e?c[0].slice(0,c[0].length-e[0].length):c[0];if(a.length>0){i(n),t.push({type:`link`,text:a,url:a,start:n,end:n+a.length}),n+=a.length,r=n;continue}}n+=1}return i(e.length),t}var Tt=/^[ \t]*[*+-][ \t]+(.*)$/;function Et(e){let t=[],n=[],r=[],i=()=>{n.length>0&&t.push({type:`text`,text:n.join(`
3
3
  `)}),n=[]},a=()=>{r.length>0&&t.push({type:`list`,items:r}),r=[]};for(let t of e.split(`
4
4
  `)){let e=t.match(Tt);e?(i(),r.push(e[1])):(a(),n.push(t))}return i(),a(),t.some(e=>e.type===`list`)?t.flatMap((e,n)=>{if(e.type===`list`)return[e];let{text:r}=e;return t[n-1]?.type===`list`&&(r=r.replace(/^(?:[ \t]*\n)+/,``)),t[n+1]?.type===`list`&&(r=r.replace(/(?:\n[ \t]*)+$/,``)),r.trim()===``?[]:[{type:`text`,text:r}]}):null}function J(e){return wt(e).map((e,t)=>{switch(e.type){case`bold`:return K(`strong`,{children:J(e.value)},t);case`italic`:return K(`em`,{children:J(e.value)},t);case`link`:return K(`a`,{href:e.url,target:`_blank`,rel:`noopener noreferrer`,children:[e.text,K(`span`,{class:`whoo-widget-sr-only`,children:` (opens in new tab)`})]},t);default:return e.value}})}function Dt(e){let t=e.replace(/\r\n?/g,`
5
- `),n=Et(t);return n?n.map((e,t)=>e.type===`list`?K(`ul`,{class:`whoo-widget-list`,children:e.items.map((e,t)=>K(`li`,{children:J(e)},t))},t):K(`span`,{children:J(e.text)},t)):J(t)}var Ot=[{value:``,label:`Select a reason (optional)`},{value:`factual`,label:`Factual error`},{value:`incomplete`,label:`Incomplete`},{value:`tone`,label:`Off tone`},{value:`other`,label:`Other`}];function kt({state:e,containerRef:t,onThumbsUp:n,onThumbsDown:r,onDraftChange:i,onSubmitDetailed:a,onCancel:o}){let s=e.correction??``,c=e.category??``,l=W(e.status);if(U(()=>{let n=l.current;if(l.current=e.status,n===e.status)return;let r=t?.current;if(!r)return;let i=r.getRootNode();r.contains(i.activeElement)||r.focus()},[e.status,t]),e.status===`expanded`)return K(`div`,{class:`whoo-widget-feedback-form`,children:[K(`label`,{children:[K(`span`,{class:`whoo-widget-sr-only`,children:`Additional feedback`}),K(`textarea`,{class:`whoo-widget-feedback-textarea`,value:s,onInput:e=>i(e.target.value,c),placeholder:`What was wrong? (optional)`})]}),K(`select`,{class:`whoo-widget-feedback-select`,"aria-label":`Feedback category`,value:c,onChange:e=>i(s,e.target.value),children:Ot.map(e=>K(`option`,{value:e.value,children:e.label},e.value))}),K(`div`,{class:`whoo-widget-feedback-form-buttons`,children:[K(`button`,{type:`button`,class:`whoo-widget-feedback-submit`,onClick:()=>a(s,c),children:`Submit`}),K(`button`,{type:`button`,class:`whoo-widget-feedback-cancel`,onClick:o,children:`Cancel`})]})]});let u=e.status===`submitting`,d=e.status===`submitted`;return K(`div`,{class:`whoo-widget-feedback`,children:[d?null:K(`div`,{class:`whoo-widget-feedback-buttons`,children:[K(`button`,{type:`button`,"aria-label":`Good response`,disabled:u,onClick:n,children:K(ut,{})}),K(`button`,{type:`button`,"aria-label":`Bad response`,disabled:u,onClick:r,children:K(dt,{})})]}),K(`div`,{role:`status`,class:d?`whoo-widget-feedback-submitted`:e.status===`error`?`whoo-widget-feedback-error`:void 0,children:d?`Thanks for the feedback`:e.status===`error`?`Couldn't send feedback`:null})]})}function At({isSlowResponse:e}){return K(`div`,{class:`whoo-widget-pending`,role:`status`,children:[K(`span`,{class:`whoo-widget-typing`,"aria-hidden":`true`,children:[K(`span`,{}),K(`span`,{}),K(`span`,{})]}),e?K(`span`,{class:`whoo-widget-pending-text`,children:`Looking that up for you…`}):null]})}function jt({url:e,alt:t}){let[n,r]=H(!1);return n?null:K(`img`,{class:`whoo-widget-empty-state-image`,src:e,alt:t,referrerpolicy:`no-referrer`,onError:()=>r(!0)})}function Mt({message:e,speaker:t,feedbackState:n,showFeedback:r,pending:i,isSlowResponse:a,onThumbsUp:o,onThumbsDown:s,onDraftChange:c,onSubmitDetailed:l,onCancelFeedback:u}){let d=W(null),f=e.id;return K(`div`,{ref:d,tabIndex:-1,class:`whoo-widget-message whoo-widget-message--${e.role}`,children:[K(`span`,{class:`whoo-widget-sr-only`,children:[t,`: `]}),i?K(At,{isSlowResponse:a}):Dt(e.content),r&&e.role===`assistant`&&f?K(kt,{state:n,containerRef:d,onThumbsUp:()=>o(f),onThumbsDown:()=>s(f),onDraftChange:(e,t)=>c(f,e,t),onSubmitDetailed:(e,t)=>l(f,e,t),onCancel:()=>u(f)}):null]})}function Nt({messages:e,messageFeedback:t,announcement:n,emptyStateImage:r,agentName:i=c,showFeedback:a=!1,isStreaming:o=!1,isSlowResponse:s=!1,onThumbsUp:l,onThumbsDown:u,onDraftChange:d=()=>{},onSubmitDetailed:f,onCancelFeedback:p}){let m=W(null);return U(()=>{let e=m.current;e&&(e.scrollTop=e.scrollHeight)},[e,s]),K(F,{children:[K(`section`,{class:`whoo-widget-message-list`,ref:m,"aria-label":`Conversation`,tabIndex:0,children:[r?K(jt,{...r}):null,e.map((n,r)=>K(Mt,{message:n,speaker:n.role===`user`?`You`:i,showFeedback:a,feedbackState:n.id?t[n.id]??{status:`idle`}:{status:`idle`},pending:o&&r===e.length-1&&n.role===`assistant`&&n.content===``,isSlowResponse:s,onThumbsUp:l,onThumbsDown:u,onDraftChange:d,onSubmitDetailed:f,onCancelFeedback:p},n.id??r))]}),K(`div`,{class:`whoo-widget-sr-only`,"aria-live":`polite`,"aria-atomic":`true`,children:n??``})]})}var Pt=`button:not(:disabled), [href], input:not(:disabled), select:not(:disabled), textarea:not(:disabled), [tabindex]:not([tabindex="-1"])`;function Ft(e){return Array.from(e.querySelectorAll(Pt)).filter(e=>{let t=getComputedStyle(e);return t.display!==`none`&&t.visibility!==`hidden`})}function It({state:e,controller:t,greeting:n}){let r=W(null),i=W(null);U(()=>{i.current?.focus()},[]);let a=e=>{if(e.key===`Escape`){t.close();return}if(e.key!==`Tab`)return;let n=r.current;if(!n)return;let i=Ft(n);if(i.length===0)return;let a=i[0],o=i[i.length-1],s=n.getRootNode().activeElement;if(!n.contains(s)){e.preventDefault(),a.focus();return}e.shiftKey&&s===a?(e.preventDefault(),o.focus()):!e.shiftKey&&s===o&&(e.preventDefault(),a.focus())},o=()=>{let n=e.draft.trim();n&&!e.isStreaming&&(t.setDraft(``),t.sendMessage(n))},s=l(t.config.name)||e.agentName||`Aiden`,c=`Chat with ${s}`,u=e.messages.length===0&&n?[{role:`assistant`,content:n,id:null}]:e.messages,d=t.emptyStateImageUrl,f=e.messages.length===0&&d?{url:d,alt:t.emptyStateImageAlt}:void 0;return K(`div`,{class:`whoo-widget-panel`,role:`dialog`,"aria-modal":`true`,"aria-label":c,ref:r,onKeyDown:a,children:[K(`div`,{class:`whoo-widget-header`,children:[K(`h2`,{class:`whoo-widget-header-title`,children:c}),K(`div`,{class:`whoo-widget-header-actions`,children:[e.messages.length>0&&K(`button`,{type:`button`,class:`whoo-widget-header-reset`,onClick:()=>{t.resetConversation(),i.current?.focus()},children:`New conversation`}),K(`button`,{type:`button`,class:`whoo-widget-header-close`,"aria-label":`Close chat`,onClick:()=>t.close(),children:K(ct,{})})]})]}),K(Nt,{messages:u,messageFeedback:e.messageFeedback,announcement:e.announcement,emptyStateImage:f,agentName:s,showFeedback:t.showFeedback,isStreaming:e.isStreaming,isSlowResponse:e.isSlowResponse,onThumbsUp:e=>t.submitFeedback(e,`up`),onThumbsDown:e=>t.expandFeedback(e),onDraftChange:(e,n,r)=>t.setFeedbackDraft(e,n,r),onSubmitDetailed:(e,n,r)=>t.submitFeedback(e,`down`,n||void 0,r||void 0),onCancelFeedback:e=>t.cancelFeedback(e)}),e.runtimeError&&K(gt,{message:e.runtimeError}),K(ht,{value:e.draft,onChange:e=>t.setDraft(e),onSend:o,disabled:e.isStreaming,inputRef:i})]})}function Lt({controller:e}){let[t,n]=H(e.getState()),r=W(null),i=W(t.isOpen);return U(()=>(n(e.getState()),e.subscribe(n)),[e]),U(()=>{i.current&&!t.isOpen&&r.current?.focus(),i.current=t.isOpen},[t.isOpen]),t.initError||t.isInitializing?null:K(F,{children:[K(mt,{isOpen:t.isOpen,onClick:()=>t.isOpen?e.close():e.open(),iconUrl:e.launcher.iconUrl,icon:e.launcher.icon,openIconUrl:e.launcher.openIconUrl,openIcon:e.launcher.openIcon,buttonRef:r}),t.isOpen&&K(It,{state:t,controller:e,greeting:e.config.greeting})]})}var Rt=class extends Error{status;constructor(e,t){super(e),this.name=`WidgetApiError`,this.status=t}};function zt(e){if(typeof e!=`string`)return null;let t=e.trim();return t===``?null:t}async function Bt(e,t){let n=await fetch(`${e}/api/v1/widget/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({publishable_key:t})});if(!n.ok)throw new Rt(`Failed to create widget session (${n.status})`,n.status);let r=await n.json();return{token:r.token,...Vt(r)}}function Vt(e){return{primaryColor:zt(e.primary_color),name:zt(e.name),accentColor:zt(e.accent_color),inkColor:zt(e.ink_color)}}async function Ht(e,t){let n=await fetch(`${e}/api/v1/widget/branding`,{headers:{Authorization:`Bearer ${t}`}});if(!n.ok)throw new Rt(`Failed to load widget branding (${n.status})`,n.status);return Vt(await n.json())}async function Ut(e,t,n){let r=await fetch(`${e}/api/v1/widget/feedback`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${t}`},body:JSON.stringify({message_id:n.messageId,rating:n.rating,correction:n.correction??null,category:n.category??null})});if(!r.ok)throw new Rt(`Feedback submission failed (${r.status})`,r.status)}async function*Wt(e,t,n,r,i){let a=await fetch(`${e}/api/v1/widget/chat`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${t}`},body:JSON.stringify({conversation_id:n,message:r}),signal:i});if(!a.ok||!a.body)throw new Rt(`Chat request failed (${a.status})`,a.status);let o=a.body.getReader(),s=new TextDecoder,c=``;for(;;){let{done:e,value:t}=await o.read();if(e)break;c+=s.decode(t,{stream:!0});let n=c.indexOf(`
5
+ `),n=Et(t);return n?n.map((e,t)=>e.type===`list`?K(`ul`,{class:`whoo-widget-list`,children:e.items.map((e,t)=>K(`li`,{children:J(e)},t))},t):K(`span`,{children:J(e.text)},t)):J(t)}var Ot=[{value:``,label:`Select a reason (optional)`},{value:`factual`,label:`Factual error`},{value:`incomplete`,label:`Incomplete`},{value:`tone`,label:`Off tone`},{value:`other`,label:`Other`}];function kt({state:e,containerRef:t,onThumbsUp:n,onThumbsDown:r,onDraftChange:i,onSubmitDetailed:a,onCancel:o}){let s=e.correction??``,c=e.category??``,l=W(e.status);if(U(()=>{let n=l.current;if(l.current=e.status,n===e.status)return;let r=t?.current;if(!r)return;let i=r.getRootNode();r.contains(i.activeElement)||r.focus()},[e.status,t]),e.status===`expanded`)return K(`div`,{class:`whoo-widget-feedback-form`,children:[K(`label`,{children:[K(`span`,{class:`whoo-widget-sr-only`,children:`Additional feedback`}),K(`textarea`,{class:`whoo-widget-feedback-textarea`,value:s,onInput:e=>i(e.target.value,c),placeholder:`What was wrong? (optional)`})]}),K(`select`,{class:`whoo-widget-feedback-select`,"aria-label":`Feedback category`,value:c,onChange:e=>i(s,e.target.value),children:Ot.map(e=>K(`option`,{value:e.value,children:e.label},e.value))}),K(`div`,{class:`whoo-widget-feedback-form-buttons`,children:[K(`button`,{type:`button`,class:`whoo-widget-feedback-submit`,onClick:()=>a(s,c),children:`Submit`}),K(`button`,{type:`button`,class:`whoo-widget-feedback-cancel`,onClick:o,children:`Cancel`})]})]});let u=e.status===`submitting`,d=e.status===`submitted`;return K(`div`,{class:`whoo-widget-feedback`,children:[d?null:K(`div`,{class:`whoo-widget-feedback-buttons`,children:[K(`button`,{type:`button`,"aria-label":`Good response`,disabled:u,onClick:n,children:K(ut,{})}),K(`button`,{type:`button`,"aria-label":`Bad response`,disabled:u,onClick:r,children:K(dt,{})})]}),K(`div`,{role:`status`,class:d?`whoo-widget-feedback-submitted`:e.status===`error`?`whoo-widget-feedback-error`:void 0,children:d?`Thanks for the feedback`:e.status===`error`?`Couldn't send feedback`:null})]})}function At({isSlowResponse:e}){return K(`div`,{class:`whoo-widget-pending`,role:`status`,children:[K(`span`,{class:`whoo-widget-typing`,"aria-hidden":`true`,children:[K(`span`,{}),K(`span`,{}),K(`span`,{})]}),e?K(`span`,{class:`whoo-widget-pending-text`,children:`Looking that up for you…`}):null]})}function jt({url:e,alt:t}){let[n,r]=H(!1);return n?null:K(`img`,{class:`whoo-widget-empty-state-image`,src:e,alt:t,referrerpolicy:`no-referrer`,onError:()=>r(!0)})}function Mt({message:e,speaker:t,feedbackState:n,showFeedback:r,pending:i,isSlowResponse:a,onThumbsUp:o,onThumbsDown:s,onDraftChange:c,onSubmitDetailed:l,onCancelFeedback:u}){let d=W(null),f=e.id;return K(`div`,{ref:d,tabIndex:-1,class:`whoo-widget-message whoo-widget-message--${e.role}`,children:[K(`span`,{class:`whoo-widget-sr-only`,children:[t,`: `]}),i?K(At,{isSlowResponse:a}):Dt(e.content),r&&e.role===`assistant`&&f?K(kt,{state:n,containerRef:d,onThumbsUp:()=>o(f),onThumbsDown:()=>s(f),onDraftChange:(e,t)=>c(f,e,t),onSubmitDetailed:(e,t)=>l(f,e,t),onCancel:()=>u(f)}):null]})}function Nt({messages:e,messageFeedback:t,announcement:n,emptyStateImage:r,agentName:i=c,showFeedback:a=!1,isStreaming:o=!1,isSlowResponse:s=!1,onThumbsUp:l,onThumbsDown:u,onDraftChange:d=()=>{},onSubmitDetailed:f,onCancelFeedback:p}){let m=W(null);return U(()=>{let e=m.current;e&&(e.scrollTop=e.scrollHeight)},[e,s]),K(F,{children:[K(`section`,{class:`whoo-widget-message-list`,ref:m,"aria-label":`Conversation`,tabIndex:0,children:[r?K(jt,{...r}):null,e.map((n,r)=>K(Mt,{message:n,speaker:n.role===`user`?`You`:i,showFeedback:a,feedbackState:n.id?t[n.id]??{status:`idle`}:{status:`idle`},pending:o&&r===e.length-1&&n.role===`assistant`&&n.content===``,isSlowResponse:s,onThumbsUp:l,onThumbsDown:u,onDraftChange:d,onSubmitDetailed:f,onCancelFeedback:p},n.id??r))]}),K(`div`,{class:`whoo-widget-sr-only`,"aria-live":`polite`,"aria-atomic":`true`,children:n??``})]})}var Pt=`button:not(:disabled), [href], input:not(:disabled), select:not(:disabled), textarea:not(:disabled), [tabindex]:not([tabindex="-1"])`;function Ft(e){return Array.from(e.querySelectorAll(Pt)).filter(e=>{let t=getComputedStyle(e);return t.display!==`none`&&t.visibility!==`hidden`})}function It({state:e,controller:t,greeting:n}){let r=W(null),i=W(null);U(()=>{i.current?.focus()},[]);let a=e=>{if(e.key===`Escape`){t.close();return}if(e.key!==`Tab`)return;let n=r.current;if(!n)return;let i=Ft(n);if(i.length===0)return;let a=i[0],o=i[i.length-1],s=n.getRootNode().activeElement;if(!n.contains(s)){e.preventDefault(),a.focus();return}e.shiftKey&&s===a?(e.preventDefault(),o.focus()):!e.shiftKey&&s===o&&(e.preventDefault(),a.focus())},o=()=>{let n=e.draft.trim();n&&!e.isStreaming&&(t.setDraft(``),t.sendMessage(n))},s=l(t.config.name)||e.agentName||`Aiden`,c=l(t.config.title)||`Chat with ${s}`,u=e.messages.length===0&&n?[{role:`assistant`,content:n,id:null}]:e.messages,d=t.emptyStateImageUrl,f=e.messages.length===0&&d?{url:d,alt:t.emptyStateImageAlt}:void 0;return K(`div`,{class:`whoo-widget-panel`,role:`dialog`,"aria-modal":`true`,"aria-label":c,ref:r,onKeyDown:a,children:[K(`div`,{class:`whoo-widget-header`,children:[K(`h2`,{class:`whoo-widget-header-title`,children:c}),K(`div`,{class:`whoo-widget-header-actions`,children:[e.messages.length>0&&K(`button`,{type:`button`,class:`whoo-widget-header-reset`,onClick:()=>{t.resetConversation(),i.current?.focus()},children:`New conversation`}),K(`button`,{type:`button`,class:`whoo-widget-header-close`,"aria-label":`Close chat`,onClick:()=>t.close(),children:K(ct,{})})]})]}),K(Nt,{messages:u,messageFeedback:e.messageFeedback,announcement:e.announcement,emptyStateImage:f,agentName:s,showFeedback:t.showFeedback,isStreaming:e.isStreaming,isSlowResponse:e.isSlowResponse,onThumbsUp:e=>t.submitFeedback(e,`up`),onThumbsDown:e=>t.expandFeedback(e),onDraftChange:(e,n,r)=>t.setFeedbackDraft(e,n,r),onSubmitDetailed:(e,n,r)=>t.submitFeedback(e,`down`,n||void 0,r||void 0),onCancelFeedback:e=>t.cancelFeedback(e)}),e.runtimeError&&K(gt,{message:e.runtimeError}),K(ht,{value:e.draft,onChange:e=>t.setDraft(e),onSend:o,disabled:e.isStreaming,inputRef:i})]})}function Lt({controller:e}){let[t,n]=H(e.getState()),r=W(null),i=W(t.isOpen);return U(()=>(n(e.getState()),e.subscribe(n)),[e]),U(()=>{i.current&&!t.isOpen&&r.current?.focus(),i.current=t.isOpen},[t.isOpen]),t.initError||t.isInitializing?null:K(F,{children:[K(mt,{isOpen:t.isOpen,onClick:()=>t.isOpen?e.close():e.open(),iconUrl:e.launcher.iconUrl,icon:e.launcher.icon,openIconUrl:e.launcher.openIconUrl,openIcon:e.launcher.openIcon,buttonRef:r}),t.isOpen&&K(It,{state:t,controller:e,greeting:e.config.greeting})]})}var Rt=class extends Error{status;constructor(e,t){super(e),this.name=`WidgetApiError`,this.status=t}};function zt(e){if(typeof e!=`string`)return null;let t=e.trim();return t===``?null:t}async function Bt(e,t){let n=await fetch(`${e}/api/v1/widget/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({publishable_key:t})});if(!n.ok)throw new Rt(`Failed to create widget session (${n.status})`,n.status);let r=await n.json();return{token:r.token,...Vt(r)}}function Vt(e){return{primaryColor:zt(e.primary_color),name:zt(e.name),accentColor:zt(e.accent_color),inkColor:zt(e.ink_color)}}async function Ht(e,t){let n=await fetch(`${e}/api/v1/widget/branding`,{headers:{Authorization:`Bearer ${t}`}});if(!n.ok)throw new Rt(`Failed to load widget branding (${n.status})`,n.status);return Vt(await n.json())}async function Ut(e,t,n){let r=await fetch(`${e}/api/v1/widget/feedback`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${t}`},body:JSON.stringify({message_id:n.messageId,rating:n.rating,correction:n.correction??null,category:n.category??null})});if(!r.ok)throw new Rt(`Feedback submission failed (${r.status})`,r.status)}async function*Wt(e,t,n,r,i){let a=await fetch(`${e}/api/v1/widget/chat`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${t}`},body:JSON.stringify({conversation_id:n,message:r}),signal:i});if(!a.ok||!a.body)throw new Rt(`Chat request failed (${a.status})`,a.status);let o=a.body.getReader(),s=new TextDecoder,c=``;for(;;){let{done:e,value:t}=await o.read();if(e)break;c+=s.decode(t,{stream:!0});let n=c.indexOf(`
6
6
 
7
7
  `);for(;n!==-1;){let e=c.slice(0,n);c=c.slice(n+2);let t=e.split(`
8
8
  `).find(e=>e.startsWith(`data: `));t&&(yield Gt(JSON.parse(t.slice(6)))),n=c.indexOf(`
package/dist/widget.js CHANGED
@@ -1137,7 +1137,7 @@ function It({ state: e, controller: t, greeting: n }) {
1137
1137
  }, o = () => {
1138
1138
  let n = e.draft.trim();
1139
1139
  n && !e.isStreaming && (t.setDraft(""), t.sendMessage(n));
1140
- }, s = c(t.config.name) || e.agentName || "Aiden", l = `Chat with ${s}`, u = e.messages.length === 0 && n ? [{
1140
+ }, s = c(t.config.name) || e.agentName || "Aiden", l = c(t.config.title) || `Chat with ${s}`, u = e.messages.length === 0 && n ? [{
1141
1141
  role: "assistant",
1142
1142
  content: n,
1143
1143
  id: null
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiden-voice/widget",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "packageManager": "pnpm@11.9.0",
5
5
  "description": "Embeddable chat widget for whoo-aiden",
6
6
  "repository": {