@bikdotai/bik-component-library 0.0.870 → 0.0.872

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.
Files changed (114) hide show
  1. package/dist/cjs/components/agent-builder/components/ConfigToolPanel.js +5 -5
  2. package/dist/cjs/components/agent-builder/components/ConfigToolPanel.js.map +1 -1
  3. package/dist/cjs/components/agent-builder/components/CreateSubAgentPanel.js +5 -5
  4. package/dist/cjs/components/agent-builder/components/CreateSubAgentPanel.js.map +1 -1
  5. package/dist/cjs/components/agent-builder/components/MentionPicker.js +27 -27
  6. package/dist/cjs/components/agent-builder/components/MentionPicker.js.map +1 -1
  7. package/dist/cjs/components/agent-builder/components/SelectableListSection.js +6 -6
  8. package/dist/cjs/components/agent-builder/components/SelectableListSection.js.map +1 -1
  9. package/dist/cjs/components/agent-builder/constants/tools.js +1 -1
  10. package/dist/cjs/components/agent-builder/constants/tools.js.map +1 -1
  11. package/dist/cjs/components/agent-builder/steps/Step3HowItResponds.js +1 -1
  12. package/dist/cjs/components/agent-builder/steps/Step3HowItResponds.js.map +1 -1
  13. package/dist/cjs/components/agent-builder/utils/sourceGrouping.js +2 -0
  14. package/dist/cjs/components/agent-builder/utils/sourceGrouping.js.map +1 -0
  15. package/dist/cjs/components/agent-builder/utils/sourceIcons.js +1 -1
  16. package/dist/cjs/components/agent-builder/utils/sourceIcons.js.map +1 -1
  17. package/dist/cjs/components/agent-builder/utils/toolActions.js +1 -1
  18. package/dist/cjs/components/agent-builder/utils/toolActions.js.map +1 -1
  19. package/dist/cjs/components/bik-copilot/CopilotPanel.js +1 -1
  20. package/dist/cjs/components/bik-copilot/CopilotPanel.js.map +1 -1
  21. package/dist/cjs/components/bik-copilot/useCopilotStreamChat.js +1 -1
  22. package/dist/cjs/components/bik-copilot/useCopilotStreamChat.js.map +1 -1
  23. package/dist/cjs/icons/Social/Channels/Aftership.js +2 -0
  24. package/dist/cjs/icons/Social/Channels/Aftership.js.map +1 -0
  25. package/dist/cjs/icons/Social/Channels/Attentive.js +2 -0
  26. package/dist/cjs/icons/Social/Channels/Attentive.js.map +1 -0
  27. package/dist/cjs/icons/Social/Channels/Freshdesk.js +2 -0
  28. package/dist/cjs/icons/Social/Channels/Freshdesk.js.map +1 -0
  29. package/dist/cjs/icons/Social/Channels/GoogleSheets.js +2 -0
  30. package/dist/cjs/icons/Social/Channels/GoogleSheets.js.map +1 -0
  31. package/dist/cjs/icons/Social/Channels/Klavyio.js +2 -0
  32. package/dist/cjs/icons/Social/Channels/Klavyio.js.map +1 -0
  33. package/dist/cjs/icons/Social/Channels/Kustomer.js +2 -0
  34. package/dist/cjs/icons/Social/Channels/Kustomer.js.map +1 -0
  35. package/dist/cjs/icons/Social/Channels/Mailchimp.js +2 -0
  36. package/dist/cjs/icons/Social/Channels/Mailchimp.js.map +1 -0
  37. package/dist/cjs/icons/Social/Channels/OmniSend.js +2 -0
  38. package/dist/cjs/icons/Social/Channels/OmniSend.js.map +1 -0
  39. package/dist/cjs/icons/Social/Channels/Segment.js +2 -0
  40. package/dist/cjs/icons/Social/Channels/Segment.js.map +1 -0
  41. package/dist/cjs/icons/Social/Channels/ShipBob.js +2 -0
  42. package/dist/cjs/icons/Social/Channels/ShipBob.js.map +1 -0
  43. package/dist/cjs/icons/Social/Channels/Skio.js +1 -1
  44. package/dist/cjs/icons/Social/Channels/Skio.js.map +1 -1
  45. package/dist/cjs/icons/index.js +1 -1
  46. package/dist/esm/components/agent-builder/__fixtures__/integrationCatalog.d.ts +17 -0
  47. package/dist/esm/components/agent-builder/components/ConfigToolPanel.js +104 -96
  48. package/dist/esm/components/agent-builder/components/ConfigToolPanel.js.map +1 -1
  49. package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.js +256 -242
  50. package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.js.map +1 -1
  51. package/dist/esm/components/agent-builder/components/MentionPicker.d.ts +0 -10
  52. package/dist/esm/components/agent-builder/components/MentionPicker.js +201 -199
  53. package/dist/esm/components/agent-builder/components/MentionPicker.js.map +1 -1
  54. package/dist/esm/components/agent-builder/components/SelectableListSection.d.ts +9 -0
  55. package/dist/esm/components/agent-builder/components/SelectableListSection.js +213 -188
  56. package/dist/esm/components/agent-builder/components/SelectableListSection.js.map +1 -1
  57. package/dist/esm/components/agent-builder/constants/tools.d.ts +46 -22
  58. package/dist/esm/components/agent-builder/constants/tools.js +86 -35
  59. package/dist/esm/components/agent-builder/constants/tools.js.map +1 -1
  60. package/dist/esm/components/agent-builder/steps/Step3HowItResponds.js +289 -279
  61. package/dist/esm/components/agent-builder/steps/Step3HowItResponds.js.map +1 -1
  62. package/dist/esm/components/agent-builder/utils/sourceGrouping.d.ts +39 -0
  63. package/dist/esm/components/agent-builder/utils/sourceGrouping.js +14 -0
  64. package/dist/esm/components/agent-builder/utils/sourceGrouping.js.map +1 -0
  65. package/dist/esm/components/agent-builder/utils/sourceIcons.d.ts +6 -4
  66. package/dist/esm/components/agent-builder/utils/sourceIcons.js +64 -33
  67. package/dist/esm/components/agent-builder/utils/sourceIcons.js.map +1 -1
  68. package/dist/esm/components/agent-builder/utils/toolActions.d.ts +11 -6
  69. package/dist/esm/components/agent-builder/utils/toolActions.js +23 -16
  70. package/dist/esm/components/agent-builder/utils/toolActions.js.map +1 -1
  71. package/dist/esm/components/bik-copilot/CopilotPanel.js +235 -244
  72. package/dist/esm/components/bik-copilot/CopilotPanel.js.map +1 -1
  73. package/dist/esm/components/bik-copilot/model.d.ts +4 -2
  74. package/dist/esm/components/bik-copilot/useCopilotStreamChat.d.ts +0 -18
  75. package/dist/esm/components/bik-copilot/useCopilotStreamChat.js +168 -163
  76. package/dist/esm/components/bik-copilot/useCopilotStreamChat.js.map +1 -1
  77. package/dist/esm/icons/Social/Channels/Aftership.d.ts +6 -0
  78. package/dist/esm/icons/Social/Channels/Aftership.js +47 -0
  79. package/dist/esm/icons/Social/Channels/Aftership.js.map +1 -0
  80. package/dist/esm/icons/Social/Channels/Attentive.d.ts +6 -0
  81. package/dist/esm/icons/Social/Channels/Attentive.js +54 -0
  82. package/dist/esm/icons/Social/Channels/Attentive.js.map +1 -0
  83. package/dist/esm/icons/Social/Channels/Freshdesk.d.ts +6 -0
  84. package/dist/esm/icons/Social/Channels/Freshdesk.js +47 -0
  85. package/dist/esm/icons/Social/Channels/Freshdesk.js.map +1 -0
  86. package/dist/esm/icons/Social/Channels/GoogleSheets.d.ts +6 -0
  87. package/dist/esm/icons/Social/Channels/GoogleSheets.js +53 -0
  88. package/dist/esm/icons/Social/Channels/GoogleSheets.js.map +1 -0
  89. package/dist/esm/icons/Social/Channels/Klavyio.d.ts +6 -0
  90. package/dist/esm/icons/Social/Channels/Klavyio.js +47 -0
  91. package/dist/esm/icons/Social/Channels/Klavyio.js.map +1 -0
  92. package/dist/esm/icons/Social/Channels/Kustomer.d.ts +6 -0
  93. package/dist/esm/icons/Social/Channels/Kustomer.js +68 -0
  94. package/dist/esm/icons/Social/Channels/Kustomer.js.map +1 -0
  95. package/dist/esm/icons/Social/Channels/Mailchimp.d.ts +6 -0
  96. package/dist/esm/icons/Social/Channels/Mailchimp.js +31 -0
  97. package/dist/esm/icons/Social/Channels/Mailchimp.js.map +1 -0
  98. package/dist/esm/icons/Social/Channels/OmniSend.d.ts +6 -0
  99. package/dist/esm/icons/Social/Channels/OmniSend.js +47 -0
  100. package/dist/esm/icons/Social/Channels/OmniSend.js.map +1 -0
  101. package/dist/esm/icons/Social/Channels/Segment.d.ts +6 -0
  102. package/dist/esm/icons/Social/Channels/Segment.js +53 -0
  103. package/dist/esm/icons/Social/Channels/Segment.js.map +1 -0
  104. package/dist/esm/icons/Social/Channels/ShipBob.d.ts +6 -0
  105. package/dist/esm/icons/Social/Channels/ShipBob.js +28 -0
  106. package/dist/esm/icons/Social/Channels/ShipBob.js.map +1 -0
  107. package/dist/esm/icons/Social/Channels/Skio.js +41 -19
  108. package/dist/esm/icons/Social/Channels/Skio.js.map +1 -1
  109. package/dist/esm/icons/Social/Channels/Zendesk.d.ts +6 -0
  110. package/dist/esm/icons/Social/Channels/index.d.ts +10 -0
  111. package/dist/esm/icons/index.d.ts +26 -25
  112. package/dist/esm/icons/index.js +658 -638
  113. package/dist/esm/icons/index.js.map +1 -1
  114. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sourceGrouping.js","sources":["../../../../../src/components/agent-builder/utils/sourceGrouping.ts"],"sourcesContent":["import { ToolSource, toolSourceRank } from '../constants/tools';\n\n/**\n * Where each tool source belongs in the picker: its own row, or inside the\n * \"Integrations\" umbrella.\n */\nexport interface SourcePartition {\n\t/** Sources with their own top-level row, in display order. */\n\toutside: string[];\n\t/** Sources the store has not connected, in display order. */\n\tinside: string[];\n}\n\n/**\n * A source belongs in the \"Integrations\" umbrella only when the store has NOT\n * connected it.\n *\n * `integrationStatus` carries three distinct states, and all three matter:\n *\n * | value | meaning | row |\n * | ----------- | ---------------------------------------- | --------- |\n * | `undefined` | never gated — needs no connection at all | outside |\n * | `true` | gated, and the store connected it | outside |\n * | `false` | gated, and the store has not connected it | inside |\n *\n * `undefined` is what makes Manifest, Google Sheets, Handover to email and REST\n * API sit outside for free: the backend never marks their tools\n * `integration: true`, so the host never puts them in the map. A gated source\n * missing from the host's app-id map lands here too — it reads as \"needs no\n * connection\", which is why the host warns rather than silently gating it.\n */\nexport const isUnconnectedSource = (\n\tsource: string,\n\tintegrationStatus?: Partial<Record<ToolSource, boolean>>,\n): boolean => integrationStatus?.[source as ToolSource] === false;\n\n/**\n * Split the picker's sources into the ones that get their own row and the ones\n * that collapse into \"Integrations\". Both lists come back in {@link\n * toolSourceRank} order, so a store's rows never reshuffle as tools are added.\n *\n * The SAME split drives the `@` picker, the Step-3 empty state and the sub-agent\n * drawer — one rule, three surfaces, so they cannot drift apart.\n */\nexport const partitionSources = (\n\tsources: string[],\n\tintegrationStatus?: Partial<Record<ToolSource, boolean>>,\n): SourcePartition => {\n\tconst byRank = (a: string, b: string) =>\n\t\ttoolSourceRank(a) - toolSourceRank(b);\n\tconst outside: string[] = [];\n\tconst inside: string[] = [];\n\tsources.forEach((source) => {\n\t\t(isUnconnectedSource(source, integrationStatus) ? inside : outside).push(\n\t\t\tsource,\n\t\t);\n\t});\n\treturn { outside: outside.sort(byRank), inside: inside.sort(byRank) };\n};\n"],"names":["isUnconnectedSource","source","integrationStatus","partitionSources","sources","byRank","a","b","toolSourceRank","outside","inside"],"mappings":"yHA+BaA,EAAsB,CAClCC,EACAC,IACaA,IAAoBD,CAAoB,IAAM,GAU/CE,EAAmB,CAC/BC,EACAF,IACqB,CACrB,MAAMG,EAAS,CAACC,EAAWC,IAC1BC,EAAAA,eAAeF,CAAC,EAAIE,EAAAA,eAAeD,CAAC,EAC/BE,EAAoB,CAAA,EACpBC,EAAmB,CAAA,EACzB,OAAAN,EAAQ,QAASH,GAAW,EAC1BD,EAAoBC,EAAQC,CAAiB,EAAIQ,EAASD,GAAS,KACnER,CAAA,CAEF,CAAC,EACM,CAAE,QAASQ,EAAQ,KAAKJ,CAAM,EAAG,OAAQK,EAAO,KAAKL,CAAM,CAAA,CACnE"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react"),e=require("../constants/tools.js"),u=require("../../../icons/Social/Social/SlackIcon.js"),l=require("../../../icons/Informational/Communication/Email.js"),i=require("../../../icons/BIK AI specific/Webhook.js"),a=require("../../../icons/Informational/Identity/PuzzlePiece.js"),s=require("../../../icons/Social/Social/Gorgias.js"),S=require("../../../icons/Social/Channels/Skio.js"),I=require("../../../icons/Social/Channels/ShipStation.js"),d=require("../../../icons/Social/Social/BigCommerce.js"),f=require("../../../icons/Social/Channels/ShopifyBrand.js"),h=require("../../../icons/Social/Channels/ManifestGlass.js"),q=require("../../../icons/Actions/Common actions/LinkSimpleHorizontal.js"),w=o=>o&&typeof o=="object"&&"default"in o?o:{default:o},C=w(n),c={[e.ToolSource.Manifest]:{Icon:h.default,w:24,h:24},[e.ToolSource.Shopify]:{Icon:f.default,w:24,h:24},[e.ToolSource.Bigcommerce]:{Icon:d.default,w:20,h:20},[e.ToolSource.Shipstation]:{Icon:I.default,w:22,h:22},[e.ToolSource.Skio]:{Icon:S.default,w:20,h:20},[e.ToolSource.Gorgias]:{Icon:s.default,w:20,h:20},[e.ToolSource.Integration]:{Icon:a.default,w:20,h:20},[e.ToolSource.RestApi]:{Icon:i.default,w:20,h:20},[e.ToolSource.EmailHandover]:{Icon:l.default,w:20,h:20},[e.ToolSource.Slack]:{Icon:u.default,w:20,h:20}},r={Icon:q.default,w:20,h:20},E=o=>o?c[o]??r:void 0,T=(o,t=0)=>o?C.default.createElement(o.Icon,{width:o.w+t,height:o.h+t}):null;exports.GENERIC_SOURCE_ICON=r;exports.SOURCE_ICONS=c;exports.renderSourceIcon=T;exports.sourceIcon=E;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react"),e=require("../constants/tools.js"),i=require("../../../icons/Social/Channels/GoogleSheets.js"),s=require("../../../icons/Social/Channels/ShipBob.js"),a=require("../../../icons/Social/Channels/Kustomer.js"),S=require("../../../icons/Social/Channels/Freshdesk.js"),I=require("../../../icons/Social/Social/Zendesk.js"),h=require("../../../icons/Social/Channels/Segment.js"),d=require("../../../icons/Social/Channels/Mailchimp.js"),f=require("../../../icons/Social/Channels/Attentive.js"),T=require("../../../icons/Social/Channels/OmniSend.js"),w=require("../../../icons/Social/Channels/Klavyio.js"),q=require("../../../icons/Social/Channels/Aftership.js"),m=require("../../../icons/Social/Social/SlackIcon.js"),p=require("../../../icons/Informational/Communication/Email.js"),O=require("../../../icons/BIK AI specific/Webhook.js"),r=require("../../../icons/Informational/Identity/PuzzlePiece.js"),E=require("../../../icons/Social/Social/Gorgias.js"),C=require("../../../icons/Social/Channels/Skio.js"),N=require("../../../icons/Social/Channels/ShipStation.js"),g=require("../../../icons/Social/Social/BigCommerce.js"),R=require("../../../icons/Social/Channels/ShopifyBrand.js"),_=require("../../../icons/Social/Channels/ManifestGlass.js"),k=require("../../../icons/Actions/Common actions/LinkSimpleHorizontal.js"),G=o=>o&&typeof o=="object"&&"default"in o?o:{default:o},A=G(l),c={[e.ToolSource.Manifest]:{Icon:_.default,w:24,h:24},[e.ToolSource.Shopify]:{Icon:R.default,w:24,h:24},[e.ToolSource.Bigcommerce]:{Icon:g.default,w:20,h:20},[e.ToolSource.Shipstation]:{Icon:N.default,w:22,h:22},[e.ToolSource.Skio]:{Icon:C.default,w:20,h:20},[e.ToolSource.Gorgias]:{Icon:E.default,w:20,h:20},[e.ToolSource.Integration]:{Icon:r.default,w:20,h:20},[e.ToolSource.RestApi]:{Icon:O.default,w:20,h:20},[e.ToolSource.EmailHandover]:{Icon:p.default,w:20,h:20},[e.ToolSource.Slack]:{Icon:m.default,w:20,h:20},[e.ToolSource.Aftership]:{Icon:q.default,w:20,h:20},[e.ToolSource.Klaviyo]:{Icon:w.default,w:20,h:20},[e.ToolSource.Omnisend]:{Icon:T.default,w:20,h:20},[e.ToolSource.Attentive]:{Icon:f.default,w:20,h:20},[e.ToolSource.Mailchimp]:{Icon:d.default,w:20,h:20},[e.ToolSource.Segment]:{Icon:h.default,w:20,h:20},[e.ToolSource.Zendesk]:{Icon:I.default,w:20,h:20},[e.ToolSource.Freshdesk]:{Icon:S.default,w:20,h:20},[e.ToolSource.Kustomer]:{Icon:a.default,w:20,h:20},[e.ToolSource.Shipbob]:{Icon:s.default,w:20,h:20},[e.ToolSource.GoogleSheets]:{Icon:i.default,w:20,h:20}},n={Icon:r.default,w:20,h:20},u={Icon:k.default,w:20,h:20},b=o=>{if(o)return o===e.INTEGRATIONS_KEY?n:c[o]??u},v=(o,t=0)=>o?A.default.createElement(o.Icon,{width:o.w+t,height:o.h+t}):null;exports.GENERIC_SOURCE_ICON=u;exports.INTEGRATIONS_ICON=n;exports.SOURCE_ICONS=c;exports.renderSourceIcon=v;exports.sourceIcon=b;
2
2
  //# sourceMappingURL=sourceIcons.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sourceIcons.js","sources":["../../../../../src/components/agent-builder/utils/sourceIcons.ts"],"sourcesContent":["import {\n\tBigCommerce,\n\tEmail,\n\tGorgias,\n\tLinkSimpleHorizontal,\n\tManifestGlass,\n\tPuzzlePiece,\n\tShipStation,\n\tShopifyBrand,\n\tSkio,\n\tSlackIcon,\n\tWebhook,\n} from '@src/icons';\nimport React from 'react';\nimport { ToolSource } from '../constants/tools';\nimport type { IconComp, SourceIcon } from '../constants/tools';\n\n// The icon types live with the source enum (constants/tools) to keep the\n// dependency one-directional (util → constants); re-exported here so existing\n// `from '../utils/sourceIcons'` importers keep resolving them.\nexport type { IconComp, SourceIcon };\n\n/**\n * Per-source brand glyph — shared by the `@` picker and the Tools source\n * buttons. Every glyph comes from the shared icon library (`@src/icons`), so all\n * of them sit on a square 24 viewBox and `w`/`h` is purely optical sizing rather\n * than aspect correction. Partial: not every source has a glyph, and the render\n * path null-guards. Look up with {@link sourceIcon} when the key is a dynamic /\n * unknown string rather than a {@link ToolSource}.\n *\n * `Aftership` is deliberately absent — we have no AfterShip brand asset yet, so\n * it resolves to {@link GENERIC_SOURCE_ICON}. Add the glyph to `@src/icons`\n * (same as ShipStation) and add its entry here to fix that.\n */\nexport const SOURCE_ICONS: Partial<Record<ToolSource, SourceIcon>> = {\n\t[ToolSource.Manifest]: { Icon: ManifestGlass as IconComp, w: 24, h: 24 },\n\t[ToolSource.Shopify]: { Icon: ShopifyBrand as IconComp, w: 24, h: 24 },\n\t[ToolSource.Bigcommerce]: { Icon: BigCommerce as IconComp, w: 20, h: 20 },\n\t[ToolSource.Shipstation]: { Icon: ShipStation as IconComp, w: 22, h: 22 },\n\t[ToolSource.Skio]: { Icon: Skio as IconComp, w: 20, h: 20 },\n\t[ToolSource.Gorgias]: { Icon: Gorgias as IconComp, w: 20, h: 20 },\n\t[ToolSource.Integration]: { Icon: PuzzlePiece as IconComp, w: 20, h: 20 },\n\t[ToolSource.RestApi]: { Icon: Webhook as IconComp, w: 20, h: 20 },\n\t[ToolSource.EmailHandover]: { Icon: Email as IconComp, w: 20, h: 20 },\n\t[ToolSource.Slack]: { Icon: SlackIcon as IconComp, w: 20, h: 20 },\n};\n\n/**\n * Generic glyph for a tool whose source has no dedicated brand icon (any custom\n * / future integration the FE doesn't bundle a logo for). Ensures EVERY tool\n * chip still leads with an icon.\n */\nexport const GENERIC_SOURCE_ICON: SourceIcon = {\n\tIcon: LinkSimpleHorizontal as IconComp,\n\tw: 20,\n\th: 20,\n};\n\n/**\n * Lenient icon lookup for a source that may be a raw/dynamic string (a\n * bik-models tool source, an integration key, or the picker's `'other'`\n * fallback). A known source returns its brand glyph; any other NON-EMPTY source\n * falls back to {@link GENERIC_SOURCE_ICON} so no tool renders iconless. An\n * empty/undefined source (e.g. a sub-agent reference) returns `undefined`.\n */\nexport const sourceIcon = (\n\tsource: string | undefined,\n): SourceIcon | undefined =>\n\tsource\n\t\t? SOURCE_ICONS[source as ToolSource] ?? GENERIC_SOURCE_ICON\n\t\t: undefined;\n\n/**\n * Render a {@link SourceIcon} at its declared box. `sizeDelta` nudges both\n * dimensions (e.g. `-4` for the smaller source-button glyph). Returns `null` when\n * no icon is supplied, so callers can drop their own `icon &&` guard.\n */\nexport const renderSourceIcon = (\n\ticon: SourceIcon | undefined,\n\tsizeDelta = 0,\n): React.ReactElement | null =>\n\ticon\n\t\t? React.createElement(icon.Icon, {\n\t\t\t\twidth: icon.w + sizeDelta,\n\t\t\t\theight: icon.h + sizeDelta,\n\t\t })\n\t\t: null;\n"],"names":["SOURCE_ICONS","ToolSource","ManifestGlass","ShopifyBrand","BigCommerce","ShipStation","Skio","Gorgias","PuzzlePiece","Webhook","Email","SlackIcon","GENERIC_SOURCE_ICON","LinkSimpleHorizontal","sourceIcon","source","renderSourceIcon","icon","sizeDelta","React"],"mappings":"61BAkCaA,EAAwD,CACpE,CAACC,EAAAA,WAAW,QAAQ,EAAG,CAAE,KAAMC,EAAAA,QAA2B,EAAG,GAAI,EAAG,EAAA,EACpE,CAACD,EAAAA,WAAW,OAAO,EAAG,CAAE,KAAME,EAAAA,QAA0B,EAAG,GAAI,EAAG,EAAA,EAClE,CAACF,EAAAA,WAAW,WAAW,EAAG,CAAE,KAAMG,EAAAA,QAAyB,EAAG,GAAI,EAAG,EAAA,EACrE,CAACH,EAAAA,WAAW,WAAW,EAAG,CAAE,KAAMI,EAAAA,QAAyB,EAAG,GAAI,EAAG,EAAA,EACrE,CAACJ,EAAAA,WAAW,IAAI,EAAG,CAAE,KAAMK,EAAAA,QAAkB,EAAG,GAAI,EAAG,EAAA,EACvD,CAACL,EAAAA,WAAW,OAAO,EAAG,CAAE,KAAMM,EAAAA,QAAqB,EAAG,GAAI,EAAG,EAAA,EAC7D,CAACN,EAAAA,WAAW,WAAW,EAAG,CAAE,KAAMO,EAAAA,QAAyB,EAAG,GAAI,EAAG,EAAA,EACrE,CAACP,EAAAA,WAAW,OAAO,EAAG,CAAE,KAAMQ,EAAAA,QAAqB,EAAG,GAAI,EAAG,EAAA,EAC7D,CAACR,EAAAA,WAAW,aAAa,EAAG,CAAE,KAAMS,EAAAA,QAAmB,EAAG,GAAI,EAAG,EAAA,EACjE,CAACT,EAAAA,WAAW,KAAK,EAAG,CAAE,KAAMU,EAAAA,QAAuB,EAAG,GAAI,EAAG,EAAA,CAC9D,EAOaC,EAAkC,CAC9C,KAAMC,EAAAA,QACN,EAAG,GACH,EAAG,EACJ,EASaC,EACZC,GAEAA,EACGf,EAAae,CAAoB,GAAKH,EACtC,OAOSI,EAAmB,CAC/BC,EACAC,EAAY,IAEZD,EACGE,UAAM,cAAcF,EAAK,KAAM,CAC/B,MAAOA,EAAK,EAAIC,EAChB,OAAQD,EAAK,EAAIC,CACjB,CAAC,EACD"}
