@shop-prompter/react 0.1.1 → 1.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/CHANGELOG.md +12 -0
- package/dist/index.js +1433 -373
- package/dist/index.mjs +1434 -374
- package/package.json +24 -23
- package/src/api/icons.ts +9 -0
- package/src/api/product-api.ts +121 -0
- package/src/api/session-handler.ts +153 -0
- package/src/api/shop-prompter-api.ts +58 -30
- package/src/api/shop-prompter.types.ts +3 -1
- package/src/product-card-list.component.jsx +271 -0
- package/src/shop-prompter.component.jsx +922 -276
- package/src/shop-prompter.service.ts +60 -18
- package/src/thumbs-down-icon.component.jsx +25 -0
- package/src/thumbs-up-icon.component.jsx +25 -0
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { shopPrompterApi } from './api/shop-prompter-api'
|
|
2
|
+
import { productApi } from './api/product-api'
|
|
2
3
|
import { sessionHandler } from './api/session-handler'
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
// Configuration - you can move these to environment variables
|
|
6
|
-
const SHOP_PROMPTER_CONFIG = {
|
|
7
|
-
baseUrl: 'https://demo.dev.shop-prompter.com/touch-points-api',
|
|
8
|
-
apiKey:
|
|
9
|
-
'864c87266ef52c079c09b3248d86b4b5ef430bf9e5a4188476124c93ee2f6dda380f337986837b30b60f73e6aceefe7a0e0f778b3d21a7fa7698cf8546afc709',
|
|
10
|
-
}
|
|
4
|
+
import { ShopPrompterApiConfiguration, ShopPrompterCartOperation } from './api/shop-prompter.types'
|
|
11
5
|
|
|
12
6
|
export interface ChatMessage {
|
|
13
7
|
id: string
|
|
@@ -15,6 +9,7 @@ export interface ChatMessage {
|
|
|
15
9
|
content: string
|
|
16
10
|
productSkus?: string[]
|
|
17
11
|
isStreaming?: boolean
|
|
12
|
+
feedback?: 'upvote' | 'downvote' | null
|
|
18
13
|
}
|
|
19
14
|
|
|
20
15
|
export class ShopPrompterService {
|
|
@@ -22,8 +17,9 @@ export class ShopPrompterService {
|
|
|
22
17
|
private error: string | null = null
|
|
23
18
|
private streamingText = ''
|
|
24
19
|
|
|
25
|
-
constructor() {
|
|
26
|
-
shopPrompterApi.setApiConfig(
|
|
20
|
+
constructor(apiConfig: ShopPrompterApiConfiguration) {
|
|
21
|
+
shopPrompterApi.setApiConfig(apiConfig)
|
|
22
|
+
productApi.setApiConfig(apiConfig)
|
|
27
23
|
sessionHandler.initialize()
|
|
28
24
|
}
|
|
29
25
|
|
|
@@ -34,11 +30,7 @@ export class ShopPrompterService {
|
|
|
34
30
|
onProductSkus?: (skus: string[]) => void
|
|
35
31
|
onComplete?: () => void
|
|
36
32
|
onCartOperation?: (
|
|
37
|
-
operations:
|
|
38
|
-
sku: string
|
|
39
|
-
action: 'add' | 'remove'
|
|
40
|
-
quantity: number
|
|
41
|
-
}[],
|
|
33
|
+
operations: ShopPrompterCartOperation[],
|
|
42
34
|
) => void
|
|
43
35
|
onError?: (error: string) => void
|
|
44
36
|
onLoadingChange?: (loading: boolean) => void
|
|
@@ -53,7 +45,19 @@ export class ShopPrompterService {
|
|
|
53
45
|
const userId = sessionHandler.getUserId()
|
|
54
46
|
const sessionId = sessionHandler.getSessionId()
|
|
55
47
|
|
|
48
|
+
// Persist the user message immediately.
|
|
49
|
+
const userMsgId = Date.now().toString() + '-user'
|
|
50
|
+
sessionHandler.saveUserMessage(sessionId, {
|
|
51
|
+
id: userMsgId,
|
|
52
|
+
role: 'user',
|
|
53
|
+
content: prompt,
|
|
54
|
+
productSkus: [],
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
// Tracking variables for the assistant reply.
|
|
58
|
+
const assistantMsgId = Date.now().toString() + '-assistant'
|
|
56
59
|
let accumulatedText = ''
|
|
60
|
+
let accumulatedSkus: string[] = []
|
|
57
61
|
|
|
58
62
|
try {
|
|
59
63
|
await shopPrompterApi.executeStream(
|
|
@@ -69,6 +73,7 @@ export class ShopPrompterService {
|
|
|
69
73
|
break
|
|
70
74
|
|
|
71
75
|
case 'productSkus':
|
|
76
|
+
accumulatedSkus = event.skus
|
|
72
77
|
callbacks.onProductSkus?.(event.skus)
|
|
73
78
|
break
|
|
74
79
|
|
|
@@ -85,6 +90,13 @@ export class ShopPrompterService {
|
|
|
85
90
|
this.isLoading = false
|
|
86
91
|
callbacks.onLoadingChange?.(false)
|
|
87
92
|
callbacks.onComplete?.()
|
|
93
|
+
// Persist the fully-streamed assistant message.
|
|
94
|
+
sessionHandler.saveAssistantMessage(sessionId, {
|
|
95
|
+
id: assistantMsgId,
|
|
96
|
+
role: 'assistant',
|
|
97
|
+
content: accumulatedText,
|
|
98
|
+
productSkus: accumulatedSkus,
|
|
99
|
+
})
|
|
88
100
|
break
|
|
89
101
|
|
|
90
102
|
case 'error':
|
|
@@ -92,6 +104,7 @@ export class ShopPrompterService {
|
|
|
92
104
|
this.isLoading = false
|
|
93
105
|
callbacks.onLoadingChange?.(false)
|
|
94
106
|
callbacks.onError?.(event.reason)
|
|
107
|
+
// Do NOT persist a failed assistant message.
|
|
95
108
|
break
|
|
96
109
|
}
|
|
97
110
|
},
|
|
@@ -109,9 +122,6 @@ export class ShopPrompterService {
|
|
|
109
122
|
}
|
|
110
123
|
|
|
111
124
|
public async getAgentExperience() {
|
|
112
|
-
console.log(
|
|
113
|
-
'## ~ ShopPrompterService ~ getAgentExperience ~ getAgentExperience:',
|
|
114
|
-
)
|
|
115
125
|
|
|
116
126
|
try {
|
|
117
127
|
return await shopPrompterApi.getAgentExperience()
|
|
@@ -121,6 +131,38 @@ export class ShopPrompterService {
|
|
|
121
131
|
}
|
|
122
132
|
}
|
|
123
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Load persisted chat messages for the current session from localStorage.
|
|
136
|
+
* Returns an empty array if nothing is stored yet.
|
|
137
|
+
*/
|
|
138
|
+
public loadMessages(): ChatMessage[] {
|
|
139
|
+
const sessionId = sessionHandler.getSessionId()
|
|
140
|
+
const persisted = sessionHandler.loadMessages(sessionId)
|
|
141
|
+
return persisted.map((msg) => ({
|
|
142
|
+
id: msg.id,
|
|
143
|
+
role: msg.role,
|
|
144
|
+
content: msg.content,
|
|
145
|
+
productSkus: msg.productSkus ?? [],
|
|
146
|
+
feedback: msg.feedback ?? null,
|
|
147
|
+
}))
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
public async sendFeedback(
|
|
151
|
+
messageId: string,
|
|
152
|
+
messageContent: string,
|
|
153
|
+
feedback: 'upvote' | 'downvote' | 'clear',
|
|
154
|
+
): Promise<void> {
|
|
155
|
+
const userId = sessionHandler.getUserId()
|
|
156
|
+
const sessionId = sessionHandler.getSessionId()
|
|
157
|
+
const threadId = `${userId}:${sessionId}`
|
|
158
|
+
|
|
159
|
+
await shopPrompterApi.sendFeedback(threadId, messageContent, feedback)
|
|
160
|
+
|
|
161
|
+
// Persist the feedback locally on success.
|
|
162
|
+
const storedFeedback = feedback === 'clear' ? null : feedback
|
|
163
|
+
sessionHandler.updateMessageFeedback(sessionId, messageId, storedFeedback)
|
|
164
|
+
}
|
|
165
|
+
|
|
124
166
|
public resetSession(): void {
|
|
125
167
|
sessionHandler.regenerate()
|
|
126
168
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
function ThumbsDownIcon(props) {
|
|
4
|
+
return (
|
|
5
|
+
<svg
|
|
6
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
+
width="18"
|
|
8
|
+
height="18"
|
|
9
|
+
viewBox="0 0 24 24"
|
|
10
|
+
stroke-width="2"
|
|
11
|
+
stroke-linecap="round"
|
|
12
|
+
stroke-linejoin="round"
|
|
13
|
+
fill={props.fill || "none"}
|
|
14
|
+
stroke={props.stroke || "currentColor"}
|
|
15
|
+
style={{
|
|
16
|
+
overflow: "visible",
|
|
17
|
+
}}
|
|
18
|
+
>
|
|
19
|
+
<path d="M17 14V2" />
|
|
20
|
+
<path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z" />
|
|
21
|
+
</svg>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default ThumbsDownIcon;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
function ThumbsUpIcon(props) {
|
|
4
|
+
return (
|
|
5
|
+
<svg
|
|
6
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
+
width="18"
|
|
8
|
+
height="18"
|
|
9
|
+
viewBox="0 0 24 24"
|
|
10
|
+
stroke-width="2"
|
|
11
|
+
stroke-linecap="round"
|
|
12
|
+
stroke-linejoin="round"
|
|
13
|
+
fill={props.fill || "none"}
|
|
14
|
+
stroke={props.stroke || "currentColor"}
|
|
15
|
+
style={{
|
|
16
|
+
overflow: "visible",
|
|
17
|
+
}}
|
|
18
|
+
>
|
|
19
|
+
<path d="M7 10v12" />
|
|
20
|
+
<path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z" />
|
|
21
|
+
</svg>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default ThumbsUpIcon;
|