@gengage/assistant-fe 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/LICENSE +61 -0
  2. package/README.md +232 -0
  3. package/dist/assistant-fe.css +1 -0
  4. package/dist/chat/api.d.ts +87 -0
  5. package/dist/chat/api.d.ts.map +1 -0
  6. package/dist/chat/attachment-utils.d.ts +10 -0
  7. package/dist/chat/attachment-utils.d.ts.map +1 -0
  8. package/dist/chat/catalog.d.ts +1114 -0
  9. package/dist/chat/catalog.d.ts.map +1 -0
  10. package/dist/chat/components/AIGroupingCards.d.ts +4 -0
  11. package/dist/chat/components/AIGroupingCards.d.ts.map +1 -0
  12. package/dist/chat/components/AISuggestedSearchCards.d.ts +4 -0
  13. package/dist/chat/components/AISuggestedSearchCards.d.ts.map +1 -0
  14. package/dist/chat/components/AITopPicks.d.ts +4 -0
  15. package/dist/chat/components/AITopPicks.d.ts.map +1 -0
  16. package/dist/chat/components/CategoriesContainer.d.ts +4 -0
  17. package/dist/chat/components/CategoriesContainer.d.ts.map +1 -0
  18. package/dist/chat/components/ChatDrawer.d.ts +140 -0
  19. package/dist/chat/components/ChatDrawer.d.ts.map +1 -0
  20. package/dist/chat/components/ChoicePrompter.d.ts +16 -0
  21. package/dist/chat/components/ChoicePrompter.d.ts.map +1 -0
  22. package/dist/chat/components/ComparisonTable.d.ts +47 -0
  23. package/dist/chat/components/ComparisonTable.d.ts.map +1 -0
  24. package/dist/chat/components/FloatingComparisonButton.d.ts +11 -0
  25. package/dist/chat/components/FloatingComparisonButton.d.ts.map +1 -0
  26. package/dist/chat/components/GroundingReviewCard.d.ts +4 -0
  27. package/dist/chat/components/GroundingReviewCard.d.ts.map +1 -0
  28. package/dist/chat/components/KvkkBanner.d.ts +6 -0
  29. package/dist/chat/components/KvkkBanner.d.ts.map +1 -0
  30. package/dist/chat/components/Launcher.d.ts +25 -0
  31. package/dist/chat/components/Launcher.d.ts.map +1 -0
  32. package/dist/chat/components/PanelTopBar.d.ts +20 -0
  33. package/dist/chat/components/PanelTopBar.d.ts.map +1 -0
  34. package/dist/chat/components/ProactivePopup.d.ts +11 -0
  35. package/dist/chat/components/ProactivePopup.d.ts.map +1 -0
  36. package/dist/chat/components/ProsAndCons.d.ts +9 -0
  37. package/dist/chat/components/ProsAndCons.d.ts.map +1 -0
  38. package/dist/chat/components/ReviewHighlights.d.ts +3 -0
  39. package/dist/chat/components/ReviewHighlights.d.ts.map +1 -0
  40. package/dist/chat/components/ThumbnailsColumn.d.ts +23 -0
  41. package/dist/chat/components/ThumbnailsColumn.d.ts.map +1 -0
  42. package/dist/chat/components/actionClassifier.d.ts +13 -0
  43. package/dist/chat/components/actionClassifier.d.ts.map +1 -0
  44. package/dist/chat/components/productMentionLinker.d.ts +26 -0
  45. package/dist/chat/components/productMentionLinker.d.ts.map +1 -0
  46. package/dist/chat/components/renderUISpec.d.ts +15 -0
  47. package/dist/chat/components/renderUISpec.d.ts.map +1 -0
  48. package/dist/chat/components/typewriter.d.ts +25 -0
  49. package/dist/chat/components/typewriter.d.ts.map +1 -0
  50. package/dist/chat/extendedModeManager.d.ts +33 -0
  51. package/dist/chat/extendedModeManager.d.ts.map +1 -0
  52. package/dist/chat/index.d.ts +192 -0
  53. package/dist/chat/index.d.ts.map +1 -0
  54. package/dist/chat/locales/en.d.ts +3 -0
  55. package/dist/chat/locales/en.d.ts.map +1 -0
  56. package/dist/chat/locales/index.d.ts +6 -0
  57. package/dist/chat/locales/index.d.ts.map +1 -0
  58. package/dist/chat/locales/tr.d.ts +3 -0
  59. package/dist/chat/locales/tr.d.ts.map +1 -0
  60. package/dist/chat/types.d.ts +212 -0
  61. package/dist/chat/types.d.ts.map +1 -0
  62. package/dist/chat.cjs +2 -0
  63. package/dist/chat.cjs.map +1 -0
  64. package/dist/chat.iife.js +59 -0
  65. package/dist/chat.iife.js.map +1 -0
  66. package/dist/chat.js +11 -0
  67. package/dist/chat.js.map +1 -0
  68. package/dist/common/action-router.d.ts +30 -0
  69. package/dist/common/action-router.d.ts.map +1 -0
  70. package/dist/common/activity-tracker.d.ts +38 -0
  71. package/dist/common/activity-tracker.d.ts.map +1 -0
  72. package/dist/common/analytics-events.d.ts +90 -0
  73. package/dist/common/analytics-events.d.ts.map +1 -0
  74. package/dist/common/analytics.d.ts +58 -0
  75. package/dist/common/analytics.d.ts.map +1 -0
  76. package/dist/common/api-paths.d.ts +14 -0
  77. package/dist/common/api-paths.d.ts.map +1 -0
  78. package/dist/common/client.d.ts +20 -0
  79. package/dist/common/client.d.ts.map +1 -0
  80. package/dist/common/communication-bridge.d.ts +51 -0
  81. package/dist/common/communication-bridge.d.ts.map +1 -0
  82. package/dist/common/config-schema.d.ts +241 -0
  83. package/dist/common/config-schema.d.ts.map +1 -0
  84. package/dist/common/context.d.ts +28 -0
  85. package/dist/common/context.d.ts.map +1 -0
  86. package/dist/common/customization-factories.d.ts +63 -0
  87. package/dist/common/customization-factories.d.ts.map +1 -0
  88. package/dist/common/events.d.ts +47 -0
  89. package/dist/common/events.d.ts.map +1 -0
  90. package/dist/common/global-error-toast.d.ts +6 -0
  91. package/dist/common/global-error-toast.d.ts.map +1 -0
  92. package/dist/common/index.d.ts +36 -0
  93. package/dist/common/index.d.ts.map +1 -0
  94. package/dist/common/indexed-db.d.ts +74 -0
  95. package/dist/common/indexed-db.d.ts.map +1 -0
  96. package/dist/common/overlay.d.ts +64 -0
  97. package/dist/common/overlay.d.ts.map +1 -0
  98. package/dist/common/preflight.d.ts +12 -0
  99. package/dist/common/preflight.d.ts.map +1 -0
  100. package/dist/common/renderer/dom.d.ts +4 -0
  101. package/dist/common/renderer/dom.d.ts.map +1 -0
  102. package/dist/common/renderer/index.d.ts +5 -0
  103. package/dist/common/renderer/index.d.ts.map +1 -0
  104. package/dist/common/renderer/overrides.d.ts +24 -0
  105. package/dist/common/renderer/overrides.d.ts.map +1 -0
  106. package/dist/common/renderer/registry.d.ts +3 -0
  107. package/dist/common/renderer/registry.d.ts.map +1 -0
  108. package/dist/common/renderer/types.d.ts +20 -0
  109. package/dist/common/renderer/types.d.ts.map +1 -0
  110. package/dist/common/safe-html.d.ts +19 -0
  111. package/dist/common/safe-html.d.ts.map +1 -0
  112. package/dist/common/streaming.d.ts +32 -0
  113. package/dist/common/streaming.d.ts.map +1 -0
  114. package/dist/common/theme-utils.d.ts +16 -0
  115. package/dist/common/theme-utils.d.ts.map +1 -0
  116. package/dist/common/types.d.ts +298 -0
  117. package/dist/common/types.d.ts.map +1 -0
  118. package/dist/common/ui-theme.d.ts +10 -0
  119. package/dist/common/ui-theme.d.ts.map +1 -0
  120. package/dist/common/uuidv7.d.ts +8 -0
  121. package/dist/common/uuidv7.d.ts.map +1 -0
  122. package/dist/common/v1-protocol-adapter.d.ts +66 -0
  123. package/dist/common/v1-protocol-adapter.d.ts.map +1 -0
  124. package/dist/common/widget-base.d.ts +75 -0
  125. package/dist/common/widget-base.d.ts.map +1 -0
  126. package/dist/common.cjs +2 -0
  127. package/dist/common.cjs.map +1 -0
  128. package/dist/common.js +584 -0
  129. package/dist/common.js.map +1 -0
  130. package/dist/index-CFA70IGF.js +3626 -0
  131. package/dist/index-CFA70IGF.js.map +1 -0
  132. package/dist/index-Dfl89zpe.cjs +13 -0
  133. package/dist/index-Dfl89zpe.cjs.map +1 -0
  134. package/dist/index.cjs +2 -0
  135. package/dist/index.cjs.map +1 -0
  136. package/dist/index.d.ts +24 -0
  137. package/dist/index.d.ts.map +1 -0
  138. package/dist/index.js +59 -0
  139. package/dist/index.js.map +1 -0
  140. package/dist/qna/api.d.ts +22 -0
  141. package/dist/qna/api.d.ts.map +1 -0
  142. package/dist/qna/catalog.d.ts +140 -0
  143. package/dist/qna/catalog.d.ts.map +1 -0
  144. package/dist/qna/components/ButtonRow.d.ts +16 -0
  145. package/dist/qna/components/ButtonRow.d.ts.map +1 -0
  146. package/dist/qna/components/TextInput.d.ts +12 -0
  147. package/dist/qna/components/TextInput.d.ts.map +1 -0
  148. package/dist/qna/components/renderUISpec.d.ts +8 -0
  149. package/dist/qna/components/renderUISpec.d.ts.map +1 -0
  150. package/dist/qna/index.d.ts +34 -0
  151. package/dist/qna/index.d.ts.map +1 -0
  152. package/dist/qna/locales/en.d.ts +3 -0
  153. package/dist/qna/locales/en.d.ts.map +1 -0
  154. package/dist/qna/locales/index.d.ts +6 -0
  155. package/dist/qna/locales/index.d.ts.map +1 -0
  156. package/dist/qna/locales/tr.d.ts +3 -0
  157. package/dist/qna/locales/tr.d.ts.map +1 -0
  158. package/dist/qna/types.d.ts +62 -0
  159. package/dist/qna/types.d.ts.map +1 -0
  160. package/dist/qna.cjs +2 -0
  161. package/dist/qna.cjs.map +1 -0
  162. package/dist/qna.css +1 -0
  163. package/dist/qna.iife.js +48 -0
  164. package/dist/qna.iife.js.map +1 -0
  165. package/dist/qna.js +435 -0
  166. package/dist/qna.js.map +1 -0
  167. package/dist/simrel/api.d.ts +26 -0
  168. package/dist/simrel/api.d.ts.map +1 -0
  169. package/dist/simrel/catalog.d.ts +319 -0
  170. package/dist/simrel/catalog.d.ts.map +1 -0
  171. package/dist/simrel/components/GroupTabs.d.ts +17 -0
  172. package/dist/simrel/components/GroupTabs.d.ts.map +1 -0
  173. package/dist/simrel/components/ProductCard.d.ts +17 -0
  174. package/dist/simrel/components/ProductCard.d.ts.map +1 -0
  175. package/dist/simrel/components/ProductGrid.d.ts +17 -0
  176. package/dist/simrel/components/ProductGrid.d.ts.map +1 -0
  177. package/dist/simrel/components/renderUISpec.d.ts +8 -0
  178. package/dist/simrel/components/renderUISpec.d.ts.map +1 -0
  179. package/dist/simrel/index.d.ts +36 -0
  180. package/dist/simrel/index.d.ts.map +1 -0
  181. package/dist/simrel/locales/en.d.ts +3 -0
  182. package/dist/simrel/locales/en.d.ts.map +1 -0
  183. package/dist/simrel/locales/index.d.ts +6 -0
  184. package/dist/simrel/locales/index.d.ts.map +1 -0
  185. package/dist/simrel/locales/tr.d.ts +3 -0
  186. package/dist/simrel/locales/tr.d.ts.map +1 -0
  187. package/dist/simrel/types.d.ts +111 -0
  188. package/dist/simrel/types.d.ts.map +1 -0
  189. package/dist/simrel.cjs +2 -0
  190. package/dist/simrel.cjs.map +1 -0
  191. package/dist/simrel.css +1 -0
  192. package/dist/simrel.iife.js +48 -0
  193. package/dist/simrel.iife.js.map +1 -0
  194. package/dist/simrel.js +620 -0
  195. package/dist/simrel.js.map +1 -0
  196. package/dist/types-CeON7iBO.cjs +48 -0
  197. package/dist/types-CeON7iBO.cjs.map +1 -0
  198. package/dist/types-yxW8WA7u.js +4132 -0
  199. package/dist/types-yxW8WA7u.js.map +1 -0
  200. package/package.json +100 -0
