@flamingo-stack/openframe-frontend-core 0.0.550 → 0.0.551
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/dist/chat-protocol/events.d.ts +2 -0
- package/dist/chat-protocol/events.d.ts.map +1 -1
- package/dist/chat-protocol/index.cjs +1 -0
- package/dist/chat-protocol/index.cjs.map +1 -1
- package/dist/chat-protocol/index.js +1 -0
- package/dist/chat-protocol/index.js.map +1 -1
- package/dist/chat-protocol/nats-decoder.d.ts.map +1 -1
- package/dist/{chunk-WTCXDYK7.js → chunk-2YLMNXLB.js} +2 -2
- package/dist/{chunk-4A5RDQ6L.cjs → chunk-72ZPQTPN.cjs} +61 -61
- package/dist/{chunk-4A5RDQ6L.cjs.map → chunk-72ZPQTPN.cjs.map} +1 -1
- package/dist/{chunk-EVCAPL5A.cjs → chunk-AK4LW6PF.cjs} +39 -39
- package/dist/{chunk-EVCAPL5A.cjs.map → chunk-AK4LW6PF.cjs.map} +1 -1
- package/dist/{chunk-LDS54O26.cjs → chunk-CPADTPX4.cjs} +15 -7
- package/dist/chunk-CPADTPX4.cjs.map +1 -0
- package/dist/{chunk-HWYUSB5A.js → chunk-EFNDA2CG.js} +2 -2
- package/dist/{chunk-5KAQ2JUQ.js → chunk-EZIKNMYV.js} +2 -2
- package/dist/{chunk-LLBU7RI5.cjs → chunk-H4OIDXP4.cjs} +27 -27
- package/dist/{chunk-LLBU7RI5.cjs.map → chunk-H4OIDXP4.cjs.map} +1 -1
- package/dist/{chunk-6RTSYEBE.js → chunk-H4RHXJHF.js} +2 -2
- package/dist/{chunk-IRV6TOEZ.js → chunk-IFH47QXW.js} +2 -2
- package/dist/{chunk-JS7FDV27.js → chunk-JI4JR3KC.js} +15 -7
- package/dist/chunk-JI4JR3KC.js.map +1 -0
- package/dist/{chunk-A4L6BEB7.cjs → chunk-MEY3PYOL.cjs} +7 -7
- package/dist/{chunk-A4L6BEB7.cjs.map → chunk-MEY3PYOL.cjs.map} +1 -1
- package/dist/{chunk-ISCWUJ72.cjs → chunk-MKDL3S4U.cjs} +3 -3
- package/dist/{chunk-ISCWUJ72.cjs.map → chunk-MKDL3S4U.cjs.map} +1 -1
- package/dist/{chunk-U7UPMD3Z.js → chunk-MVK7SNVO.js} +4 -4
- package/dist/{chunk-H7ORFGB6.cjs → chunk-NRTKEPUX.cjs} +11 -11
- package/dist/{chunk-H7ORFGB6.cjs.map → chunk-NRTKEPUX.cjs.map} +1 -1
- package/dist/{chunk-5VGIDZAM.js → chunk-NVK7YZHN.js} +2 -2
- package/dist/{chunk-6M6EZK4R.cjs → chunk-O24VSDVN.cjs} +31 -31
- package/dist/{chunk-6M6EZK4R.cjs.map → chunk-O24VSDVN.cjs.map} +1 -1
- package/dist/{chunk-7T2HI44L.js → chunk-OMSEQDCU.js} +2 -2
- package/dist/{chunk-ISLQTWWW.cjs → chunk-PPPIBTCO.cjs} +9 -9
- package/dist/{chunk-ISLQTWWW.cjs.map → chunk-PPPIBTCO.cjs.map} +1 -1
- package/dist/{chunk-M3GOE7OF.js → chunk-RJFD55SK.js} +2 -2
- package/dist/{chunk-R7RCGLII.js → chunk-SWDTM5O6.js} +5 -5
- package/dist/{chunk-MGRCFN2K.cjs → chunk-T2JKOG6K.cjs} +5 -5
- package/dist/{chunk-MGRCFN2K.cjs.map → chunk-T2JKOG6K.cjs.map} +1 -1
- package/dist/{chunk-XO4YU5GN.js → chunk-TXFJFO4A.js} +2 -2
- package/dist/{chunk-GXNSFW3N.cjs → chunk-V3HNIPTE.cjs} +20 -20
- package/dist/{chunk-GXNSFW3N.cjs.map → chunk-V3HNIPTE.cjs.map} +1 -1
- package/dist/{chunk-7YDLMRVR.js → chunk-V5PDJFZS.js} +6 -6
- package/dist/{chunk-UYQFUEIK.cjs → chunk-YA5JDHWE.cjs} +86 -86
- package/dist/{chunk-UYQFUEIK.cjs.map → chunk-YA5JDHWE.cjs.map} +1 -1
- package/dist/{chunk-2I6KJN7F.js → chunk-YEXTFNVE.js} +4 -4
- package/dist/{chunk-HCGS2AAS.cjs → chunk-ZDWWXME5.cjs} +14 -14
- package/dist/{chunk-HCGS2AAS.cjs.map → chunk-ZDWWXME5.cjs.map} +1 -1
- package/dist/{chunk-CN2VQPLX.cjs → chunk-ZYQAFJLF.cjs} +4 -4
- package/dist/{chunk-CN2VQPLX.cjs.map → chunk-ZYQAFJLF.cjs.map} +1 -1
- package/dist/components/case-studies/index.cjs +8 -8
- package/dist/components/case-studies/index.js +2 -2
- package/dist/components/chat/index.cjs +2 -2
- package/dist/components/chat/index.js +1 -1
- package/dist/components/chat/stream/chat-stream-reducer.d.ts.map +1 -1
- package/dist/components/chat/ticket-event-message.d.ts +4 -3
- package/dist/components/chat/ticket-event-message.d.ts.map +1 -1
- package/dist/components/chat/types/message.types.d.ts +6 -0
- package/dist/components/chat/types/message.types.d.ts.map +1 -1
- package/dist/components/chat/utils/message-segment-accumulator.d.ts.map +1 -1
- package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +3 -3
- package/dist/components/contact/index.js +2 -2
- package/dist/components/docs/index.cjs +5 -5
- package/dist/components/docs/index.js +4 -4
- package/dist/components/embeds/index.cjs +3 -3
- package/dist/components/embeds/index.js +2 -2
- package/dist/components/faq/index.cjs +3 -3
- package/dist/components/faq/index.js +2 -2
- package/dist/components/features/index.cjs +2 -2
- package/dist/components/features/index.js +1 -1
- package/dist/components/help-center-pages/index.cjs +22 -22
- package/dist/components/help-center-pages/index.js +13 -13
- package/dist/components/index.cjs +131 -131
- package/dist/components/index.js +11 -11
- package/dist/components/meeting-scheduler/index.cjs +28 -28
- package/dist/components/meeting-scheduler/index.js +3 -3
- package/dist/components/navigation/index.cjs +2 -2
- package/dist/components/navigation/index.js +1 -1
- package/dist/components/onboarding-guides/index.cjs +5 -5
- package/dist/components/onboarding-guides/index.js +4 -4
- package/dist/components/related-content/index.cjs +3 -3
- package/dist/components/related-content/index.js +2 -2
- package/dist/components/tickets/index.cjs +6 -6
- package/dist/components/tickets/index.js +5 -5
- package/dist/components/ui/index.cjs +2 -2
- package/dist/components/ui/index.js +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.js +1 -1
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/src/chat-protocol/__tests__/__snapshots__/nats-decoder-golden.test.ts.snap +25 -0
- package/src/chat-protocol/__tests__/nats-decoder-golden.test.ts +17 -0
- package/src/chat-protocol/events.ts +2 -0
- package/src/chat-protocol/nats-decoder.ts +4 -0
- package/src/components/chat/__tests__/ticket-event.test.ts +19 -0
- package/src/components/chat/stream/chat-stream-reducer.ts +1 -0
- package/src/components/chat/ticket-event-message.tsx +18 -8
- package/src/components/chat/types/message.types.ts +6 -0
- package/src/components/chat/utils/message-segment-accumulator.ts +2 -1
- package/src/components/chat/utils/process-historical-messages.ts +5 -0
- package/src/stories/TicketEventMessage.stories.tsx +12 -4
- package/dist/chunk-JS7FDV27.js.map +0 -1
- package/dist/chunk-LDS54O26.cjs.map +0 -1
- /package/dist/{chunk-WTCXDYK7.js.map → chunk-2YLMNXLB.js.map} +0 -0
- /package/dist/{chunk-HWYUSB5A.js.map → chunk-EFNDA2CG.js.map} +0 -0
- /package/dist/{chunk-5KAQ2JUQ.js.map → chunk-EZIKNMYV.js.map} +0 -0
- /package/dist/{chunk-6RTSYEBE.js.map → chunk-H4RHXJHF.js.map} +0 -0
- /package/dist/{chunk-IRV6TOEZ.js.map → chunk-IFH47QXW.js.map} +0 -0
- /package/dist/{chunk-U7UPMD3Z.js.map → chunk-MVK7SNVO.js.map} +0 -0
- /package/dist/{chunk-5VGIDZAM.js.map → chunk-NVK7YZHN.js.map} +0 -0
- /package/dist/{chunk-7T2HI44L.js.map → chunk-OMSEQDCU.js.map} +0 -0
- /package/dist/{chunk-M3GOE7OF.js.map → chunk-RJFD55SK.js.map} +0 -0
- /package/dist/{chunk-R7RCGLII.js.map → chunk-SWDTM5O6.js.map} +0 -0
- /package/dist/{chunk-XO4YU5GN.js.map → chunk-TXFJFO4A.js.map} +0 -0
- /package/dist/{chunk-7YDLMRVR.js.map → chunk-V5PDJFZS.js.map} +0 -0
- /package/dist/{chunk-2I6KJN7F.js.map → chunk-YEXTFNVE.js.map} +0 -0
package/package.json
CHANGED
|
@@ -412,9 +412,30 @@ exports[`decodeNatsChunk — golden corpus > maps the full recorded corpus to no
|
|
|
412
412
|
"actorType": undefined,
|
|
413
413
|
"kind": "RESOLVED",
|
|
414
414
|
"reason": undefined,
|
|
415
|
+
"targetStatusKind": undefined,
|
|
416
|
+
"type": "ticket-event",
|
|
417
|
+
},
|
|
418
|
+
"ticket_event_blank_target_kind_dropped": {
|
|
419
|
+
"actorId": undefined,
|
|
420
|
+
"actorName": undefined,
|
|
421
|
+
"actorType": undefined,
|
|
422
|
+
"kind": "REOPENED",
|
|
423
|
+
"reason": undefined,
|
|
424
|
+
"seq": 415,
|
|
425
|
+
"targetStatusKind": undefined,
|
|
415
426
|
"type": "ticket-event",
|
|
416
427
|
},
|
|
417
428
|
"ticket_event_missing_kind": null,
|
|
429
|
+
"ticket_event_reopened_target_kind": {
|
|
430
|
+
"actorId": "user-42",
|
|
431
|
+
"actorName": "John Smith",
|
|
432
|
+
"actorType": "CLIENT",
|
|
433
|
+
"kind": "REOPENED",
|
|
434
|
+
"reason": undefined,
|
|
435
|
+
"seq": 414,
|
|
436
|
+
"targetStatusKind": "AI_ASSISTANCE",
|
|
437
|
+
"type": "ticket-event",
|
|
438
|
+
},
|
|
418
439
|
"ticket_event_reopened_with_reason": {
|
|
419
440
|
"actorId": "user-42",
|
|
420
441
|
"actorName": "John Smith",
|
|
@@ -422,6 +443,7 @@ exports[`decodeNatsChunk — golden corpus > maps the full recorded corpus to no
|
|
|
422
443
|
"kind": "REOPENED",
|
|
423
444
|
"reason": "The printer stopped working again",
|
|
424
445
|
"seq": 413,
|
|
446
|
+
"targetStatusKind": undefined,
|
|
425
447
|
"type": "ticket-event",
|
|
426
448
|
},
|
|
427
449
|
"ticket_event_resolved": {
|
|
@@ -431,6 +453,7 @@ exports[`decodeNatsChunk — golden corpus > maps the full recorded corpus to no
|
|
|
431
453
|
"kind": "RESOLVED",
|
|
432
454
|
"reason": undefined,
|
|
433
455
|
"seq": 412,
|
|
456
|
+
"targetStatusKind": undefined,
|
|
434
457
|
"type": "ticket-event",
|
|
435
458
|
},
|
|
436
459
|
"ticket_event_stream_seq_wins": {
|
|
@@ -440,6 +463,7 @@ exports[`decodeNatsChunk — golden corpus > maps the full recorded corpus to no
|
|
|
440
463
|
"kind": "RESOLVED",
|
|
441
464
|
"reason": undefined,
|
|
442
465
|
"seq": 500,
|
|
466
|
+
"targetStatusKind": undefined,
|
|
443
467
|
"type": "ticket-event",
|
|
444
468
|
},
|
|
445
469
|
"ticket_event_unknown_kind": {
|
|
@@ -448,6 +472,7 @@ exports[`decodeNatsChunk — golden corpus > maps the full recorded corpus to no
|
|
|
448
472
|
"actorType": undefined,
|
|
449
473
|
"kind": "ON_HOLD",
|
|
450
474
|
"reason": undefined,
|
|
475
|
+
"targetStatusKind": undefined,
|
|
451
476
|
"type": "ticket-event",
|
|
452
477
|
},
|
|
453
478
|
"token_usage": {
|
|
@@ -279,6 +279,23 @@ const CORPUS: Record<string, unknown> = {
|
|
|
279
279
|
sequenceId: 413,
|
|
280
280
|
},
|
|
281
281
|
ticket_event_unknown_kind: { type: 'TICKET_EVENT', kind: 'ON_HOLD', actorName: 'Roman Smith' },
|
|
282
|
+
// Where the ticket reopened INTO - decides the card's subtitle without
|
|
283
|
+
// guessing from the actor. Blank strings are folded to undefined.
|
|
284
|
+
ticket_event_reopened_target_kind: {
|
|
285
|
+
type: 'TICKET_EVENT',
|
|
286
|
+
kind: 'REOPENED',
|
|
287
|
+
actorId: 'user-42',
|
|
288
|
+
actorName: 'John Smith',
|
|
289
|
+
actorType: 'CLIENT',
|
|
290
|
+
targetStatusKind: 'AI_ASSISTANCE',
|
|
291
|
+
streamSeq: 414,
|
|
292
|
+
},
|
|
293
|
+
ticket_event_blank_target_kind_dropped: {
|
|
294
|
+
type: 'TICKET_EVENT',
|
|
295
|
+
kind: 'REOPENED',
|
|
296
|
+
targetStatusKind: ' ',
|
|
297
|
+
streamSeq: 415,
|
|
298
|
+
},
|
|
282
299
|
ticket_event_missing_kind: { type: 'TICKET_EVENT', actorName: 'Fae' },
|
|
283
300
|
ticket_event_blank_reason_dropped: { type: 'TICKET_EVENT', kind: 'RESOLVED', reason: ' ' },
|
|
284
301
|
// Transport-stamped streamSeq wins over the payload's sequenceId copy.
|
|
@@ -264,6 +264,8 @@ export interface TicketEventEvent extends ChatStreamEventBase {
|
|
|
264
264
|
/** Who acted — e.g. an AI agent vs a human technician. Open string. */
|
|
265
265
|
actorType?: string
|
|
266
266
|
reason?: string
|
|
267
|
+
/** Kind-token the ticket reopened INTO (AI_ASSISTANCE / TECH_REQUIRED / ...). */
|
|
268
|
+
targetStatusKind?: string
|
|
267
269
|
}
|
|
268
270
|
|
|
269
271
|
/** Per-turn metadata. Raw wire values pass through UNVALIDATED — the
|
|
@@ -393,6 +393,10 @@ export function decodeNatsChunk(chunk: unknown): ChatStreamEvent | null {
|
|
|
393
393
|
actorType: typeof data.actorType === 'string' ? data.actorType : undefined,
|
|
394
394
|
reason:
|
|
395
395
|
typeof data.reason === 'string' && data.reason.trim() ? data.reason : undefined,
|
|
396
|
+
targetStatusKind:
|
|
397
|
+
typeof data.targetStatusKind === 'string' && data.targetStatusKind.trim()
|
|
398
|
+
? data.targetStatusKind
|
|
399
|
+
: undefined,
|
|
396
400
|
...eventSeq,
|
|
397
401
|
}
|
|
398
402
|
}
|
|
@@ -45,6 +45,7 @@ describe('decodeNatsChunk — TICKET_EVENT', () => {
|
|
|
45
45
|
actorName: 'Fae',
|
|
46
46
|
actorType: 'AI',
|
|
47
47
|
reason: undefined,
|
|
48
|
+
targetStatusKind: undefined,
|
|
48
49
|
seq: 7,
|
|
49
50
|
})
|
|
50
51
|
})
|
|
@@ -58,6 +59,15 @@ describe('decodeNatsChunk — TICKET_EVENT', () => {
|
|
|
58
59
|
expect(decodeNatsChunk(resolvedChunk(500, { sequenceId: 499 }))).toMatchObject({ seq: 500 })
|
|
59
60
|
})
|
|
60
61
|
|
|
62
|
+
it('decodes the reopen target kind and folds blanks to undefined', () => {
|
|
63
|
+
expect(
|
|
64
|
+
decodeNatsChunk({ type: 'TICKET_EVENT', kind: 'REOPENED', targetStatusKind: 'TECH_REQUIRED', streamSeq: 8 }),
|
|
65
|
+
).toMatchObject({ targetStatusKind: 'TECH_REQUIRED' })
|
|
66
|
+
expect(
|
|
67
|
+
decodeNatsChunk({ type: 'TICKET_EVENT', kind: 'REOPENED', targetStatusKind: ' ', streamSeq: 9 }),
|
|
68
|
+
).toMatchObject({ targetStatusKind: undefined })
|
|
69
|
+
})
|
|
70
|
+
|
|
61
71
|
it('keeps unknown kinds — the vocabulary is open', () => {
|
|
62
72
|
expect(decodeNatsChunk({ type: 'TICKET_EVENT', kind: 'ON_HOLD', streamSeq: 1 })).toMatchObject({
|
|
63
73
|
type: 'ticket-event',
|
|
@@ -178,6 +188,15 @@ describe('processHistoricalMessages — ticket event', () => {
|
|
|
178
188
|
})
|
|
179
189
|
})
|
|
180
190
|
|
|
191
|
+
it('replays the persisted reopen target kind', () => {
|
|
192
|
+
const { messages } = processHistoricalMessages([
|
|
193
|
+
historyRow('m1', { type: 'TICKET_EVENT', kind: 'REOPENED', targetStatusKind: 'AI_ASSISTANCE' }),
|
|
194
|
+
])
|
|
195
|
+
expect(events(messages[0].content)[0]).toMatchObject({
|
|
196
|
+
data: { kind: 'REOPENED', targetStatusKind: 'AI_ASSISTANCE' },
|
|
197
|
+
})
|
|
198
|
+
})
|
|
199
|
+
|
|
181
200
|
it('keeps an unknown persisted kind renderable', () => {
|
|
182
201
|
const { messages } = processHistoricalMessages([
|
|
183
202
|
historyRow('m1', { type: 'TICKET_EVENT', kind: 'ON_HOLD' }),
|
|
@@ -29,6 +29,14 @@ export interface TicketEventMessageProps extends HTMLAttributes<HTMLDivElement>
|
|
|
29
29
|
timestamp?: Date
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
/** Where the ticket reopened INTO → the "who picks it up next" line.
|
|
33
|
+
* Kind-tokens per the lifecycle statuses; the vocabulary is open, so an
|
|
34
|
+
* unrecognized target falls back to the actor heuristic below. */
|
|
35
|
+
const REOPEN_TARGET_COPY: Record<string, string> = {
|
|
36
|
+
AI_ASSISTANCE: "The AI assistant will continue helping you in this conversation.",
|
|
37
|
+
TECH_REQUIRED: "A technician will reply when available.",
|
|
38
|
+
}
|
|
39
|
+
|
|
32
40
|
/**
|
|
33
41
|
* Ticket lifecycle receipt — resolved / reopened / an unknown future kind.
|
|
34
42
|
* Figma `ai-assistant-info` (type=resolved-fae | resolved-tech |
|
|
@@ -37,15 +45,16 @@ export interface TicketEventMessageProps extends HTMLAttributes<HTMLDivElement>
|
|
|
37
45
|
* Copy is composed client-side from the event's fields (unlike
|
|
38
46
|
* `ticket_escalated`, whose body the backend authors):
|
|
39
47
|
* RESOLVED → "Resolved by {actorName}." under a green check;
|
|
40
|
-
* REOPENED → the reason when the wire carries one
|
|
41
|
-
* conversation up next
|
|
42
|
-
*
|
|
48
|
+
* REOPENED → the reason when the wire carries one; otherwise who picks the
|
|
49
|
+
* conversation up next — `targetStatusKind` decides deterministically,
|
|
50
|
+
* with the `actorType` heuristic as the fallback for older backends
|
|
51
|
+
* that don't send the target;
|
|
43
52
|
* unknown kind → a neutral info line: humanized kind as the title, the
|
|
44
53
|
* reason or actor as the body. Never dropped — the vocabulary is open.
|
|
45
54
|
*/
|
|
46
55
|
const TicketEventMessage = forwardRef<HTMLDivElement, TicketEventMessageProps>(
|
|
47
56
|
({ data, timestamp, ...props }, ref) => {
|
|
48
|
-
const { kind, actorName, actorType, reason } = data
|
|
57
|
+
const { kind, actorName, actorType, reason, targetStatusKind } = data
|
|
49
58
|
const resolved = kind === TICKET_EVENT_KIND.RESOLVED
|
|
50
59
|
const reopened = kind === TICKET_EVENT_KIND.REOPENED
|
|
51
60
|
|
|
@@ -55,11 +64,12 @@ const TicketEventMessage = forwardRef<HTMLDivElement, TicketEventMessageProps>(
|
|
|
55
64
|
if (resolved) {
|
|
56
65
|
body = actorName ? `Resolved by ${actorName}.` : "The ticket has been resolved."
|
|
57
66
|
} else if (reopened) {
|
|
58
|
-
body =
|
|
59
|
-
? `Reason: ${reason}`
|
|
60
|
-
:
|
|
67
|
+
body =
|
|
68
|
+
(reason ? `Reason: ${reason}` : undefined) ??
|
|
69
|
+
(targetStatusKind ? REOPEN_TARGET_COPY[targetStatusKind] : undefined) ??
|
|
70
|
+
(isAiActor(actorType)
|
|
61
71
|
? `${actorName || "Fae"} will continue assisting in this conversation.`
|
|
62
|
-
: "A technician will reply when available."
|
|
72
|
+
: "A technician will reply when available.")
|
|
63
73
|
} else {
|
|
64
74
|
body = reason || (actorName ? `By ${actorName}.` : undefined)
|
|
65
75
|
}
|
|
@@ -185,6 +185,11 @@ export interface TicketEventData {
|
|
|
185
185
|
/** Who acted — e.g. an AI agent vs a human. Open string like `kind`. */
|
|
186
186
|
actorType?: string
|
|
187
187
|
reason?: string
|
|
188
|
+
/** Kind-token of the status the ticket reopened INTO (AI_ASSISTANCE /
|
|
189
|
+
* TECH_REQUIRED / CUSTOM / ...) — same open vocabulary the lifecycle
|
|
190
|
+
* statuses use. Picks the REOPENED card's subtitle deterministically;
|
|
191
|
+
* absent on RESOLVED events and older backends. */
|
|
192
|
+
targetStatusKind?: string
|
|
188
193
|
}
|
|
189
194
|
|
|
190
195
|
/**
|
|
@@ -483,6 +488,7 @@ export interface TicketEventMessageData extends MessageDataBase {
|
|
|
483
488
|
actorName?: string | null
|
|
484
489
|
actorType?: string | null
|
|
485
490
|
reason?: string | null
|
|
491
|
+
targetStatusKind?: string | null
|
|
486
492
|
}
|
|
487
493
|
|
|
488
494
|
export interface ErrorMessageData extends MessageDataBase {
|
|
@@ -562,7 +562,8 @@ export class MessageSegmentAccumulator {
|
|
|
562
562
|
s.data.actorId === data.actorId &&
|
|
563
563
|
s.data.actorName === data.actorName &&
|
|
564
564
|
s.data.actorType === data.actorType &&
|
|
565
|
-
s.data.reason === data.reason
|
|
565
|
+
s.data.reason === data.reason &&
|
|
566
|
+
s.data.targetStatusKind === data.targetStatusKind
|
|
566
567
|
)
|
|
567
568
|
})
|
|
568
569
|
if (existingIndex !== -1) {
|
|
@@ -257,6 +257,10 @@ export function decodeHistoricalMessageData(data: MessageData): ChatStreamEvent
|
|
|
257
257
|
actorName: typeof data.actorName === 'string' ? data.actorName : undefined,
|
|
258
258
|
actorType: typeof data.actorType === 'string' ? data.actorType : undefined,
|
|
259
259
|
reason: typeof data.reason === 'string' && data.reason.trim() ? data.reason : undefined,
|
|
260
|
+
targetStatusKind:
|
|
261
|
+
typeof data.targetStatusKind === 'string' && data.targetStatusKind.trim()
|
|
262
|
+
? data.targetStatusKind
|
|
263
|
+
: undefined,
|
|
260
264
|
}
|
|
261
265
|
}
|
|
262
266
|
|
|
@@ -364,6 +368,7 @@ function applyHistoryEvent(
|
|
|
364
368
|
actorName: event.actorName,
|
|
365
369
|
actorType: event.actorType,
|
|
366
370
|
reason: event.reason,
|
|
371
|
+
targetStatusKind: event.targetStatusKind,
|
|
367
372
|
})
|
|
368
373
|
break
|
|
369
374
|
|
|
@@ -71,18 +71,26 @@ export const ReopenedWithReason: Story = {
|
|
|
71
71
|
},
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
-
/** Reopened
|
|
74
|
+
/** Reopened into AI Assistance (targetStatusKind decides) — Figma type=reopened-fae. */
|
|
75
75
|
export const ReopenedFaeContinues: Story = {
|
|
76
76
|
args: {
|
|
77
|
-
data: { kind: "REOPENED", actorId: "
|
|
77
|
+
data: { kind: "REOPENED", actorId: "u-7", actorName: "John Smith", actorType: "CLIENT", targetStatusKind: "AI_ASSISTANCE" },
|
|
78
78
|
timestamp: TIMESTAMP,
|
|
79
79
|
},
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
-
/** Reopened
|
|
82
|
+
/** Reopened into Tech Required (targetStatusKind decides) — Figma type=reopened-tech. */
|
|
83
83
|
export const ReopenedTechnicianReplies: Story = {
|
|
84
84
|
args: {
|
|
85
|
-
data: { kind: "REOPENED", actorId: "u-
|
|
85
|
+
data: { kind: "REOPENED", actorId: "u-7", actorName: "John Smith", actorType: "CLIENT", targetStatusKind: "TECH_REQUIRED" },
|
|
86
|
+
timestamp: TIMESTAMP,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/** Older backend without targetStatusKind — the actorType heuristic still decides. */
|
|
91
|
+
export const ReopenedLegacyActorFallback: Story = {
|
|
92
|
+
args: {
|
|
93
|
+
data: { kind: "REOPENED", actorId: "fae", actorName: "Fae", actorType: "AI" },
|
|
86
94
|
timestamp: TIMESTAMP,
|
|
87
95
|
},
|
|
88
96
|
};
|