@webless/agent 0.7.0 → 0.7.3

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.
@@ -3372,6 +3372,126 @@ function toSpeechText(text) {
3372
3372
  function isSpeechSupported() {
3373
3373
  return typeof window !== "undefined" && "speechSynthesis" in window && typeof window.SpeechSynthesisUtterance === "function";
3374
3374
  }
3375
+ function stopSpeech() {
3376
+ if (!isSpeechSupported()) return;
3377
+ window.speechSynthesis.cancel();
3378
+ }
3379
+ var speechInterruptListeners = /* @__PURE__ */ new Set();
3380
+ var pageListenersAttached = false;
3381
+ var lastPathname = "";
3382
+ var originalPushState = null;
3383
+ var originalReplaceState = null;
3384
+ var patchedPushState = null;
3385
+ var patchedReplaceState = null;
3386
+ function currentPathname() {
3387
+ return window.location.pathname;
3388
+ }
3389
+ function notifySpeechInterrupts() {
3390
+ if (speechInterruptListeners.size === 0) return;
3391
+ stopSpeech();
3392
+ for (const listener of speechInterruptListeners) {
3393
+ listener();
3394
+ }
3395
+ }
3396
+ function interruptIfPathChanged(nextPath) {
3397
+ if (nextPath === lastPathname) return;
3398
+ lastPathname = nextPath;
3399
+ notifySpeechInterrupts();
3400
+ }
3401
+ function patchHistoryMethod(original) {
3402
+ return function patched(data, unused, url) {
3403
+ const result = original.call(this, data, unused, url);
3404
+ interruptIfPathChanged(currentPathname());
3405
+ return result;
3406
+ };
3407
+ }
3408
+ function historyMethodState(name) {
3409
+ return name === "pushState" ? {
3410
+ original: originalPushState,
3411
+ patched: patchedPushState,
3412
+ set(original, patched) {
3413
+ originalPushState = original;
3414
+ patchedPushState = patched;
3415
+ }
3416
+ } : {
3417
+ original: originalReplaceState,
3418
+ patched: patchedReplaceState,
3419
+ set(original, patched) {
3420
+ originalReplaceState = original;
3421
+ patchedReplaceState = patched;
3422
+ }
3423
+ };
3424
+ }
3425
+ function patchHistoryNamed(name) {
3426
+ const state = historyMethodState(name);
3427
+ const current = history[name];
3428
+ if (state.patched && current === state.patched) return;
3429
+ const patched = patchHistoryMethod(current);
3430
+ state.set(current, patched);
3431
+ history[name] = patched;
3432
+ }
3433
+ function restoreHistoryMethod(name) {
3434
+ const state = historyMethodState(name);
3435
+ if (!state.patched || !state.original || typeof history === "undefined") {
3436
+ return false;
3437
+ }
3438
+ if (history[name] !== state.patched) return false;
3439
+ history[name] = state.original;
3440
+ state.set(null, null);
3441
+ return true;
3442
+ }
3443
+ function handlePageHide() {
3444
+ notifySpeechInterrupts();
3445
+ }
3446
+ function handlePopState() {
3447
+ interruptIfPathChanged(currentPathname());
3448
+ }
3449
+ function handleVisibilityChange() {
3450
+ if (document.visibilityState === "hidden") {
3451
+ notifySpeechInterrupts();
3452
+ }
3453
+ }
3454
+ function attachPageListeners() {
3455
+ if (pageListenersAttached || typeof window === "undefined") return;
3456
+ pageListenersAttached = true;
3457
+ window.addEventListener("pagehide", handlePageHide);
3458
+ window.addEventListener("popstate", handlePopState);
3459
+ document.addEventListener("visibilitychange", handleVisibilityChange);
3460
+ }
3461
+ function detachPageListeners() {
3462
+ if (!pageListenersAttached || typeof window === "undefined") return;
3463
+ window.removeEventListener("pagehide", handlePageHide);
3464
+ window.removeEventListener("popstate", handlePopState);
3465
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
3466
+ pageListenersAttached = false;
3467
+ }
3468
+ function ensureSpeechInterruptsPatched() {
3469
+ if (typeof window === "undefined") return;
3470
+ lastPathname = currentPathname();
3471
+ patchHistoryNamed("pushState");
3472
+ patchHistoryNamed("replaceState");
3473
+ attachPageListeners();
3474
+ }
3475
+ function teardownSpeechInterrupts() {
3476
+ detachPageListeners();
3477
+ restoreHistoryMethod("pushState");
3478
+ restoreHistoryMethod("replaceState");
3479
+ if (!patchedPushState && !patchedReplaceState) {
3480
+ lastPathname = "";
3481
+ }
3482
+ }
3483
+ function subscribeSpeechInterrupts(onInterrupt) {
3484
+ if (typeof window === "undefined") return () => {
3485
+ };
3486
+ ensureSpeechInterruptsPatched();
3487
+ speechInterruptListeners.add(onInterrupt);
3488
+ return () => {
3489
+ speechInterruptListeners.delete(onInterrupt);
3490
+ if (speechInterruptListeners.size === 0) {
3491
+ teardownSpeechInterrupts();
3492
+ }
3493
+ };
3494
+ }
3375
3495
 
3376
3496
  // src/react/components/AgentRail/AgentRailOverlayContext.tsx
3377
3497
  import { createContext, useContext } from "react";
@@ -3637,15 +3757,20 @@ function MessageActions({
3637
3757
  const [menuOpen, setMenuOpen] = useState2(false);
3638
3758
  const [menuPosition, setMenuPosition] = useState2(null);
3639
3759
  const [speaking, setSpeaking] = useState2(false);
3760
+ const [speechSupported, setSpeechSupported] = useState2(null);
3640
3761
  const copyTimerRef = useRef2(null);
3641
3762
  const menuRef = useRef2(null);
3642
3763
  const portaledMenuRef = useRef2(null);
3643
3764
  const moreButtonRef = useRef2(null);
3644
3765
  const answeredLabel = formatAnsweredAt(answeredAt ?? 0);
3645
3766
  const resolvedSpeechText = speechText ?? toSpeechText(copyText);
3646
- const canReadAloud = readAloud && isSpeechSupported() && resolvedSpeechText;
3647
- const showMenu = Boolean(answeredLabel) || Boolean(receiptSteps) || canReadAloud;
3648
3767
  const canOpenReceipt = Boolean(receiptSteps) && Boolean(onOpenReceipt);
3768
+ const readAloudEligible = Boolean(readAloud && resolvedSpeechText);
3769
+ const canReadAloud = readAloudEligible && speechSupported === true;
3770
+ const showMenu = canOpenReceipt || (speechSupported === null ? readAloudEligible : canReadAloud);
3771
+ useLayoutEffect(() => {
3772
+ setSpeechSupported(isSpeechSupported());
3773
+ }, []);
3649
3774
  useLayoutEffect(() => {
3650
3775
  if (!menuOpen || !moreButtonRef.current || !portaledMenuRef.current) {
3651
3776
  setMenuPosition(null);
@@ -3663,17 +3788,16 @@ function MessageActions({
3663
3788
  })
3664
3789
  );
3665
3790
  }, [menuOpen, menuPortalRoot]);
3666
- useEffect2(
3667
- () => () => {
3791
+ useEffect2(() => {
3792
+ const unsubscribe = subscribeSpeechInterrupts(() => setSpeaking(false));
3793
+ return () => {
3794
+ unsubscribe();
3668
3795
  if (copyTimerRef.current !== null) {
3669
3796
  window.clearTimeout(copyTimerRef.current);
3670
3797
  }
3671
- if (speaking) window.speechSynthesis.cancel();
3672
- },
3673
- // Cancel speech only when this answer's actions unmount.
3674
- // eslint-disable-next-line react-hooks/exhaustive-deps
3675
- []
3676
- );
3798
+ stopSpeech();
3799
+ };
3800
+ }, []);
3677
3801
  useEffect2(() => {
3678
3802
  if (!menuOpen) return;
3679
3803
  const handlePointerDown = (event) => {
@@ -3712,14 +3836,14 @@ function MessageActions({
3712
3836
  if (!canReadAloud) return;
3713
3837
  setMenuOpen(false);
3714
3838
  if (speaking) {
3715
- window.speechSynthesis.cancel();
3839
+ stopSpeech();
3716
3840
  setSpeaking(false);
3717
3841
  return;
3718
3842
  }
3719
3843
  const utterance = new SpeechSynthesisUtterance(resolvedSpeechText);
3720
3844
  utterance.onend = () => setSpeaking(false);
3721
3845
  utterance.onerror = () => setSpeaking(false);
3722
- window.speechSynthesis.cancel();
3846
+ stopSpeech();
3723
3847
  window.speechSynthesis.speak(utterance);
3724
3848
  setSpeaking(true);
3725
3849
  }
@@ -4149,7 +4273,7 @@ import {
4149
4273
  useRef as useRef4,
4150
4274
  useState as useState4
4151
4275
  } from "react";
4152
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
4276
+ import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
4153
4277
  function SendIcon() {
4154
4278
  return /* @__PURE__ */ jsx4("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx4(
4155
4279
  "path",
@@ -4167,42 +4291,72 @@ function emptyValues(form) {
4167
4291
  for (const field of form?.fields ?? []) values[field.id] = "";
4168
4292
  return values;
4169
4293
  }
4294
+ function createDraft(form) {
4295
+ return {
4296
+ form,
4297
+ values: emptyValues(form),
4298
+ expanded: Boolean(form),
4299
+ submitted: false,
4300
+ dismissalSent: false,
4301
+ attempted: false
4302
+ };
4303
+ }
4170
4304
  function Composer({
4171
4305
  disabled = false,
4172
4306
  placeholder = "Ask anything\u2026",
4173
4307
  variant = "default",
4174
4308
  form = null,
4309
+ allowFormResume = true,
4175
4310
  onSubmit
4176
4311
  }) {
4177
4312
  const [value, setValue] = useState4("");
4178
- const [values, setValues] = useState4(
4179
- () => emptyValues(form)
4180
- );
4181
- const [blurred, setBlurred] = useState4({});
4313
+ const [draft, setDraft] = useState4(() => createDraft(form));
4182
4314
  const inputRef = useRef4(null);
4183
4315
  const firstFieldRef = useRef4(null);
4316
+ const formRef = useRef4(null);
4184
4317
  const formId = useId();
4185
- const activeForm = form;
4186
- const canSendForm = activeForm ? isComposerFormComplete(activeForm, values) : Boolean(value.trim());
4187
- useEffect4(() => {
4188
- setValues(emptyValues(form));
4189
- setBlurred({});
4190
- }, [form?.id]);
4318
+ if (form && form.id !== draft.form?.id) setDraft(createDraft(form));
4319
+ const savedForm = allowFormResume && !draft.submitted ? draft.form : null;
4320
+ const activeForm = !disabled && draft.expanded ? savedForm : null;
4321
+ const hasDraft = Object.values(draft.values).some((value2) => value2.trim());
4191
4322
  useEffect4(() => {
4192
4323
  if (activeForm) firstFieldRef.current?.focus();
4193
- }, [activeForm?.id]);
4324
+ else if ((savedForm || draft.submitted) && !disabled)
4325
+ inputRef.current?.focus();
4326
+ }, [activeForm?.id, disabled, savedForm?.id, draft.submitted]);
4194
4327
  function submitChat() {
4195
4328
  const trimmed = value.trim();
4196
4329
  if (!trimmed || disabled) return;
4197
- onSubmit?.(trimmed);
4330
+ const shareDismissal = savedForm && !draft.dismissalSent;
4331
+ onSubmit?.(
4332
+ shareDismissal ? `I'd like to keep chatting without sharing the requested details for now. Please don't ask for them again unless I choose to proceed with something that needs them.
4333
+
4334
+ ${trimmed}` : trimmed
4335
+ );
4336
+ if (shareDismissal)
4337
+ setDraft((current) => ({ ...current, dismissalSent: true }));
4198
4338
  setValue("");
4199
4339
  inputRef.current?.focus();
4200
4340
  }
4201
4341
  function submitForm() {
4202
- if (!activeForm || disabled || !canSendForm) return;
4203
- onSubmit?.(formatComposerFormMessage(activeForm, values));
4204
- setValues(emptyValues(activeForm));
4205
- setBlurred({});
4342
+ if (!activeForm || disabled) return;
4343
+ if (!isComposerFormComplete(activeForm, draft.values)) {
4344
+ setDraft((current) => ({ ...current, attempted: true }));
4345
+ const invalidField = activeForm.fields.find(
4346
+ (field) => !isValidComposerFieldValue(field, draft.values[field.id] ?? "")
4347
+ );
4348
+ const control = invalidField && formRef.current?.elements.namedItem(invalidField.id);
4349
+ if (control instanceof HTMLElement) control.focus();
4350
+ return;
4351
+ }
4352
+ onSubmit?.(formatComposerFormMessage(activeForm, draft.values));
4353
+ setDraft((current) => ({
4354
+ ...current,
4355
+ values: emptyValues(activeForm),
4356
+ expanded: false,
4357
+ submitted: true,
4358
+ attempted: false
4359
+ }));
4206
4360
  }
4207
4361
  function handleSubmit(event) {
4208
4362
  event.preventDefault();
@@ -4226,112 +4380,151 @@ function Composer({
4226
4380
  return /* @__PURE__ */ jsx4(
4227
4381
  "form",
4228
4382
  {
4383
+ ref: formRef,
4384
+ noValidate: true,
4229
4385
  className: [
4230
4386
  "composer",
4231
4387
  variant === "dock" ? "composer--dock" : "",
4232
4388
  activeForm ? "composer--form" : ""
4233
4389
  ].filter(Boolean).join(" "),
4234
4390
  onSubmit: handleSubmit,
4235
- children: activeForm ? /* @__PURE__ */ jsxs4("div", { className: "composer__sheet", role: "group", "aria-label": "Required details", children: [
4236
- activeForm.fields.map((field, index) => {
4237
- const fieldId = `${formId}-${field.id}`;
4238
- const invalid = Boolean(blurred[field.id]) && !isValidComposerFieldValue(field, values[field.id] ?? "");
4239
- const controlProps = {
4240
- id: fieldId,
4241
- name: field.id,
4242
- disabled,
4243
- required: field.required,
4244
- autoComplete: field.autocomplete,
4245
- placeholder: field.placeholder,
4246
- spellCheck: false,
4247
- value: values[field.id] ?? "",
4248
- "aria-invalid": invalid || void 0,
4249
- "aria-describedby": invalid ? `${fieldId}-error` : void 0,
4250
- onBlur: () => setBlurred((current) => ({ ...current, [field.id]: true })),
4251
- onChange: (event) => {
4252
- const next = readComposerControlValue(event);
4253
- setValues((current) => ({
4254
- ...current,
4255
- [field.id]: next
4256
- }));
4257
- },
4258
- onKeyDown: handleFormKeyDown
4259
- };
4260
- return /* @__PURE__ */ jsxs4(
4261
- "div",
4391
+ children: activeForm ? /* @__PURE__ */ jsxs4(
4392
+ "div",
4393
+ {
4394
+ className: "composer__sheet",
4395
+ role: "group",
4396
+ "aria-label": "Contact details",
4397
+ children: [
4398
+ /* @__PURE__ */ jsxs4("div", { className: "composer__form-heading", children: [
4399
+ /* @__PURE__ */ jsx4("strong", { children: "Share your details" }),
4400
+ /* @__PURE__ */ jsx4("span", { children: "Optional" }),
4401
+ /* @__PURE__ */ jsx4("p", { children: "You can also keep chatting." })
4402
+ ] }),
4403
+ /* @__PURE__ */ jsx4("div", { className: "composer__fields", children: activeForm.fields.map((field, index) => {
4404
+ const fieldId = `${formId}-${field.id}`;
4405
+ const invalid = draft.attempted && !isValidComposerFieldValue(field, draft.values[field.id] ?? "");
4406
+ const controlProps = {
4407
+ id: fieldId,
4408
+ name: field.id,
4409
+ disabled,
4410
+ required: field.required,
4411
+ autoComplete: field.autocomplete,
4412
+ placeholder: field.placeholder,
4413
+ spellCheck: false,
4414
+ value: draft.values[field.id] ?? "",
4415
+ "aria-invalid": invalid || void 0,
4416
+ "aria-describedby": invalid ? `${fieldId}-error` : void 0,
4417
+ onChange: (event) => {
4418
+ const next = readComposerControlValue(event);
4419
+ setDraft((current) => ({
4420
+ ...current,
4421
+ values: { ...current.values, [field.id]: next }
4422
+ }));
4423
+ },
4424
+ onKeyDown: handleFormKeyDown
4425
+ };
4426
+ return /* @__PURE__ */ jsxs4(
4427
+ "div",
4428
+ {
4429
+ className: [
4430
+ "composer__row",
4431
+ field.kind === "textarea" ? "composer__row--grow" : ""
4432
+ ].filter(Boolean).join(" "),
4433
+ children: [
4434
+ /* @__PURE__ */ jsxs4("label", { className: "composer__label", htmlFor: fieldId, children: [
4435
+ /* @__PURE__ */ jsx4("span", { className: "composer__field-label", children: field.label }),
4436
+ field.kind === "textarea" ? /* @__PURE__ */ jsx4(
4437
+ "textarea",
4438
+ {
4439
+ ...controlProps,
4440
+ ref: index === 0 ? (node) => {
4441
+ firstFieldRef.current = node;
4442
+ } : void 0,
4443
+ className: "composer__control composer__control--area",
4444
+ rows: 3
4445
+ }
4446
+ ) : /* @__PURE__ */ jsx4(
4447
+ "input",
4448
+ {
4449
+ ...controlProps,
4450
+ ref: index === 0 ? (node) => {
4451
+ firstFieldRef.current = node;
4452
+ } : void 0,
4453
+ className: "composer__control",
4454
+ type: field.kind,
4455
+ inputMode: field.kind === "tel" ? "tel" : void 0
4456
+ }
4457
+ )
4458
+ ] }),
4459
+ invalid ? /* @__PURE__ */ jsx4("p", { className: "composer__error", id: `${fieldId}-error`, children: field.kind === "email" ? "Enter a valid email to share your details." : `Add your ${field.label.toLowerCase()} to share your details.` }) : null
4460
+ ]
4461
+ },
4462
+ field.id
4463
+ );
4464
+ }) }),
4465
+ /* @__PURE__ */ jsxs4("div", { className: "composer__toolbar", children: [
4466
+ /* @__PURE__ */ jsx4(
4467
+ "button",
4468
+ {
4469
+ type: "submit",
4470
+ className: "composer__action composer__action--primary",
4471
+ disabled,
4472
+ children: "Share details"
4473
+ }
4474
+ ),
4475
+ /* @__PURE__ */ jsx4(
4476
+ "button",
4477
+ {
4478
+ type: "button",
4479
+ className: "composer__action",
4480
+ disabled,
4481
+ onClick: () => setDraft((current) => ({ ...current, expanded: false })),
4482
+ children: "Keep chatting"
4483
+ }
4484
+ )
4485
+ ] })
4486
+ ]
4487
+ }
4488
+ ) : /* @__PURE__ */ jsxs4(Fragment, { children: [
4489
+ savedForm ? /* @__PURE__ */ jsxs4("div", { className: "composer__resume", children: [
4490
+ /* @__PURE__ */ jsx4("span", { children: hasDraft ? "Your details aren\u2019t shared yet" : "Contact details are optional" }),
4491
+ /* @__PURE__ */ jsx4(
4492
+ "button",
4262
4493
  {
4263
- className: [
4264
- "composer__row",
4265
- field.kind === "textarea" ? "composer__row--grow" : ""
4266
- ].filter(Boolean).join(" "),
4267
- children: [
4268
- /* @__PURE__ */ jsxs4("label", { className: "composer__label", htmlFor: fieldId, children: [
4269
- /* @__PURE__ */ jsx4("span", { className: "composer__sr-only", children: field.label }),
4270
- field.kind === "textarea" ? /* @__PURE__ */ jsx4(
4271
- "textarea",
4272
- {
4273
- ...controlProps,
4274
- ref: index === 0 ? (node) => {
4275
- firstFieldRef.current = node;
4276
- } : void 0,
4277
- className: "composer__control composer__control--area",
4278
- rows: 3
4279
- }
4280
- ) : /* @__PURE__ */ jsx4(
4281
- "input",
4282
- {
4283
- ...controlProps,
4284
- ref: index === 0 ? (node) => {
4285
- firstFieldRef.current = node;
4286
- } : void 0,
4287
- className: "composer__control",
4288
- type: field.kind,
4289
- inputMode: field.kind === "tel" ? "tel" : void 0
4290
- }
4291
- )
4292
- ] }),
4293
- invalid ? /* @__PURE__ */ jsx4("p", { className: "composer__error", id: `${fieldId}-error`, children: field.kind === "email" ? "Enter a valid email to continue." : `Add your ${field.label.toLowerCase()} to continue.` }) : null
4294
- ]
4295
- },
4296
- field.id
4297
- );
4298
- }),
4299
- /* @__PURE__ */ jsx4("div", { className: "composer__toolbar", children: /* @__PURE__ */ jsx4(
4300
- "button",
4301
- {
4302
- type: "submit",
4303
- className: "composer__send",
4304
- disabled: disabled || !canSendForm,
4305
- "aria-label": "Send details",
4306
- children: /* @__PURE__ */ jsx4(SendIcon, {})
4307
- }
4308
- ) })
4309
- ] }) : /* @__PURE__ */ jsxs4("div", { className: "composer__field", children: [
4310
- /* @__PURE__ */ jsx4(
4311
- "textarea",
4312
- {
4313
- ref: inputRef,
4314
- className: "composer__input",
4315
- rows: 1,
4316
- value,
4317
- placeholder,
4318
- disabled,
4319
- spellCheck: false,
4320
- "aria-label": "Message",
4321
- onChange: (event) => setValue(event.target.value),
4322
- onKeyDown: handleChatKeyDown
4323
- }
4324
- ),
4325
- /* @__PURE__ */ jsx4(
4326
- "button",
4327
- {
4328
- type: "submit",
4329
- className: "composer__send",
4330
- disabled: disabled || !value.trim(),
4331
- "aria-label": "Send message",
4332
- children: /* @__PURE__ */ jsx4(SendIcon, {})
4333
- }
4334
- )
4494
+ type: "button",
4495
+ disabled,
4496
+ onClick: () => setDraft((current) => ({ ...current, expanded: true })),
4497
+ children: hasDraft ? "Resume details" : "Add details"
4498
+ }
4499
+ )
4500
+ ] }) : null,
4501
+ /* @__PURE__ */ jsxs4("div", { className: "composer__field", children: [
4502
+ /* @__PURE__ */ jsx4(
4503
+ "textarea",
4504
+ {
4505
+ ref: inputRef,
4506
+ className: "composer__input",
4507
+ rows: 1,
4508
+ value,
4509
+ placeholder,
4510
+ disabled,
4511
+ spellCheck: false,
4512
+ "aria-label": "Message",
4513
+ onChange: (event) => setValue(event.target.value),
4514
+ onKeyDown: handleChatKeyDown
4515
+ }
4516
+ ),
4517
+ /* @__PURE__ */ jsx4(
4518
+ "button",
4519
+ {
4520
+ type: "submit",
4521
+ className: "composer__send",
4522
+ disabled: disabled || !value.trim(),
4523
+ "aria-label": "Send message",
4524
+ children: /* @__PURE__ */ jsx4(SendIcon, {})
4525
+ }
4526
+ )
4527
+ ] })
4335
4528
  ] })
4336
4529
  }
4337
4530
  );
@@ -5556,7 +5749,7 @@ function isRenderableVisitorToolResult(result) {
5556
5749
  }
5557
5750
 
5558
5751
  // src/react/components/AgentRail/AgentRail.tsx
5559
- import { Fragment, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
5752
+ import { Fragment as Fragment2, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
5560
5753
  function MinimizeIcon() {
5561
5754
  return /* @__PURE__ */ jsx16("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx16(
5562
5755
  "path",
@@ -5634,8 +5827,9 @@ function AgentRail({
5634
5827
  colorScheme = "auto",
5635
5828
  brandLabel = "",
5636
5829
  brandLogoUrl,
5637
- poweredByLabel = "Powered by Webless",
5830
+ poweredByLabel,
5638
5831
  disclaimerLabel,
5832
+ disclaimerLink,
5639
5833
  answerReceipt = false,
5640
5834
  readAloud = false,
5641
5835
  composerPlaceholder = "Ask anything\u2026",
@@ -6022,7 +6216,7 @@ function AgentRail({
6022
6216
  onFeedback: onFeedback ? (rating) => onFeedback(rating, message) : void 0
6023
6217
  }
6024
6218
  ) : null,
6025
- index === lastVisitorIndex ? /* @__PURE__ */ jsxs15(Fragment, { children: [
6219
+ index === lastVisitorIndex ? /* @__PURE__ */ jsxs15(Fragment2, { children: [
6026
6220
  showActivity ? /* @__PURE__ */ jsx16(
6027
6221
  AgentActivityBubble,
6028
6222
  {
@@ -6070,7 +6264,15 @@ function AgentRail({
6070
6264
  onRetry ? /* @__PURE__ */ jsx16("button", { type: "button", onClick: onRetry, children: "Try again" }) : null
6071
6265
  ] }) : null
6072
6266
  ] }) }),
6073
- showDisclaimerLabel ? /* @__PURE__ */ jsx16("div", { className: "agent-rail__disclaimer", children: /* @__PURE__ */ jsx16("p", { children: resolvedDisclaimerLabel }) }) : null,
6267
+ showDisclaimerLabel ? /* @__PURE__ */ jsx16("div", { className: "agent-rail__disclaimer", children: /* @__PURE__ */ jsx16("p", { children: disclaimerLink ? /* @__PURE__ */ jsx16(
6268
+ "a",
6269
+ {
6270
+ href: disclaimerLink,
6271
+ rel: "noopener noreferrer",
6272
+ target: "_blank",
6273
+ children: resolvedDisclaimerLabel
6274
+ }
6275
+ ) : resolvedDisclaimerLabel }) }) : null,
6074
6276
  /* @__PURE__ */ jsxs15("div", { className: "agent-rail__composer-wrap", children: [
6075
6277
  showJumpToLatest ? /* @__PURE__ */ jsx16(
6076
6278
  "button",
@@ -6088,10 +6290,12 @@ function AgentRail({
6088
6290
  {
6089
6291
  variant: expanded || mobileFullscreen ? "dock" : "default",
6090
6292
  disabled: isBusy,
6091
- form: composerForm,
6293
+ form: composerForm && lastMessage ? { ...composerForm, id: `${lastMessage.id}:${composerForm.id}` } : null,
6294
+ allowFormResume: !state.pendingOffer && !waitingForBooking && !hasPendingConfirmation,
6092
6295
  placeholder: composerPlaceholder,
6093
6296
  onSubmit: handleSubmit
6094
- }
6297
+ },
6298
+ state.messages.find((message) => message.role === "visitor")?.id ?? "empty"
6095
6299
  ),
6096
6300
  poweredByLabel ? /* @__PURE__ */ jsx16("div", { className: "agent-rail__footer", children: /* @__PURE__ */ jsx16("p", { children: /* @__PURE__ */ jsx16("span", { children: poweredByLabel }) }) }) : null
6097
6301
  ] })
@@ -6113,7 +6317,7 @@ function AgentRail({
6113
6317
  }
6114
6318
 
6115
6319
  // src/react/components/AssistEdgeTab/AssistEdgeTab.tsx
6116
- import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
6320
+ import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
6117
6321
  function SparklesIcon() {
6118
6322
  return /* @__PURE__ */ jsxs16(
6119
6323
  "svg",
@@ -6246,7 +6450,7 @@ function AssistEdgeTab({
6246
6450
  tabIndex: visible ? 0 : -1,
6247
6451
  onClick: onOpen,
6248
6452
  children: [
6249
- mobile ? /* @__PURE__ */ jsxs16(Fragment2, { children: [
6453
+ mobile ? /* @__PURE__ */ jsxs16(Fragment3, { children: [
6250
6454
  /* @__PURE__ */ jsxs16(
6251
6455
  "span",
6252
6456
  {
@@ -6269,7 +6473,7 @@ function AssistEdgeTab({
6269
6473
  }
6270
6474
  ),
6271
6475
  /* @__PURE__ */ jsx17("span", { className: "assist-edge-tab__label", children: visibleLabel })
6272
- ] }) : variant === "outline" ? /* @__PURE__ */ jsxs16(Fragment2, { children: [
6476
+ ] }) : variant === "outline" ? /* @__PURE__ */ jsxs16(Fragment3, { children: [
6273
6477
  /* @__PURE__ */ jsxs16("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
6274
6478
  /* @__PURE__ */ jsx17(TabMarkIcon, { customIconUrl }),
6275
6479
  showLogo ? /* @__PURE__ */ jsx17(
@@ -6287,12 +6491,12 @@ function AssistEdgeTab({
6287
6491
  /* @__PURE__ */ jsx17("span", { className: "assist-edge-tab__label", children: visibleLabel }),
6288
6492
  /* @__PURE__ */ jsx17(ChevronDownIcon2, {})
6289
6493
  ] }) : null,
6290
- variant === "ask" ? /* @__PURE__ */ jsxs16(Fragment2, { children: [
6494
+ variant === "ask" ? /* @__PURE__ */ jsxs16(Fragment3, { children: [
6291
6495
  /* @__PURE__ */ jsx17(ChevronLeftIcon, {}),
6292
6496
  /* @__PURE__ */ jsx17("span", { className: "assist-edge-tab__label", children: visibleLabel }),
6293
6497
  /* @__PURE__ */ jsx17(DragDots, {})
6294
6498
  ] }) : null,
6295
- variant === "fill" ? /* @__PURE__ */ jsxs16(Fragment2, { children: [
6499
+ variant === "fill" ? /* @__PURE__ */ jsxs16(Fragment3, { children: [
6296
6500
  /* @__PURE__ */ jsxs16("span", { className: "assist-edge-tab__mark", "aria-hidden": "true", children: [
6297
6501
  /* @__PURE__ */ jsx17(TabMarkIcon, { customIconUrl }),
6298
6502
  showLogo ? /* @__PURE__ */ jsx17(
@@ -6634,8 +6838,9 @@ function AgentWidget({
6634
6838
  brandLabel: agentName,
6635
6839
  brandLogoUrl: branding?.logoUrl,
6636
6840
  composerPlaceholder: branding?.composerPlaceholder ?? "Ask a question\u2026",
6637
- poweredByLabel: branding?.poweredByLabel ?? "Powered by Webless",
6841
+ poweredByLabel: branding?.poweredByLabel,
6638
6842
  disclaimerLabel: branding?.disclaimer,
6843
+ disclaimerLink: branding?.disclaimerLink,
6639
6844
  answerReceipt: branding?.answerReceipt,
6640
6845
  readAloud: branding?.readAloud,
6641
6846
  state,
@@ -6716,4 +6921,4 @@ export {
6716
6921
  sendAgentAnswerFeedback,
6717
6922
  AgentWidget
6718
6923
  };
6719
- //# sourceMappingURL=chunk-CYI3OSWG.js.map
6924
+ //# sourceMappingURL=chunk-GS65OJFL.js.map