1
+ {"version":3,"file":"sourceIcons.js","sources":["../../../../../src/components/agent-builder/utils/sourceIcons.ts"],"sourcesContent":["import {\n\tAftership,\n\tAttentive,\n\tBigCommerce,\n\tEmail,\n\tFreshdesk,\n\tGoogleSheets,\n\tGorgias,\n\tKlavyio,\n\tKustomer,\n\tLinkSimpleHorizontal,\n\tMailchimp,\n\tManifestGlass,\n\tOmniSend,\n\tPuzzlePiece,\n\tSegment,\n\tShipBob,\n\tShipStation,\n\tShopifyBrand,\n\tSkio,\n\tSlackIcon,\n\tWebhook,\n\tZendesk,\n} from '@src/icons';\nimport React from 'react';\nimport { INTEGRATIONS_KEY, ToolSource } from '../constants/tools';\nimport type { IconComp, SourceIcon } from '../constants/tools';\n\n// The icon types live with the source enum (constants/tools) to keep the\n// dependency one-directional (util → constants); re-exported here so existing\n// `from '../utils/sourceIcons'` importers keep resolving them.\nexport type { IconComp, SourceIcon };\n\n/**\n * Per-source brand glyph — shared by the `@` picker and the Tools source\n * buttons. Every glyph comes from the shared icon library (`@src/icons`), so all\n * of them sit on a square 24 viewBox and `w`/`h` is purely optical sizing rather\n * than aspect correction. Partial: not every source has a glyph, and the render\n * path null-guards. Look up with {@link sourceIcon} when the key is a dynamic /\n * unknown string rather than a {@link ToolSource}.\n */\nexport const SOURCE_ICONS: Partial<Record<ToolSource, SourceIcon>> = {\n\t[ToolSource.Manifest]: { Icon: ManifestGlass as IconComp, w: 24, h: 24 },\n\t[ToolSource.Shopify]: { Icon: ShopifyBrand as IconComp, w: 24, h: 24 },\n\t[ToolSource.Bigcommerce]: { Icon: BigCommerce as IconComp, w: 20, h: 20 },\n\t[ToolSource.Shipstation]: { Icon: ShipStation as IconComp, w: 22, h: 22 },\n\t[ToolSource.Skio]: { Icon: Skio as IconComp, w: 20, h: 20 },\n\t[ToolSource.Gorgias]: { Icon: Gorgias as IconComp, w: 20, h: 20 },\n\t[ToolSource.Integration]: { Icon: PuzzlePiece as IconComp, w: 20, h: 20 },\n\t[ToolSource.RestApi]: { Icon: Webhook as IconComp, w: 20, h: 20 },\n\t[ToolSource.EmailHandover]: { Icon: Email as IconComp, w: 20, h: 20 },\n\t[ToolSource.Slack]: { Icon: SlackIcon as IconComp, w: 20, h: 20 },\n\t// Standard-contract vendors — brand glyphs from the shared icon set.\n\t[ToolSource.Aftership]: { Icon: Aftership as IconComp, w: 20, h: 20 },\n\t[ToolSource.Klaviyo]: { Icon: Klavyio as IconComp, w: 20, h: 20 },\n\t[ToolSource.Omnisend]: { Icon: OmniSend as IconComp, w: 20, h: 20 },\n\t[ToolSource.Attentive]: { Icon: Attentive as IconComp, w: 20, h: 20 },\n\t[ToolSource.Mailchimp]: { Icon: Mailchimp as IconComp, w: 20, h: 20 },\n\t[ToolSource.Segment]: { Icon: Segment as IconComp, w: 20, h: 20 },\n\t[ToolSource.Zendesk]: { Icon: Zendesk as IconComp, w: 20, h: 20 },\n\t[ToolSource.Freshdesk]: { Icon: Freshdesk as IconComp, w: 20, h: 20 },\n\t[ToolSource.Kustomer]: { Icon: Kustomer as IconComp, w: 20, h: 20 },\n\t[ToolSource.Shipbob]: { Icon: ShipBob as IconComp, w: 20, h: 20 },\n\t[ToolSource.GoogleSheets]: { Icon: GoogleSheets as IconComp, w: 20, h: 20 },\n};\n\n/**\n * Glyph for the synthetic \"Integrations\" umbrella row — the group that holds\n * every source the store has not connected. Not a real source, so it has no\n * entry in {@link SOURCE_ICONS}; {@link sourceIcon} resolves it by key.\n */\nexport const INTEGRATIONS_ICON: SourceIcon = {\n\tIcon: PuzzlePiece as IconComp,\n\tw: 20,\n\th: 20,\n};\n\n/**\n * Generic glyph for a tool whose source has no dedicated brand icon (any custom\n * / future integration the FE doesn't bundle a logo for). Ensures EVERY tool\n * chip still leads with an icon.\n */\nexport const GENERIC_SOURCE_ICON: SourceIcon = {\n\tIcon: LinkSimpleHorizontal as IconComp,\n\tw: 20,\n\th: 20,\n};\n\n/**\n * Lenient icon lookup for a source that may be a raw/dynamic string (a\n * bik-models tool source, an integration key, or the picker's `'other'`\n * fallback). A known source returns its brand glyph; any other NON-EMPTY source\n * falls back to {@link GENERIC_SOURCE_ICON} so no tool renders iconless. An\n * empty/undefined source (e.g. a sub-agent reference) returns `undefined`.\n */\nexport const sourceIcon = (\n\tsource: string | undefined,\n): SourceIcon | undefined => {\n\tif (!source) {\n\t\treturn undefined;\n\t}\n\tif (source === INTEGRATIONS_KEY) {\n\t\treturn INTEGRATIONS_ICON;\n\t}\n\treturn SOURCE_ICONS[source as ToolSource] ?? GENERIC_SOURCE_ICON;\n};\n\n/**\n * Render a {@link SourceIcon} at its declared box. `sizeDelta` nudges both\n * dimensions (e.g. `-4` for the smaller source-button glyph). Returns `null` when\n * no icon is supplied, so callers can drop their own `icon &&` guard.\n */\nexport const renderSourceIcon = (\n\ticon: SourceIcon | undefined,\n\tsizeDelta = 0,\n): React.ReactElement | null =>\n\ticon\n\t\t? React.createElement(icon.Icon, {\n\t\t\t\twidth: icon.w + sizeDelta,\n\t\t\t\theight: icon.h + sizeDelta,\n\t\t })\n\t\t: null;\n"],"names":["SOURCE_ICONS","ToolSource","ManifestGlass","ShopifyBrand","BigCommerce","ShipStation","Skio","Gorgias","PuzzlePiece","Webhook","Email","SlackIcon","Aftership","Klavyio","OmniSend","Attentive","Mailchimp","Segment","Zendesk","Freshdesk","Kustomer","ShipBob","GoogleSheets","INTEGRATIONS_ICON","GENERIC_SOURCE_ICON","LinkSimpleHorizontal","sourceIcon","source","INTEGRATIONS_KEY","renderSourceIcon","icon","sizeDelta","React"],"mappings":"u8CAyCaA,EAAwD,CACpE,CAACC,EAAAA,WAAW,QAAQ,EAAG,CAAE,KAAMC,EAAAA,QAA2B,EAAG,GAAI,EAAG,EAAA,EACpE,CAACD,EAAAA,WAAW,OAAO,EAAG,CAAE,KAAME,EAAAA,QAA0B,EAAG,GAAI,EAAG,EAAA,EAClE,CAACF,EAAAA,WAAW,WAAW,EAAG,CAAE,KAAMG,EAAAA,QAAyB,EAAG,GAAI,EAAG,EAAA,EACrE,CAACH,EAAAA,WAAW,WAAW,EAAG,CAAE,KAAMI,EAAAA,QAAyB,EAAG,GAAI,EAAG,EAAA,EACrE,CAACJ,EAAAA,WAAW,IAAI,EAAG,CAAE,KAAMK,EAAAA,QAAkB,EAAG,GAAI,EAAG,EAAA,EACvD,CAACL,EAAAA,WAAW,OAAO,EAAG,CAAE,KAAMM,EAAAA,QAAqB,EAAG,GAAI,EAAG,EAAA,EAC7D,CAACN,EAAAA,WAAW,WAAW,EAAG,CAAE,KAAMO,EAAAA,QAAyB,EAAG,GAAI,EAAG,EAAA,EACrE,CAACP,EAAAA,WAAW,OAAO,EAAG,CAAE,KAAMQ,EAAAA,QAAqB,EAAG,GAAI,EAAG,EAAA,EAC7D,CAACR,EAAAA,WAAW,aAAa,EAAG,CAAE,KAAMS,EAAAA,QAAmB,EAAG,GAAI,EAAG,EAAA,EACjE,CAACT,EAAAA,WAAW,KAAK,EAAG,CAAE,KAAMU,EAAAA,QAAuB,EAAG,GAAI,EAAG,EAAA,EAE7D,CAACV,EAAAA,WAAW,SAAS,EAAG,CAAE,KAAMW,EAAAA,QAAuB,EAAG,GAAI,EAAG,EAAA,EACjE,CAACX,EAAAA,WAAW,OAAO,EAAG,CAAE,KAAMY,EAAAA,QAAqB,EAAG,GAAI,EAAG,EAAA,EAC7D,CAACZ,EAAAA,WAAW,QAAQ,EAAG,CAAE,KAAMa,EAAAA,QAAsB,EAAG,GAAI,EAAG,EAAA,EAC/D,CAACb,EAAAA,WAAW,SAAS,EAAG,CAAE,KAAMc,EAAAA,QAAuB,EAAG,GAAI,EAAG,EAAA,EACjE,CAACd,EAAAA,WAAW,SAAS,EAAG,CAAE,KAAMe,EAAAA,QAAuB,EAAG,GAAI,EAAG,EAAA,EACjE,CAACf,EAAAA,WAAW,OAAO,EAAG,CAAE,KAAMgB,EAAAA,QAAqB,EAAG,GAAI,EAAG,EAAA,EAC7D,CAAChB,EAAAA,WAAW,OAAO,EAAG,CAAE,KAAMiB,EAAAA,QAAqB,EAAG,GAAI,EAAG,EAAA,EAC7D,CAACjB,EAAAA,WAAW,SAAS,EAAG,CAAE,KAAMkB,EAAAA,QAAuB,EAAG,GAAI,EAAG,EAAA,EACjE,CAAClB,EAAAA,WAAW,QAAQ,EAAG,CAAE,KAAMmB,EAAAA,QAAsB,EAAG,GAAI,EAAG,EAAA,EAC/D,CAACnB,EAAAA,WAAW,OAAO,EAAG,CAAE,KAAMoB,EAAAA,QAAqB,EAAG,GAAI,EAAG,EAAA,EAC7D,CAACpB,EAAAA,WAAW,YAAY,EAAG,CAAE,KAAMqB,EAAAA,QAA0B,EAAG,GAAI,EAAG,EAAA,CACxE,EAOaC,EAAgC,CAC5C,KAAMf,EAAAA,QACN,EAAG,GACH,EAAG,EACJ,EAOagB,EAAkC,CAC9C,KAAMC,EAAAA,QACN,EAAG,GACH,EAAG,EACJ,EASaC,EACZC,GAC4B,CAC5B,GAAKA,EAGL,OAAIA,IAAWC,EAAAA,iBACPL,EAEDvB,EAAa2B,CAAoB,GAAKH,CAC9C,EAOaK,EAAmB,CAC/BC,EACAC,EAAY,IAEZD,EACGE,UAAM,cAAcF,EAAK,KAAM,CAC/B,MAAOA,EAAK,EAAIC,EAChB,OAAQD,EAAK,EAAIC,CACjB,CAAC,EACD"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("../constants/tools.js"),i=require("./sourceIcons.js"),c=(O,e,l,S)=>t.TOOL_ACTION_SOURCES.filter(o=>{const n=t.CONFIG_TOOL_SOURCES[o];return!n||!!O?.[n]}).map(o=>({source:o,label:t.TOOL_ACTION_LABELS[o]??t.TOOL_SOURCE_LABELS[o],icon:i.SOURCE_ICONS[o],onSelect:()=>e(o),connected:l?.[o],onConnect:()=>S?.(o)}));exports.buildToolActions=c;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("../constants/tools.js"),C=require("./sourceIcons.js"),L=(S,o,i,_)=>t.TOOL_ACTION_SOURCES.flatMap(O=>{const e=t.CONFIG_TOOL_SOURCES[O],l={source:O,icon:C.SOURCE_ICONS[O],connected:i?.[O],onConnect:()=>_?.(O)};return e?e.filter(n=>!!S?.[n]).map(n=>({...l,toolKey:n,label:t.CONFIG_TOOL_ACTION_LABELS[n],onSelect:()=>o(O,n)})):[{...l,label:t.TOOL_ACTION_LABELS[O]??t.TOOL_SOURCE_LABELS[O],onSelect:()=>o(O)}]});exports.buildToolActions=L;
2
2
  //# sourceMappingURL=toolActions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toolActions.js","sources":["../../../../../src/components/agent-builder/utils/toolActions.ts"],"sourcesContent":["import { ConfigToolKey, ParamsBlob } from '../AgentBuilder.model';\nimport {\n\tCONFIG_TOOL_SOURCES,\n\tTOOL_ACTION_LABELS,\n\tTOOL_ACTION_SOURCES,\n\tTOOL_SOURCE_LABELS,\n\tToolAction,\n\tToolSource,\n} from '../constants/tools';\nimport { SOURCE_ICONS } from './sourceIcons';\n\n/**\n * Single source of truth for the built-in tool \"action\" list (Rest API / email /\n * Slack) shown in the `@` picker AND the Step-3 / sub-agent Tools panel. A config\n * tool (email / Slack) is offered only when its backend template was provided.\n * The category name comes from `TOOL_SOURCE_LABELS`; the addable-action name from\n * `TOOL_ACTION_LABELS`. Consumers pass only how to open the drawer (`onSelect`) so\n * every surface renders identical actions/labels.\n */\nexport const buildToolActions = (\n\tconfigToolTemplates: Partial<Record<ConfigToolKey, ParamsBlob>> | undefined,\n\tonSelect: (source: ToolSource) => void,\n\tintegrationStatus?: Partial<Record<ToolSource, boolean>>,\n\tonConnect?: (source: ToolSource) => void,\n): ToolAction[] =>\n\tTOOL_ACTION_SOURCES.filter((source) => {\n\t\tconst toolKey = CONFIG_TOOL_SOURCES[source];\n\t\treturn !toolKey || Boolean(configToolTemplates?.[toolKey]);\n\t}).map((source) => ({\n\t\tsource,\n\t\tlabel: TOOL_ACTION_LABELS[source] ?? TOOL_SOURCE_LABELS[source],\n\t\ticon: SOURCE_ICONS[source],\n\t\tonSelect: () => onSelect(source),\n\t\t// `undefined` unless the consumer reports this source's connection state,\n\t\t// in which case `false` makes the picker render a \"Connect\" row.\n\t\tconnected: integrationStatus?.[source],\n\t\tonConnect: () => onConnect?.(source),\n\t}));\n"],"names":["buildToolActions","configToolTemplates","onSelect","integrationStatus","onConnect","TOOL_ACTION_SOURCES","source","toolKey","CONFIG_TOOL_SOURCES","TOOL_ACTION_LABELS","TOOL_SOURCE_LABELS","SOURCE_ICONS"],"mappings":"uJAmBaA,EAAmB,CAC/BC,EACAC,EACAC,EACAC,IAEAC,EAAAA,oBAAoB,OAAQC,GAAW,CACtC,MAAMC,EAAUC,EAAAA,oBAAoBF,CAAM,EAC1C,MAAO,CAACC,GAAW,EAAQN,IAAsBM,CAAO,CACzD,CAAC,EAAE,IAAKD,IAAY,CACnB,OAAAA,EACA,MAAOG,EAAAA,mBAAmBH,CAAM,GAAKI,EAAAA,mBAAmBJ,CAAM,EAC9D,KAAMK,EAAAA,aAAaL,CAAM,EACzB,SAAU,IAAMJ,EAASI,CAAM,EAG/B,UAAWH,IAAoBG,CAAM,EACrC,UAAW,IAAMF,IAAYE,CAAM,CACpC,EAAE"}
1
+ {"version":3,"file":"toolActions.js","sources":["../../../../../src/components/agent-builder/utils/toolActions.ts"],"sourcesContent":["import { ConfigToolKey, ParamsBlob } from '../AgentBuilder.model';\nimport {\n\tCONFIG_TOOL_ACTION_LABELS,\n\tCONFIG_TOOL_SOURCES,\n\tTOOL_ACTION_LABELS,\n\tTOOL_ACTION_SOURCES,\n\tTOOL_SOURCE_LABELS,\n\tToolAction,\n\tToolSource,\n} from '../constants/tools';\nimport { SOURCE_ICONS } from './sourceIcons';\n\n/**\n * Single source of truth for the built-in tool \"action\" list (Rest API / email /\n * Slack / Google Sheets) shown in the `@` picker AND the Step-3 / sub-agent Tools\n * panel. A config tool is offered only when its backend template was provided.\n *\n * A source can offer SEVERAL actions — Google Sheets has one for reading a sheet\n * and one for appending a row — so this yields one action per (source, tool key)\n * and names it from `CONFIG_TOOL_ACTION_LABELS`. Rest API has no tool key: it\n * keeps the source-level name from `TOOL_ACTION_LABELS`.\n *\n * Consumers pass only how to open the drawer (`onSelect`) so every surface\n * renders identical actions/labels.\n */\nexport const buildToolActions = (\n\tconfigToolTemplates: Partial<Record<ConfigToolKey, ParamsBlob>> | undefined,\n\tonSelect: (source: ToolSource, toolKey?: ConfigToolKey) => void,\n\tintegrationStatus?: Partial<Record<ToolSource, boolean>>,\n\tonConnect?: (source: ToolSource) => void,\n): ToolAction[] =>\n\tTOOL_ACTION_SOURCES.flatMap((source) => {\n\t\tconst toolKeys = CONFIG_TOOL_SOURCES[source];\n\t\t// `undefined` unless the consumer reports this source's connection state,\n\t\t// in which case `false` makes the picker render a \"Connect\" row.\n\t\tconst shared = {\n\t\t\tsource,\n\t\t\ticon: SOURCE_ICONS[source],\n\t\t\tconnected: integrationStatus?.[source],\n\t\t\tonConnect: () => onConnect?.(source),\n\t\t};\n\t\tif (!toolKeys) {\n\t\t\t// Rest API: one bespoke panel, no backend template to wait for.\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\t...shared,\n\t\t\t\t\tlabel: TOOL_ACTION_LABELS[source] ?? TOOL_SOURCE_LABELS[source],\n\t\t\t\t\tonSelect: () => onSelect(source),\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\treturn toolKeys\n\t\t\t.filter((toolKey) => Boolean(configToolTemplates?.[toolKey]))\n\t\t\t.map((toolKey) => ({\n\t\t\t\t...shared,\n\t\t\t\ttoolKey,\n\t\t\t\tlabel: CONFIG_TOOL_ACTION_LABELS[toolKey],\n\t\t\t\tonSelect: () => onSelect(source, toolKey),\n\t\t\t}));\n\t});\n"],"names":["buildToolActions","configToolTemplates","onSelect","integrationStatus","onConnect","TOOL_ACTION_SOURCES","source","toolKeys","CONFIG_TOOL_SOURCES","shared","SOURCE_ICONS","toolKey","CONFIG_TOOL_ACTION_LABELS","TOOL_ACTION_LABELS","TOOL_SOURCE_LABELS"],"mappings":"uJAyBaA,EAAmB,CAC/BC,EACAC,EACAC,EACAC,IAEAC,EAAAA,oBAAoB,QAASC,GAAW,CACvC,MAAMC,EAAWC,EAAAA,oBAAoBF,CAAM,EAGrCG,EAAS,CACd,OAAAH,EACA,KAAMI,EAAAA,aAAaJ,CAAM,EACzB,UAAWH,IAAoBG,CAAM,EACrC,UAAW,IAAMF,IAAYE,CAAM,CAAA,EAEpC,OAAKC,EAUEA,EACL,OAAQI,GAAY,EAAQV,IAAsBU,CAAO,CAAE,EAC3D,IAAKA,IAAa,CAClB,GAAGF,EACH,QAAAE,EACA,MAAOC,EAAAA,0BAA0BD,CAAO,EACxC,SAAU,IAAMT,EAASI,EAAQK,CAAO,CAAA,EACvC,EAfK,CACN,CACC,GAAGF,EACH,MAAOI,EAAAA,mBAAmBP,CAAM,GAAKQ,EAAAA,mBAAmBR,CAAM,EAC9D,SAAU,IAAMJ,EAASI,CAAM,CAAA,CAChC,CAWH,CAAC"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),Fe=require("../../assets/icons/arrow_down.svg.js"),f=require("../../assets/icons/bik_ai_stars_icon.svg.js"),le=require("../../assets/icons/cross.svg.js"),Oe=require("../../assets/icons/refresh.svg.js"),i=require("react"),p=require("../../constants/Theme.js"),T=require("../TypographyStyle.js"),qe=require("./CopilotFeedbackModal.js"),o=require("./CopilotPanel.styled.js"),We=require("./copilotRegenerate.js"),Ne=require("./copilotSelectionPrompt.js"),$e=require("./utils/markdown.js"),De=require("./utils/toolCtas.js"),se=require("../dot-pulse/DotPulse.js"),Ue=r=>r&&typeof r=="object"&&"default"in r?r:{default:r},Ve=Ue(i),Ke=96,Xe=24,Ge=1800,ze=async r=>{try{if(navigator.clipboard?.writeText)return await navigator.clipboard.writeText(r),!0}catch{}try{const l=document.createElement("textarea");l.value=r,l.setAttribute("readonly",""),l.style.position="fixed",l.style.top="-1000px",l.style.opacity="0",document.body.appendChild(l),l.select();const S=document.execCommand("copy");return document.body.removeChild(l),S}catch{return!1}},Je=48,Ze=r=>{if(!r||!Number.isFinite(r))return"";const l=new Date(r);return Number.isNaN(l.getTime())?"":l.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"})},Qe=()=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M12 19V5"}),e.jsx("path",{d:"M6 11l6-6 6 6"})]}),Ye=()=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M5 12h14"}),e.jsx("path",{d:"M13 6l6 6-6 6"})]}),ce=({size:r=16})=>e.jsx("svg",{viewBox:"0 0 24 24",width:r,height:r,fill:"currentColor","aria-hidden":"true",children:e.jsx("rect",{x:"7",y:"7",width:"10",height:"10",rx:"2"})}),et=()=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("rect",{x:"9",y:"9",width:"11",height:"11",rx:"2"}),e.jsx("path",{d:"M15 5.5A1.5 1.5 0 0 0 13.5 4H5.5A1.5 1.5 0 0 0 4 5.5v8A1.5 1.5 0 0 0 5.5 15"})]}),tt=()=>e.jsx("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor",strokeWidth:"2.2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("path",{d:"M5 13l4 4L19 7"})}),ot=()=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M20 12a8 8 0 1 1-2.34-5.66"}),e.jsx("path",{d:"M20 4v4h-4"})]}),rt=({filled:r=!1})=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:r?"currentColor":"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M7 10v11H4a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h3Z"}),e.jsx("path",{d:"M7 10l4.5-7a2 2 0 0 1 3.7 1.3L14.5 9H19a2 2 0 0 1 2 2.3l-1.1 7A2 2 0 0 1 18 20H7"})]}),nt=({filled:r=!1})=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:r?"currentColor":"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M7 14V3H4a1 1 0 0 0-1 1v9a1 1 0 0 0 1 1h3Z"}),e.jsx("path",{d:"M7 14l4.5 7a2 2 0 0 0 3.7-1.3L14.5 15H19a2 2 0 0 0 2-2.3l-1.1-7A2 2 0 0 0 18 4H7"})]}),it=({messages:r,onSend:l,onClose:S,title:k="Copilot",badge:q,subtitle:W,avatar:de,placeholder:ae="Write your message...",disclaimer:N="AI can make mistakes, Verify the responses.",emptyStateTitle:he,emptyStateSubtitle:$="Here are some things you can try",suggestions:v,onSuggestionClick:ue,showRefresh:pe=!0,onRefresh:D,onRegenerate:U,onFeedback:M,dislikeTitle:xe,dislikeSubtitle:je,dislikeReasons:fe,dislikeNotePlaceholder:ke,dislikeSubmitLabel:Ce,isThinking:C=!1,thinkingLabel:V="Thinking",isStreaming:we=!1,onStop:K,interruptedLabel:X="This message was interrupted",followUpsLabel:G="Follow ups",onToolCtaClick:ye,hasMoreHistory:be=!1,isLoadingHistory:w=!1,onLoadOlderMessages:z,historyLoadingLabel:ge="Loading earlier messages",inputDisabled:d=!1,attachment:a,onAttachmentRemove:J,errorMessage:Z,width:Te,height:Se,className:ve,style:Me})=>{const[R,Q]=i.useState(""),[Re,Y]=i.useState(!1),[L,A]=i.useState(!0),[y,ee]=i.useState(null),[u,Le]=i.useState({}),[b,I]=i.useState(null),B=i.useRef(null),x=i.useRef(null),m=i.useRef(null),_=i.useRef(null),H=i.useRef(0),P=i.useRef(null),g=r.filter(t=>(t.content.length>0||t.wasInterrupted)&&!We.isCopilotRegeneratePrompt(t.content)),te=g.length===0&&!C,h=C||we,oe=!d&&!h&&(R.trim().length>0||!!a),j=h&&!!K,E=g[g.length-1],F=!h&&E?.role==="assistant"?E.followUps:void 0,O=!te&&!L;i.useEffect(()=>{L&&m.current?.scrollIntoView({behavior:"smooth"})},[r,C,L]),i.useEffect(()=>{const t=_.current,n=P.current;!t||n===null||w||(P.current=null,t.scrollTop=t.scrollHeight-n,H.current=t.scrollTop)},[r,w]);const Ae=()=>{const t=_.current;if(!t)return;const n=t.scrollHeight-t.scrollTop-t.clientHeight;t.scrollTop<=Je&&be&&!w&&z&&(P.current=t.scrollHeight-t.scrollTop,z());const c=t.scrollTop<H.current-1;if(H.current=t.scrollTop,n<=Xe){A(!0);return}c&&A(!1)},Ie=()=>{A(!0),m.current?.scrollIntoView({behavior:"smooth"})};i.useEffect(()=>()=>{x.current&&window.clearTimeout(x.current)},[]);const Be=async t=>{await ze(t.content)&&(x.current&&window.clearTimeout(x.current),ee(t.id),x.current=window.setTimeout(()=>ee(null),Ge))},re=(t,n)=>{const c=u[t]===n;if(Le(s=>({...s,[t]:s[t]===n?void 0:n})),c){n==="dislike"&&I(s=>s===t?null:s);return}if(n==="like"){M?.(t,"like");return}b&&b!==t&&M?.(b,"dislike"),I(t)},ne=(t,n)=>{I(c=>c===t?null:c),M?.(t,"dislike",n)},me=()=>{d||h||U?.()},ie=()=>{const t=R.trim();if(!t&&!a||d||h)return;l(a?Ne.buildCopilotSelectionPrompt(a,t):t),Q(""),J?.();const n=B.current;n&&(n.style.height="auto")};i.useEffect(()=>{a&&B.current?.focus()},[a]);const _e=t=>{Q(t.target.value);const n=t.target;n.style.height="auto",n.style.height=`${Math.min(n.scrollHeight,Ke)}px`},He=t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),ie())},Pe=t=>{d||h||(ue?.(t),l(t.text))},Ee=t=>{d||h||l(t)};return e.jsxs(o.PanelContainer,{className:ve,style:{width:Te,height:Se,...Me},role:"dialog","aria-label":k,children:[e.jsxs(o.PanelHeader,{children:[e.jsx(o.HeaderAvatar,{children:de??e.jsx(f.default,{width:18,height:18})}),e.jsxs(o.HeaderText,{children:[e.jsxs(o.HeaderTitleRow,{children:[e.jsx(T.TitleSmall,{children:k}),q&&e.jsx(o.HeaderBadge,{children:q})]}),W&&e.jsx(T.BodyCaption,{color:p.COLORS.content.secondary,children:W})]}),e.jsxs(o.HeaderActions,{children:[pe&&D&&e.jsx(o.IconAction,{type:"button",onClick:D,"aria-label":"Start a new conversation",children:e.jsx(Oe.default,{width:16,height:16})}),e.jsx(o.IconAction,{type:"button",onClick:S,"aria-label":"Close copilot",children:e.jsx(le.default,{width:18,height:18})})]})]}),e.jsxs(o.MessagesViewport,{children:[e.jsx(o.MessagesArea,{ref:_,onScroll:Ae,role:"region","aria-label":"Conversation",children:te?e.jsxs(o.EmptyState,{children:[e.jsx(o.EmptyStateIcon,{children:e.jsx(f.default,{width:28,height:28})}),e.jsx(T.BodySecondary,{style:{fontWeight:600},children:he||k}),$&&e.jsx(T.BodyCaption,{color:p.COLORS.content.secondary,children:$}),v&&v.length>0&&e.jsx(o.SuggestionList,{children:v.map(t=>e.jsxs(o.SuggestionChip,{type:"button",disabled:d||h,onClick:()=>Pe(t),children:[e.jsx(f.default,{width:14,height:14}),t.text]},t.id))})]}):e.jsxs(e.Fragment,{children:[w&&e.jsxs(o.HistoryLoader,{role:"status","aria-live":"polite",children:[e.jsx(se.DotPulse,{color:p.COLORS.content.placeholder,size:4}),ge]}),g.map(t=>{const n=t.role==="user"?Ze(t.timestamp):"";return e.jsxs(Ve.default.Fragment,{children:[t.content.length>0&&e.jsx(o.MessageBubble,{$role:t.role,children:t.role==="assistant"?e.jsx("div",{dangerouslySetInnerHTML:{__html:$e.renderCopilotMarkdown(t.content)}}):e.jsx("div",{style:{whiteSpace:"pre-wrap"},children:t.content})}),t.role==="assistant"&&!t.isStreaming&&(()=>{const c=De.toolResultCtas(t.toolResults);return c.length===0?null:e.jsx(o.ToolCtaList,{children:c.map(s=>e.jsx(o.ToolCtaLink,{href:s.url,target:"_blank",rel:"noopener noreferrer",onClick:()=>ye?.({tool:s.tool,url:s.url}),children:s.label},`${s.tool}-${s.url}`))})})(),n&&e.jsx(o.MessageTimestamp,{children:n}),t.wasInterrupted&&X&&e.jsxs(o.InterruptedNote,{children:[e.jsx(ce,{size:12}),X]}),t.role==="assistant"&&t.content.length>0&&!t.isStreaming&&e.jsxs(o.MessageActions,{children:[e.jsx(o.MessageAction,{type:"button",onClick:()=>{Be(t)},"data-copied":y===t.id,title:y===t.id?"Copied":"Copy","aria-label":y===t.id?"Response copied to clipboard":"Copy response",children:y===t.id?e.jsx(tt,{}):e.jsx(et,{})}),U&&t.id===E?.id&&e.jsx(o.MessageAction,{type:"button",onClick:me,disabled:d||h,title:"Regenerate","aria-label":"Regenerate response",children:e.jsx(ot,{})}),e.jsx(o.MessageAction,{type:"button",onClick:()=>re(t.id,"like"),"data-selected":u[t.id]==="like","aria-pressed":u[t.id]==="like",title:"Good response","aria-label":"Good response",children:e.jsx(rt,{filled:u[t.id]==="like"})}),e.jsx(o.MessageAction,{type:"button",onClick:()=>re(t.id,"dislike"),"data-selected":u[t.id]==="dislike","aria-pressed":u[t.id]==="dislike",title:"Bad response","aria-label":"Bad response",children:e.jsx(nt,{filled:u[t.id]==="dislike"})})]}),b===t.id&&e.jsx(qe.CopilotFeedbackModal,{title:xe,subtitle:je??`Help us improve ${k}`,reasons:fe,notePlaceholder:ke,submitLabel:Ce,onSubmit:c=>ne(t.id,c),onDismiss:()=>ne(t.id)})]},t.id)}),F&&F.length>0&&e.jsxs(o.FollowUpList,{children:[G&&e.jsx(o.FollowUpsLabel,{children:G}),F.map(t=>e.jsxs(o.FollowUpChip,{type:"button",disabled:d,onClick:()=>Ee(t),children:[e.jsx(Ye,{}),t]},t))]}),C&&e.jsxs(o.ThinkingBubble,{role:"status","aria-live":"polite",children:[e.jsx(f.default,{width:14,height:14,color:p.COLORS.content.brand}),V&&e.jsx(o.ThinkingLabel,{children:V}),e.jsx(se.DotPulse,{color:p.COLORS.background.brand,size:5})]}),e.jsx("div",{ref:m})]})}),e.jsx(o.ScrollFade,{$visible:O,"aria-hidden":"true"}),e.jsx(o.JumpToLatestButton,{type:"button",$visible:O,onClick:Ie,tabIndex:O?0:-1,"aria-label":"Scroll to the latest message",children:e.jsx(Fe.default,{width:16,height:16})})]}),Z&&e.jsx(o.ErrorBanner,{role:"alert",children:Z}),e.jsxs(o.InputArea,{children:[a&&e.jsxs(o.AttachmentChip,{children:[e.jsx(f.default,{width:14,height:14,color:p.COLORS.content.brand}),e.jsx(o.AttachmentText,{title:a,children:a}),e.jsx(o.AttachmentRemove,{type:"button",onClick:J,"aria-label":"Remove the selected text",children:e.jsx(le.default,{width:12,height:12})})]}),e.jsxs(o.InputWrapper,{$focused:Re,children:[e.jsx(o.MessageInput,{ref:B,rows:1,value:R,placeholder:ae,disabled:d,onChange:_e,onKeyDown:He,onFocus:()=>Y(!0),onBlur:()=>Y(!1)}),e.jsx(o.SendButton,{type:"button",$active:j||oe,disabled:!j&&!oe,onClick:j?K:ie,"aria-label":j?"Stop generating":"Send message",children:j?e.jsx(ce,{}):e.jsx(Qe,{})})]})]}),N&&e.jsx(o.Disclaimer,{children:N})]})};exports.CopilotPanel=it;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),Oe=require("../../assets/icons/arrow_down.svg.js"),f=require("../../assets/icons/bik_ai_stars_icon.svg.js"),se=require("../../assets/icons/cross.svg.js"),qe=require("../../assets/icons/refresh.svg.js"),i=require("react"),p=require("../../constants/Theme.js"),T=require("../TypographyStyle.js"),We=require("./CopilotFeedbackModal.js"),o=require("./CopilotPanel.styled.js"),Ne=require("./copilotRegenerate.js"),$e=require("./copilotSelectionPrompt.js"),Ue=require("./utils/markdown.js"),Ve=require("./utils/toolCtas.js"),ce=require("../dot-pulse/DotPulse.js"),De=r=>r&&typeof r=="object"&&"default"in r?r:{default:r},Ke=De(i),Xe=96,Ge=24,Je=1800,ze=async r=>{try{if(navigator.clipboard?.writeText)return await navigator.clipboard.writeText(r),!0}catch{}try{const l=document.createElement("textarea");l.value=r,l.setAttribute("readonly",""),l.style.position="fixed",l.style.top="-1000px",l.style.opacity="0",document.body.appendChild(l),l.select();const S=document.execCommand("copy");return document.body.removeChild(l),S}catch{return!1}},Ze=48,Qe=r=>{if(!r||!Number.isFinite(r))return"";const l=new Date(r);return Number.isNaN(l.getTime())?"":l.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"})},Ye=()=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M12 19V5"}),e.jsx("path",{d:"M6 11l6-6 6 6"})]}),et=()=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M5 12h14"}),e.jsx("path",{d:"M13 6l6 6-6 6"})]}),de=({size:r=16})=>e.jsx("svg",{viewBox:"0 0 24 24",width:r,height:r,fill:"currentColor","aria-hidden":"true",children:e.jsx("rect",{x:"7",y:"7",width:"10",height:"10",rx:"2"})}),tt=()=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("rect",{x:"9",y:"9",width:"11",height:"11",rx:"2"}),e.jsx("path",{d:"M15 5.5A1.5 1.5 0 0 0 13.5 4H5.5A1.5 1.5 0 0 0 4 5.5v8A1.5 1.5 0 0 0 5.5 15"})]}),ot=()=>e.jsx("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor",strokeWidth:"2.2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("path",{d:"M5 13l4 4L19 7"})}),rt=()=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M20 12a8 8 0 1 1-2.34-5.66"}),e.jsx("path",{d:"M20 4v4h-4"})]}),nt=({filled:r=!1})=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:r?"currentColor":"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M7 10v11H4a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h3Z"}),e.jsx("path",{d:"M7 10l4.5-7a2 2 0 0 1 3.7 1.3L14.5 9H19a2 2 0 0 1 2 2.3l-1.1 7A2 2 0 0 1 18 20H7"})]}),it=({filled:r=!1})=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:r?"currentColor":"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M7 14V3H4a1 1 0 0 0-1 1v9a1 1 0 0 0 1 1h3Z"}),e.jsx("path",{d:"M7 14l4.5 7a2 2 0 0 0 3.7-1.3L14.5 15H19a2 2 0 0 0 2-2.3l-1.1-7A2 2 0 0 0 18 4H7"})]}),lt=({messages:r,onSend:l,onClose:S,title:C="Copilot",badge:O,subtitle:q,avatar:ae,placeholder:ue="Write your message...",disclaimer:W="AI can make mistakes, Verify the responses.",emptyStateTitle:he,emptyStateSubtitle:N="Here are some things you can try",suggestions:v,onSuggestionClick:pe,showRefresh:xe=!0,onRefresh:$,onRegenerate:U,onFeedback:R,dislikeTitle:je,dislikeSubtitle:fe,dislikeReasons:Ce,dislikeNotePlaceholder:we,dislikeSubmitLabel:ke,isThinking:w=!1,thinkingLabel:V="Thinking",isStreaming:ye=!1,onStop:D,interruptedLabel:K="This message was interrupted",followUpsLabel:X="Follow ups",onToolCtaClick:be,hasMoreHistory:ge=!1,isLoadingHistory:k=!1,onLoadOlderMessages:G,historyLoadingLabel:Te="Loading earlier messages",inputDisabled:d=!1,attachment:u,onAttachmentRemove:J,errorMessage:z,width:Se,height:ve,className:Re,style:Me})=>{const[M,Z]=i.useState(""),[Le,Q]=i.useState(!1),[L,A]=i.useState(!0),[y,Y]=i.useState(null),[ee,Ae]=i.useState({}),[h,I]=i.useState(null),b=i.useRef(null),te=i.useRef(!1),x=i.useRef(null),m=i.useRef(null),B=i.useRef(null),_=i.useRef(0),E=i.useRef(null),g=r.filter(t=>(t.content.length>0||t.wasInterrupted)&&!Ne.isCopilotRegeneratePrompt(t.content)),oe=g.length===0&&!w,s=w||ye,re=!d&&!s&&(M.trim().length>0||!!u),j=s&&!!D,H=g[g.length-1],P=!s&&H?.role==="assistant"?H.followUps:void 0,F=!oe&&!L;i.useEffect(()=>{L&&m.current?.scrollIntoView({behavior:"smooth"})},[r,w,L]),i.useEffect(()=>{const t=B.current,n=E.current;!t||n===null||k||(E.current=null,t.scrollTop=t.scrollHeight-n,_.current=t.scrollTop)},[r,k]);const Ie=()=>{const t=B.current;if(!t)return;const n=t.scrollHeight-t.scrollTop-t.clientHeight;t.scrollTop<=Ze&&ge&&!k&&G&&(E.current=t.scrollHeight-t.scrollTop,G());const a=t.scrollTop<_.current-1;if(_.current=t.scrollTop,n<=Ge){A(!0);return}a&&A(!1)},me=()=>{A(!0),m.current?.scrollIntoView({behavior:"smooth"})};i.useEffect(()=>()=>{x.current&&window.clearTimeout(x.current)},[]);const Be=async t=>{await ze(t.content)&&(x.current&&window.clearTimeout(x.current),Y(t.id),x.current=window.setTimeout(()=>Y(null),Je))},ne=(t,n)=>{const a=ee[t]===n;if(Ae(c=>({...c,[t]:c[t]===n?void 0:n})),a){n==="dislike"&&I(c=>c===t?null:c);return}if(n==="like"){R?.(t,"like");return}h&&h!==t&&R?.(h,"dislike"),I(t)},ie=(t,n)=>{I(a=>a===t?null:a),R?.(t,"dislike",n)},_e=()=>{d||s||U?.()},le=()=>{const t=M.trim();if(!t&&!u||d||s)return;l(u?$e.buildCopilotSelectionPrompt(u,t):t),Z(""),J?.();const n=b.current;n&&(n.style.height="auto")};i.useEffect(()=>{u&&b.current?.focus()},[u]),i.useEffect(()=>{const t=te.current&&!s;te.current=s,t&&!d&&!h&&b.current?.focus()},[s,d,h]);const Ee=t=>{Z(t.target.value);const n=t.target;n.style.height="auto",n.style.height=`${Math.min(n.scrollHeight,Xe)}px`},He=t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),le())},Pe=t=>{d||s||(pe?.(t),l(t.text))},Fe=t=>{d||s||l(t)};return e.jsxs(o.PanelContainer,{className:Re,style:{width:Se,height:ve,...Me},role:"dialog","aria-label":C,children:[e.jsxs(o.PanelHeader,{children:[e.jsx(o.HeaderAvatar,{children:ae??e.jsx(f.default,{width:18,height:18})}),e.jsxs(o.HeaderText,{children:[e.jsxs(o.HeaderTitleRow,{children:[e.jsx(T.TitleSmall,{children:C}),O&&e.jsx(o.HeaderBadge,{children:O})]}),q&&e.jsx(T.BodyCaption,{color:p.COLORS.content.secondary,children:q})]}),e.jsxs(o.HeaderActions,{children:[xe&&$&&e.jsx(o.IconAction,{type:"button",onClick:$,"aria-label":"Start a new conversation",children:e.jsx(qe.default,{width:16,height:16})}),e.jsx(o.IconAction,{type:"button",onClick:S,"aria-label":"Close copilot",children:e.jsx(se.default,{width:18,height:18})})]})]}),e.jsxs(o.MessagesViewport,{children:[e.jsx(o.MessagesArea,{ref:B,onScroll:Ie,role:"region","aria-label":"Conversation",children:oe?e.jsxs(o.EmptyState,{children:[e.jsx(o.EmptyStateIcon,{children:e.jsx(f.default,{width:28,height:28})}),e.jsx(T.BodySecondary,{style:{fontWeight:600},children:he||C}),N&&e.jsx(T.BodyCaption,{color:p.COLORS.content.secondary,children:N}),v&&v.length>0&&e.jsx(o.SuggestionList,{children:v.map(t=>e.jsxs(o.SuggestionChip,{type:"button",disabled:d||s,onClick:()=>Pe(t),children:[e.jsx(f.default,{width:14,height:14}),t.text]},t.id))})]}):e.jsxs(e.Fragment,{children:[k&&e.jsxs(o.HistoryLoader,{role:"status","aria-live":"polite",children:[e.jsx(ce.DotPulse,{color:p.COLORS.content.placeholder,size:4}),Te]}),g.map(t=>{const n=t.role==="user"?Qe(t.timestamp):"";return e.jsxs(Ke.default.Fragment,{children:[t.content.length>0&&e.jsx(o.MessageBubble,{$role:t.role,children:t.role==="assistant"?e.jsx("div",{dangerouslySetInnerHTML:{__html:Ue.renderCopilotMarkdown(t.content)}}):e.jsx("div",{style:{whiteSpace:"pre-wrap"},children:t.content})}),t.role==="assistant"&&!t.isStreaming&&(()=>{const a=Ve.toolResultCtas(t.toolResults);return a.length===0?null:e.jsx(o.ToolCtaList,{children:a.map(c=>e.jsx(o.ToolCtaLink,{href:c.url,target:"_blank",rel:"noopener noreferrer",onClick:()=>be?.({tool:c.tool,url:c.url}),children:c.label},`${c.tool}-${c.url}`))})})(),n&&e.jsx(o.MessageTimestamp,{children:n}),t.wasInterrupted&&K&&e.jsxs(o.InterruptedNote,{children:[e.jsx(de,{size:12}),K]}),t.role==="assistant"&&t.content.length>0&&!t.isStreaming&&e.jsxs(o.MessageActions,{children:[e.jsx(o.MessageAction,{type:"button",onClick:()=>{Be(t)},"data-copied":y===t.id,title:y===t.id?"Copied":"Copy","aria-label":y===t.id?"Response copied to clipboard":"Copy response",children:y===t.id?e.jsx(ot,{}):e.jsx(tt,{})}),U&&t.id===H?.id&&e.jsx(o.MessageAction,{type:"button",onClick:_e,disabled:d||s,title:"Regenerate","aria-label":"Regenerate response",children:e.jsx(rt,{})}),!t.isRestored&&ee[t.id]===void 0&&e.jsxs(e.Fragment,{children:[e.jsx(o.MessageAction,{type:"button",onClick:()=>ne(t.id,"like"),title:"Good response","aria-label":"Good response",children:e.jsx(nt,{})}),e.jsx(o.MessageAction,{type:"button",onClick:()=>ne(t.id,"dislike"),title:"Bad response","aria-label":"Bad response",children:e.jsx(it,{})})]})]}),h===t.id&&e.jsx(We.CopilotFeedbackModal,{title:je,subtitle:fe??`Help us improve ${C}`,reasons:Ce,notePlaceholder:we,submitLabel:ke,onSubmit:a=>ie(t.id,a),onDismiss:()=>ie(t.id)})]},t.id)}),P&&P.length>0&&e.jsxs(o.FollowUpList,{children:[X&&e.jsx(o.FollowUpsLabel,{children:X}),P.map(t=>e.jsxs(o.FollowUpChip,{type:"button",disabled:d,onClick:()=>Fe(t),children:[e.jsx(et,{}),t]},t))]}),w&&e.jsxs(o.ThinkingBubble,{role:"status","aria-live":"polite",children:[e.jsx(f.default,{width:14,height:14,color:p.COLORS.content.brand}),V&&e.jsx(o.ThinkingLabel,{children:V}),e.jsx(ce.DotPulse,{color:p.COLORS.background.brand,size:5})]}),e.jsx("div",{ref:m})]})}),e.jsx(o.ScrollFade,{$visible:F,"aria-hidden":"true"}),e.jsx(o.JumpToLatestButton,{type:"button",$visible:F,onClick:me,tabIndex:F?0:-1,"aria-label":"Scroll to the latest message",children:e.jsx(Oe.default,{width:16,height:16})})]}),z&&e.jsx(o.ErrorBanner,{role:"alert",children:z}),e.jsxs(o.InputArea,{children:[u&&e.jsxs(o.AttachmentChip,{children:[e.jsx(f.default,{width:14,height:14,color:p.COLORS.content.brand}),e.jsx(o.AttachmentText,{title:u,children:u}),e.jsx(o.AttachmentRemove,{type:"button",onClick:J,"aria-label":"Remove the selected text",children:e.jsx(se.default,{width:12,height:12})})]}),e.jsxs(o.InputWrapper,{$focused:Le,children:[e.jsx(o.MessageInput,{ref:b,rows:1,value:M,placeholder:ue,disabled:d,onChange:Ee,onKeyDown:He,onFocus:()=>Q(!0),onBlur:()=>Q(!1)}),e.jsx(o.SendButton,{type:"button",$active:j||re,disabled:!j&&!re,onClick:j?D:le,"aria-label":j?"Stop generating":"Send message",children:j?e.jsx(de,{}):e.jsx(Ye,{})})]})]}),W&&e.jsx(o.Disclaimer,{children:W})]})};exports.CopilotPanel=lt;
2
2
  //# sourceMappingURL=CopilotPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CopilotPanel.js","sources":["../../../../src/components/bik-copilot/CopilotPanel.tsx"],"sourcesContent":["import ArrowDownIcon from '@src/assets/icons/arrow_down.svg';\nimport AiStarsIcon from '@src/assets/icons/bik_ai_stars_icon.svg';\nimport CrossIcon from '@src/assets/icons/cross.svg';\nimport RefreshIcon from '@src/assets/icons/refresh.svg';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { COLORS } from '@src/constants/Theme';\nimport { DotPulse } from '../dot-pulse';\nimport { BodyCaption, BodySecondary, TitleSmall } from '../TypographyStyle';\nimport { CopilotFeedbackModal } from './CopilotFeedbackModal';\nimport {\n\tAttachmentChip,\n\tAttachmentRemove,\n\tAttachmentText,\n\tDisclaimer,\n\tEmptyState,\n\tEmptyStateIcon,\n\tErrorBanner,\n\tFollowUpChip,\n\tFollowUpList,\n\tFollowUpsLabel,\n\tHeaderActions,\n\tHeaderAvatar,\n\tHeaderBadge,\n\tHeaderText,\n\tHeaderTitleRow,\n\tHistoryLoader,\n\tIconAction,\n\tInputArea,\n\tInputWrapper,\n\tInterruptedNote,\n\tJumpToLatestButton,\n\tMessageAction,\n\tMessageActions,\n\tMessageBubble,\n\tMessageInput,\n\tMessagesArea,\n\tMessagesViewport,\n\tMessageTimestamp,\n\tPanelContainer,\n\tPanelHeader,\n\tScrollFade,\n\tSendButton,\n\tSuggestionChip,\n\tSuggestionList,\n\tThinkingBubble,\n\tThinkingLabel,\n\tToolCtaLink,\n\tToolCtaList,\n} from './CopilotPanel.styled';\nimport { isCopilotRegeneratePrompt } from './copilotRegenerate';\nimport { buildCopilotSelectionPrompt } from './copilotSelectionPrompt';\nimport { CopilotFeedbackDetail, CopilotPanelProps } from './model';\nimport { renderCopilotMarkdown } from './utils/markdown';\nimport { toolResultCtas } from './utils/toolCtas';\n\nconst MAX_INPUT_HEIGHT_PX = 96;\n\n/** Slack at the bottom of the scroller that still counts as \"at the latest\". */\nconst AT_BOTTOM_TOLERANCE_PX = 24;\n\n/** How long the copy button shows its confirmation before reverting. */\nconst COPIED_FEEDBACK_MS = 1800;\n\n/**\n * Writes text to the clipboard.\n *\n * `navigator.clipboard` is missing outside a secure context and can reject when\n * the document is not focused, so a hidden-textarea `execCommand` fallback keeps\n * the button working there rather than failing silently.\n */\nconst writeToClipboard = async (text: string): Promise<boolean> => {\n\ttry {\n\t\tif (navigator.clipboard?.writeText) {\n\t\t\tawait navigator.clipboard.writeText(text);\n\t\t\treturn true;\n\t\t}\n\t} catch {\n\t\t// Fall through to the legacy path.\n\t}\n\n\ttry {\n\t\tconst textarea = document.createElement('textarea');\n\t\ttextarea.value = text;\n\t\t// Off-screen rather than hidden: `display: none` cannot be selected.\n\t\ttextarea.setAttribute('readonly', '');\n\t\ttextarea.style.position = 'fixed';\n\t\ttextarea.style.top = '-1000px';\n\t\ttextarea.style.opacity = '0';\n\t\tdocument.body.appendChild(textarea);\n\t\ttextarea.select();\n\t\tconst copied = document.execCommand('copy');\n\t\tdocument.body.removeChild(textarea);\n\t\treturn copied;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\n/** How close to the top counts as asking for the previous page. */\nconst NEAR_TOP_TOLERANCE_PX = 48;\n\nconst formatMessageTime = (timestamp: number): string => {\n\tif (!timestamp || !Number.isFinite(timestamp)) {\n\t\treturn '';\n\t}\n\tconst date = new Date(timestamp);\n\tif (Number.isNaN(date.getTime())) {\n\t\treturn '';\n\t}\n\treturn date.toLocaleTimeString('en-US', {\n\t\thour: 'numeric',\n\t\tminute: '2-digit',\n\t});\n};\n\nconst SendArrowIcon = () => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"16\"\n\t\theight=\"16\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M12 19V5\" />\n\t\t<path d=\"M6 11l6-6 6 6\" />\n\t</svg>\n);\n\nconst ArrowRightIcon = () => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M5 12h14\" />\n\t\t<path d=\"M13 6l6 6-6 6\" />\n\t</svg>\n);\n\nconst StopIcon = ({ size = 16 }: { size?: number }) => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth={size}\n\t\theight={size}\n\t\tfill=\"currentColor\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<rect x=\"7\" y=\"7\" width=\"10\" height=\"10\" rx=\"2\" />\n\t</svg>\n);\n\nconst CopyIcon = () => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"1.8\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<rect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"2\" />\n\t\t<path d=\"M15 5.5A1.5 1.5 0 0 0 13.5 4H5.5A1.5 1.5 0 0 0 4 5.5v8A1.5 1.5 0 0 0 5.5 15\" />\n\t</svg>\n);\n\nconst CheckIcon = () => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2.2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M5 13l4 4L19 7\" />\n\t</svg>\n);\n\nconst RegenerateIcon = () => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"1.8\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M20 12a8 8 0 1 1-2.34-5.66\" />\n\t\t<path d=\"M20 4v4h-4\" />\n\t</svg>\n);\n\nconst ThumbUpIcon = ({ filled = false }: { filled?: boolean }) => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill={filled ? 'currentColor' : 'none'}\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"1.8\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M7 10v11H4a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h3Z\" />\n\t\t<path d=\"M7 10l4.5-7a2 2 0 0 1 3.7 1.3L14.5 9H19a2 2 0 0 1 2 2.3l-1.1 7A2 2 0 0 1 18 20H7\" />\n\t</svg>\n);\n\nconst ThumbDownIcon = ({ filled = false }: { filled?: boolean }) => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill={filled ? 'currentColor' : 'none'}\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"1.8\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M7 14V3H4a1 1 0 0 0-1 1v9a1 1 0 0 0 1 1h3Z\" />\n\t\t<path d=\"M7 14l4.5 7a2 2 0 0 0 3.7-1.3L14.5 15H19a2 2 0 0 0 2-2.3l-1.1-7A2 2 0 0 0 18 4H7\" />\n\t</svg>\n);\n\n/**\n * Chat panel used by the copilot. Fully presentational: it renders the\n * transcript it is given and reports user intent through callbacks, so it works\n * against any backend.\n */\nexport const CopilotPanel: React.FC<CopilotPanelProps> = ({\n\tmessages,\n\tonSend,\n\tonClose,\n\ttitle = 'Copilot',\n\tbadge,\n\tsubtitle,\n\tavatar,\n\tplaceholder = 'Write your message...',\n\tdisclaimer = 'AI can make mistakes, Verify the responses.',\n\temptyStateTitle,\n\temptyStateSubtitle = 'Here are some things you can try',\n\tsuggestions,\n\tonSuggestionClick,\n\tshowRefresh = true,\n\tonRefresh,\n\tonRegenerate,\n\tonFeedback,\n\tdislikeTitle,\n\tdislikeSubtitle,\n\tdislikeReasons,\n\tdislikeNotePlaceholder,\n\tdislikeSubmitLabel,\n\tisThinking = false,\n\tthinkingLabel = 'Thinking',\n\tisStreaming = false,\n\tonStop,\n\tinterruptedLabel = 'This message was interrupted',\n\tfollowUpsLabel = 'Follow ups',\n\tonToolCtaClick,\n\thasMoreHistory = false,\n\tisLoadingHistory = false,\n\tonLoadOlderMessages,\n\thistoryLoadingLabel = 'Loading earlier messages',\n\tinputDisabled = false,\n\tattachment,\n\tonAttachmentRemove,\n\terrorMessage,\n\twidth,\n\theight,\n\tclassName,\n\tstyle,\n}) => {\n\tconst [input, setInput] = useState('');\n\tconst [isInputFocused, setIsInputFocused] = useState(false);\n\tconst [isAtLatest, setIsAtLatest] = useState(true);\n\t// Which reply is showing \"Copied\" — per message, so copying one does not tick\n\t// the button under another.\n\tconst [copiedMessageId, setCopiedMessageId] = useState<string | null>(null);\n\n\tconst [feedback, setFeedback] = useState<\n\t\tRecord<string, 'like' | 'dislike' | undefined>\n\t>({});\n\t// Which reply is being asked about. A thumbs-down opens the prompt and the\n\t// rating is reported once it is answered or dismissed -- so pressing the\n\t// thumb is never lost, and one thumb never becomes two ratings.\n\tconst [dislikePromptId, setDislikePromptId] = useState<string | null>(null);\n\tconst inputRef = useRef<HTMLTextAreaElement>(null);\n\tconst copiedTimeoutRef = useRef<number | null>(null);\n\tconst bottomRef = useRef<HTMLDivElement>(null);\n\tconst scrollerRef = useRef<HTMLDivElement>(null);\n\tconst lastScrollTopRef = useRef(0);\n\t// Distance from the bottom at the moment an older page was asked for. Older\n\t// messages land *above* the viewport, so without restoring against this the\n\t// content under the reader jumps down by the height of what arrived.\n\tconst anchorFromBottomRef = useRef<number | null>(null);\n\n\t// An assistant bubble is pushed the moment a turn starts, before any text has\n\t// arrived; the thinking indicator stands in for it until then, so rendering it\n\t// too would show an empty balloon next to the dots. A turn stopped before its\n\t// first token keeps its place, carrying only the interrupted note.\n\tconst visibleMessages = messages.filter(\n\t\t(message) =>\n\t\t\t(message.content.length > 0 || message.wasInterrupted) &&\n\t\t\t!isCopilotRegeneratePrompt(message.content),\n\t);\n\tconst isEmpty = visibleMessages.length === 0 && !isThinking;\n\tconst isTurnInFlight = isThinking || isStreaming;\n\tconst canSend =\n\t\t!inputDisabled &&\n\t\t!isTurnInFlight &&\n\t\t(input.trim().length > 0 || Boolean(attachment));\n\t// Stopping is the only thing the button can do mid-answer, so it becomes the\n\t// stop button rather than sitting there disabled.\n\tconst canStop = isTurnInFlight && Boolean(onStop);\n\t// Only the newest reply's suggestions are on offer — older ones answer a\n\t// question the conversation has already moved past.\n\tconst newestMessage = visibleMessages[visibleMessages.length - 1];\n\tconst followUps =\n\t\t!isTurnInFlight && newestMessage?.role === 'assistant'\n\t\t\t? newestMessage.followUps\n\t\t\t: undefined;\n\t// A long answer that the reader has scrolled up from: the tail is clipped, so\n\t// the fade and the arrow say there is more below.\n\tconst showScrollAffordance = !isEmpty && !isAtLatest;\n\n\t// Following the conversation is the default, but a reader who has scrolled up\n\t// mid-answer must not be yanked back down by the next chunk.\n\tuseEffect(() => {\n\t\tif (!isAtLatest) {\n\t\t\treturn;\n\t\t}\n\t\tbottomRef.current?.scrollIntoView({ behavior: 'smooth' });\n\t}, [messages, isThinking, isAtLatest]);\n\n\t// Older messages have landed: put the reader back on the message they were\n\t// looking at, which is now that much further down.\n\tuseEffect(() => {\n\t\tconst scroller = scrollerRef.current;\n\t\tconst anchor = anchorFromBottomRef.current;\n\t\tif (!scroller || anchor === null || isLoadingHistory) {\n\t\t\treturn;\n\t\t}\n\t\tanchorFromBottomRef.current = null;\n\t\tscroller.scrollTop = scroller.scrollHeight - anchor;\n\t\tlastScrollTopRef.current = scroller.scrollTop;\n\t}, [messages, isLoadingHistory]);\n\n\tconst handleScroll = () => {\n\t\tconst scroller = scrollerRef.current;\n\t\tif (!scroller) {\n\t\t\treturn;\n\t\t}\n\t\tconst distanceFromBottom =\n\t\t\tscroller.scrollHeight - scroller.scrollTop - scroller.clientHeight;\n\n\t\t// Reaching the top asks for the page before this one. The threshold gives\n\t\t// the request a head start, so the page is usually there by the time the\n\t\t// reader arrives.\n\t\tif (\n\t\t\tscroller.scrollTop <= NEAR_TOP_TOLERANCE_PX &&\n\t\t\thasMoreHistory &&\n\t\t\t!isLoadingHistory &&\n\t\t\tonLoadOlderMessages\n\t\t) {\n\t\t\tanchorFromBottomRef.current = scroller.scrollHeight - scroller.scrollTop;\n\t\t\tonLoadOlderMessages();\n\t\t}\n\t\t// Scrolling *up* is the only thing that detaches from the latest message:\n\t\t// growing content also pushes the bottom away, and auto-scroll itself only\n\t\t// ever moves down, so distance alone would flap mid-stream.\n\t\tconst scrolledUp = scroller.scrollTop < lastScrollTopRef.current - 1;\n\t\tlastScrollTopRef.current = scroller.scrollTop;\n\n\t\tif (distanceFromBottom <= AT_BOTTOM_TOLERANCE_PX) {\n\t\t\tsetIsAtLatest(true);\n\t\t\treturn;\n\t\t}\n\t\tif (scrolledUp) {\n\t\t\tsetIsAtLatest(false);\n\t\t}\n\t};\n\n\tconst handleJumpToLatest = () => {\n\t\tsetIsAtLatest(true);\n\t\tbottomRef.current?.scrollIntoView({ behavior: 'smooth' });\n\t};\n\n\tuseEffect(\n\t\t() => () => {\n\t\t\tif (copiedTimeoutRef.current) {\n\t\t\t\twindow.clearTimeout(copiedTimeoutRef.current);\n\t\t\t}\n\t\t},\n\t\t[],\n\t);\n\n\tconst handleCopyMessage = async (\n\t\tmessage: CopilotPanelProps['messages'][number],\n\t) => {\n\t\t// The raw markdown, not the rendered HTML — that is what a reader wants to\n\t\t// paste into a doc or a ticket.\n\t\tconst copied = await writeToClipboard(message.content);\n\t\tif (!copied) {\n\t\t\treturn;\n\t\t}\n\t\tif (copiedTimeoutRef.current) {\n\t\t\twindow.clearTimeout(copiedTimeoutRef.current);\n\t\t}\n\t\tsetCopiedMessageId(message.id);\n\t\tcopiedTimeoutRef.current = window.setTimeout(\n\t\t\t() => setCopiedMessageId(null),\n\t\t\tCOPIED_FEEDBACK_MS,\n\t\t);\n\t};\n\n\tconst handleFeedback = (messageId: string, vote: 'like' | 'dislike') => {\n\t\t// Pressing the same thumb again clears the vote. Nothing is reported for\n\t\t// that: the backend records ratings, not their absence.\n\t\tconst cleared = feedback[messageId] === vote;\n\t\tsetFeedback((previous) => ({\n\t\t\t...previous,\n\t\t\t[messageId]: previous[messageId] === vote ? undefined : vote,\n\t\t}));\n\t\t// Everything below sits outside the updater on purpose: React may run an\n\t\t// updater twice, which would report the same vote twice.\n\t\tif (cleared) {\n\t\t\tif (vote === 'dislike') {\n\t\t\t\tsetDislikePromptId((current) =>\n\t\t\t\t\tcurrent === messageId ? null : current,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (vote === 'like') {\n\t\t\tonFeedback?.(messageId, 'like');\n\t\t\treturn;\n\t\t}\n\t\t// A thumbs-down asks what went wrong first. Moving the prompt to another\n\t\t// reply still records the one it is leaving.\n\t\tif (dislikePromptId && dislikePromptId !== messageId) {\n\t\t\tonFeedback?.(dislikePromptId, 'dislike');\n\t\t}\n\t\tsetDislikePromptId(messageId);\n\t};\n\n\tconst reportDislike = (messageId: string, detail?: CopilotFeedbackDetail) => {\n\t\tsetDislikePromptId((current) => (current === messageId ? null : current));\n\t\tonFeedback?.(messageId, 'dislike', detail);\n\t};\n\n\tconst handleRegenerate = () => {\n\t\tif (inputDisabled || isTurnInFlight) {\n\t\t\treturn;\n\t\t}\n\t\tonRegenerate?.();\n\t};\n\n\tconst handleSend = () => {\n\t\tconst trimmed = input.trim();\n\t\tif ((!trimmed && !attachment) || inputDisabled || isTurnInFlight) {\n\t\t\treturn;\n\t\t}\n\t\t// The endpoint has no context field, so a quoted selection has to ride\n\t\t// inside the prompt itself.\n\t\tonSend(\n\t\t\tattachment ? buildCopilotSelectionPrompt(attachment, trimmed) : trimmed,\n\t\t);\n\t\tsetInput('');\n\t\t// The quote belongs to the turn that used it; the next question starts\n\t\t// clean unless the merchant selects something again.\n\t\tonAttachmentRemove?.();\n\t\tconst textarea = inputRef.current;\n\t\tif (textarea) {\n\t\t\ttextarea.style.height = 'auto';\n\t\t}\n\t};\n\n\t// A selection is attached so the merchant can ask about it, so the caret\n\t// should already be waiting for the question.\n\tuseEffect(() => {\n\t\tif (attachment) {\n\t\t\tinputRef.current?.focus();\n\t\t}\n\t}, [attachment]);\n\n\tconst handleInputChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n\t\tsetInput(event.target.value);\n\t\tconst textarea = event.target;\n\t\ttextarea.style.height = 'auto';\n\t\ttextarea.style.height = `${Math.min(\n\t\t\ttextarea.scrollHeight,\n\t\t\tMAX_INPUT_HEIGHT_PX,\n\t\t)}px`;\n\t};\n\n\tconst handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n\t\tif (event.key === 'Enter' && !event.shiftKey) {\n\t\t\tevent.preventDefault();\n\t\t\thandleSend();\n\t\t}\n\t};\n\n\tconst handleSuggestionClick = (\n\t\tsuggestion: NonNullable<CopilotPanelProps['suggestions']>[number],\n\t) => {\n\t\tif (inputDisabled || isTurnInFlight) {\n\t\t\treturn;\n\t\t}\n\t\tonSuggestionClick?.(suggestion);\n\t\tonSend(suggestion.text);\n\t};\n\n\tconst handleFollowUpClick = (followUp: string) => {\n\t\tif (inputDisabled || isTurnInFlight) {\n\t\t\treturn;\n\t\t}\n\t\tonSend(followUp);\n\t};\n\n\treturn (\n\t\t<PanelContainer\n\t\t\tclassName={className}\n\t\t\tstyle={{ width, height, ...style }}\n\t\t\trole=\"dialog\"\n\t\t\taria-label={title}\n\t\t>\n\t\t\t<PanelHeader>\n\t\t\t\t<HeaderAvatar>\n\t\t\t\t\t{avatar ?? <AiStarsIcon width={18} height={18} />}\n\t\t\t\t</HeaderAvatar>\n\t\t\t\t<HeaderText>\n\t\t\t\t\t<HeaderTitleRow>\n\t\t\t\t\t\t<TitleSmall>{title}</TitleSmall>\n\t\t\t\t\t\t{badge && <HeaderBadge>{badge}</HeaderBadge>}\n\t\t\t\t\t</HeaderTitleRow>\n\t\t\t\t\t{subtitle && (\n\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t{subtitle}\n\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t)}\n\t\t\t\t</HeaderText>\n\t\t\t\t<HeaderActions>\n\t\t\t\t\t{showRefresh && onRefresh && (\n\t\t\t\t\t\t<IconAction\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={onRefresh}\n\t\t\t\t\t\t\taria-label=\"Start a new conversation\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<RefreshIcon width={16} height={16} />\n\t\t\t\t\t\t</IconAction>\n\t\t\t\t\t)}\n\t\t\t\t\t<IconAction\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={onClose}\n\t\t\t\t\t\taria-label=\"Close copilot\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<CrossIcon width={18} height={18} />\n\t\t\t\t\t</IconAction>\n\t\t\t\t</HeaderActions>\n\t\t\t</PanelHeader>\n\n\t\t\t<MessagesViewport>\n\t\t\t\t<MessagesArea\n\t\t\t\t\tref={scrollerRef}\n\t\t\t\t\tonScroll={handleScroll}\n\t\t\t\t\trole=\"region\"\n\t\t\t\t\taria-label=\"Conversation\"\n\t\t\t\t>\n\t\t\t\t\t{isEmpty ? (\n\t\t\t\t\t\t<EmptyState>\n\t\t\t\t\t\t\t<EmptyStateIcon>\n\t\t\t\t\t\t\t\t<AiStarsIcon width={28} height={28} />\n\t\t\t\t\t\t\t</EmptyStateIcon>\n\t\t\t\t\t\t\t<BodySecondary style={{ fontWeight: 600 }}>\n\t\t\t\t\t\t\t\t{emptyStateTitle || title}\n\t\t\t\t\t\t\t</BodySecondary>\n\t\t\t\t\t\t\t{emptyStateSubtitle && (\n\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t\t\t{emptyStateSubtitle}\n\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{suggestions && suggestions.length > 0 && (\n\t\t\t\t\t\t\t\t<SuggestionList>\n\t\t\t\t\t\t\t\t\t{suggestions.map((suggestion) => (\n\t\t\t\t\t\t\t\t\t\t<SuggestionChip\n\t\t\t\t\t\t\t\t\t\t\tkey={suggestion.id}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={inputDisabled || isTurnInFlight}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleSuggestionClick(suggestion)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<AiStarsIcon width={14} height={14} />\n\t\t\t\t\t\t\t\t\t\t\t{suggestion.text}\n\t\t\t\t\t\t\t\t\t\t</SuggestionChip>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</SuggestionList>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</EmptyState>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{isLoadingHistory && (\n\t\t\t\t\t\t\t\t<HistoryLoader role=\"status\" aria-live=\"polite\">\n\t\t\t\t\t\t\t\t\t<DotPulse color={COLORS.content.placeholder} size={4} />\n\t\t\t\t\t\t\t\t\t{historyLoadingLabel}\n\t\t\t\t\t\t\t\t</HistoryLoader>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{visibleMessages.map((message) => {\n\t\t\t\t\t\t\t\tconst sentAt =\n\t\t\t\t\t\t\t\t\tmessage.role === 'user'\n\t\t\t\t\t\t\t\t\t\t? formatMessageTime(message.timestamp)\n\t\t\t\t\t\t\t\t\t\t: '';\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<React.Fragment key={message.id}>\n\t\t\t\t\t\t\t\t\t\t{message.content.length > 0 && (\n\t\t\t\t\t\t\t\t\t\t\t<MessageBubble $role={message.role}>\n\t\t\t\t\t\t\t\t\t\t\t\t{message.role === 'assistant' ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdangerouslySetInnerHTML={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t__html: renderCopilotMarkdown(message.content),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div style={{ whiteSpace: 'pre-wrap' }}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{message.content}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</MessageBubble>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{/* Tool CTAs (e.g. the support-portal link) — only once the\n\t\t\t\t\t\t\t\t\t\t reply has finished, so a button cannot flash mid-stream. */}\n\t\t\t\t\t\t\t\t\t\t{message.role === 'assistant' &&\n\t\t\t\t\t\t\t\t\t\t\t!message.isStreaming &&\n\t\t\t\t\t\t\t\t\t\t\t(() => {\n\t\t\t\t\t\t\t\t\t\t\t\tconst ctas = toolResultCtas(message.toolResults);\n\t\t\t\t\t\t\t\t\t\t\t\tif (ctas.length === 0) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<ToolCtaList>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ctas.map((cta) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<ToolCtaLink\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={`${cta.tool}-${cta.url}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thref={cta.url}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonToolCtaClick?.({\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttool: cta.tool,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\turl: cta.url,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{cta.label}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</ToolCtaLink>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</ToolCtaList>\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t})()}\n\t\t\t\t\t\t\t\t\t\t{sentAt && <MessageTimestamp>{sentAt}</MessageTimestamp>}\n\t\t\t\t\t\t\t\t\t\t{message.wasInterrupted && interruptedLabel && (\n\t\t\t\t\t\t\t\t\t\t\t<InterruptedNote>\n\t\t\t\t\t\t\t\t\t\t\t\t<StopIcon size={12} />\n\t\t\t\t\t\t\t\t\t\t\t\t{interruptedLabel}\n\t\t\t\t\t\t\t\t\t\t\t</InterruptedNote>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{/* Only under a finished reply: mid-stream the text is still\n\t\t\t\t\t\t\t\t\t\t changing, so copying it would capture a partial answer. */}\n\t\t\t\t\t\t\t\t\t\t{message.role === 'assistant' &&\n\t\t\t\t\t\t\t\t\t\t\tmessage.content.length > 0 &&\n\t\t\t\t\t\t\t\t\t\t\t!message.isStreaming && (\n\t\t\t\t\t\t\t\t\t\t\t\t<MessageActions>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MessageAction\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => void handleCopyMessage(message)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata-copied={copiedMessageId === message.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcopiedMessageId === message.id ? 'Copied' : 'Copy'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcopiedMessageId === message.id\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? 'Response copied to clipboard'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: 'Copy response'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{copiedMessageId === message.id ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<CheckIcon />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<CopyIcon />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MessageAction>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{/* Only under the newest reply: regenerating appends a\n\t\t\t\t\t\t\t\t\t\t\t\t\t fresh turn at the end, so offering it against an\n\t\t\t\t\t\t\t\t\t\t\t\t\t older answer would not replace that answer. */}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{onRegenerate && message.id === newestMessage?.id && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<MessageAction\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={handleRegenerate}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={inputDisabled || isTurnInFlight}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Regenerate\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Regenerate response\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<RegenerateIcon />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</MessageAction>\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MessageAction\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleFeedback(message.id, 'like')}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata-selected={feedback[message.id] === 'like'}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-pressed={feedback[message.id] === 'like'}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Good response\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Good response\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<ThumbUpIcon\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfilled={feedback[message.id] === 'like'}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MessageAction>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MessageAction\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleFeedback(message.id, 'dislike')\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata-selected={feedback[message.id] === 'dislike'}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-pressed={feedback[message.id] === 'dislike'}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Bad response\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Bad response\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<ThumbDownIcon\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfilled={feedback[message.id] === 'dislike'}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MessageAction>\n\t\t\t\t\t\t\t\t\t\t\t\t</MessageActions>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{dislikePromptId === message.id && (\n\t\t\t\t\t\t\t\t\t\t\t<CopilotFeedbackModal\n\t\t\t\t\t\t\t\t\t\t\t\ttitle={dislikeTitle}\n\t\t\t\t\t\t\t\t\t\t\t\tsubtitle={dislikeSubtitle ?? `Help us improve ${title}`}\n\t\t\t\t\t\t\t\t\t\t\t\treasons={dislikeReasons}\n\t\t\t\t\t\t\t\t\t\t\t\tnotePlaceholder={dislikeNotePlaceholder}\n\t\t\t\t\t\t\t\t\t\t\t\tsubmitLabel={dislikeSubmitLabel}\n\t\t\t\t\t\t\t\t\t\t\t\tonSubmit={(detail) => reportDislike(message.id, detail)}\n\t\t\t\t\t\t\t\t\t\t\t\tonDismiss={() => reportDislike(message.id)}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</React.Fragment>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t{followUps && followUps.length > 0 && (\n\t\t\t\t\t\t\t\t<FollowUpList>\n\t\t\t\t\t\t\t\t\t{followUpsLabel && (\n\t\t\t\t\t\t\t\t\t\t<FollowUpsLabel>{followUpsLabel}</FollowUpsLabel>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t{followUps.map((followUp) => (\n\t\t\t\t\t\t\t\t\t\t<FollowUpChip\n\t\t\t\t\t\t\t\t\t\t\tkey={followUp}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={inputDisabled}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleFollowUpClick(followUp)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<ArrowRightIcon />\n\t\t\t\t\t\t\t\t\t\t\t{followUp}\n\t\t\t\t\t\t\t\t\t\t</FollowUpChip>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</FollowUpList>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{isThinking && (\n\t\t\t\t\t\t\t\t<ThinkingBubble role=\"status\" aria-live=\"polite\">\n\t\t\t\t\t\t\t\t\t<AiStarsIcon\n\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.brand}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t{thinkingLabel && (\n\t\t\t\t\t\t\t\t\t\t<ThinkingLabel>{thinkingLabel}</ThinkingLabel>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t<DotPulse color={COLORS.background.brand} size={5} />\n\t\t\t\t\t\t\t\t</ThinkingBubble>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<div ref={bottomRef} />\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</MessagesArea>\n\n\t\t\t\t<ScrollFade $visible={showScrollAffordance} aria-hidden=\"true\" />\n\t\t\t\t<JumpToLatestButton\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t$visible={showScrollAffordance}\n\t\t\t\t\tonClick={handleJumpToLatest}\n\t\t\t\t\ttabIndex={showScrollAffordance ? 0 : -1}\n\t\t\t\t\taria-label=\"Scroll to the latest message\"\n\t\t\t\t>\n\t\t\t\t\t<ArrowDownIcon width={16} height={16} />\n\t\t\t\t</JumpToLatestButton>\n\t\t\t</MessagesViewport>\n\n\t\t\t{errorMessage && <ErrorBanner role=\"alert\">{errorMessage}</ErrorBanner>}\n\n\t\t\t<InputArea>\n\t\t\t\t{attachment && (\n\t\t\t\t\t<AttachmentChip>\n\t\t\t\t\t\t<AiStarsIcon width={14} height={14} color={COLORS.content.brand} />\n\t\t\t\t\t\t<AttachmentText title={attachment}>{attachment}</AttachmentText>\n\t\t\t\t\t\t<AttachmentRemove\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={onAttachmentRemove}\n\t\t\t\t\t\t\taria-label=\"Remove the selected text\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<CrossIcon width={12} height={12} />\n\t\t\t\t\t\t</AttachmentRemove>\n\t\t\t\t\t</AttachmentChip>\n\t\t\t\t)}\n\t\t\t\t<InputWrapper $focused={isInputFocused}>\n\t\t\t\t\t<MessageInput\n\t\t\t\t\t\tref={inputRef}\n\t\t\t\t\t\trows={1}\n\t\t\t\t\t\tvalue={input}\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\tdisabled={inputDisabled}\n\t\t\t\t\t\tonChange={handleInputChange}\n\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\tonFocus={() => setIsInputFocused(true)}\n\t\t\t\t\t\tonBlur={() => setIsInputFocused(false)}\n\t\t\t\t\t/>\n\t\t\t\t\t<SendButton\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t$active={canStop || canSend}\n\t\t\t\t\t\tdisabled={!canStop && !canSend}\n\t\t\t\t\t\tonClick={canStop ? onStop : handleSend}\n\t\t\t\t\t\taria-label={canStop ? 'Stop generating' : 'Send message'}\n\t\t\t\t\t>\n\t\t\t\t\t\t{canStop ? <StopIcon /> : <SendArrowIcon />}\n\t\t\t\t\t</SendButton>\n\t\t\t\t</InputWrapper>\n\t\t\t</InputArea>\n\n\t\t\t{disclaimer && <Disclaimer>{disclaimer}</Disclaimer>}\n\t\t</PanelContainer>\n\t);\n};\n\nexport default CopilotPanel;\n"],"names":["MAX_INPUT_HEIGHT_PX","AT_BOTTOM_TOLERANCE_PX","COPIED_FEEDBACK_MS","writeToClipboard","text","textarea","copied","NEAR_TOP_TOLERANCE_PX","formatMessageTime","timestamp","date","SendArrowIcon","jsxs","jsx","ArrowRightIcon","StopIcon","size","CopyIcon","CheckIcon","RegenerateIcon","ThumbUpIcon","filled","ThumbDownIcon","CopilotPanel","messages","onSend","onClose","title","badge","subtitle","avatar","placeholder","disclaimer","emptyStateTitle","emptyStateSubtitle","suggestions","onSuggestionClick","showRefresh","onRefresh","onRegenerate","onFeedback","dislikeTitle","dislikeSubtitle","dislikeReasons","dislikeNotePlaceholder","dislikeSubmitLabel","isThinking","thinkingLabel","isStreaming","onStop","interruptedLabel","followUpsLabel","onToolCtaClick","hasMoreHistory","isLoadingHistory","onLoadOlderMessages","historyLoadingLabel","inputDisabled","attachment","onAttachmentRemove","errorMessage","width","height","className","style","input","setInput","useState","isInputFocused","setIsInputFocused","isAtLatest","setIsAtLatest","copiedMessageId","setCopiedMessageId","feedback","setFeedback","dislikePromptId","setDislikePromptId","inputRef","useRef","copiedTimeoutRef","bottomRef","scrollerRef","lastScrollTopRef","anchorFromBottomRef","visibleMessages","message","isCopilotRegeneratePrompt","isEmpty","isTurnInFlight","canSend","canStop","newestMessage","followUps","showScrollAffordance","useEffect","scroller","anchor","handleScroll","distanceFromBottom","scrolledUp","handleJumpToLatest","handleCopyMessage","handleFeedback","messageId","vote","cleared","previous","current","reportDislike","detail","handleRegenerate","handleSend","trimmed","buildCopilotSelectionPrompt","handleInputChange","event","handleKeyDown","handleSuggestionClick","suggestion","handleFollowUpClick","followUp","PanelContainer","PanelHeader","HeaderAvatar","AiStarsIcon","HeaderText","HeaderTitleRow","TitleSmall","HeaderBadge","BodyCaption","COLORS","HeaderActions","IconAction","RefreshIcon","CrossIcon","MessagesViewport","MessagesArea","EmptyState","EmptyStateIcon","BodySecondary","SuggestionList","SuggestionChip","Fragment","HistoryLoader","DotPulse","sentAt","React","MessageBubble","renderCopilotMarkdown","ctas","toolResultCtas","ToolCtaList","cta","ToolCtaLink","MessageTimestamp","InterruptedNote","MessageActions","MessageAction","CopilotFeedbackModal","FollowUpList","FollowUpsLabel","FollowUpChip","ThinkingBubble","ThinkingLabel","ScrollFade","JumpToLatestButton","ArrowDownIcon","ErrorBanner","InputArea","AttachmentChip","AttachmentText","AttachmentRemove","InputWrapper","MessageInput","SendButton","Disclaimer"],"mappings":"quBAuDMA,GAAsB,GAGtBC,GAAyB,GAGzBC,GAAqB,KASrBC,GAAmB,MAAOC,GAAmC,CAClE,GAAI,CACH,GAAI,UAAU,WAAW,UACxB,aAAM,UAAU,UAAU,UAAUA,CAAI,EACjC,EAET,MAAQ,CAER,CAEA,GAAI,CACH,MAAMC,EAAW,SAAS,cAAc,UAAU,EAClDA,EAAS,MAAQD,EAEjBC,EAAS,aAAa,WAAY,EAAE,EACpCA,EAAS,MAAM,SAAW,QAC1BA,EAAS,MAAM,IAAM,UACrBA,EAAS,MAAM,QAAU,IACzB,SAAS,KAAK,YAAYA,CAAQ,EAClCA,EAAS,OAAA,EACT,MAAMC,EAAS,SAAS,YAAY,MAAM,EAC1C,gBAAS,KAAK,YAAYD,CAAQ,EAC3BC,CACR,MAAQ,CACP,MAAO,EACR,CACD,EAGMC,GAAwB,GAExBC,GAAqBC,GAA8B,CACxD,GAAI,CAACA,GAAa,CAAC,OAAO,SAASA,CAAS,EAC3C,MAAO,GAER,MAAMC,EAAO,IAAI,KAAKD,CAAS,EAC/B,OAAI,OAAO,MAAMC,EAAK,QAAA,CAAS,EACvB,GAEDA,EAAK,mBAAmB,QAAS,CACvC,KAAM,UACN,OAAQ,SAAA,CACR,CACF,EAEMC,GAAgB,IACrBC,EAAAA,KAAC,MAAA,CACA,QAAQ,YACR,MAAM,KACN,OAAO,KACP,KAAK,OACL,OAAO,eACP,YAAY,IACZ,cAAc,QACd,eAAe,QACf,cAAY,OAEZ,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,EAAE,UAAA,CAAW,EACnBA,EAAAA,IAAC,OAAA,CAAK,EAAE,eAAA,CAAgB,CAAA,CAAA,CACzB,EAGKC,GAAiB,IACtBF,EAAAA,KAAC,MAAA,CACA,QAAQ,YACR,MAAM,KACN,OAAO,KACP,KAAK,OACL,OAAO,eACP,YAAY,IACZ,cAAc,QACd,eAAe,QACf,cAAY,OAEZ,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,EAAE,UAAA,CAAW,EACnBA,EAAAA,IAAC,OAAA,CAAK,EAAE,eAAA,CAAgB,CAAA,CAAA,CACzB,EAGKE,GAAW,CAAC,CAAE,KAAAC,EAAO,MAC1BH,EAAAA,IAAC,MAAA,CACA,QAAQ,YACR,MAAOG,EACP,OAAQA,EACR,KAAK,eACL,cAAY,OAEZ,SAAAH,EAAAA,IAAC,OAAA,CAAK,EAAE,IAAI,EAAE,IAAI,MAAM,KAAK,OAAO,KAAK,GAAG,GAAA,CAAI,CAAA,CACjD,EAGKI,GAAW,IAChBL,EAAAA,KAAC,MAAA,CACA,QAAQ,YACR,MAAM,KACN,OAAO,KACP,KAAK,OACL,OAAO,eACP,YAAY,MACZ,cAAc,QACd,eAAe,QACf,cAAY,OAEZ,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,EAAE,IAAI,EAAE,IAAI,MAAM,KAAK,OAAO,KAAK,GAAG,GAAA,CAAI,EAChDA,EAAAA,IAAC,OAAA,CAAK,EAAE,6EAAA,CAA8E,CAAA,CAAA,CACvF,EAGKK,GAAY,IACjBL,EAAAA,IAAC,MAAA,CACA,QAAQ,YACR,MAAM,KACN,OAAO,KACP,KAAK,OACL,OAAO,eACP,YAAY,MACZ,cAAc,QACd,eAAe,QACf,cAAY,OAEZ,SAAAA,EAAAA,IAAC,OAAA,CAAK,EAAE,gBAAA,CAAiB,CAAA,CAC1B,EAGKM,GAAiB,IACtBP,EAAAA,KAAC,MAAA,CACA,QAAQ,YACR,MAAM,KACN,OAAO,KACP,KAAK,OACL,OAAO,eACP,YAAY,MACZ,cAAc,QACd,eAAe,QACf,cAAY,OAEZ,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,EAAE,4BAAA,CAA6B,EACrCA,EAAAA,IAAC,OAAA,CAAK,EAAE,YAAA,CAAa,CAAA,CAAA,CACtB,EAGKO,GAAc,CAAC,CAAE,OAAAC,EAAS,MAC/BT,EAAAA,KAAC,MAAA,CACA,QAAQ,YACR,MAAM,KACN,OAAO,KACP,KAAMS,EAAS,eAAiB,OAChC,OAAO,eACP,YAAY,MACZ,cAAc,QACd,eAAe,QACf,cAAY,OAEZ,SAAA,CAAAR,EAAAA,IAAC,OAAA,CAAK,EAAE,8CAAA,CAA+C,EACvDA,EAAAA,IAAC,OAAA,CAAK,EAAE,kFAAA,CAAmF,CAAA,CAAA,CAC5F,EAGKS,GAAgB,CAAC,CAAE,OAAAD,EAAS,MACjCT,EAAAA,KAAC,MAAA,CACA,QAAQ,YACR,MAAM,KACN,OAAO,KACP,KAAMS,EAAS,eAAiB,OAChC,OAAO,eACP,YAAY,MACZ,cAAc,QACd,eAAe,QACf,cAAY,OAEZ,SAAA,CAAAR,EAAAA,IAAC,OAAA,CAAK,EAAE,4CAAA,CAA6C,EACrDA,EAAAA,IAAC,OAAA,CAAK,EAAE,kFAAA,CAAmF,CAAA,CAAA,CAC5F,EAQYU,GAA4C,CAAC,CACzD,SAAAC,EACA,OAAAC,EACA,QAAAC,EACA,MAAAC,EAAQ,UACR,MAAAC,EACA,SAAAC,EACA,OAAAC,GACA,YAAAC,GAAc,wBACd,WAAAC,EAAa,8CACb,gBAAAC,GACA,mBAAAC,EAAqB,mCACrB,YAAAC,EACA,kBAAAC,GACA,YAAAC,GAAc,GACd,UAAAC,EACA,aAAAC,EACA,WAAAC,EACA,aAAAC,GACA,gBAAAC,GACA,eAAAC,GACA,uBAAAC,GACA,mBAAAC,GACA,WAAAC,EAAa,GACb,cAAAC,EAAgB,WAChB,YAAAC,GAAc,GACd,OAAAC,EACA,iBAAAC,EAAmB,+BACnB,eAAAC,EAAiB,aACjB,eAAAC,GACA,eAAAC,GAAiB,GACjB,iBAAAC,EAAmB,GACnB,oBAAAC,EACA,oBAAAC,GAAsB,2BACtB,cAAAC,EAAgB,GAChB,WAAAC,EACA,mBAAAC,EACA,aAAAC,EACA,MAAAC,GACA,OAAAC,GACA,UAAAC,GACA,MAAAC,EACD,IAAM,CACL,KAAM,CAACC,EAAOC,CAAQ,EAAIC,EAAAA,SAAS,EAAE,EAC/B,CAACC,GAAgBC,CAAiB,EAAIF,EAAAA,SAAS,EAAK,EACpD,CAACG,EAAYC,CAAa,EAAIJ,EAAAA,SAAS,EAAI,EAG3C,CAACK,EAAiBC,EAAkB,EAAIN,EAAAA,SAAwB,IAAI,EAEpE,CAACO,EAAUC,EAAW,EAAIR,EAAAA,SAE9B,CAAA,CAAE,EAIE,CAACS,EAAiBC,CAAkB,EAAIV,EAAAA,SAAwB,IAAI,EACpEW,EAAWC,EAAAA,OAA4B,IAAI,EAC3CC,EAAmBD,EAAAA,OAAsB,IAAI,EAC7CE,EAAYF,EAAAA,OAAuB,IAAI,EACvCG,EAAcH,EAAAA,OAAuB,IAAI,EACzCI,EAAmBJ,EAAAA,OAAO,CAAC,EAI3BK,EAAsBL,EAAAA,OAAsB,IAAI,EAMhDM,EAAkB7D,EAAS,OAC/B8D,IACCA,EAAQ,QAAQ,OAAS,GAAKA,EAAQ,iBACvC,CAACC,GAAAA,0BAA0BD,EAAQ,OAAO,CAAA,EAEtCE,GAAUH,EAAgB,SAAW,GAAK,CAACvC,EAC3C2C,EAAiB3C,GAAcE,GAC/B0C,GACL,CAACjC,GACD,CAACgC,IACAxB,EAAM,KAAA,EAAO,OAAS,GAAK,EAAQP,GAG/BiC,EAAUF,GAAkB,EAAQxC,EAGpC2C,EAAgBP,EAAgBA,EAAgB,OAAS,CAAC,EAC1DQ,EACL,CAACJ,GAAkBG,GAAe,OAAS,YACxCA,EAAc,UACd,OAGEE,EAAuB,CAACN,IAAW,CAAClB,EAI1CyB,EAAAA,UAAU,IAAM,CACVzB,GAGLW,EAAU,SAAS,eAAe,CAAE,SAAU,SAAU,CACzD,EAAG,CAACzD,EAAUsB,EAAYwB,CAAU,CAAC,EAIrCyB,EAAAA,UAAU,IAAM,CACf,MAAMC,EAAWd,EAAY,QACvBe,EAASb,EAAoB,QAC/B,CAACY,GAAYC,IAAW,MAAQ3C,IAGpC8B,EAAoB,QAAU,KAC9BY,EAAS,UAAYA,EAAS,aAAeC,EAC7Cd,EAAiB,QAAUa,EAAS,UACrC,EAAG,CAACxE,EAAU8B,CAAgB,CAAC,EAE/B,MAAM4C,GAAe,IAAM,CAC1B,MAAMF,EAAWd,EAAY,QAC7B,GAAI,CAACc,EACJ,OAED,MAAMG,EACLH,EAAS,aAAeA,EAAS,UAAYA,EAAS,aAMtDA,EAAS,WAAazF,IACtB8C,IACA,CAACC,GACDC,IAEA6B,EAAoB,QAAUY,EAAS,aAAeA,EAAS,UAC/DzC,EAAA,GAKD,MAAM6C,EAAaJ,EAAS,UAAYb,EAAiB,QAAU,EAGnE,GAFAA,EAAiB,QAAUa,EAAS,UAEhCG,GAAsBlG,GAAwB,CACjDsE,EAAc,EAAI,EAClB,MACD,CACI6B,GACH7B,EAAc,EAAK,CAErB,EAEM8B,GAAqB,IAAM,CAChC9B,EAAc,EAAI,EAClBU,EAAU,SAAS,eAAe,CAAE,SAAU,SAAU,CACzD,EAEAc,EAAAA,UACC,IAAM,IAAM,CACPf,EAAiB,SACpB,OAAO,aAAaA,EAAiB,OAAO,CAE9C,EACA,CAAA,CAAC,EAGF,MAAMsB,GAAoB,MACzBhB,GACI,CAGW,MAAMnF,GAAiBmF,EAAQ,OAAO,IAIjDN,EAAiB,SACpB,OAAO,aAAaA,EAAiB,OAAO,EAE7CP,GAAmBa,EAAQ,EAAE,EAC7BN,EAAiB,QAAU,OAAO,WACjC,IAAMP,GAAmB,IAAI,EAC7BvE,EAAA,EAEF,EAEMqG,GAAiB,CAACC,EAAmBC,IAA6B,CAGvE,MAAMC,EAAUhC,EAAS8B,CAAS,IAAMC,EAOxC,GANA9B,GAAagC,IAAc,CAC1B,GAAGA,EACH,CAACH,CAAS,EAAGG,EAASH,CAAS,IAAMC,EAAO,OAAYA,CAAA,EACvD,EAGEC,EAAS,CACRD,IAAS,WACZ5B,EAAoB+B,GACnBA,IAAYJ,EAAY,KAAOI,CAAA,EAGjC,MACD,CACA,GAAIH,IAAS,OAAQ,CACpBjE,IAAagE,EAAW,MAAM,EAC9B,MACD,CAGI5B,GAAmBA,IAAoB4B,GAC1ChE,IAAaoC,EAAiB,SAAS,EAExCC,EAAmB2B,CAAS,CAC7B,EAEMK,GAAgB,CAACL,EAAmBM,IAAmC,CAC5EjC,EAAoB+B,GAAaA,IAAYJ,EAAY,KAAOI,CAAQ,EACxEpE,IAAagE,EAAW,UAAWM,CAAM,CAC1C,EAEMC,GAAmB,IAAM,CAC1BtD,GAAiBgC,GAGrBlD,IAAA,CACD,EAEMyE,GAAa,IAAM,CACxB,MAAMC,EAAUhD,EAAM,KAAA,EACtB,GAAK,CAACgD,GAAW,CAACvD,GAAeD,GAAiBgC,EACjD,OAIDhE,EACCiC,EAAawD,GAAAA,4BAA4BxD,EAAYuD,CAAO,EAAIA,CAAA,EAEjE/C,EAAS,EAAE,EAGXP,IAAA,EACA,MAAMtD,EAAWyE,EAAS,QACtBzE,IACHA,EAAS,MAAM,OAAS,OAE1B,EAIA0F,EAAAA,UAAU,IAAM,CACXrC,GACHoB,EAAS,SAAS,MAAA,CAEpB,EAAG,CAACpB,CAAU,CAAC,EAEf,MAAMyD,GAAqBC,GAAkD,CAC5ElD,EAASkD,EAAM,OAAO,KAAK,EAC3B,MAAM/G,EAAW+G,EAAM,OACvB/G,EAAS,MAAM,OAAS,OACxBA,EAAS,MAAM,OAAS,GAAG,KAAK,IAC/BA,EAAS,aACTL,EAAA,CACA,IACF,EAEMqH,GAAiBD,GAAoD,CACtEA,EAAM,MAAQ,SAAW,CAACA,EAAM,WACnCA,EAAM,eAAA,EACNJ,GAAA,EAEF,EAEMM,GACLC,GACI,CACA9D,GAAiBgC,IAGrBrD,KAAoBmF,CAAU,EAC9B9F,EAAO8F,EAAW,IAAI,EACvB,EAEMC,GAAuBC,GAAqB,CAC7ChE,GAAiBgC,GAGrBhE,EAAOgG,CAAQ,CAChB,EAEA,OACC7G,EAAAA,KAAC8G,EAAAA,eAAA,CACA,UAAA3D,GACA,MAAO,CAAE,MAAAF,GAAO,OAAAC,GAAQ,GAAGE,EAAA,EAC3B,KAAK,SACL,aAAYrC,EAEZ,SAAA,CAAAf,OAAC+G,EAAAA,YAAA,CACA,SAAA,CAAA9G,EAAAA,IAAC+G,EAAAA,aAAA,CACC,aAAU/G,EAAAA,IAACgH,EAAAA,QAAA,CAAY,MAAO,GAAI,OAAQ,GAAI,CAAA,CAChD,SACCC,EAAAA,WAAA,CACA,SAAA,CAAAlH,OAACmH,EAAAA,eAAA,CACA,SAAA,CAAAlH,EAAAA,IAACmH,EAAAA,YAAY,SAAArG,CAAA,CAAM,EAClBC,GAASf,EAAAA,IAACoH,EAAAA,YAAA,CAAa,SAAArG,CAAA,CAAM,CAAA,EAC/B,EACCC,GACAhB,EAAAA,IAACqH,EAAAA,YAAA,CAAY,MAAOC,EAAAA,OAAO,QAAQ,UACjC,SAAAtG,CAAA,CACF,CAAA,EAEF,SACCuG,EAAAA,cAAA,CACC,SAAA,CAAA/F,IAAeC,GACfzB,EAAAA,IAACwH,EAAAA,WAAA,CACA,KAAK,SACL,QAAS/F,EACT,aAAW,2BAEX,SAAAzB,EAAAA,IAACyH,WAAA,CAAY,MAAO,GAAI,OAAQ,EAAA,CAAI,CAAA,CAAA,EAGtCzH,EAAAA,IAACwH,EAAAA,WAAA,CACA,KAAK,SACL,QAAS3G,EACT,aAAW,gBAEX,SAAAb,EAAAA,IAAC0H,WAAA,CAAU,MAAO,GAAI,OAAQ,EAAA,CAAI,CAAA,CAAA,CACnC,CAAA,CACD,CAAA,EACD,SAECC,EAAAA,iBAAA,CACA,SAAA,CAAA3H,EAAAA,IAAC4H,EAAAA,aAAA,CACA,IAAKvD,EACL,SAAUgB,GACV,KAAK,SACL,aAAW,eAEV,SAAAV,UACCkD,EAAAA,WAAA,CACA,SAAA,CAAA7H,EAAAA,IAAC8H,EAAAA,gBACA,SAAA9H,EAAAA,IAACgH,EAAAA,QAAA,CAAY,MAAO,GAAI,OAAQ,GAAI,CAAA,CACrC,EACAhH,MAAC+H,EAAAA,eAAc,MAAO,CAAE,WAAY,GAAA,EAClC,aAAmBjH,EACrB,EACCO,GACArB,EAAAA,IAACqH,EAAAA,YAAA,CAAY,MAAOC,SAAO,QAAQ,UACjC,SAAAjG,EACF,EAEAC,GAAeA,EAAY,OAAS,SACnC0G,EAAAA,eAAA,CACC,SAAA1G,EAAY,IAAKoF,GACjB3G,EAAAA,KAACkI,EAAAA,eAAA,CAEA,KAAK,SACL,SAAUrF,GAAiBgC,EAC3B,QAAS,IAAM6B,GAAsBC,CAAU,EAE/C,SAAA,CAAA1G,EAAAA,IAACgH,EAAAA,QAAA,CAAY,MAAO,GAAI,OAAQ,GAAI,EACnCN,EAAW,IAAA,CAAA,EANPA,EAAW,EAAA,CAQjB,CAAA,CACF,CAAA,CAAA,CAEF,EAEA3G,EAAAA,KAAAmI,EAAAA,SAAA,CACE,SAAA,CAAAzF,GACA1C,EAAAA,KAACoI,EAAAA,cAAA,CAAc,KAAK,SAAS,YAAU,SACtC,SAAA,CAAAnI,MAACoI,GAAAA,UAAS,MAAOd,EAAAA,OAAO,QAAQ,YAAa,KAAM,EAAG,EACrD3E,EAAA,EACF,EAEA6B,EAAgB,IAAKC,GAAY,CACjC,MAAM4D,EACL5D,EAAQ,OAAS,OACd9E,GAAkB8E,EAAQ,SAAS,EACnC,GACJ,OACC1E,OAACuI,GAAAA,QAAM,SAAN,CACC,SAAA,CAAA7D,EAAQ,QAAQ,OAAS,GACzBzE,EAAAA,IAACuI,EAAAA,cAAA,CAAc,MAAO9D,EAAQ,KAC5B,SAAAA,EAAQ,OAAS,YACjBzE,EAAAA,IAAC,MAAA,CACA,wBAAyB,CACxB,OAAQwI,GAAAA,sBAAsB/D,EAAQ,OAAO,CAAA,CAC9C,CAAA,EAGDzE,MAAC,MAAA,CAAI,MAAO,CAAE,WAAY,UAAA,EACxB,SAAAyE,EAAQ,OAAA,CACV,CAAA,CAEF,EAIAA,EAAQ,OAAS,aACjB,CAACA,EAAQ,cACR,IAAM,CACN,MAAMgE,EAAOC,GAAAA,eAAejE,EAAQ,WAAW,EAC/C,OAAIgE,EAAK,SAAW,EACZ,KAGPzI,EAAAA,IAAC2I,EAAAA,YAAA,CACC,SAAAF,EAAK,IAAKG,GACV5I,EAAAA,IAAC6I,EAAAA,YAAA,CAEA,KAAMD,EAAI,IACV,OAAO,SACP,IAAI,sBACJ,QAAS,IACRrG,KAAiB,CAChB,KAAMqG,EAAI,KACV,IAAKA,EAAI,GAAA,CACT,EAGD,SAAAA,EAAI,KAAA,EAXA,GAAGA,EAAI,IAAI,IAAIA,EAAI,GAAG,EAAA,CAa5B,EACF,CAEF,GAAA,EACAP,GAAUrI,EAAAA,IAAC8I,EAAAA,iBAAA,CAAkB,SAAAT,CAAA,CAAO,EACpC5D,EAAQ,gBAAkBpC,GAC1BtC,EAAAA,KAACgJ,EAAAA,gBAAA,CACA,SAAA,CAAA/I,EAAAA,IAACE,GAAA,CAAS,KAAM,EAAA,CAAI,EACnBmC,CAAA,EACF,EAIAoC,EAAQ,OAAS,aACjBA,EAAQ,QAAQ,OAAS,GACzB,CAACA,EAAQ,aACR1E,EAAAA,KAACiJ,EAAAA,eAAA,CACA,SAAA,CAAAhJ,EAAAA,IAACiJ,EAAAA,cAAA,CACA,KAAK,SACL,QAAS,IAAA,CAAWxD,GAAkBhB,CAAO,GAC7C,cAAad,IAAoBc,EAAQ,GACzC,MACCd,IAAoBc,EAAQ,GAAK,SAAW,OAE7C,aACCd,IAAoBc,EAAQ,GACzB,+BACA,gBAGH,aAAoBA,EAAQ,SAC3BpE,GAAA,EAAU,QAEVD,GAAA,CAAA,CAAS,CAAA,CAAA,EAMXsB,GAAgB+C,EAAQ,KAAOM,GAAe,IAC9C/E,EAAAA,IAACiJ,EAAAA,cAAA,CACA,KAAK,SACL,QAAS/C,GACT,SAAUtD,GAAiBgC,EAC3B,MAAM,aACN,aAAW,sBAEX,eAACtE,GAAA,CAAA,CAAe,CAAA,CAAA,EAGlBN,EAAAA,IAACiJ,EAAAA,cAAA,CACA,KAAK,SACL,QAAS,IAAMvD,GAAejB,EAAQ,GAAI,MAAM,EAChD,gBAAeZ,EAASY,EAAQ,EAAE,IAAM,OACxC,eAAcZ,EAASY,EAAQ,EAAE,IAAM,OACvC,MAAM,gBACN,aAAW,gBAEX,SAAAzE,EAAAA,IAACO,GAAA,CACA,OAAQsD,EAASY,EAAQ,EAAE,IAAM,MAAA,CAAA,CAClC,CAAA,EAEDzE,EAAAA,IAACiJ,EAAAA,cAAA,CACA,KAAK,SACL,QAAS,IACRvD,GAAejB,EAAQ,GAAI,SAAS,EAErC,gBAAeZ,EAASY,EAAQ,EAAE,IAAM,UACxC,eAAcZ,EAASY,EAAQ,EAAE,IAAM,UACvC,MAAM,eACN,aAAW,eAEX,SAAAzE,EAAAA,IAACS,GAAA,CACA,OAAQoD,EAASY,EAAQ,EAAE,IAAM,SAAA,CAAA,CAClC,CAAA,CACD,EACD,EAEDV,IAAoBU,EAAQ,IAC5BzE,EAAAA,IAACkJ,GAAAA,qBAAA,CACA,MAAOtH,GACP,SAAUC,IAAmB,mBAAmBf,CAAK,GACrD,QAASgB,GACT,gBAAiBC,GACjB,YAAaC,GACb,SAAWiE,GAAWD,GAAcvB,EAAQ,GAAIwB,CAAM,EACtD,UAAW,IAAMD,GAAcvB,EAAQ,EAAE,CAAA,CAAA,CAC1C,CAAA,EAjImBA,EAAQ,EAmI7B,CAEF,CAAC,EACAO,GAAaA,EAAU,OAAS,UAC/BmE,EAAAA,aAAA,CACC,SAAA,CAAA7G,GACAtC,EAAAA,IAACoJ,EAAAA,gBAAgB,SAAA9G,CAAA,CAAe,EAEhC0C,EAAU,IAAK4B,GACf7G,EAAAA,KAACsJ,EAAAA,aAAA,CAEA,KAAK,SACL,SAAUzG,EACV,QAAS,IAAM+D,GAAoBC,CAAQ,EAE3C,SAAA,CAAA5G,EAAAA,IAACC,GAAA,EAAe,EACf2G,CAAA,CAAA,EANIA,CAAA,CAQN,CAAA,EACF,EAEA3E,GACAlC,EAAAA,KAACuJ,EAAAA,eAAA,CAAe,KAAK,SAAS,YAAU,SACvC,SAAA,CAAAtJ,EAAAA,IAACgH,EAAAA,QAAA,CACA,MAAO,GACP,OAAQ,GACR,MAAOM,EAAAA,OAAO,QAAQ,KAAA,CAAA,EAEtBpF,GACAlC,EAAAA,IAACuJ,EAAAA,cAAA,CAAe,SAAArH,CAAA,CAAc,QAE9BkG,GAAAA,SAAA,CAAS,MAAOd,EAAAA,OAAO,WAAW,MAAO,KAAM,CAAA,CAAG,CAAA,EACpD,EAEDtH,EAAAA,IAAC,MAAA,CAAI,IAAKoE,CAAA,CAAW,CAAA,CAAA,CACtB,CAAA,CAAA,EAIFpE,EAAAA,IAACwJ,EAAAA,WAAA,CAAW,SAAUvE,EAAsB,cAAY,OAAO,EAC/DjF,EAAAA,IAACyJ,EAAAA,mBAAA,CACA,KAAK,SACL,SAAUxE,EACV,QAASO,GACT,SAAUP,EAAuB,EAAI,GACrC,aAAW,+BAEX,SAAAjF,EAAAA,IAAC0J,WAAA,CAAc,MAAO,GAAI,OAAQ,EAAA,CAAI,CAAA,CAAA,CACvC,EACD,EAEC3G,GAAgB/C,EAAAA,IAAC2J,cAAA,CAAY,KAAK,QAAS,SAAA5G,EAAa,SAExD6G,EAAAA,UAAA,CACC,SAAA,CAAA/G,UACCgH,iBAAA,CACA,SAAA,CAAA7J,EAAAA,IAACgH,EAAAA,QAAA,CAAY,MAAO,GAAI,OAAQ,GAAI,MAAOM,EAAAA,OAAO,QAAQ,KAAA,CAAO,EACjEtH,EAAAA,IAAC8J,EAAAA,eAAA,CAAe,MAAOjH,EAAa,SAAAA,EAAW,EAC/C7C,EAAAA,IAAC+J,EAAAA,iBAAA,CACA,KAAK,SACL,QAASjH,EACT,aAAW,2BAEX,SAAA9C,EAAAA,IAAC0H,WAAA,CAAU,MAAO,GAAI,OAAQ,EAAA,CAAI,CAAA,CAAA,CACnC,EACD,EAED3H,EAAAA,KAACiK,EAAAA,aAAA,CAAa,SAAUzG,GACvB,SAAA,CAAAvD,EAAAA,IAACiK,EAAAA,aAAA,CACA,IAAKhG,EACL,KAAM,EACN,MAAOb,EACP,YAAAlC,GACA,SAAU0B,EACV,SAAU0D,GACV,UAAWE,GACX,QAAS,IAAMhD,EAAkB,EAAI,EACrC,OAAQ,IAAMA,EAAkB,EAAK,CAAA,CAAA,EAEtCxD,EAAAA,IAACkK,EAAAA,WAAA,CACA,KAAK,SACL,QAASpF,GAAWD,GACpB,SAAU,CAACC,GAAW,CAACD,GACvB,QAASC,EAAU1C,EAAS+D,GAC5B,aAAYrB,EAAU,kBAAoB,eAEzC,SAAAA,EAAU9E,MAACE,GAAA,CAAA,CAAS,QAAMJ,GAAA,CAAA,CAAc,CAAA,CAAA,CAC1C,CAAA,CACD,CAAA,EACD,EAECqB,GAAcnB,EAAAA,IAACmK,EAAAA,WAAA,CAAY,SAAAhJ,CAAA,CAAW,CAAA,CAAA,CAAA,CAG1C"}