package/LICENSE ADDED
@@ -0,0 +1,61 @@
1
+ GENGAGE FRONTEND SOURCE-AVAILABLE LICENSE v1.0
2
+
3
+ Copyright (c) 2024 Gengage AI.
4
+ All rights reserved, except as expressly granted below.
5
+
6
+ 1. Definitions
7
+ 1.1 "Code" means the source code and related files in this repository.
8
+ 1.2 "Gengage Service" means the Gengage-hosted backend service at
9
+ `https://chatbe.gengage.ai` and any successor endpoint designated by Gengage.
10
+ 1.3 "Registered Customer" means a person or entity with an active, authorized
11
+ account/contract with Gengage for use of the Gengage Service.
12
+
13
+ 2. License Grant
14
+ 2.1 Subject to this License, Gengage grants you a limited, non-exclusive,
15
+ non-transferable, revocable license to:
16
+ - view, fork, copy, and modify the Code;
17
+ - use the Code for internal development, evaluation, and customization; and
18
+ - deploy/use the Code only for integrations that connect to the Gengage Service
19
+ by or for a Registered Customer.
20
+
21
+ 3. Redistribution
22
+ 3.1 Redistribution of the Code (modified or unmodified) is permitted only when all
23
+ of the following are true:
24
+ - the redistribution is for enabling use by/for a Registered Customer;
25
+ - the redistributed copy remains subject to this License;
26
+ - all copyright, license, and trademark notices are preserved.
27
+ 3.2 Redistribution for any purpose other than the Registered Customer + Gengage Service
28
+ use case is prohibited.
29
+
30
+ 4. Prohibited Uses
31
+ You may not:
32
+ 4.1 use, deploy, or operate the Code with non-Gengage backends as a substitute for
33
+ the Gengage Service;
34
+ 4.2 sell, sublicense, or commercially distribute the Code as a standalone software
35
+ product, toolkit, or white-label package;
36
+ 4.3 remove or alter legal/trademark notices required by this repository.
37
+
38
+ 5. Service Access
39
+ This License does not grant access rights to the Gengage Service itself.
40
+ Service access is governed separately by Gengage commercial terms, onboarding,
41
+ and technical access controls.
42
+
43
+ 6. Trademark and Brand Notice
44
+ 6.1 No trademark rights are granted under this License.
45
+ 6.2 Third-party names, logos, and marks are owned by their respective owners.
46
+ 6.3 Account names and design examples in this repository are for customization/testing
47
+ only and do not represent official brand design systems.
48
+
49
+ 7. Termination
50
+ Any use outside this License terminates your rights immediately.
51
+ Upon termination, you must stop use and distribution of the Code.
52
+
53
+ 8. Warranty Disclaimer
54
+ THE CODE IS PROVIDED "AS IS", WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
55
+ EXPRESS OR IMPLIED, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
56
+ AND NON-INFRINGEMENT.
57
+
58
+ 9. Limitation of Liability
59
+ TO THE MAXIMUM EXTENT PERMITTED BY LAW, GENGAGE IS NOT LIABLE FOR ANY INDIRECT,
60
+ INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES, OR ANY LOSS OF DATA,
61
+ REVENUE, PROFITS, OR GOODWILL, ARISING FROM USE OF THE CODE.
package/README.md ADDED
@@ -0,0 +1,232 @@
1
+ # gengage-assistant-fe
2
+
3
+ Source-available frontend widgets for the **Gengage AI Assistant** — embeddable chat,
4
+ contextual Q&A buttons, and a similar-products grid.
5
+
6
+ > **Note:** This repo contains UI and client-side logic only.
7
+ > Backend services are proprietary and require a [gengage.ai](https://gengage.ai) subscription.
8
+ > Use/deployment is intended for Registered Gengage customers connecting to `chatbe.gengage.ai`.
9
+
10
+ > **Legal:** See [LEGAL.md](./LEGAL.md) and [TRADEMARKS.md](./TRADEMARKS.md) for
11
+ > service-access restrictions, branding disclaimers, and license boundaries.
12
+
13
+ ---
14
+
15
+ ## Widgets
16
+
17
+ | Widget | Import path | Description |
18
+ |--------|------------|-------------|
19
+ | **Chat** | `@gengage/assistant-fe/chat` | Floating AI chat drawer with streaming responses |
20
+ | **QNA** | `@gengage/assistant-fe/qna` | Contextual action buttons for product pages |
21
+ | **SimRel** | `@gengage/assistant-fe/simrel` | Similar / related product grid |
22
+
23
+ ---
24
+
25
+ ## Quick Start (CDN embed)
26
+
27
+ ```html
28
+ <script>
29
+ window.__gengageSessionId =
30
+ sessionStorage.getItem('gengage_session_id') ?? crypto.randomUUID();
31
+ sessionStorage.setItem('gengage_session_id', window.__gengageSessionId);
32
+ </script>
33
+ <script src="https://cdn.gengage.ai/widgets/latest/chat.iife.js"></script>
34
+ <script>
35
+ const chat = new GengageChat();
36
+ chat.init({
37
+ accountId: 'YOUR_ACCOUNT_ID',
38
+ middlewareUrl: 'https://YOUR_MIDDLEWARE_URL',
39
+ session: { sessionId: window.__gengageSessionId },
40
+ theme: { primaryColor: '#3b82f6' },
41
+ });
42
+ </script>
43
+ ```
44
+
45
+ ## Quick Start (ES module)
46
+
47
+ ```bash
48
+ npm install @gengage/assistant-fe
49
+ ```
50
+
51
+ ```ts
52
+ import { GengageChat, GengageQNA, GengageSimRel, bootstrapSession, wireQNAToChat } from '@gengage/assistant-fe';
53
+
54
+ const sessionId = bootstrapSession();
55
+
56
+ const chat = new GengageChat();
57
+ await chat.init({ accountId: 'mystore', session: { sessionId } });
58
+
59
+ // On PDP pages — mount QNA buttons and similar products
60
+ const qna = new GengageQNA();
61
+ await qna.init({
62
+ accountId: 'mystore',
63
+ mountTarget: '#qna-section',
64
+ pageContext: { pageType: 'pdp', sku: currentSku },
65
+ session: { sessionId },
66
+ });
67
+
68
+ const simrel = new GengageSimRel();
69
+ await simrel.init({
70
+ accountId: 'mystore',
71
+ sku: currentSku,
72
+ mountTarget: '#similar-section',
73
+ session: { sessionId },
74
+ onAddToCart: ({ sku }) => myCart.add(sku),
75
+ });
76
+
77
+ wireQNAToChat(); // auto-wires QNA button clicks → chat.openWithAction()
78
+ ```
79
+
80
+ ## GTM / Overlay Bootstrap (idempotent, no iframe)
81
+
82
+ ```html
83
+ <script type="module">
84
+ import { initOverlayWidgets } from 'https://cdn.jsdelivr.net/npm/@gengage/assistant-fe/dist/index.js';
85
+
86
+ await initOverlayWidgets({
87
+ accountId: 'koctascomtr',
88
+ middlewareUrl: 'https://chatbe.gengage.ai',
89
+ sku: window.productSku,
90
+ pageContext: { pageType: 'pdp' },
91
+ chat: {
92
+ variant: 'floating',
93
+ mobileBreakpoint: 992,
94
+ mobileInitialState: 'half',
95
+ },
96
+ qna: {
97
+ mountTarget: '#koctas-qna-section',
98
+ },
99
+ simrel: {
100
+ mountTarget: '#koctas-similar-products',
101
+ },
102
+ });
103
+ </script>
104
+ ```
105
+
106
+ `initOverlayWidgets()` is safe to call multiple times from GTM; it de-duplicates by idempotency key.
107
+
108
+ ---
109
+
110
+ ## Repository Structure
111
+
112
+ ```
113
+ gengage-assistant-fe/
114
+ ├── src/
115
+ │ ├── common/ # Shared types, NDJSON stream parser, event bus, BaseWidget
116
+ │ ├── chat/ # Chat widget
117
+ │ │ ├── catalog.ts # json-render component schemas (Zod)
118
+ │ │ ├── types.ts # Config interface + domain types
119
+ │ │ ├── index.ts # Public class GengageChat
120
+ │ │ └── components/ # Vanilla TS renderers (ChatDrawer, AITopPicks, etc.)
121
+ │ ├── qna/ # QNA widget (same structure)
122
+ │ ├── simrel/ # Similar Products widget (same structure)
123
+ │ └── index.ts # Barrel export
124
+ ├── demos/
125
+ │ ├── koctascomtr/ # Koçtaş branded PDP (inline config)
126
+ │ ├── arcelikcomtr/ # Arçelik branded PDP
127
+ │ ├── n11com/ # N11 branded PDP
128
+ │ ├── yatasbeddingcomtr/ # Yataş Bedding branded PDP
129
+ │ ├── hepsiburadacom/ # Hepsiburada branded PDP
130
+ │ ├── vanilla-script/ # IIFE script tags, no bundler
131
+ │ ├── vanilla-esm/ # ESM import, Vite-served
132
+ │ ├── react/ # React CDN + IIFE bundles
133
+ │ ├── nextjs/ # Next.js integration guide
134
+ │ └── native/ # Mobile WebView overlay
135
+ ├── scripts/
136
+ │ └── dev.ts # Dev server entry point (npm run dev)
137
+ ├── docs/
138
+ │ ├── architecture.md # System design and data flows
139
+ │ ├── wire-protocol.md # Backend ↔ frontend NDJSON contract
140
+ │ ├── config-files.md # File-based account configuration contract
141
+ │ └── analytics-contract.md # Analytics + attribution event contract
142
+ └── tests/ # Vitest unit tests + Playwright E2E
143
+ ```
144
+
145
+ ---
146
+
147
+ ## npm Scripts
148
+
149
+ | Command | Description |
150
+ |---------|-------------|
151
+ | `npm run dev -- <accountId> <sku>` | Start local dev server in PDP mode for an account + SKU |
152
+ | `npm run kill` | Kill zombie listeners on ports 3000-3010 |
153
+ | `npm run prerequisites:check` | Validate kickoff prerequisites (docs/config/schema/action routing) |
154
+ | `npm run dev -- koctascomtr --sku=1000465056` | Example: Koçtaş PDP with SKU 1000465056 |
155
+ | `npm run dev -- n11com --sku=ABC123 --port=3005` | Custom port |
156
+ | `npm run build` | Build all widgets to `dist/` |
157
+ | `npm run typecheck` | TypeScript strict check (no emit) |
158
+ | `npm run lint` | ESLint `src/` |
159
+ | `npm run test` | Vitest unit tests |
160
+ | `npm run test:e2e` | Playwright smoke tests |
161
+ | `npm run docs:dev` | VitePress docs server |
162
+
163
+ ### `npm run dev` — Local Widget Test Server
164
+
165
+ The dev server spins up an account-aware PDP host shell with all three widgets initialised
166
+ for the given account and SKU. Every invocation generates fresh UUIDs printed to the console:
167
+
168
+ Current focus is PDP mode (`product details`) with a concrete SKU.
169
+ PLP mode (`category / sku-list`) is planned and will be added as a separate harness flow.
170
+
171
+ ```
172
+ ── Gengage Dev Server ──────────────────────────────
173
+ Account: koctascomtr
174
+ SKU: 1234567
175
+ Page type: pdp
176
+ Session ID: 550e8400-e29b-41d4-a716-446655440000
177
+ User ID: 6ba7b810-9dad-11d1-80b4-00c04fd430c8
178
+ View ID: 6ba7b811-9dad-11d1-80b4-00c04fd430c8
179
+ URL: http://localhost:3000
180
+ ────────────────────────────────────────────────────
181
+ ```
182
+
183
+ The page shows:
184
+ - A dev info banner with all context values
185
+ - A realistic PDP scaffold (gallery, summary, tabs, recommendation rails)
186
+ - The QNA widget mounted at the account's expected selector (for example `#koctas-qna-section`, `#arcelik-qna-section`, `#n11-qna-section`)
187
+ - The SimRel widget mounted at the account's expected selector (for example `#koctas-similar-products`, `#arcelik-similar-products`, `#n11-similar-products`)
188
+ - The Chat floating launcher
189
+
190
+ HMR is active — editing `src/` files updates the page without a full reload.
191
+
192
+ > The dev server serves the account's demo page from `demos/<accountId>/index.html`,
193
+ > generating fresh session/user/view IDs on each start.
194
+
195
+ ---
196
+
197
+ ## Customization
198
+
199
+ Three levels — no fork required for themes, fork required for components:
200
+
201
+ 1. **Theme tokens** — pass a `theme` object to `init()` (CSS custom properties)
202
+ 2. **Component overrides** — replace entries in `components/registry.tsx`
203
+ 3. **Full replacement** — replace all of `components/` (keep `catalog.ts` + `index.ts`)
204
+
205
+ See [CUSTOMIZATION-GUIDE.md](CUSTOMIZATION-GUIDE.md) for details, examples, and fork/customize/deploy guidance.
206
+
207
+ Reference account implementations are in `demos/`. Koçtaş (`demos/koctascomtr/`)
208
+ is the fully-wired reference. Copy it as a starting point for a new account.
209
+
210
+ ---
211
+
212
+ ## Documentation
213
+
214
+ | Doc | Description |
215
+ |-----|-------------|
216
+ | [docs/architecture.md](docs/architecture.md) | System design, data flows, json-render integration |
217
+ | [docs/wire-protocol.md](docs/wire-protocol.md) | Backend ↔ frontend NDJSON contract |
218
+ | [docs/config-files.md](docs/config-files.md) | File-driven self-service account configuration |
219
+ | [docs/analytics-contract.md](docs/analytics-contract.md) | Stream/token/metering/history/checkout analytics contract |
220
+ | [CUSTOMIZATION-GUIDE.md](CUSTOMIZATION-GUIDE.md) | Fork/customize/deploy playbook for integrators and coding agents |
221
+ | [CONTRIBUTION-GUIDE.md](CONTRIBUTION-GUIDE.md) | SDK/core development guide for contributors and coding agents |
222
+
223
+ ---
224
+
225
+ ## License
226
+
227
+ Licensed under the **GENGAGE FRONTEND SOURCE-AVAILABLE LICENSE v1.0** — see [LICENSE](LICENSE).
228
+
229
+ Backend services are proprietary and require a separate [gengage.ai](https://gengage.ai) subscription.
230
+ They are not covered by this license.
231
+
232
+ For trademark and account-design disclaimers, see [TRADEMARKS.md](./TRADEMARKS.md).
@@ -0,0 +1 @@
1
+ .gengage-simrel-container{font-family:var(--gengage-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);font-size:var(--gengage-font-size, 14px);color:var(--gengage-foreground-color, #333)}.gengage-simrel-uispec>*{animation:gengage-simrel-enter .2s cubic-bezier(.2,.72,.2,1) both}@keyframes gengage-simrel-enter{0%{opacity:0;transform:translateY(8px) scale(.99)}to{opacity:1;transform:translateY(0) scale(1)}}.gengage-simrel-grid{display:grid;grid-template-columns:repeat(var(--gengage-simrel-columns, 4),minmax(0,1fr));gap:14px;padding:10px 0 16px}@media(max-width:992px){.gengage-simrel-grid{grid-template-columns:repeat(3,1fr)}}@media(max-width:768px){.gengage-simrel-grid{grid-template-columns:repeat(2,1fr);gap:12px}}.gengage-simrel-card{display:flex;flex-direction:column;border:1px solid #e6e9f0;border-radius:var(--gengage-simrel-card-radius, 14px);overflow:hidden;background:var(--gengage-background-color, #fff);cursor:pointer;transition:box-shadow .16s ease,transform .16s cubic-bezier(.2,.8,.2,1),border-color .16s ease;box-shadow:0 2px 10px #0f172a14}.gengage-simrel-card:hover{border-color:#bfd6ff;border-color:color-mix(in srgb,var(--gengage-primary-color, #3b82f6) 44%,#d1d5db 56%);box-shadow:0 12px 24px #0f172a24;transform:translateY(-2px)}.gengage-simrel-card-image{position:relative;aspect-ratio:1;overflow:hidden;background:radial-gradient(circle at 80% 15%,#94a3b826,#f9fafb 62%)}.gengage-simrel-card-image img{width:100%;height:100%;object-fit:contain;transition:transform .18s ease}.gengage-simrel-card:hover .gengage-simrel-card-image img{transform:scale(1.02)}.gengage-simrel-badge{position:absolute;top:8px;left:8px;padding:2px 8px;border-radius:4px;background:#ef4444;color:#fff;font-size:12px;font-weight:600}.gengage-simrel-card-info{flex:1;padding:12px 12px 10px;display:flex;flex-direction:column;gap:4px}.gengage-simrel-card-brand{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:#6b7280}.gengage-simrel-card-name{font-weight:600;line-height:1.3;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:36px}.gengage-simrel-card-rating{font-size:12px;color:#f59e0b}.gengage-simrel-card-review-count{color:#9ca3af}.gengage-simrel-card-price{margin-top:auto;padding-top:4px;display:flex;align-items:baseline;gap:6px}.gengage-simrel-card-price-original{text-decoration:line-through;color:#9ca3af;font-size:12px}.gengage-simrel-card-price-current{font-weight:700;color:var(--gengage-primary-color, #333)}.gengage-simrel-atc{display:block;width:100%;padding:10px 12px;border:none;border-top:1px solid #e5e7eb;background:transparent;color:var(--gengage-primary-color, #3b82f6);font-weight:600;font-size:inherit;font-family:inherit;cursor:pointer;transition:background-color .2s}.gengage-simrel-atc:hover{background:var(--gengage-primary-color, #3b82f6);color:var(--gengage-primary-foreground, #fff)}.gengage-simrel-quick-actions{display:flex;flex-wrap:wrap;gap:8px;padding:6px 12px 12px}.gengage-simrel-quick-action{border:1px solid #d2d8e3;background:#f8fafc;color:#334155;border-radius:999px;padding:8px 10px;font-size:12px;font-weight:600;cursor:pointer;transition:transform .12s ease,box-shadow .12s ease,border-color .12s ease}.gengage-simrel-quick-action:hover{border-color:var(--gengage-primary-color, #3b82f6);color:var(--gengage-primary-color, #3b82f6);box-shadow:0 6px 14px #0f172a1f;transform:translateY(-1px)}.gengage-simrel-empty{grid-column:1 / -1;text-align:center;padding:40px 20px;color:#6b7280}.gengage-simrel-tabs{display:flex;gap:4px;border-bottom:2px solid #e5e7eb;margin-bottom:16px;overflow-x:auto}.gengage-simrel-tab{padding:10px 14px;border:none;background:transparent;color:#6b7280;font-size:inherit;font-family:inherit;cursor:pointer;white-space:nowrap;border-bottom:2px solid transparent;margin-bottom:-2px;transition:color .2s,border-color .2s}.gengage-simrel-tab:hover{color:var(--gengage-primary-color, #3b82f6)}.gengage-simrel-tab--active{color:var(--gengage-primary-color, #3b82f6);border-bottom-color:var(--gengage-primary-color, #3b82f6);font-weight:600}.gengage-simrel-loading{display:flex;justify-content:center;padding:40px}.gengage-simrel-spinner{width:32px;height:32px;border:3px solid #e5e7eb;border-top-color:var(--gengage-primary-color, #3b82f6);border-radius:50%;animation:gengage-simrel-spin .7s linear infinite}@keyframes gengage-simrel-spin{to{transform:rotate(360deg)}}@media(max-width:768px){.gengage-simrel-grid{gap:10px;padding-top:8px}}@media(prefers-reduced-motion:reduce){.gengage-simrel-uispec>*,.gengage-simrel-card,.gengage-simrel-card-image img,.gengage-simrel-quick-action{animation:none!important;transition:none!important;transform:none!important}}
@@ -0,0 +1,87 @@
1
+ import { StreamEvent, UISpec, PageContext } from '../common/types.js';
2
+ import { ChatTransportConfig } from '../common/api-paths.js';
3
+ export interface BackendRequestMeta {
4
+ outputLanguage: string;
5
+ parentUrl: string;
6
+ windowWidth: string;
7
+ windowHeight: string;
8
+ selfUrl: string;
9
+ id: string;
10
+ userId: string;
11
+ appId: string;
12
+ threads: unknown[];
13
+ createdAt: string;
14
+ kvkkApproved: boolean;
15
+ voiceEnabled: boolean;
16
+ threadId: string;
17
+ isControlGroup: boolean;
18
+ isMobile: boolean;
19
+ viewId?: string;
20
+ }
21
+ export interface ProcessActionRequest {
22
+ account_id: string;
23
+ session_id: string;
24
+ correlation_id: string;
25
+ user_id?: string;
26
+ view_id?: string;
27
+ action: {
28
+ title: string;
29
+ type: string;
30
+ payload?: unknown;
31
+ };
32
+ sku?: string;
33
+ page_type?: string;
34
+ locale?: string;
35
+ meta?: BackendRequestMeta;
36
+ context?: {
37
+ messages?: Array<{
38
+ role: string;
39
+ content: string;
40
+ }>;
41
+ [key: string]: unknown;
42
+ };
43
+ }
44
+ export interface ActionEnrichmentContext {
45
+ pageContext?: PageContext | undefined;
46
+ backendContext?: Record<string, unknown> | null | undefined;
47
+ isMobile?: boolean | undefined;
48
+ }
49
+ /**
50
+ * Enriches action payloads with fields the v1 backend expects.
51
+ * Only adds fields that are not already present in the payload.
52
+ */
53
+ export declare function enrichActionPayload(action: {
54
+ title: string;
55
+ type: string;
56
+ payload?: unknown;
57
+ }, ctx: ActionEnrichmentContext): {
58
+ title: string;
59
+ type: string;
60
+ payload?: unknown;
61
+ };
62
+ export interface StreamCallbacks {
63
+ onTextChunk: (content: string, isFinal: boolean, extra?: {
64
+ productMentions?: Array<{
65
+ sku: string;
66
+ short_name: string;
67
+ }> | undefined;
68
+ skuToProductItem?: Record<string, Record<string, unknown>> | undefined;
69
+ conversationMode?: string | undefined;
70
+ }) => void;
71
+ onUISpec: (spec: UISpec, widget: string, panelHint?: 'panel') => void;
72
+ onAction: (event: StreamEvent) => void;
73
+ onMetadata: (event: StreamEvent) => void;
74
+ onError: (err: Error) => void;
75
+ onDone: () => void;
76
+ }
77
+ export declare function sendChatMessage(request: ProcessActionRequest, callbacks: StreamCallbacks, transport: ChatTransportConfig): AbortController;
78
+ export declare function fetchProactiveAction(request: {
79
+ account_id: string;
80
+ sku?: string;
81
+ page_type?: string;
82
+ }, transport: ChatTransportConfig): Promise<{
83
+ title?: string;
84
+ question?: string;
85
+ actions?: unknown[];
86
+ } | null>;
87
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/chat/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export declare const ALLOWED_MIME_TYPES: readonly ["image/jpeg", "image/png", "image/webp"];
2
+ export declare const MAX_FILE_SIZE: number;
3
+ export type ValidationResult = {
4
+ ok: true;
5
+ } | {
6
+ ok: false;
7
+ reason: 'invalid_type' | 'too_large';
8
+ };
9
+ export declare function validateImageFile(file: File): ValidationResult;
10
+ //# sourceMappingURL=attachment-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-utils.d.ts","sourceRoot":"","sources":["../../src/chat/attachment-utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,oDAAqD,CAAC;AACrF,eAAO,MAAM,aAAa,QAAkB,CAAC;AAE7C,MAAM,MAAM,gBAAgB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CAAA;CAAE,CAAC;AAElG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,gBAAgB,CAQ9D"}