@csntgao/uni-base 0.6.3 → 0.6.6

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 (35) hide show
  1. package/AGENTS.md +10 -8
  2. package/CLAUDE.md +10 -8
  3. package/README.md +27 -21
  4. package/docs//346/225/260/345/255/227/345/221/230/345/267/245/345/256/214/346/225/264/346/212/275/345/261/211/346/216/245/345/205/245/350/257/264/346/230/216.md +46 -0
  5. package/docs//347/273/204/347/273/207/345/221/230/345/267/245/345/215/225/351/200/211/347/273/204/344/273/266/346/216/245/345/205/245/350/257/264/346/230/216.md +1 -1
  6. package/docs//347/273/204/347/273/207/345/221/230/345/267/245/345/244/232/351/200/211/347/273/204/344/273/266/346/216/245/345/205/245/350/257/264/346/230/216.md +1 -1
  7. package/examples/vanilla/main.js +1 -1
  8. package/examples/vanilla/package.json +3 -3
  9. package/package.json +12 -13
  10. package/packages/core/package.json +2 -2
  11. package/packages/core/src/assistant-actions.ts +120 -0
  12. package/packages/core/src/customer-support-types.ts +15 -0
  13. package/packages/core/src/index.ts +8 -0
  14. package/packages/core/src/types.ts +6 -0
  15. package/packages/core/tests/assistant-actions.test.ts +76 -0
  16. package/packages/web-components/package.json +3 -3
  17. package/packages/web-components/scripts/verify-runtime-build.mjs +1 -0
  18. package/packages/web-components/src/chat.ts +267 -15
  19. package/packages/web-components/src/customer-support-chat.ts +1 -1
  20. package/packages/web-components/src/customer-support-transport.ts +118 -16
  21. package/packages/web-components/src/index.ts +14 -2
  22. package/packages/web-components/src/notification-center.ts +1 -1
  23. package/packages/web-components/src/notification-popover.ts +1 -1
  24. package/packages/web-components/src/uniplat-base-notification-center-transport.ts +1 -1
  25. package/packages/web-components/tests/chat.test.ts +418 -10
  26. package/packages/web-components/tests/customer-support-chat.test.ts +1 -1
  27. package/packages/web-components/tests/customer-support-transport.test.ts +89 -1
  28. package/packages/web-components/tests/notification-center.test.ts +1 -1
  29. package/packages/web-components/tests/notification-popover.test.ts +1 -1
  30. package/packages/web-components/tsup.config.ts +1 -1
  31. package/packages/web-components/tsup.runtime.config.ts +1 -1
  32. package/restart +0 -0
  33. package/tsconfig.base.json +2 -2
  34. package/vitest.config.ts +2 -2
  35. package//344/272/244/346/216/245/346/226/207/346/241/243.md +21 -26
@@ -1,13 +1,15 @@
1
1
  import type {
2
2
  CustomerSupportAgent,
3
3
  CustomerSupportCreateSessionResult,
4
+ CustomerSupportHandoffResult,
4
5
  CustomerSupportMessage,
5
6
  CustomerSupportMessagePage,
6
7
  CustomerSupportSenderType,
7
8
  CustomerSupportSession,
8
9
  CustomerSupportSessionStatus,
9
10
  CustomerSupportTransport,
10
- } from '@uniplat/ai-employee-client'
11
+ } from '@csntgao/ai-employee-client'
12
+ import { isUuidV4 } from '@csntgao/ai-employee-client'
11
13
 
