@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.
- package/LICENSE +61 -0
- package/README.md +232 -0
- package/dist/assistant-fe.css +1 -0
- package/dist/chat/api.d.ts +87 -0
- package/dist/chat/api.d.ts.map +1 -0
- package/dist/chat/attachment-utils.d.ts +10 -0
- package/dist/chat/attachment-utils.d.ts.map +1 -0
- package/dist/chat/catalog.d.ts +1114 -0
- package/dist/chat/catalog.d.ts.map +1 -0
- package/dist/chat/components/AIGroupingCards.d.ts +4 -0
- package/dist/chat/components/AIGroupingCards.d.ts.map +1 -0
- package/dist/chat/components/AISuggestedSearchCards.d.ts +4 -0
- package/dist/chat/components/AISuggestedSearchCards.d.ts.map +1 -0
- package/dist/chat/components/AITopPicks.d.ts +4 -0
- package/dist/chat/components/AITopPicks.d.ts.map +1 -0
- package/dist/chat/components/CategoriesContainer.d.ts +4 -0
- package/dist/chat/components/CategoriesContainer.d.ts.map +1 -0
- package/dist/chat/components/ChatDrawer.d.ts +140 -0
- package/dist/chat/components/ChatDrawer.d.ts.map +1 -0
- package/dist/chat/components/ChoicePrompter.d.ts +16 -0
- package/dist/chat/components/ChoicePrompter.d.ts.map +1 -0
- package/dist/chat/components/ComparisonTable.d.ts +47 -0
- package/dist/chat/components/ComparisonTable.d.ts.map +1 -0
- package/dist/chat/components/FloatingComparisonButton.d.ts +11 -0
- package/dist/chat/components/FloatingComparisonButton.d.ts.map +1 -0
- package/dist/chat/components/GroundingReviewCard.d.ts +4 -0
- package/dist/chat/components/GroundingReviewCard.d.ts.map +1 -0
- package/dist/chat/components/KvkkBanner.d.ts +6 -0
- package/dist/chat/components/KvkkBanner.d.ts.map +1 -0
- package/dist/chat/components/Launcher.d.ts +25 -0
- package/dist/chat/components/Launcher.d.ts.map +1 -0
- package/dist/chat/components/PanelTopBar.d.ts +20 -0
- package/dist/chat/components/PanelTopBar.d.ts.map +1 -0
- package/dist/chat/components/ProactivePopup.d.ts +11 -0
- package/dist/chat/components/ProactivePopup.d.ts.map +1 -0
- package/dist/chat/components/ProsAndCons.d.ts +9 -0
- package/dist/chat/components/ProsAndCons.d.ts.map +1 -0
- package/dist/chat/components/ReviewHighlights.d.ts +3 -0
- package/dist/chat/components/ReviewHighlights.d.ts.map +1 -0
- package/dist/chat/components/ThumbnailsColumn.d.ts +23 -0
- package/dist/chat/components/ThumbnailsColumn.d.ts.map +1 -0
- package/dist/chat/components/actionClassifier.d.ts +13 -0
- package/dist/chat/components/actionClassifier.d.ts.map +1 -0
- package/dist/chat/components/productMentionLinker.d.ts +26 -0
- package/dist/chat/components/productMentionLinker.d.ts.map +1 -0
- package/dist/chat/components/renderUISpec.d.ts +15 -0
- package/dist/chat/components/renderUISpec.d.ts.map +1 -0
- package/dist/chat/components/typewriter.d.ts +25 -0
- package/dist/chat/components/typewriter.d.ts.map +1 -0
- package/dist/chat/extendedModeManager.d.ts +33 -0
- package/dist/chat/extendedModeManager.d.ts.map +1 -0
- package/dist/chat/index.d.ts +192 -0
- package/dist/chat/index.d.ts.map +1 -0
- package/dist/chat/locales/en.d.ts +3 -0
- package/dist/chat/locales/en.d.ts.map +1 -0
- package/dist/chat/locales/index.d.ts +6 -0
- package/dist/chat/locales/index.d.ts.map +1 -0
- package/dist/chat/locales/tr.d.ts +3 -0
- package/dist/chat/locales/tr.d.ts.map +1 -0
- package/dist/chat/types.d.ts +212 -0
- package/dist/chat/types.d.ts.map +1 -0
- package/dist/chat.cjs +2 -0
- package/dist/chat.cjs.map +1 -0
- package/dist/chat.iife.js +59 -0
- package/dist/chat.iife.js.map +1 -0
- package/dist/chat.js +11 -0
- package/dist/chat.js.map +1 -0
- package/dist/common/action-router.d.ts +30 -0
- package/dist/common/action-router.d.ts.map +1 -0
- package/dist/common/activity-tracker.d.ts +38 -0
- package/dist/common/activity-tracker.d.ts.map +1 -0
- package/dist/common/analytics-events.d.ts +90 -0
- package/dist/common/analytics-events.d.ts.map +1 -0
- package/dist/common/analytics.d.ts +58 -0
- package/dist/common/analytics.d.ts.map +1 -0
- package/dist/common/api-paths.d.ts +14 -0
- package/dist/common/api-paths.d.ts.map +1 -0
- package/dist/common/client.d.ts +20 -0
- package/dist/common/client.d.ts.map +1 -0
- package/dist/common/communication-bridge.d.ts +51 -0
- package/dist/common/communication-bridge.d.ts.map +1 -0
- package/dist/common/config-schema.d.ts +241 -0
- package/dist/common/config-schema.d.ts.map +1 -0
- package/dist/common/context.d.ts +28 -0
- package/dist/common/context.d.ts.map +1 -0
- package/dist/common/customization-factories.d.ts +63 -0
- package/dist/common/customization-factories.d.ts.map +1 -0
- package/dist/common/events.d.ts +47 -0
- package/dist/common/events.d.ts.map +1 -0
- package/dist/common/global-error-toast.d.ts +6 -0
- package/dist/common/global-error-toast.d.ts.map +1 -0
- package/dist/common/index.d.ts +36 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/indexed-db.d.ts +74 -0
- package/dist/common/indexed-db.d.ts.map +1 -0
- package/dist/common/overlay.d.ts +64 -0
- package/dist/common/overlay.d.ts.map +1 -0
- package/dist/common/preflight.d.ts +12 -0
- package/dist/common/preflight.d.ts.map +1 -0
- package/dist/common/renderer/dom.d.ts +4 -0
- package/dist/common/renderer/dom.d.ts.map +1 -0
- package/dist/common/renderer/index.d.ts +5 -0
- package/dist/common/renderer/index.d.ts.map +1 -0
- package/dist/common/renderer/overrides.d.ts +24 -0
- package/dist/common/renderer/overrides.d.ts.map +1 -0
- package/dist/common/renderer/registry.d.ts +3 -0
- package/dist/common/renderer/registry.d.ts.map +1 -0
- package/dist/common/renderer/types.d.ts +20 -0
- package/dist/common/renderer/types.d.ts.map +1 -0
- package/dist/common/safe-html.d.ts +19 -0
- package/dist/common/safe-html.d.ts.map +1 -0
- package/dist/common/streaming.d.ts +32 -0
- package/dist/common/streaming.d.ts.map +1 -0
- package/dist/common/theme-utils.d.ts +16 -0
- package/dist/common/theme-utils.d.ts.map +1 -0
- package/dist/common/types.d.ts +298 -0
- package/dist/common/types.d.ts.map +1 -0
- package/dist/common/ui-theme.d.ts +10 -0
- package/dist/common/ui-theme.d.ts.map +1 -0
- package/dist/common/uuidv7.d.ts +8 -0
- package/dist/common/uuidv7.d.ts.map +1 -0
- package/dist/common/v1-protocol-adapter.d.ts +66 -0
- package/dist/common/v1-protocol-adapter.d.ts.map +1 -0
- package/dist/common/widget-base.d.ts +75 -0
- package/dist/common/widget-base.d.ts.map +1 -0
- package/dist/common.cjs +2 -0
- package/dist/common.cjs.map +1 -0
- package/dist/common.js +584 -0
- package/dist/common.js.map +1 -0
- package/dist/index-CFA70IGF.js +3626 -0
- package/dist/index-CFA70IGF.js.map +1 -0
- package/dist/index-Dfl89zpe.cjs +13 -0
- package/dist/index-Dfl89zpe.cjs.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/qna/api.d.ts +22 -0
- package/dist/qna/api.d.ts.map +1 -0
- package/dist/qna/catalog.d.ts +140 -0
- package/dist/qna/catalog.d.ts.map +1 -0
- package/dist/qna/components/ButtonRow.d.ts +16 -0
- package/dist/qna/components/ButtonRow.d.ts.map +1 -0
- package/dist/qna/components/TextInput.d.ts +12 -0
- package/dist/qna/components/TextInput.d.ts.map +1 -0
- package/dist/qna/components/renderUISpec.d.ts +8 -0
- package/dist/qna/components/renderUISpec.d.ts.map +1 -0
- package/dist/qna/index.d.ts +34 -0
- package/dist/qna/index.d.ts.map +1 -0
- package/dist/qna/locales/en.d.ts +3 -0
- package/dist/qna/locales/en.d.ts.map +1 -0
- package/dist/qna/locales/index.d.ts +6 -0
- package/dist/qna/locales/index.d.ts.map +1 -0
- package/dist/qna/locales/tr.d.ts +3 -0
- package/dist/qna/locales/tr.d.ts.map +1 -0
- package/dist/qna/types.d.ts +62 -0
- package/dist/qna/types.d.ts.map +1 -0
- package/dist/qna.cjs +2 -0
- package/dist/qna.cjs.map +1 -0
- package/dist/qna.css +1 -0
- package/dist/qna.iife.js +48 -0
- package/dist/qna.iife.js.map +1 -0
- package/dist/qna.js +435 -0
- package/dist/qna.js.map +1 -0
- package/dist/simrel/api.d.ts +26 -0
- package/dist/simrel/api.d.ts.map +1 -0
- package/dist/simrel/catalog.d.ts +319 -0
- package/dist/simrel/catalog.d.ts.map +1 -0
- package/dist/simrel/components/GroupTabs.d.ts +17 -0
- package/dist/simrel/components/GroupTabs.d.ts.map +1 -0
- package/dist/simrel/components/ProductCard.d.ts +17 -0
- package/dist/simrel/components/ProductCard.d.ts.map +1 -0
- package/dist/simrel/components/ProductGrid.d.ts +17 -0
- package/dist/simrel/components/ProductGrid.d.ts.map +1 -0
- package/dist/simrel/components/renderUISpec.d.ts +8 -0
- package/dist/simrel/components/renderUISpec.d.ts.map +1 -0
- package/dist/simrel/index.d.ts +36 -0
- package/dist/simrel/index.d.ts.map +1 -0
- package/dist/simrel/locales/en.d.ts +3 -0
- package/dist/simrel/locales/en.d.ts.map +1 -0
- package/dist/simrel/locales/index.d.ts +6 -0
- package/dist/simrel/locales/index.d.ts.map +1 -0
- package/dist/simrel/locales/tr.d.ts +3 -0
- package/dist/simrel/locales/tr.d.ts.map +1 -0
- package/dist/simrel/types.d.ts +111 -0
- package/dist/simrel/types.d.ts.map +1 -0
- package/dist/simrel.cjs +2 -0
- package/dist/simrel.cjs.map +1 -0
- package/dist/simrel.css +1 -0
- package/dist/simrel.iife.js +48 -0
- package/dist/simrel.iife.js.map +1 -0
- package/dist/simrel.js +620 -0
- package/dist/simrel.js.map +1 -0
- package/dist/types-CeON7iBO.cjs +48 -0
- package/dist/types-CeON7iBO.cjs.map +1 -0
- package/dist/types-yxW8WA7u.js +4132 -0
- package/dist/types-yxW8WA7u.js.map +1 -0
- 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"}
|