1
+ {"version":3,"file":"CopilotPanel.js","sources":["../../../../src/components/bik-copilot/CopilotPanel.tsx"],"sourcesContent":["import ArrowDownIcon from '@src/assets/icons/arrow_down.svg';\nimport AiStarsIcon from '@src/assets/icons/bik_ai_stars_icon.svg';\nimport CrossIcon from '@src/assets/icons/cross.svg';\nimport RefreshIcon from '@src/assets/icons/refresh.svg';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { COLORS } from '@src/constants/Theme';\nimport { DotPulse } from '../dot-pulse';\nimport { BodyCaption, BodySecondary, TitleSmall } from '../TypographyStyle';\nimport { CopilotFeedbackModal } from './CopilotFeedbackModal';\nimport {\n\tAttachmentChip,\n\tAttachmentRemove,\n\tAttachmentText,\n\tDisclaimer,\n\tEmptyState,\n\tEmptyStateIcon,\n\tErrorBanner,\n\tFollowUpChip,\n\tFollowUpList,\n\tFollowUpsLabel,\n\tHeaderActions,\n\tHeaderAvatar,\n\tHeaderBadge,\n\tHeaderText,\n\tHeaderTitleRow,\n\tHistoryLoader,\n\tIconAction,\n\tInputArea,\n\tInputWrapper,\n\tInterruptedNote,\n\tJumpToLatestButton,\n\tMessageAction,\n\tMessageActions,\n\tMessageBubble,\n\tMessageInput,\n\tMessagesArea,\n\tMessagesViewport,\n\tMessageTimestamp,\n\tPanelContainer,\n\tPanelHeader,\n\tScrollFade,\n\tSendButton,\n\tSuggestionChip,\n\tSuggestionList,\n\tThinkingBubble,\n\tThinkingLabel,\n\tToolCtaLink,\n\tToolCtaList,\n} from './CopilotPanel.styled';\nimport { isCopilotRegeneratePrompt } from './copilotRegenerate';\nimport { buildCopilotSelectionPrompt } from './copilotSelectionPrompt';\nimport { CopilotFeedbackDetail, CopilotPanelProps } from './model';\nimport { renderCopilotMarkdown } from './utils/markdown';\nimport { toolResultCtas } from './utils/toolCtas';\n\nconst MAX_INPUT_HEIGHT_PX = 96;\n\n/** Slack at the bottom of the scroller that still counts as \"at the latest\". */\nconst AT_BOTTOM_TOLERANCE_PX = 24;\n\n/** How long the copy button shows its confirmation before reverting. */\nconst COPIED_FEEDBACK_MS = 1800;\n\n/**\n * Writes text to the clipboard.\n *\n * `navigator.clipboard` is missing outside a secure context and can reject when\n * the document is not focused, so a hidden-textarea `execCommand` fallback keeps\n * the button working there rather than failing silently.\n */\nconst writeToClipboard = async (text: string): Promise<boolean> => {\n\ttry {\n\t\tif (navigator.clipboard?.writeText) {\n\t\t\tawait navigator.clipboard.writeText(text);\n\t\t\treturn true;\n\t\t}\n\t} catch {\n\t\t// Fall through to the legacy path.\n\t}\n\n\ttry {\n\t\tconst textarea = document.createElement('textarea');\n\t\ttextarea.value = text;\n\t\t// Off-screen rather than hidden: `display: none` cannot be selected.\n\t\ttextarea.setAttribute('readonly', '');\n\t\ttextarea.style.position = 'fixed';\n\t\ttextarea.style.top = '-1000px';\n\t\ttextarea.style.opacity = '0';\n\t\tdocument.body.appendChild(textarea);\n\t\ttextarea.select();\n\t\tconst copied = document.execCommand('copy');\n\t\tdocument.body.removeChild(textarea);\n\t\treturn copied;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\n/** How close to the top counts as asking for the previous page. */\nconst NEAR_TOP_TOLERANCE_PX = 48;\n\nconst formatMessageTime = (timestamp: number): string => {\n\tif (!timestamp || !Number.isFinite(timestamp)) {\n\t\treturn '';\n\t}\n\tconst date = new Date(timestamp);\n\tif (Number.isNaN(date.getTime())) {\n\t\treturn '';\n\t}\n\treturn date.toLocaleTimeString('en-US', {\n\t\thour: 'numeric',\n\t\tminute: '2-digit',\n\t});\n};\n\nconst SendArrowIcon = () => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"16\"\n\t\theight=\"16\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M12 19V5\" />\n\t\t<path d=\"M6 11l6-6 6 6\" />\n\t</svg>\n);\n\nconst ArrowRightIcon = () => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M5 12h14\" />\n\t\t<path d=\"M13 6l6 6-6 6\" />\n\t</svg>\n);\n\nconst StopIcon = ({ size = 16 }: { size?: number }) => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth={size}\n\t\theight={size}\n\t\tfill=\"currentColor\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<rect x=\"7\" y=\"7\" width=\"10\" height=\"10\" rx=\"2\" />\n\t</svg>\n);\n\nconst CopyIcon = () => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"1.8\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<rect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"2\" />\n\t\t<path d=\"M15 5.5A1.5 1.5 0 0 0 13.5 4H5.5A1.5 1.5 0 0 0 4 5.5v8A1.5 1.5 0 0 0 5.5 15\" />\n\t</svg>\n);\n\nconst CheckIcon = () => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2.2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M5 13l4 4L19 7\" />\n\t</svg>\n);\n\nconst RegenerateIcon = () => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"1.8\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M20 12a8 8 0 1 1-2.34-5.66\" />\n\t\t<path d=\"M20 4v4h-4\" />\n\t</svg>\n);\n\nconst ThumbUpIcon = ({ filled = false }: { filled?: boolean }) => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill={filled ? 'currentColor' : 'none'}\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"1.8\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M7 10v11H4a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h3Z\" />\n\t\t<path d=\"M7 10l4.5-7a2 2 0 0 1 3.7 1.3L14.5 9H19a2 2 0 0 1 2 2.3l-1.1 7A2 2 0 0 1 18 20H7\" />\n\t</svg>\n);\n\nconst ThumbDownIcon = ({ filled = false }: { filled?: boolean }) => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill={filled ? 'currentColor' : 'none'}\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"1.8\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M7 14V3H4a1 1 0 0 0-1 1v9a1 1 0 0 0 1 1h3Z\" />\n\t\t<path d=\"M7 14l4.5 7a2 2 0 0 0 3.7-1.3L14.5 15H19a2 2 0 0 0 2-2.3l-1.1-7A2 2 0 0 0 18 4H7\" />\n\t</svg>\n);\n\n/**\n * Chat panel used by the copilot. Fully presentational: it renders the\n * transcript it is given and reports user intent through callbacks, so it works\n * against any backend.\n */\nexport const CopilotPanel: React.FC<CopilotPanelProps> = ({\n\tmessages,\n\tonSend,\n\tonClose,\n\ttitle = 'Copilot',\n\tbadge,\n\tsubtitle,\n\tavatar,\n\tplaceholder = 'Write your message...',\n\tdisclaimer = 'AI can make mistakes, Verify the responses.',\n\temptyStateTitle,\n\temptyStateSubtitle = 'Here are some things you can try',\n\tsuggestions,\n\tonSuggestionClick,\n\tshowRefresh = true,\n\tonRefresh,\n\tonRegenerate,\n\tonFeedback,\n\tdislikeTitle,\n\tdislikeSubtitle,\n\tdislikeReasons,\n\tdislikeNotePlaceholder,\n\tdislikeSubmitLabel,\n\tisThinking = false,\n\tthinkingLabel = 'Thinking',\n\tisStreaming = false,\n\tonStop,\n\tinterruptedLabel = 'This message was interrupted',\n\tfollowUpsLabel = 'Follow ups',\n\tonToolCtaClick,\n\thasMoreHistory = false,\n\tisLoadingHistory = false,\n\tonLoadOlderMessages,\n\thistoryLoadingLabel = 'Loading earlier messages',\n\tinputDisabled = false,\n\tattachment,\n\tonAttachmentRemove,\n\terrorMessage,\n\twidth,\n\theight,\n\tclassName,\n\tstyle,\n}) => {\n\tconst [input, setInput] = useState('');\n\tconst [isInputFocused, setIsInputFocused] = useState(false);\n\tconst [isAtLatest, setIsAtLatest] = useState(true);\n\t// Which reply is showing \"Copied\" — per message, so copying one does not tick\n\t// the button under another.\n\tconst [copiedMessageId, setCopiedMessageId] = useState<string | null>(null);\n\n\tconst [feedback, setFeedback] = useState<\n\t\tRecord<string, 'like' | 'dislike' | undefined>\n\t>({});\n\t// Which reply is being asked about. A thumbs-down opens the prompt and the\n\t// rating is reported once it is answered or dismissed -- so pressing the\n\t// thumb is never lost, and one thumb never becomes two ratings.\n\tconst [dislikePromptId, setDislikePromptId] = useState<string | null>(null);\n\tconst inputRef = useRef<HTMLTextAreaElement>(null);\n\tconst wasTurnInFlightRef = useRef(false);\n\tconst copiedTimeoutRef = useRef<number | null>(null);\n\tconst bottomRef = useRef<HTMLDivElement>(null);\n\tconst scrollerRef = useRef<HTMLDivElement>(null);\n\tconst lastScrollTopRef = useRef(0);\n\t// Distance from the bottom at the moment an older page was asked for. Older\n\t// messages land *above* the viewport, so without restoring against this the\n\t// content under the reader jumps down by the height of what arrived.\n\tconst anchorFromBottomRef = useRef<number | null>(null);\n\n\t// An assistant bubble is pushed the moment a turn starts, before any text has\n\t// arrived; the thinking indicator stands in for it until then, so rendering it\n\t// too would show an empty balloon next to the dots. A turn stopped before its\n\t// first token keeps its place, carrying only the interrupted note.\n\tconst visibleMessages = messages.filter(\n\t\t(message) =>\n\t\t\t(message.content.length > 0 || message.wasInterrupted) &&\n\t\t\t!isCopilotRegeneratePrompt(message.content),\n\t);\n\tconst isEmpty = visibleMessages.length === 0 && !isThinking;\n\tconst isTurnInFlight = isThinking || isStreaming;\n\tconst canSend =\n\t\t!inputDisabled &&\n\t\t!isTurnInFlight &&\n\t\t(input.trim().length > 0 || Boolean(attachment));\n\t// Stopping is the only thing the button can do mid-answer, so it becomes the\n\t// stop button rather than sitting there disabled.\n\tconst canStop = isTurnInFlight && Boolean(onStop);\n\t// Only the newest reply's suggestions are on offer — older ones answer a\n\t// question the conversation has already moved past.\n\tconst newestMessage = visibleMessages[visibleMessages.length - 1];\n\tconst followUps =\n\t\t!isTurnInFlight && newestMessage?.role === 'assistant'\n\t\t\t? newestMessage.followUps\n\t\t\t: undefined;\n\t// A long answer that the reader has scrolled up from: the tail is clipped, so\n\t// the fade and the arrow say there is more below.\n\tconst showScrollAffordance = !isEmpty && !isAtLatest;\n\n\t// Following the conversation is the default, but a reader who has scrolled up\n\t// mid-answer must not be yanked back down by the next chunk.\n\tuseEffect(() => {\n\t\tif (!isAtLatest) {\n\t\t\treturn;\n\t\t}\n\t\tbottomRef.current?.scrollIntoView({ behavior: 'smooth' });\n\t}, [messages, isThinking, isAtLatest]);\n\n\t// Older messages have landed: put the reader back on the message they were\n\t// looking at, which is now that much further down.\n\tuseEffect(() => {\n\t\tconst scroller = scrollerRef.current;\n\t\tconst anchor = anchorFromBottomRef.current;\n\t\tif (!scroller || anchor === null || isLoadingHistory) {\n\t\t\treturn;\n\t\t}\n\t\tanchorFromBottomRef.current = null;\n\t\tscroller.scrollTop = scroller.scrollHeight - anchor;\n\t\tlastScrollTopRef.current = scroller.scrollTop;\n\t}, [messages, isLoadingHistory]);\n\n\tconst handleScroll = () => {\n\t\tconst scroller = scrollerRef.current;\n\t\tif (!scroller) {\n\t\t\treturn;\n\t\t}\n\t\tconst distanceFromBottom =\n\t\t\tscroller.scrollHeight - scroller.scrollTop - scroller.clientHeight;\n\n\t\t// Reaching the top asks for the page before this one. The threshold gives\n\t\t// the request a head start, so the page is usually there by the time the\n\t\t// reader arrives.\n\t\tif (\n\t\t\tscroller.scrollTop <= NEAR_TOP_TOLERANCE_PX &&\n\t\t\thasMoreHistory &&\n\t\t\t!isLoadingHistory &&\n\t\t\tonLoadOlderMessages\n\t\t) {\n\t\t\tanchorFromBottomRef.current = scroller.scrollHeight - scroller.scrollTop;\n\t\t\tonLoadOlderMessages();\n\t\t}\n\t\t// Scrolling *up* is the only thing that detaches from the latest message:\n\t\t// growing content also pushes the bottom away, and auto-scroll itself only\n\t\t// ever moves down, so distance alone would flap mid-stream.\n\t\tconst scrolledUp = scroller.scrollTop < lastScrollTopRef.current - 1;\n\t\tlastScrollTopRef.current = scroller.scrollTop;\n\n\t\tif (distanceFromBottom <= AT_BOTTOM_TOLERANCE_PX) {\n\t\t\tsetIsAtLatest(true);\n\t\t\treturn;\n\t\t}\n\t\tif (scrolledUp) {\n\t\t\tsetIsAtLatest(false);\n\t\t}\n\t};\n\n\tconst handleJumpToLatest = () => {\n\t\tsetIsAtLatest(true);\n\t\tbottomRef.current?.scrollIntoView({ behavior: 'smooth' });\n\t};\n\n\tuseEffect(\n\t\t() => () => {\n\t\t\tif (copiedTimeoutRef.current) {\n\t\t\t\twindow.clearTimeout(copiedTimeoutRef.current);\n\t\t\t}\n\t\t},\n\t\t[],\n\t);\n\n\tconst handleCopyMessage = async (\n\t\tmessage: CopilotPanelProps['messages'][number],\n\t) => {\n\t\t// The raw markdown, not the rendered HTML — that is what a reader wants to\n\t\t// paste into a doc or a ticket.\n\t\tconst copied = await writeToClipboard(message.content);\n\t\tif (!copied) {\n\t\t\treturn;\n\t\t}\n\t\tif (copiedTimeoutRef.current) {\n\t\t\twindow.clearTimeout(copiedTimeoutRef.current);\n\t\t}\n\t\tsetCopiedMessageId(message.id);\n\t\tcopiedTimeoutRef.current = window.setTimeout(\n\t\t\t() => setCopiedMessageId(null),\n\t\t\tCOPIED_FEEDBACK_MS,\n\t\t);\n\t};\n\n\tconst handleFeedback = (messageId: string, vote: 'like' | 'dislike') => {\n\t\t// Pressing the same thumb again clears the vote. Nothing is reported for\n\t\t// that: the backend records ratings, not their absence.\n\t\tconst cleared = feedback[messageId] === vote;\n\t\tsetFeedback((previous) => ({\n\t\t\t...previous,\n\t\t\t[messageId]: previous[messageId] === vote ? undefined : vote,\n\t\t}));\n\t\t// Everything below sits outside the updater on purpose: React may run an\n\t\t// updater twice, which would report the same vote twice.\n\t\tif (cleared) {\n\t\t\tif (vote === 'dislike') {\n\t\t\t\tsetDislikePromptId((current) =>\n\t\t\t\t\tcurrent === messageId ? null : current,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (vote === 'like') {\n\t\t\tonFeedback?.(messageId, 'like');\n\t\t\treturn;\n\t\t}\n\t\t// A thumbs-down asks what went wrong first. Moving the prompt to another\n\t\t// reply still records the one it is leaving.\n\t\tif (dislikePromptId && dislikePromptId !== messageId) {\n\t\t\tonFeedback?.(dislikePromptId, 'dislike');\n\t\t}\n\t\tsetDislikePromptId(messageId);\n\t};\n\n\tconst reportDislike = (messageId: string, detail?: CopilotFeedbackDetail) => {\n\t\tsetDislikePromptId((current) => (current === messageId ? null : current));\n\t\tonFeedback?.(messageId, 'dislike', detail);\n\t};\n\n\tconst handleRegenerate = () => {\n\t\tif (inputDisabled || isTurnInFlight) {\n\t\t\treturn;\n\t\t}\n\t\tonRegenerate?.();\n\t};\n\n\tconst handleSend = () => {\n\t\tconst trimmed = input.trim();\n\t\tif ((!trimmed && !attachment) || inputDisabled || isTurnInFlight) {\n\t\t\treturn;\n\t\t}\n\t\t// The endpoint has no context field, so a quoted selection has to ride\n\t\t// inside the prompt itself.\n\t\tonSend(\n\t\t\tattachment ? buildCopilotSelectionPrompt(attachment, trimmed) : trimmed,\n\t\t);\n\t\tsetInput('');\n\t\t// The quote belongs to the turn that used it; the next question starts\n\t\t// clean unless the merchant selects something again.\n\t\tonAttachmentRemove?.();\n\t\tconst textarea = inputRef.current;\n\t\tif (textarea) {\n\t\t\ttextarea.style.height = 'auto';\n\t\t}\n\t};\n\n\t// A selection is attached so the merchant can ask about it, so the caret\n\t// should already be waiting for the question.\n\tuseEffect(() => {\n\t\tif (attachment) {\n\t\t\tinputRef.current?.focus();\n\t\t}\n\t}, [attachment]);\n\n\tuseEffect(() => {\n\t\tconst turnJustEnded = wasTurnInFlightRef.current && !isTurnInFlight;\n\t\twasTurnInFlightRef.current = isTurnInFlight;\n\t\tif (turnJustEnded && !inputDisabled && !dislikePromptId) {\n\t\t\tinputRef.current?.focus();\n\t\t}\n\t}, [isTurnInFlight, inputDisabled, dislikePromptId]);\n\n\tconst handleInputChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n\t\tsetInput(event.target.value);\n\t\tconst textarea = event.target;\n\t\ttextarea.style.height = 'auto';\n\t\ttextarea.style.height = `${Math.min(\n\t\t\ttextarea.scrollHeight,\n\t\t\tMAX_INPUT_HEIGHT_PX,\n\t\t)}px`;\n\t};\n\n\tconst handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n\t\tif (event.key === 'Enter' && !event.shiftKey) {\n\t\t\tevent.preventDefault();\n\t\t\thandleSend();\n\t\t}\n\t};\n\n\tconst handleSuggestionClick = (\n\t\tsuggestion: NonNullable<CopilotPanelProps['suggestions']>[number],\n\t) => {\n\t\tif (inputDisabled || isTurnInFlight) {\n\t\t\treturn;\n\t\t}\n\t\tonSuggestionClick?.(suggestion);\n\t\tonSend(suggestion.text);\n\t};\n\n\tconst handleFollowUpClick = (followUp: string) => {\n\t\tif (inputDisabled || isTurnInFlight) {\n\t\t\treturn;\n\t\t}\n\t\tonSend(followUp);\n\t};\n\n\treturn (\n\t\t<PanelContainer\n\t\t\tclassName={className}\n\t\t\tstyle={{ width, height, ...style }}\n\t\t\trole=\"dialog\"\n\t\t\taria-label={title}\n\t\t>\n\t\t\t<PanelHeader>\n\t\t\t\t<HeaderAvatar>\n\t\t\t\t\t{avatar ?? <AiStarsIcon width={18} height={18} />}\n\t\t\t\t</HeaderAvatar>\n\t\t\t\t<HeaderText>\n\t\t\t\t\t<HeaderTitleRow>\n\t\t\t\t\t\t<TitleSmall>{title}</TitleSmall>\n\t\t\t\t\t\t{badge && <HeaderBadge>{badge}</HeaderBadge>}\n\t\t\t\t\t</HeaderTitleRow>\n\t\t\t\t\t{subtitle && (\n\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t{subtitle}\n\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t)}\n\t\t\t\t</HeaderText>\n\t\t\t\t<HeaderActions>\n\t\t\t\t\t{showRefresh && onRefresh && (\n\t\t\t\t\t\t<IconAction\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={onRefresh}\n\t\t\t\t\t\t\taria-label=\"Start a new conversation\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<RefreshIcon width={16} height={16} />\n\t\t\t\t\t\t</IconAction>\n\t\t\t\t\t)}\n\t\t\t\t\t<IconAction\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={onClose}\n\t\t\t\t\t\taria-label=\"Close copilot\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<CrossIcon width={18} height={18} />\n\t\t\t\t\t</IconAction>\n\t\t\t\t</HeaderActions>\n\t\t\t</PanelHeader>\n\n\t\t\t<MessagesViewport>\n\t\t\t\t<MessagesArea\n\t\t\t\t\tref={scrollerRef}\n\t\t\t\t\tonScroll={handleScroll}\n\t\t\t\t\trole=\"region\"\n\t\t\t\t\taria-label=\"Conversation\"\n\t\t\t\t>\n\t\t\t\t\t{isEmpty ? (\n\t\t\t\t\t\t<EmptyState>\n\t\t\t\t\t\t\t<EmptyStateIcon>\n\t\t\t\t\t\t\t\t<AiStarsIcon width={28} height={28} />\n\t\t\t\t\t\t\t</EmptyStateIcon>\n\t\t\t\t\t\t\t<BodySecondary style={{ fontWeight: 600 }}>\n\t\t\t\t\t\t\t\t{emptyStateTitle || title}\n\t\t\t\t\t\t\t</BodySecondary>\n\t\t\t\t\t\t\t{emptyStateSubtitle && (\n\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t\t\t{emptyStateSubtitle}\n\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{suggestions && suggestions.length > 0 && (\n\t\t\t\t\t\t\t\t<SuggestionList>\n\t\t\t\t\t\t\t\t\t{suggestions.map((suggestion) => (\n\t\t\t\t\t\t\t\t\t\t<SuggestionChip\n\t\t\t\t\t\t\t\t\t\t\tkey={suggestion.id}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={inputDisabled || isTurnInFlight}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleSuggestionClick(suggestion)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<AiStarsIcon width={14} height={14} />\n\t\t\t\t\t\t\t\t\t\t\t{suggestion.text}\n\t\t\t\t\t\t\t\t\t\t</SuggestionChip>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</SuggestionList>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</EmptyState>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{isLoadingHistory && (\n\t\t\t\t\t\t\t\t<HistoryLoader role=\"status\" aria-live=\"polite\">\n\t\t\t\t\t\t\t\t\t<DotPulse color={COLORS.content.placeholder} size={4} />\n\t\t\t\t\t\t\t\t\t{historyLoadingLabel}\n\t\t\t\t\t\t\t\t</HistoryLoader>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{visibleMessages.map((message) => {\n\t\t\t\t\t\t\t\tconst sentAt =\n\t\t\t\t\t\t\t\t\tmessage.role === 'user'\n\t\t\t\t\t\t\t\t\t\t? formatMessageTime(message.timestamp)\n\t\t\t\t\t\t\t\t\t\t: '';\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<React.Fragment key={message.id}>\n\t\t\t\t\t\t\t\t\t\t{message.content.length > 0 && (\n\t\t\t\t\t\t\t\t\t\t\t<MessageBubble $role={message.role}>\n\t\t\t\t\t\t\t\t\t\t\t\t{message.role === 'assistant' ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdangerouslySetInnerHTML={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t__html: renderCopilotMarkdown(message.content),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div style={{ whiteSpace: 'pre-wrap' }}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{message.content}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</MessageBubble>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{/* Tool CTAs (e.g. the support-portal link) — only once the\n\t\t\t\t\t\t\t\t\t\t reply has finished, so a button cannot flash mid-stream. */}\n\t\t\t\t\t\t\t\t\t\t{message.role === 'assistant' &&\n\t\t\t\t\t\t\t\t\t\t\t!message.isStreaming &&\n\t\t\t\t\t\t\t\t\t\t\t(() => {\n\t\t\t\t\t\t\t\t\t\t\t\tconst ctas = toolResultCtas(message.toolResults);\n\t\t\t\t\t\t\t\t\t\t\t\tif (ctas.length === 0) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<ToolCtaList>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ctas.map((cta) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<ToolCtaLink\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={`${cta.tool}-${cta.url}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thref={cta.url}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonToolCtaClick?.({\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttool: cta.tool,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\turl: cta.url,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{cta.label}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</ToolCtaLink>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</ToolCtaList>\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t})()}\n\t\t\t\t\t\t\t\t\t\t{sentAt && <MessageTimestamp>{sentAt}</MessageTimestamp>}\n\t\t\t\t\t\t\t\t\t\t{message.wasInterrupted && interruptedLabel && (\n\t\t\t\t\t\t\t\t\t\t\t<InterruptedNote>\n\t\t\t\t\t\t\t\t\t\t\t\t<StopIcon size={12} />\n\t\t\t\t\t\t\t\t\t\t\t\t{interruptedLabel}\n\t\t\t\t\t\t\t\t\t\t\t</InterruptedNote>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{/* Only under a finished reply: mid-stream the text is still\n\t\t\t\t\t\t\t\t\t\t changing, so copying it would capture a partial answer. */}\n\t\t\t\t\t\t\t\t\t\t{message.role === 'assistant' &&\n\t\t\t\t\t\t\t\t\t\t\tmessage.content.length > 0 &&\n\t\t\t\t\t\t\t\t\t\t\t!message.isStreaming && (\n\t\t\t\t\t\t\t\t\t\t\t\t<MessageActions>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MessageAction\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => void handleCopyMessage(message)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata-copied={copiedMessageId === message.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcopiedMessageId === message.id ? 'Copied' : 'Copy'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcopiedMessageId === message.id\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? 'Response copied to clipboard'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: 'Copy response'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{copiedMessageId === message.id ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<CheckIcon />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<CopyIcon />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MessageAction>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{/* Only under the newest reply: regenerating appends a\n\t\t\t\t\t\t\t\t\t\t\t\t\t fresh turn at the end, so offering it against an\n\t\t\t\t\t\t\t\t\t\t\t\t\t older answer would not replace that answer. */}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{onRegenerate && message.id === newestMessage?.id && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<MessageAction\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={handleRegenerate}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={inputDisabled || isTurnInFlight}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Regenerate\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Regenerate response\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<RegenerateIcon />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</MessageAction>\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{!message.isRestored &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfeedback[message.id] === undefined && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<MessageAction\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleFeedback(message.id, 'like')\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Good response\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Good response\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<ThumbUpIcon />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</MessageAction>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<MessageAction\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleFeedback(message.id, 'dislike')\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Bad response\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Bad response\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<ThumbDownIcon />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</MessageAction>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t</MessageActions>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{dislikePromptId === message.id && (\n\t\t\t\t\t\t\t\t\t\t\t<CopilotFeedbackModal\n\t\t\t\t\t\t\t\t\t\t\t\ttitle={dislikeTitle}\n\t\t\t\t\t\t\t\t\t\t\t\tsubtitle={dislikeSubtitle ?? `Help us improve ${title}`}\n\t\t\t\t\t\t\t\t\t\t\t\treasons={dislikeReasons}\n\t\t\t\t\t\t\t\t\t\t\t\tnotePlaceholder={dislikeNotePlaceholder}\n\t\t\t\t\t\t\t\t\t\t\t\tsubmitLabel={dislikeSubmitLabel}\n\t\t\t\t\t\t\t\t\t\t\t\tonSubmit={(detail) => reportDislike(message.id, detail)}\n\t\t\t\t\t\t\t\t\t\t\t\tonDismiss={() => reportDislike(message.id)}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</React.Fragment>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t{followUps && followUps.length > 0 && (\n\t\t\t\t\t\t\t\t<FollowUpList>\n\t\t\t\t\t\t\t\t\t{followUpsLabel && (\n\t\t\t\t\t\t\t\t\t\t<FollowUpsLabel>{followUpsLabel}</FollowUpsLabel>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t{followUps.map((followUp) => (\n\t\t\t\t\t\t\t\t\t\t<FollowUpChip\n\t\t\t\t\t\t\t\t\t\t\tkey={followUp}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={inputDisabled}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleFollowUpClick(followUp)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<ArrowRightIcon />\n\t\t\t\t\t\t\t\t\t\t\t{followUp}\n\t\t\t\t\t\t\t\t\t\t</FollowUpChip>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</FollowUpList>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{isThinking && (\n\t\t\t\t\t\t\t\t<ThinkingBubble role=\"status\" aria-live=\"polite\">\n\t\t\t\t\t\t\t\t\t<AiStarsIcon\n\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.brand}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t{thinkingLabel && (\n\t\t\t\t\t\t\t\t\t\t<ThinkingLabel>{thinkingLabel}</ThinkingLabel>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t<DotPulse color={COLORS.background.brand} size={5} />\n\t\t\t\t\t\t\t\t</ThinkingBubble>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<div ref={bottomRef} />\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</MessagesArea>\n\n\t\t\t\t<ScrollFade $visible={showScrollAffordance} aria-hidden=\"true\" />\n\t\t\t\t<JumpToLatestButton\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t$visible={showScrollAffordance}\n\t\t\t\t\tonClick={handleJumpToLatest}\n\t\t\t\t\ttabIndex={showScrollAffordance ? 0 : -1}\n\t\t\t\t\taria-label=\"Scroll to the latest message\"\n\t\t\t\t>\n\t\t\t\t\t<ArrowDownIcon width={16} height={16} />\n\t\t\t\t</JumpToLatestButton>\n\t\t\t</MessagesViewport>\n\n\t\t\t{errorMessage && <ErrorBanner role=\"alert\">{errorMessage}</ErrorBanner>}\n\n\t\t\t<InputArea>\n\t\t\t\t{attachment && (\n\t\t\t\t\t<AttachmentChip>\n\t\t\t\t\t\t<AiStarsIcon width={14} height={14} color={COLORS.content.brand} />\n\t\t\t\t\t\t<AttachmentText title={attachment}>{attachment}</AttachmentText>\n\t\t\t\t\t\t<AttachmentRemove\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={onAttachmentRemove}\n\t\t\t\t\t\t\taria-label=\"Remove the selected text\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<CrossIcon width={12} height={12} />\n\t\t\t\t\t\t</AttachmentRemove>\n\t\t\t\t\t</AttachmentChip>\n\t\t\t\t)}\n\t\t\t\t<InputWrapper $focused={isInputFocused}>\n\t\t\t\t\t<MessageInput\n\t\t\t\t\t\tref={inputRef}\n\t\t\t\t\t\trows={1}\n\t\t\t\t\t\tvalue={input}\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\tdisabled={inputDisabled}\n\t\t\t\t\t\tonChange={handleInputChange}\n\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\tonFocus={() => setIsInputFocused(true)}\n\t\t\t\t\t\tonBlur={() => setIsInputFocused(false)}\n\t\t\t\t\t/>\n\t\t\t\t\t<SendButton\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t$active={canStop || canSend}\n\t\t\t\t\t\tdisabled={!canStop && !canSend}\n\t\t\t\t\t\tonClick={canStop ? onStop : handleSend}\n\t\t\t\t\t\taria-label={canStop ? 'Stop generating' : 'Send message'}\n\t\t\t\t\t>\n\t\t\t\t\t\t{canStop ? <StopIcon /> : <SendArrowIcon />}\n\t\t\t\t\t</SendButton>\n\t\t\t\t</InputWrapper>\n\t\t\t</InputArea>\n\n\t\t\t{disclaimer && <Disclaimer>{disclaimer}</Disclaimer>}\n\t\t</PanelContainer>\n\t);\n};\n\nexport default CopilotPanel;\n"],"names":["MAX_INPUT_HEIGHT_PX","AT_BOTTOM_TOLERANCE_PX","COPIED_FEEDBACK_MS","writeToClipboard","text","textarea","copied","NEAR_TOP_TOLERANCE_PX","formatMessageTime","timestamp","date","SendArrowIcon","jsxs","jsx","ArrowRightIcon","StopIcon","size","CopyIcon","CheckIcon","RegenerateIcon","ThumbUpIcon","filled","ThumbDownIcon","CopilotPanel","messages","onSend","onClose","title","badge","subtitle","avatar","placeholder","disclaimer","emptyStateTitle","emptyStateSubtitle","suggestions","onSuggestionClick","showRefresh","onRefresh","onRegenerate","onFeedback","dislikeTitle","dislikeSubtitle","dislikeReasons","dislikeNotePlaceholder","dislikeSubmitLabel","isThinking","thinkingLabel","isStreaming","onStop","interruptedLabel","followUpsLabel","onToolCtaClick","hasMoreHistory","isLoadingHistory","onLoadOlderMessages","historyLoadingLabel","inputDisabled","attachment","onAttachmentRemove","errorMessage","width","height","className","style","input","setInput","useState","isInputFocused","setIsInputFocused","isAtLatest","setIsAtLatest","copiedMessageId","setCopiedMessageId","feedback","setFeedback","dislikePromptId","setDislikePromptId","inputRef","useRef","wasTurnInFlightRef","copiedTimeoutRef","bottomRef","scrollerRef","lastScrollTopRef","anchorFromBottomRef","visibleMessages","message","isCopilotRegeneratePrompt","isEmpty","isTurnInFlight","canSend","canStop","newestMessage","followUps","showScrollAffordance","useEffect","scroller","anchor","handleScroll","distanceFromBottom","scrolledUp","handleJumpToLatest","handleCopyMessage","handleFeedback","messageId","vote","cleared","previous","current","reportDislike","detail","handleRegenerate","handleSend","trimmed","buildCopilotSelectionPrompt","turnJustEnded","handleInputChange","event","handleKeyDown","handleSuggestionClick","suggestion","handleFollowUpClick","followUp","PanelContainer","PanelHeader","HeaderAvatar","AiStarsIcon","HeaderText","HeaderTitleRow","TitleSmall","HeaderBadge","BodyCaption","COLORS","HeaderActions","IconAction","RefreshIcon","CrossIcon","MessagesViewport","MessagesArea","EmptyState","EmptyStateIcon","BodySecondary","SuggestionList","SuggestionChip","Fragment","HistoryLoader","DotPulse","sentAt","React","MessageBubble","renderCopilotMarkdown","ctas","toolResultCtas","ToolCtaList","cta","ToolCtaLink","MessageTimestamp","InterruptedNote","MessageActions","MessageAction","CopilotFeedbackModal","FollowUpList","FollowUpsLabel","FollowUpChip","ThinkingBubble","ThinkingLabel","ScrollFade","JumpToLatestButton","ArrowDownIcon","ErrorBanner","InputArea","AttachmentChip","AttachmentText","AttachmentRemove","InputWrapper","MessageInput","SendButton","Disclaimer"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react"),Ie=require("./copilotRegenerate.js"),F=require("./services/copilotDb.js"),me=require("./services/copilotFeedbackClient.js"),re=require("./services/copilotMessagesClient.js"),z=require("./services/copilotPageSession.js"),U=require("./services/copilotStreamClient.js"),se=require("./useCopilotIcebreakers.js"),ne="Something went wrong. Please try again.",he=({storeId:l,agent:w=se.DEFAULT_COPILOT_AGENT,route:R=se.DEFAULT_COPILOT_ROUTE,messagesPath:X,feedbackPath:Y,user:Z,loadHistory:J=!0,systemPrompt:K,sessionId:g,persist:i=!0,onError:b,onResponseComplete:Q,onSessionIdChange:D,baseUrl:M,endpointPath:V,headers:O,authToken:P,getAuthToken:H,fetchImpl:_})=>{const[G,N]=s.useState([]),[oe,W]=s.useState(g??null),[T,y]=s.useState(!1),[ce,ee]=s.useState(!0),[ue,k]=s.useState(),[ae,le]=s.useState(),[ie,L]=s.useState(!1),[B,p]=s.useState(!1),f=s.useRef([]),$=s.useRef(void 0),I=s.useRef(null),u=s.useRef(null),m=s.useRef(g??null),q=s.useRef(R);q.current=R;const h=s.useRef(1),v=s.useRef(!1),a=s.useCallback(e=>{const t=e(f.current);f.current=t,N(t)},[]),E=s.useCallback(e=>{$.current=e,le(e)},[]),C=s.useCallback(()=>{const e=m.current;!i||!e||F.persistCopilotTurn({route:q.current,sessionId:e,messages:f.current,previousResponseId:$.current,storeId:l,agent:w})},[w,i,l]),x=s.useRef({baseUrl:M,messagesPath:X,feedbackPath:Y,headers:O,authToken:P,getAuthToken:H,fetchImpl:_,storeId:l,loadHistory:J,user:Z});x.current={baseUrl:M,messagesPath:X,feedbackPath:Y,headers:O,authToken:P,getAuthToken:H,fetchImpl:_,storeId:l,loadHistory:J,user:Z};const A=s.useCallback(async e=>{const t=x.current,r=m.current;return!t.loadHistory||!r?null:re.fetchCopilotMessages({baseUrl:t.baseUrl,endpointPath:t.messagesPath,headers:t.headers,authToken:t.authToken,getAuthToken:t.getAuthToken,fetchImpl:t.fetchImpl,storeId:t.storeId,sessionId:r,page:e,pageSize:re.COPILOT_HISTORY_PAGE_SIZE})},[]);s.useEffect(()=>{let e=!1;return(async()=>{u.current?.(),u.current=null,I.current=null,y(!1),k(void 0),ee(!0),p(!1),v.current=!1,L(!1);const r=g??(i?await z.resolveCopilotSessionIdForRoute({route:R,storeId:l}):z.getCopilotSessionIdForRoute({route:R,storeId:l})),n=i?await F.loadCopilotSession(R,r):null;if(!e){if(m.current=r,W(r),f.current=n?.messages??[],N(f.current),E(n?.previousResponseId),ee(!1),D?.(r),f.current.length>0){h.current=2,p(x.current.loadHistory);return}if(!g){h.current=1,p(!1);return}h.current=1;try{const o=await A(1);if(e||!o)return;h.current=2,a(()=>o.messages),p(o.hasMore)}catch{p(!1)}}})(),()=>{e=!0}},[R,l,g,i,E,a,A]);const fe=s.useCallback(()=>{if(v.current||!B)return;v.current=!0,L(!0);const e=h.current;(async()=>{try{const t=await A(e);if(!t){p(!1);return}h.current=e+1,p(t.hasMore),a(r=>{const n=new Set(r.flatMap(c=>c.messageId?[c.id,c.messageId]:[c.id])),o=t.messages.filter(c=>!n.has(c.id));return o.length>0?[...o,...r]:r})}catch(t){b?.(t instanceof Error?t:new Error(String(t)))}finally{v.current=!1,L(!1)}})()},[a,B,b,A]);s.useEffect(()=>{i&&F.pruneCopilotSessions()},[i]),s.useEffect(()=>()=>u.current?.(),[]);const S=s.useCallback(e=>{const t=I.current;I.current=null,t&&a(r=>r.map(n=>{if(n.id!==t)return n;const o={...n,isStreaming:!1};return e?e(o):o}).filter(n=>n.id!==t||n.content.length>0||n.wasInterrupted===!0))},[a]),te=s.useCallback(e=>{const t=I.current;if(e.type==="STREAM"){const r=U.readCopilotEventContent(e).text;if(!t||!r)return;a(n=>n.map(o=>o.id===t?{...o,content:o.content+r,messageId:e.messageId??o.messageId}:o));return}if(e.type==="TEXT"){const{text:r,followUps:n,toolResults:o,responseId:c}=U.readCopilotEventContent(e);S(d=>({...d,content:r,messageId:e.messageId??d.messageId,...n?{followUps:n}:{},...o?{toolResults:o}:{}})),E(c),C(),Q?.({text:r,responseId:c,followUps:n});return}e.type==="ERROR"&&(k(U.readCopilotEventContent(e).text||ne),S(),C())},[a,S,Q,C,E]),j=s.useCallback(e=>{const t=e.trim(),r=m.current;if(!t||!r||T)return;k(void 0);const n=Date.now(),o=`copilot-a-${n}`;I.current=o,a(c=>[...c,{id:`copilot-u-${n}`,role:"user",content:t,timestamp:n},{id:o,role:"assistant",content:"",timestamp:n+1,isStreaming:!0}]),y(!0),C(),u.current=U.streamCopilotChat({baseUrl:M,endpointPath:V,headers:O,authToken:P,getAuthToken:H,fetchImpl:_,storeId:l,agent:w,route:R,userPrompt:t,sessionId:r,previousResponseId:$.current,systemPrompt:K},{onEvent:te,onComplete:()=>{S(),y(!1),u.current=null,C()},onError:c=>{k(c.message||ne),S(),y(!1),u.current=null,C(),b?.(c)},onAbort:()=>{S(),y(!1),u.current=null,C()}})},[a,P,M,V,_,w,S,H,te,O,T,b,R,C,l,K]),de=s.useCallback(()=>{f.current.some(t=>t.role==="assistant"&&t.content.length>0)&&j(Ie.COPILOT_REGENERATE_PROMPT)},[j]),Re=s.useCallback((e,t,r)=>{const n=x.current,o=m.current;if(!o)return;const c=f.current.find(d=>(d.messageId??d.id)===e);me.sendCopilotFeedback({baseUrl:n.baseUrl,endpointPath:n.feedbackPath,headers:n.headers,authToken:n.authToken,getAuthToken:n.getAuthToken,fetchImpl:n.fetchImpl,storeId:n.storeId,sessionId:o,messageId:e,feedback:t,route:q.current,reply:c?.content,user:n.user,reasons:r?.reasons,comment:r?.comment}).catch(d=>{b?.(d instanceof Error?d:new Error(String(d)))})},[b]),pe=s.useCallback(()=>{if(!u.current)return;const e=I.current;e&&a(t=>t.map(r=>r.id===e?{...r,wasInterrupted:!0}:r)),u.current(),u.current=null},[a]),Ce=s.useCallback(()=>{u.current?.(),u.current=null,I.current=null,y(!1),k(void 0),h.current=1,v.current=!1,L(!1),p(!1);const e=q.current,t=m.current,r=g??z.resetCopilotSessionForRoute({route:e,storeId:l});m.current=r,W(r),f.current=[],N([]),E(void 0),i&&t&&F.deleteCopilotSession(e,t),D?.(r)},[D,i,g,E,l]),ge=s.useMemo(()=>T&&!G.some(e=>e.isStreaming&&e.content),[T,G]);return{messages:G,sessionId:oe,previousResponseId:ae,isStreaming:T,isThinking:ge,isRestoring:ce,isLoadingHistory:ie,hasMoreHistory:B,error:ue,sendMessage:j,regenerate:de,submitFeedback:Re,loadOlderMessages:fe,stopStreaming:pe,startNewConversation:Ce}};exports.useCopilotStreamChat=he;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react"),me=require("./copilotRegenerate.js"),F=require("./services/copilotDb.js"),he=require("./services/copilotFeedbackClient.js"),re=require("./services/copilotMessagesClient.js"),z=require("./services/copilotPageSession.js"),U=require("./services/copilotStreamClient.js"),se=require("./useCopilotIcebreakers.js"),ne="Something went wrong. Please try again.",oe=u=>u.map(R=>R.role==="assistant"?{...R,isRestored:!0}:R),Se=({storeId:u,agent:R=se.DEFAULT_COPILOT_AGENT,route:p=se.DEFAULT_COPILOT_ROUTE,messagesPath:X,feedbackPath:Y,user:Z,loadHistory:J=!0,systemPrompt:K,sessionId:I,persist:l=!0,onError:y,onResponseComplete:Q,onSessionIdChange:D,baseUrl:P,endpointPath:V,headers:M,authToken:O,getAuthToken:H,fetchImpl:_})=>{const[G,N]=n.useState([]),[ce,W]=n.useState(I??null),[k,E]=n.useState(!1),[ue,ee]=n.useState(!0),[ae,v]=n.useState(),[ie,le]=n.useState(),[fe,L]=n.useState(!1),[B,C]=n.useState(!1),f=n.useRef([]),$=n.useRef(void 0),m=n.useRef(null),a=n.useRef(null),h=n.useRef(I??null),q=n.useRef(p);q.current=p;const S=n.useRef(1),w=n.useRef(!1),i=n.useCallback(e=>{const t=e(f.current);f.current=t,N(t)},[]),T=n.useCallback(e=>{$.current=e,le(e)},[]),g=n.useCallback(()=>{const e=h.current;!l||!e||F.persistCopilotTurn({route:q.current,sessionId:e,messages:f.current,previousResponseId:$.current,storeId:u,agent:R})},[R,l,u]),x=n.useRef({baseUrl:P,messagesPath:X,feedbackPath:Y,headers:M,authToken:O,getAuthToken:H,fetchImpl:_,storeId:u,loadHistory:J,user:Z});x.current={baseUrl:P,messagesPath:X,feedbackPath:Y,headers:M,authToken:O,getAuthToken:H,fetchImpl:_,storeId:u,loadHistory:J,user:Z};const A=n.useCallback(async e=>{const t=x.current,s=h.current;if(!t.loadHistory||!s)return null;const r=await re.fetchCopilotMessages({baseUrl:t.baseUrl,endpointPath:t.messagesPath,headers:t.headers,authToken:t.authToken,getAuthToken:t.getAuthToken,fetchImpl:t.fetchImpl,storeId:t.storeId,sessionId:s,page:e,pageSize:re.COPILOT_HISTORY_PAGE_SIZE});return{...r,messages:oe(r.messages)}},[]);n.useEffect(()=>{let e=!1;return(async()=>{a.current?.(),a.current=null,m.current=null,E(!1),v(void 0),ee(!0),C(!1),w.current=!1,L(!1);const s=I??(l?await z.resolveCopilotSessionIdForRoute({route:p,storeId:u}):z.getCopilotSessionIdForRoute({route:p,storeId:u})),r=l?await F.loadCopilotSession(p,s):null;if(!e){if(h.current=s,W(s),f.current=oe(r?.messages??[]),N(f.current),T(r?.previousResponseId),ee(!1),D?.(s),f.current.length>0){S.current=2,C(x.current.loadHistory);return}if(!I){S.current=1,C(!1);return}S.current=1;try{const o=await A(1);if(e||!o)return;S.current=2,i(()=>o.messages),C(o.hasMore)}catch{C(!1)}}})(),()=>{e=!0}},[p,u,I,l,T,i,A]);const de=n.useCallback(()=>{if(w.current||!B)return;w.current=!0,L(!0);const e=S.current;(async()=>{try{const t=await A(e);if(!t){C(!1);return}S.current=e+1,C(t.hasMore),i(s=>{const r=new Set(s.flatMap(c=>c.messageId?[c.id,c.messageId]:[c.id])),o=t.messages.filter(c=>!r.has(c.id));return o.length>0?[...o,...s]:s})}catch(t){y?.(t instanceof Error?t:new Error(String(t)))}finally{w.current=!1,L(!1)}})()},[i,B,y,A]);n.useEffect(()=>{l&&F.pruneCopilotSessions()},[l]),n.useEffect(()=>()=>a.current?.(),[]);const b=n.useCallback(e=>{const t=m.current;m.current=null,t&&i(s=>s.map(r=>{if(r.id!==t)return r;const o={...r,isStreaming:!1};return e?e(o):o}).filter(r=>r.id!==t||r.content.length>0||r.wasInterrupted===!0))},[i]),te=n.useCallback(e=>{const t=m.current;if(e.type==="STREAM"){const s=U.readCopilotEventContent(e).text;if(!t||!s)return;i(r=>r.map(o=>o.id===t?{...o,content:o.content+s,messageId:e.messageId??o.messageId}:o));return}if(e.type==="TEXT"){const{text:s,followUps:r,toolResults:o,responseId:c}=U.readCopilotEventContent(e);b(d=>({...d,content:s,messageId:e.messageId??d.messageId,...r?{followUps:r}:{},...o?{toolResults:o}:{}})),T(c),g(),Q?.({text:s,responseId:c,followUps:r});return}e.type==="ERROR"&&(v(U.readCopilotEventContent(e).text||ne),b(),g())},[i,b,Q,g,T]),j=n.useCallback(e=>{const t=e.trim(),s=h.current;if(!t||!s||k)return;v(void 0);const r=Date.now(),o=`copilot-a-${r}`;m.current=o,i(c=>[...c,{id:`copilot-u-${r}`,role:"user",content:t,timestamp:r},{id:o,role:"assistant",content:"",timestamp:r+1,isStreaming:!0}]),E(!0),g(),a.current=U.streamCopilotChat({baseUrl:P,endpointPath:V,headers:M,authToken:O,getAuthToken:H,fetchImpl:_,storeId:u,agent:R,route:p,userPrompt:t,sessionId:s,previousResponseId:$.current,systemPrompt:K},{onEvent:te,onComplete:()=>{b(),E(!1),a.current=null,g()},onError:c=>{v(c.message||ne),b(),E(!1),a.current=null,g(),y?.(c)},onAbort:()=>{b(),E(!1),a.current=null,g()}})},[i,O,P,V,_,R,b,H,te,M,k,y,p,g,u,K]),Re=n.useCallback(()=>{f.current.some(t=>t.role==="assistant"&&t.content.length>0)&&j(me.COPILOT_REGENERATE_PROMPT)},[j]),pe=n.useCallback((e,t,s)=>{const r=x.current,o=h.current;if(!o)return;const c=f.current.find(d=>(d.messageId??d.id)===e);he.sendCopilotFeedback({baseUrl:r.baseUrl,endpointPath:r.feedbackPath,headers:r.headers,authToken:r.authToken,getAuthToken:r.getAuthToken,fetchImpl:r.fetchImpl,storeId:r.storeId,sessionId:o,messageId:e,feedback:t,route:q.current,reply:c?.content,user:r.user,reasons:s?.reasons,comment:s?.comment}).catch(d=>{y?.(d instanceof Error?d:new Error(String(d)))})},[y]),Ce=n.useCallback(()=>{if(!a.current)return;const e=m.current;e&&i(t=>t.map(s=>s.id===e?{...s,wasInterrupted:!0}:s)),a.current(),a.current=null},[i]),ge=n.useCallback(()=>{a.current?.(),a.current=null,m.current=null,E(!1),v(void 0),S.current=1,w.current=!1,L(!1),C(!1);const e=q.current,t=h.current,s=I??z.resetCopilotSessionForRoute({route:e,storeId:u});h.current=s,W(s),f.current=[],N([]),T(void 0),l&&t&&F.deleteCopilotSession(e,t),D?.(s)},[D,l,I,T,u]),Ie=n.useMemo(()=>k&&!G.some(e=>e.isStreaming&&e.content),[k,G]);return{messages:G,sessionId:ce,previousResponseId:ie,isStreaming:k,isThinking:Ie,isRestoring:ue,isLoadingHistory:fe,hasMoreHistory:B,error:ae,sendMessage:j,regenerate:Re,submitFeedback:pe,loadOlderMessages:de,stopStreaming:Ce,startNewConversation:ge}};exports.useCopilotStreamChat=Se;
2
2
  //# sourceMappingURL=useCopilotStreamChat.js.map