12
14
  export interface HrSaasCustomerSupportTransportOptions {
13
15
  serviceBaseUrl: string
@@ -15,8 +17,30 @@ export interface HrSaasCustomerSupportTransportOptions {
15
17
  fetch?: typeof fetch
16
18
  }
17
19
 
20
+ export type HrSaasCustomerSupportTransportErrorCode =
21
+ | 'AUTH_REQUIRED'
22
+ | 'SOURCE_SESSION_NOT_FOUND'
23
+ | 'SOURCE_SESSION_ACCESS_DENIED'
24
+ | 'HANDOFF_ACTION_NOT_FOUND'
25
+ | 'HANDOFF_ACTION_MISMATCH'
26
+ | 'UNAUTHORIZED'
27
+ | 'CUSTOMER_SUPPORT_UNAVAILABLE'
28
+ | 'REQUEST_FAILED'
29
+ | 'INVALID_RESPONSE'
30
+
31
+ export class HrSaasCustomerSupportTransportError extends Error {
32
+ readonly code: HrSaasCustomerSupportTransportErrorCode
33
+
34
+ constructor(code: HrSaasCustomerSupportTransportErrorCode) {
35
+ super('Customer support request failed')
36
+ this.name = 'HrSaasCustomerSupportTransportError'
37
+ this.code = code
38
+ }
39
+ }
40
+
18
41
  const SESSION_PAGE_ACTION = 'user_session_page'
19
42
  const SESSION_CREATE_ACTION = 'user_session_create'
43
+ const SESSION_HANDOFF_CREATE_ACTION = 'user_session_handoff_create'
20
44
  const SESSION_DETAIL_ACTION = 'user_session_detail'
21
45
  const MESSAGE_PAGE_ACTION = 'user_message_page'
22
46
  const MESSAGE_SEND_ACTION = 'user_message_send'
@@ -63,6 +87,37 @@ export function createHrSaasCustomerSupportTransport(
63
87
  if (parsedInitialMessage) result.initialMessage = parsedInitialMessage
64
88
  return result
65
89
  },
90
+ async createHandoffSession(handoffRequest) {
91
+ const sourceSessionId = requiredText(handoffRequest.sourceSessionId, 128)
92
+ const actionTransactionId = requiredText(handoffRequest.actionTransactionId, 36)
93
+ if (!isUuidV4(actionTransactionId)) {
94
+ throw new HrSaasCustomerSupportTransportError('INVALID_RESPONSE')
95
+ }
96
+ const data = record(
97
+ await request(SESSION_HANDOFF_CREATE_ACTION, {
98
+ source_session_id: sourceSessionId,
99
+ action_transaction_id: actionTransactionId,
100
+ }),
101
+ )
102
+ const session = parseSession(data.session)
103
+ const initialMessage = parseMessage(data.initial_message)
104
+ if (
105
+ !session ||
106
+ !initialMessage ||
107
+ initialMessage.sessionId !== session.id ||
108
+ typeof data.created !== 'boolean' ||
109
+ typeof data.repaired !== 'boolean'
110
+ ) {
111
+ throw new HrSaasCustomerSupportTransportError('INVALID_RESPONSE')
112
+ }
113
+ const result: CustomerSupportHandoffResult = {
114
+ session,
115
+ initialMessage,
116
+ created: data.created,
117
+ repaired: data.repaired,
118
+ }
119
+ return result
120
+ },
66
121
  async getSession(sessionId) {
67
122
  const data = await request(SESSION_DETAIL_ACTION, {
68
123
  session_id: requiredText(sessionId, 128),
@@ -169,27 +224,74 @@ async function requestData(
169
224
  accessToken: string,
170
225
  body: Record<string, unknown>,
171
226
  ): Promise<unknown> {
172
- if (!fetchImplementation) throw new Error('Fetch is unavailable')
173
- const response = await fetchImplementation(endpoint, {
174
- method: 'POST',
175
- credentials: 'include',
176
- headers: {
177
- accept: 'application/json',
178
- authorization: `Bearer ${accessToken}`,
179
- 'content-type': 'application/json',
180
- },
181
- body: JSON.stringify(body),
182
- })
183
- if (!response.ok) throw new Error('Customer support request failed')
184
- const payload: unknown = await response.json()
227
+ if (!fetchImplementation) throw new HrSaasCustomerSupportTransportError('REQUEST_FAILED')
228
+ let response: Response
229
+ try {
230
+ response = await fetchImplementation(endpoint, {
231
+ method: 'POST',
232
+ credentials: 'include',
233
+ headers: {
234
+ accept: 'application/json',
235
+ authorization: `Bearer ${accessToken}`,
236
+ 'content-type': 'application/json',
237
+ },
238
+ body: JSON.stringify(body),
239
+ })
240
+ } catch {
241
+ throw new HrSaasCustomerSupportTransportError('REQUEST_FAILED')
242
+ }
243
+ let payload: unknown = null
244
+ try {
245
+ payload = await response.json()
246
+ } catch {
247
+ if (!response.ok) throw transportResponseError({}, response.status)
248
+ throw new HrSaasCustomerSupportTransportError('INVALID_RESPONSE')
249
+ }
185
250
  const envelope = record(payload)
251
+ if (!response.ok) throw transportResponseError(envelope, response.status)
186
252
  if ('rescode' in envelope) {
187
- if (Number(envelope.rescode) !== 0) throw new Error('Customer support request failed')
253
+ if (Number(envelope.rescode) !== 0) {
254
+ throw transportResponseError(envelope, response.status)
255
+ }
188
256
  return envelope.data
189
257
  }
190
258
  return payload
191
259
  }
192
260
 
261
+ function transportResponseError(
262
+ envelope: Record<string, unknown>,
263
+ status: number,
264
+ ): HrSaasCustomerSupportTransportError {
265
+ const detail = record(envelope.data)
266
+ const error = record(envelope.error)
267
+ const candidate = [
268
+ envelope.error_code,
269
+ envelope.code,
270
+ detail.error_code,
271
+ detail.code,
272
+ error.error_code,
273
+ error.code,
274
+ ].find((value) => typeof value === 'string' && value.trim())
275
+ const code = typeof candidate === 'string' ? candidate.trim().toUpperCase() : ''
276
+ if (isTransportErrorCode(code)) return new HrSaasCustomerSupportTransportError(code)
277
+ if (status === 401) return new HrSaasCustomerSupportTransportError('UNAUTHORIZED')
278
+ if (status === 503) {
279
+ return new HrSaasCustomerSupportTransportError('CUSTOMER_SUPPORT_UNAVAILABLE')
280
+ }
281
+ return new HrSaasCustomerSupportTransportError('REQUEST_FAILED')
282
+ }
283
+
284
+ function isTransportErrorCode(value: string): value is HrSaasCustomerSupportTransportErrorCode {
285
+ return [
286
+ 'SOURCE_SESSION_NOT_FOUND',
287
+ 'SOURCE_SESSION_ACCESS_DENIED',
288
+ 'HANDOFF_ACTION_NOT_FOUND',
289
+ 'HANDOFF_ACTION_MISMATCH',
290
+ 'UNAUTHORIZED',
291
+ 'CUSTOMER_SUPPORT_UNAVAILABLE',
292
+ ].includes(value)
293
+ }
294
+
193
295
  function validateServiceBaseUrl(value: string): string {
194
296
  const raw = typeof value === 'string' ? value.trim() : ''
195
297
  if (!raw) throw new TypeError('Customer support serviceBaseUrl is required')
@@ -216,7 +318,7 @@ async function resolveAccessToken(provider: () => string | Promise<string>): Pro
216
318
  } catch {
217
319
  // Provider details may contain credentials and are intentionally discarded.
218
320
  }
219
- if (!value) throw new Error('Access token is unavailable')
321
+ if (!value) throw new HrSaasCustomerSupportTransportError('AUTH_REQUIRED')
220
322
  return value
221
323
  }
222
324
 
@@ -77,8 +77,20 @@ export type {
77
77
  CustomerSupportChatConfig,
78
78
  CustomerSupportChatEventMap,
79
79
  } from './customer-support-chat'
80
- export { createHrSaasCustomerSupportTransport } from './customer-support-transport'
81
- export type { HrSaasCustomerSupportTransportOptions } from './customer-support-transport'
80
+ export {
81
+ createHrSaasCustomerSupportTransport,
82
+ HrSaasCustomerSupportTransportError,
83
+ } from './customer-support-transport'
84
+ export type {
85
+ HrSaasCustomerSupportTransportErrorCode,
86
+ HrSaasCustomerSupportTransportOptions,
87
+ } from './customer-support-transport'
88
+ export { isUuidV4, parseAiEmployeeAssistantContent } from '@csntgao/ai-employee-client'
89
+ export type {
90
+ AiEmployeeAssistantAction,
91
+ OpenCustomerSupportAssistantAction,
92
+ ParsedAiEmployeeAssistantContent,
93
+ } from '@csntgao/ai-employee-client'
82
94
  export type {
83
95
  NotificationCenterConfig,
84
96
  NotificationCenterEventMap,
@@ -4,7 +4,7 @@ import {
4
4
  type NotificationCenterErrorDetail,
5
5
  type NotificationDto,
6
6
  type NotificationTypeSummary,
7
- } from '@uniplat/ai-employee-client'
7
+ } from '@csntgao/ai-employee-client'
8
8
  import { LitElement, css, html, nothing, type TemplateResult } from 'lit'
9
9
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js'
10
10
  import { renderSafeMarkdown } from './safe-markdown'
@@ -3,7 +3,7 @@ import {
3
3
  type NotificationCenterErrorDetail,
4
4
  type NotificationCenterTransport,
5
5
  type NotificationDto,
6
- } from '@uniplat/ai-employee-client'
6
+ } from '@csntgao/ai-employee-client'
7
7
  import { LitElement, css, html, nothing, type TemplateResult } from 'lit'
8
8
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js'
9
9
  import { prototypeIcon, type PrototypeIconName } from './prototype-icons'
@@ -10,7 +10,7 @@ import type {
10
10
  NotificationResource,
11
11
  NotificationSource,
12
12
  NotificationTypeSummary,
13
- } from '@uniplat/ai-employee-client'
13
+ } from '@csntgao/ai-employee-client'
14
14
 
15
15
  export interface UniplatBaseNotificationCenterTransportOptions {
16
16
  serviceBaseUrl: string