@zeniai/client-epic-state 5.2.4 → 5.2.5
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/lib/epic.js +12 -0
- package/lib/esm/epic.js +12 -0
- package/lib/esm/index.js +2 -2
- package/lib/esm/view/aiCfoView/aiCfoViewReducer.js +411 -9
- package/lib/esm/view/aiCfoView/aiCfoViewSelector.js +49 -0
- package/lib/esm/view/aiCfoView/epics/deleteSkillEpic.js +23 -0
- package/lib/esm/view/aiCfoView/epics/fetchSkillDetailEpic.js +35 -0
- package/lib/esm/view/aiCfoView/epics/fetchSkillVersionBodyEpic.js +45 -0
- package/lib/esm/view/aiCfoView/epics/fetchSkillVersionsEpic.js +37 -0
- package/lib/esm/view/aiCfoView/epics/fetchSkillsEpic.js +11 -6
- package/lib/esm/view/aiCfoView/epics/saveSkillEpic.js +72 -0
- package/lib/esm/view/aiCfoView/epics/setSkillVisibilityEpic.js +32 -0
- package/lib/esm/view/aiCfoView/epics/toSkillDetail.js +102 -0
- package/lib/index.d.ts +3 -3
- package/lib/index.js +26 -11
- package/lib/view/aiCfoView/aiCfoViewPayload.d.ts +85 -0
- package/lib/view/aiCfoView/aiCfoViewReducer.d.ts +67 -2
- package/lib/view/aiCfoView/aiCfoViewReducer.js +413 -10
- package/lib/view/aiCfoView/aiCfoViewSelector.d.ts +7 -1
- package/lib/view/aiCfoView/aiCfoViewSelector.js +54 -0
- package/lib/view/aiCfoView/aiCfoViewState.d.ts +143 -1
- package/lib/view/aiCfoView/epics/deleteSkillEpic.d.ts +8 -0
- package/lib/view/aiCfoView/epics/deleteSkillEpic.js +27 -0
- package/lib/view/aiCfoView/epics/fetchSkillDetailEpic.d.ts +8 -0
- package/lib/view/aiCfoView/epics/fetchSkillDetailEpic.js +39 -0
- package/lib/view/aiCfoView/epics/fetchSkillVersionBodyEpic.d.ts +13 -0
- package/lib/view/aiCfoView/epics/fetchSkillVersionBodyEpic.js +49 -0
- package/lib/view/aiCfoView/epics/fetchSkillVersionsEpic.d.ts +8 -0
- package/lib/view/aiCfoView/epics/fetchSkillVersionsEpic.js +41 -0
- package/lib/view/aiCfoView/epics/fetchSkillsEpic.js +11 -6
- package/lib/view/aiCfoView/epics/saveSkillEpic.d.ts +14 -0
- package/lib/view/aiCfoView/epics/saveSkillEpic.js +76 -0
- package/lib/view/aiCfoView/epics/setSkillVisibilityEpic.d.ts +14 -0
- package/lib/view/aiCfoView/epics/setSkillVisibilityEpic.js +36 -0
- package/lib/view/aiCfoView/epics/toSkillDetail.d.ts +88 -0
- package/lib/view/aiCfoView/epics/toSkillDetail.js +110 -0
- package/lib/view/taskManager/taskListView/taskList.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var _a;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.
|
|
4
|
+
exports.clearSkillDetail = exports.fetchSkillDetailFailure = exports.fetchSkillDetailSuccess = exports.fetchSkillDetail = exports.fetchSkillsFailure = exports.fetchSkillsSuccess = exports.fetchSkills = exports.fetchSuggestedQuestionsFailure = exports.fetchSuggestedQuestionsSuccess = exports.fetchSuggestedQuestions = exports.updateCotCollapsedState = exports.clearDeleteChatSessionStatus = exports.deleteChatSessionFailure = exports.deleteChatSessionSuccess = exports.deleteChatSession = exports.acceptMasterTOSFailure = exports.acceptMasterTOSSuccess = exports.acceptMasterTOS = exports.stopSubmitQuestionFailure = exports.stopSubmitQuestionSuccess = exports.stopSubmitQuestion = exports.stopSubmitFailure = exports.stopSubmitSuccess = exports.stopSubmit = exports.clearLastContextMessage = exports.clearCurrentSessionId = exports.fetchChatHistoryFailure = exports.fetchChatHistorySuccess = exports.fetchChatHistory = exports.fetchChatSessionsForUserFailure = exports.fetchChatSessionsForUserSuccess = exports.fetchChatSessionsForUser = exports.createSessionAndSubmitFailure = exports.createSessionAndSubmitSuccess = exports.initializeNewSessionState = exports.createSessionAndSubmit = exports.createSessionFailure = exports.createSessionSuccess = exports.createSession = exports.setSession = exports.submitFeedbackFailure = exports.submitFeedbackSuccess = exports.submitFeedback = exports.updateCurrentInput = exports.updateAiCfoViewScrollPosition = exports.updateResponseState = exports.submitQuestionFailure = exports.submitQuestionSuccess = exports.submitQuestion = exports.initialAiCfoViewState = void 0;
|
|
5
|
+
exports.clearAiCfoSidePanelHostPageContext = exports.applyAiCfoSidePanelHostPageTransition = exports.closeSkillsBrowser = exports.openSkillsBrowser = exports.setSkillVisibilityFailure = exports.setSkillVisibilitySuccess = exports.setSkillVisibility = exports.saveSkillFailure = exports.saveSkillSuccess = exports.saveSkill = exports.fetchSkillVersionsFailure = exports.fetchSkillVersionsSuccess = exports.fetchSkillVersions = exports.fetchSkillVersionBodyFailure = exports.fetchSkillVersionBodySuccess = exports.fetchSkillVersionBody = exports.deleteSkillFailure = exports.deleteSkillSuccess = exports.deleteSkill = exports.clearSkillMutation = void 0;
|
|
5
6
|
const toolkit_1 = require("@reduxjs/toolkit");
|
|
6
7
|
const rootActions_1 = require("../../rootActions");
|
|
7
8
|
function removeSessionIdFromPageKeyMap(draft, sessionId) {
|
|
@@ -52,8 +53,81 @@ exports.initialAiCfoViewState = {
|
|
|
52
53
|
responseStateByChatSessionId: {},
|
|
53
54
|
stopSubmitStateByChatSessionId: {},
|
|
54
55
|
suggestedQuestionsByPageContext: {},
|
|
55
|
-
|
|
56
|
+
skillDetail: {
|
|
57
|
+
fetchState: 'Not-Started',
|
|
58
|
+
error: undefined,
|
|
59
|
+
detail: undefined,
|
|
60
|
+
macroId: undefined,
|
|
61
|
+
},
|
|
62
|
+
skillMutation: {
|
|
63
|
+
fetchState: 'Not-Started',
|
|
64
|
+
error: undefined,
|
|
65
|
+
savedMacroId: undefined,
|
|
66
|
+
},
|
|
67
|
+
skillVersionBody: {
|
|
68
|
+
fetchState: 'Not-Started',
|
|
69
|
+
error: undefined,
|
|
70
|
+
instructions: undefined,
|
|
71
|
+
macroId: undefined,
|
|
72
|
+
version: undefined,
|
|
73
|
+
},
|
|
74
|
+
skillVersions: {
|
|
75
|
+
fetchState: 'Not-Started',
|
|
76
|
+
error: undefined,
|
|
77
|
+
versions: [],
|
|
78
|
+
macroId: undefined,
|
|
79
|
+
},
|
|
80
|
+
skills: {
|
|
81
|
+
fetchState: 'Not-Started',
|
|
82
|
+
error: undefined,
|
|
83
|
+
deletedMacroIds: [],
|
|
84
|
+
skills: [],
|
|
85
|
+
skillsEnabled: false,
|
|
86
|
+
canPublish: false,
|
|
87
|
+
},
|
|
56
88
|
};
|
|
89
|
+
/**
|
|
90
|
+
* Forget the skill that was open — prompt AND history together.
|
|
91
|
+
*
|
|
92
|
+
* Both, always. They are two slices describing one selection, so clearing only the
|
|
93
|
+
* prompt leaves `skillVersions.macroId` matching: an in-flight history response then
|
|
94
|
+
* passes its own stale-response guard and renders the previous skill's versions under
|
|
95
|
+
* whatever the user opened next.
|
|
96
|
+
*/
|
|
97
|
+
function clearOpenSkillState(draft) {
|
|
98
|
+
draft.skillDetail = {
|
|
99
|
+
fetchState: 'Not-Started',
|
|
100
|
+
error: undefined,
|
|
101
|
+
detail: undefined,
|
|
102
|
+
macroId: undefined,
|
|
103
|
+
};
|
|
104
|
+
draft.skillVersions = {
|
|
105
|
+
fetchState: 'Not-Started',
|
|
106
|
+
error: undefined,
|
|
107
|
+
versions: [],
|
|
108
|
+
macroId: undefined,
|
|
109
|
+
};
|
|
110
|
+
// Part of the same selection: a pinned body left behind would seed a restore form for
|
|
111
|
+
// a skill the user has left.
|
|
112
|
+
draft.skillVersionBody = {
|
|
113
|
+
fetchState: 'Not-Started',
|
|
114
|
+
error: undefined,
|
|
115
|
+
instructions: undefined,
|
|
116
|
+
macroId: undefined,
|
|
117
|
+
version: undefined,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Take the Skills browser down and drop the prompt it had open.
|
|
122
|
+
*
|
|
123
|
+
* Both halves together, always. Closing without clearing leaves the next open landing on
|
|
124
|
+
* the previous skill instead of the list, and leaves a `macroId` that makes an in-flight
|
|
125
|
+
* detail response look current to the stale-response guard.
|
|
126
|
+
*/
|
|
127
|
+
function closeSkillsBrowserState(draft) {
|
|
128
|
+
draft.uiState.isSkillsBrowserOpen = false;
|
|
129
|
+
clearOpenSkillState(draft);
|
|
130
|
+
}
|
|
57
131
|
const aiCfoView = (0, toolkit_1.createSlice)({
|
|
58
132
|
name: 'aiCfoView',
|
|
59
133
|
initialState: exports.initialAiCfoViewState,
|
|
@@ -61,6 +135,16 @@ const aiCfoView = (0, toolkit_1.createSlice)({
|
|
|
61
135
|
submitQuestion: {
|
|
62
136
|
reducer(draft, action) {
|
|
63
137
|
const { sessionId } = action.payload;
|
|
138
|
+
// A turn is being sent, so the chat body has to be what the user sees. Doing this
|
|
139
|
+
// here rather than at each call site is deliberate: the composer, the sample
|
|
140
|
+
// chips, Run, and the `/` menu all submit, and every one of them was a separate
|
|
141
|
+
// chance to forget and leave the answer hidden behind the browser.
|
|
142
|
+
//
|
|
143
|
+
// Guarded so a submit with the browser already closed — i.e. almost every submit
|
|
144
|
+
// — does not produce a new `uiState` for every subscriber to re-render on.
|
|
145
|
+
if (draft.uiState.isSkillsBrowserOpen === true) {
|
|
146
|
+
closeSkillsBrowserState(draft);
|
|
147
|
+
}
|
|
64
148
|
draft.responseStateByChatSessionId[sessionId] = {
|
|
65
149
|
thought: { fetchState: 'In-Progress', error: undefined },
|
|
66
150
|
analysis: { fetchState: 'In-Progress', error: undefined },
|
|
@@ -187,6 +271,13 @@ const aiCfoView = (0, toolkit_1.createSlice)({
|
|
|
187
271
|
setSession(draft, action) {
|
|
188
272
|
draft.uiState.currentChatSessionId = action.payload.sessionId;
|
|
189
273
|
draft.uiState.agentId = action.payload.agentId;
|
|
274
|
+
// Picking a session means wanting to see that chat, so the browser cannot stay over
|
|
275
|
+
// it. In the reducer because there are six dispatch sites across three separate
|
|
276
|
+
// rails, and covering them one at a time missed half of them.
|
|
277
|
+
if (action.payload.isRestore !== true &&
|
|
278
|
+
draft.uiState.isSkillsBrowserOpen === true) {
|
|
279
|
+
closeSkillsBrowserState(draft);
|
|
280
|
+
}
|
|
190
281
|
mirrorCurrentSessionToPageKeyMapIfActive(draft);
|
|
191
282
|
},
|
|
192
283
|
createSession: {
|
|
@@ -206,6 +297,12 @@ const aiCfoView = (0, toolkit_1.createSlice)({
|
|
|
206
297
|
draft.uiState.agentId = agentId;
|
|
207
298
|
draft.createSessionState.fetchState = 'Completed';
|
|
208
299
|
draft.createSessionState.error = undefined;
|
|
300
|
+
// Same invariant as submitQuestion and initializeNewSessionState: a new chat exists
|
|
301
|
+
// and is now current, so the browser cannot stay over it. This is the fifth entry
|
|
302
|
+
// point to that rule — the others are submit, new-session, New Chat and setSession.
|
|
303
|
+
if (draft.uiState.isSkillsBrowserOpen === true) {
|
|
304
|
+
closeSkillsBrowserState(draft);
|
|
305
|
+
}
|
|
209
306
|
draft.uiState.currentChatSessionId = sessionId;
|
|
210
307
|
draft.uiState.lastContextMessage = contextMessage;
|
|
211
308
|
draft.uiState.lastContextStatus = contextStatus;
|
|
@@ -247,6 +344,10 @@ const aiCfoView = (0, toolkit_1.createSlice)({
|
|
|
247
344
|
},
|
|
248
345
|
initializeNewSessionState(draft, action) {
|
|
249
346
|
const { agentId, sessionId } = action.payload;
|
|
347
|
+
// Same invariant as submitQuestion — this is the new-session half of submitting.
|
|
348
|
+
if (draft.uiState.isSkillsBrowserOpen === true) {
|
|
349
|
+
closeSkillsBrowserState(draft);
|
|
350
|
+
}
|
|
250
351
|
draft.uiState.currentChatSessionId = sessionId;
|
|
251
352
|
draft.uiState.agentId = agentId;
|
|
252
353
|
draft.uiState.chatHistoryNextPageToken[sessionId] = {
|
|
@@ -367,6 +468,10 @@ const aiCfoView = (0, toolkit_1.createSlice)({
|
|
|
367
468
|
};
|
|
368
469
|
draft.allChatSessionIds = draft.allChatSessionIds.filter((id) => id !== chatSessionId);
|
|
369
470
|
if (draft.uiState.currentChatSessionId === chatSessionId) {
|
|
471
|
+
// Deliberately does NOT close the Skills browser, unlike the other writers of
|
|
472
|
+
// this field. Deleting a chat from the history list is housekeeping: if the
|
|
473
|
+
// browser is open the user is not looking at that chat, and closing it would
|
|
474
|
+
// yank them out of what they were doing to reveal an empty chat area.
|
|
370
475
|
draft.uiState.currentChatSessionId = undefined;
|
|
371
476
|
draft.uiState.agentId = undefined;
|
|
372
477
|
}
|
|
@@ -419,6 +524,10 @@ const aiCfoView = (0, toolkit_1.createSlice)({
|
|
|
419
524
|
},
|
|
420
525
|
},
|
|
421
526
|
clearCurrentSessionId(draft) {
|
|
527
|
+
// New Chat: the empty composer is the point, so the browser cannot stay over it.
|
|
528
|
+
if (draft.uiState.isSkillsBrowserOpen === true) {
|
|
529
|
+
closeSkillsBrowserState(draft);
|
|
530
|
+
}
|
|
422
531
|
draft.uiState.currentChatSessionId = undefined;
|
|
423
532
|
const key = draft.uiState.aiCfoSidePanelHostPageKey;
|
|
424
533
|
if (key != null) {
|
|
@@ -435,8 +544,24 @@ const aiCfoView = (0, toolkit_1.createSlice)({
|
|
|
435
544
|
draft.uiState.chatSessionIdByPageKey[prevKey] = curId;
|
|
436
545
|
}
|
|
437
546
|
draft.uiState.aiCfoSidePanelHostPageKey = newAiCfoSidePanelHostPageKey;
|
|
438
|
-
|
|
439
|
-
|
|
547
|
+
const nextId = nextCurrentChatSessionId != null ? nextCurrentChatSessionId : undefined;
|
|
548
|
+
// The sixth entry point to the same invariant as submitQuestion,
|
|
549
|
+
// initializeNewSessionState, clearCurrentSessionId, setSession and
|
|
550
|
+
// createSessionSuccess: a different chat is now visible, so the browser cannot stay
|
|
551
|
+
// over it. Missing here, this path swapped the session underneath an open browser
|
|
552
|
+
// and left its macroId looking current to the stale-response guards.
|
|
553
|
+
//
|
|
554
|
+
// Only when the session actually CHANGES, and only when there WAS one. A host page
|
|
555
|
+
// resolving back to the same chat has not changed what is on screen. And
|
|
556
|
+
// `undefined` becoming a saved id is a hydrate, not a navigation — the same
|
|
557
|
+
// settle/restore race `setSession` exempts via `isRestore`: opening Skills on a
|
|
558
|
+
// host page whose chat has not resolved yet would otherwise close the browser
|
|
559
|
+
// under the user the moment the sessions list arrives.
|
|
560
|
+
const hadASession = draft.uiState.currentChatSessionId != null;
|
|
561
|
+
if (hadASession && nextId !== draft.uiState.currentChatSessionId) {
|
|
562
|
+
closeSkillsBrowserState(draft);
|
|
563
|
+
}
|
|
564
|
+
draft.uiState.currentChatSessionId = nextId;
|
|
440
565
|
draft.uiState.currentInput = '';
|
|
441
566
|
mirrorCurrentSessionToPageKeyMapIfActive(draft);
|
|
442
567
|
},
|
|
@@ -481,28 +606,306 @@ const aiCfoView = (0, toolkit_1.createSlice)({
|
|
|
481
606
|
};
|
|
482
607
|
},
|
|
483
608
|
fetchSkills(draft) {
|
|
484
|
-
//
|
|
485
|
-
//
|
|
609
|
+
// Read straight off `draft.skills` — no optional chain. This store is never
|
|
610
|
+
// persisted or rehydrated (no redux-persist anywhere in the repo, and no
|
|
611
|
+
// `preloadedState` in any consumer), and `initialAiCfoViewState` gives every skills
|
|
612
|
+
// slice a concrete value, so an undefined slice is unreachable here rather than
|
|
613
|
+
// merely unlikely. An earlier version of this comment claimed the opposite and
|
|
614
|
+
// justified a guard by a mechanism that does not exist — which then got applied to
|
|
615
|
+
// some accesses and not others, so the file read as if the slice were sometimes
|
|
616
|
+
// missing and sometimes not. The one guard that IS meaningful lives in the
|
|
617
|
+
// selectors, where `state.aiCfoViewState` may genuinely be absent for a host that
|
|
618
|
+
// composes a partial root reducer; that is a boundary, and this is not.
|
|
486
619
|
draft.skills = {
|
|
487
620
|
fetchState: 'In-Progress',
|
|
488
621
|
error: undefined,
|
|
489
|
-
skills: draft.skills
|
|
622
|
+
skills: draft.skills.skills,
|
|
623
|
+
skillsEnabled: draft.skills.skillsEnabled,
|
|
624
|
+
// Carried for the same reason as skillsEnabled: a refetch in flight is not a
|
|
625
|
+
// reason to hide the publish control the user was just looking at.
|
|
626
|
+
canPublish: draft.skills.canPublish,
|
|
627
|
+
// Carried, not cleared: the response this is about to fetch may still contain a
|
|
628
|
+
// skill deleted moments ago, which is the whole reason the list is kept.
|
|
629
|
+
deletedMacroIds: draft.skills.deletedMacroIds,
|
|
490
630
|
};
|
|
491
631
|
},
|
|
492
632
|
fetchSkillsSuccess(draft, action) {
|
|
633
|
+
// A list response can predate a delete — a save emits fetchSkills, and a delete can
|
|
634
|
+
// land while that is still outstanding — so replacing the array wholesale would put
|
|
635
|
+
// the deleted row back and read as the delete having failed.
|
|
493
636
|
draft.skills = {
|
|
494
637
|
fetchState: 'Completed',
|
|
495
638
|
error: undefined,
|
|
496
|
-
skills: action.payload.skills,
|
|
639
|
+
skills: action.payload.skills.filter((skill) => !draft.skills.deletedMacroIds.includes(skill.macroId)),
|
|
640
|
+
skillsEnabled: action.payload.skillsEnabled,
|
|
641
|
+
canPublish: action.payload.canPublish,
|
|
642
|
+
// Applied ONCE, then forgotten — the tombstone covers a race window, not a
|
|
643
|
+
// permanent state.
|
|
644
|
+
//
|
|
645
|
+
// The previous rule (keep it until a response omits that skill) was wrong in the
|
|
646
|
+
// case it was written for: nothing refetches after a delete, and a create emits
|
|
647
|
+
// fetchSkills whose response DOES contain the id, so the tombstone was kept and
|
|
648
|
+
// reapplied forever. A skill recreated under the same id stayed invisible with no
|
|
649
|
+
// way to clear it.
|
|
650
|
+
deletedMacroIds: [],
|
|
497
651
|
};
|
|
498
652
|
},
|
|
499
653
|
fetchSkillsFailure(draft, action) {
|
|
500
654
|
draft.skills = {
|
|
501
655
|
fetchState: 'Error',
|
|
502
656
|
error: action.payload,
|
|
503
|
-
skills: draft.skills
|
|
657
|
+
skills: draft.skills.skills,
|
|
658
|
+
// Kept, not reset: a failed refresh is not evidence the feature was turned
|
|
659
|
+
// off, and dropping it to false would make the Skills entry vanish on any
|
|
660
|
+
// transient error.
|
|
661
|
+
skillsEnabled: draft.skills.skillsEnabled,
|
|
662
|
+
// Same reasoning again: a transient error must not revoke a privilege the server
|
|
663
|
+
// already granted, or the control flickers away on every failed refresh.
|
|
664
|
+
canPublish: draft.skills.canPublish,
|
|
665
|
+
// Same reasoning: a failed refresh is not confirmation the delete was undone.
|
|
666
|
+
deletedMacroIds: draft.skills.deletedMacroIds,
|
|
667
|
+
};
|
|
668
|
+
},
|
|
669
|
+
fetchSkillDetail(draft, action) {
|
|
670
|
+
// Opening a skill IS the selection change, so forget the previous one whole —
|
|
671
|
+
// history included. Resetting only the prompt left `skillVersions.macroId` pointing
|
|
672
|
+
// at the skill just navigated away from, so a history response still in flight for
|
|
673
|
+
// it passed its own guard and rendered under the new title. Close, back and delete
|
|
674
|
+
// all go through the same helper for the same reason.
|
|
675
|
+
clearOpenSkillState(draft);
|
|
676
|
+
draft.skillDetail = {
|
|
677
|
+
fetchState: 'In-Progress',
|
|
678
|
+
error: undefined,
|
|
679
|
+
// Cleared rather than kept: holding the previous skill's prompt while a new
|
|
680
|
+
// one loads would show the wrong instructions under the right title.
|
|
681
|
+
detail: undefined,
|
|
682
|
+
macroId: action.payload.macroId,
|
|
683
|
+
};
|
|
684
|
+
},
|
|
685
|
+
fetchSkillDetailSuccess(draft, action) {
|
|
686
|
+
// Ignore a response for a skill the user has already navigated away from.
|
|
687
|
+
if (draft.skillDetail.macroId !== action.payload.macroId) {
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
draft.skillDetail = {
|
|
691
|
+
fetchState: 'Completed',
|
|
692
|
+
error: undefined,
|
|
693
|
+
detail: action.payload.detail,
|
|
694
|
+
macroId: action.payload.macroId,
|
|
695
|
+
};
|
|
696
|
+
},
|
|
697
|
+
fetchSkillDetailFailure(draft, action) {
|
|
698
|
+
if (draft.skillDetail.macroId !== action.payload.macroId) {
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
draft.skillDetail = {
|
|
702
|
+
fetchState: 'Error',
|
|
703
|
+
error: action.payload.error,
|
|
704
|
+
detail: undefined,
|
|
705
|
+
macroId: action.payload.macroId,
|
|
504
706
|
};
|
|
505
707
|
},
|
|
708
|
+
clearSkillDetail(draft) {
|
|
709
|
+
// Back to the list. History belongs to the detail view, so it goes too.
|
|
710
|
+
clearOpenSkillState(draft);
|
|
711
|
+
},
|
|
712
|
+
fetchSkillVersions: {
|
|
713
|
+
reducer(draft, action) {
|
|
714
|
+
draft.skillVersions = {
|
|
715
|
+
fetchState: 'In-Progress',
|
|
716
|
+
error: undefined,
|
|
717
|
+
// Cleared, not kept: showing the previous skill's history under a new title
|
|
718
|
+
// is worse than showing none while this loads.
|
|
719
|
+
versions: [],
|
|
720
|
+
macroId: action.payload.macroId,
|
|
721
|
+
};
|
|
722
|
+
},
|
|
723
|
+
prepare(payload) {
|
|
724
|
+
return { payload };
|
|
725
|
+
},
|
|
726
|
+
},
|
|
727
|
+
fetchSkillVersionsSuccess(draft, action) {
|
|
728
|
+
// Same stale-response guard as skillDetail: a switchMap cancels the request but
|
|
729
|
+
// cannot un-dispatch one already in flight.
|
|
730
|
+
if (draft.skillVersions.macroId !== action.payload.macroId) {
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
draft.skillVersions.fetchState = 'Completed';
|
|
734
|
+
draft.skillVersions.error = undefined;
|
|
735
|
+
draft.skillVersions.versions = action.payload.versions;
|
|
736
|
+
},
|
|
737
|
+
fetchSkillVersionsFailure(draft, action) {
|
|
738
|
+
if (draft.skillVersions.macroId !== action.payload.macroId) {
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
draft.skillVersions.fetchState = 'Error';
|
|
742
|
+
draft.skillVersions.error = action.payload.error;
|
|
743
|
+
},
|
|
744
|
+
fetchSkillVersionBody: {
|
|
745
|
+
reducer(draft, action) {
|
|
746
|
+
draft.skillVersionBody = {
|
|
747
|
+
fetchState: 'In-Progress',
|
|
748
|
+
error: undefined,
|
|
749
|
+
// Cleared: seeding a restore form from the PREVIOUS version's body is the same
|
|
750
|
+
// class of mistake as showing one skill's prompt under another's title.
|
|
751
|
+
instructions: undefined,
|
|
752
|
+
macroId: action.payload.macroId,
|
|
753
|
+
version: action.payload.version,
|
|
754
|
+
};
|
|
755
|
+
},
|
|
756
|
+
prepare(payload) {
|
|
757
|
+
return { payload };
|
|
758
|
+
},
|
|
759
|
+
},
|
|
760
|
+
fetchSkillVersionBodySuccess(draft, action) {
|
|
761
|
+
// Both parts of the key: a user can jump between versions of the same skill, so
|
|
762
|
+
// macroId alone would let an earlier version's body land on a later request.
|
|
763
|
+
if (draft.skillVersionBody.macroId !== action.payload.macroId ||
|
|
764
|
+
draft.skillVersionBody.version !== action.payload.version) {
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
draft.skillVersionBody.fetchState = 'Completed';
|
|
768
|
+
draft.skillVersionBody.error = undefined;
|
|
769
|
+
draft.skillVersionBody.instructions = action.payload.instructions;
|
|
770
|
+
},
|
|
771
|
+
fetchSkillVersionBodyFailure(draft, action) {
|
|
772
|
+
if (draft.skillVersionBody.macroId !== action.payload.macroId ||
|
|
773
|
+
draft.skillVersionBody.version !== action.payload.version) {
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
draft.skillVersionBody.fetchState = 'Error';
|
|
777
|
+
draft.skillVersionBody.error = action.payload.error;
|
|
778
|
+
},
|
|
779
|
+
saveSkill: {
|
|
780
|
+
reducer(draft) {
|
|
781
|
+
draft.skillMutation = {
|
|
782
|
+
fetchState: 'In-Progress',
|
|
783
|
+
error: undefined,
|
|
784
|
+
savedMacroId: undefined,
|
|
785
|
+
};
|
|
786
|
+
},
|
|
787
|
+
prepare(payload) {
|
|
788
|
+
return { payload };
|
|
789
|
+
},
|
|
790
|
+
},
|
|
791
|
+
saveSkillSuccess(draft, action) {
|
|
792
|
+
draft.skillMutation.fetchState = 'Completed';
|
|
793
|
+
draft.skillMutation.error = undefined;
|
|
794
|
+
draft.skillMutation.savedMacroId = action.payload.macroId;
|
|
795
|
+
// ONLY when the saved skill is still the one on screen. The save is a mergeMap —
|
|
796
|
+
// deliberately not cancellable, because cancelling a write only hides its outcome —
|
|
797
|
+
// so it can land after the user opened another skill, went back to the list, closed
|
|
798
|
+
// the browser, or deleted it. Writing unconditionally would drop one skill's prompt
|
|
799
|
+
// on top of another's, which is precisely what the fetch guards exist to prevent.
|
|
800
|
+
//
|
|
801
|
+
// A create lands here with nothing open, and is deliberately NOT force-opened:
|
|
802
|
+
// `savedMacroId` is the signal for "what did I just create", and the caller decides
|
|
803
|
+
// whether to open it.
|
|
804
|
+
if (draft.skillDetail.macroId !== action.payload.macroId) {
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
// The save response IS a detail read, so adopt it. Discarding it left an editor
|
|
808
|
+
// sitting on the same skill showing the prompt and card it had BEFORE the save —
|
|
809
|
+
// the user's own change missing from the thing they just saved.
|
|
810
|
+
draft.skillDetail = {
|
|
811
|
+
fetchState: 'Completed',
|
|
812
|
+
error: undefined,
|
|
813
|
+
detail: action.payload.detail,
|
|
814
|
+
macroId: action.payload.macroId,
|
|
815
|
+
};
|
|
816
|
+
// History is now a version behind; the epic refetches it.
|
|
817
|
+
draft.skillVersions = {
|
|
818
|
+
fetchState: 'Not-Started',
|
|
819
|
+
error: undefined,
|
|
820
|
+
versions: [],
|
|
821
|
+
macroId: undefined,
|
|
822
|
+
};
|
|
823
|
+
},
|
|
824
|
+
saveSkillFailure(draft, action) {
|
|
825
|
+
draft.skillMutation.fetchState = 'Error';
|
|
826
|
+
draft.skillMutation.error = action.payload;
|
|
827
|
+
},
|
|
828
|
+
setSkillVisibility: {
|
|
829
|
+
reducer(draft) {
|
|
830
|
+
// Shares skillMutation with save and delete. One in-flight write at a time is the
|
|
831
|
+
// existing contract here, and publishing is a write like any other.
|
|
832
|
+
draft.skillMutation = {
|
|
833
|
+
fetchState: 'In-Progress',
|
|
834
|
+
error: undefined,
|
|
835
|
+
savedMacroId: undefined,
|
|
836
|
+
};
|
|
837
|
+
},
|
|
838
|
+
prepare(payload) {
|
|
839
|
+
return { payload };
|
|
840
|
+
},
|
|
841
|
+
},
|
|
842
|
+
setSkillVisibilitySuccess(draft, action) {
|
|
843
|
+
draft.skillMutation.fetchState = 'Completed';
|
|
844
|
+
draft.skillMutation.error = undefined;
|
|
845
|
+
draft.skillMutation.savedMacroId = action.payload.macroId;
|
|
846
|
+
// Same staleness guard as saveSkillSuccess, for the same reason: this is a mergeMap
|
|
847
|
+
// write, so it can land after the user opened another skill.
|
|
848
|
+
if (draft.skillDetail.macroId !== action.payload.macroId) {
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
draft.skillDetail = {
|
|
852
|
+
fetchState: 'Completed',
|
|
853
|
+
error: undefined,
|
|
854
|
+
detail: action.payload.detail,
|
|
855
|
+
macroId: action.payload.macroId,
|
|
856
|
+
};
|
|
857
|
+
// Deliberately NOT clearing skillVersions, unlike saveSkillSuccess. No version was
|
|
858
|
+
// created, so the history the user is looking at is still correct — refetching it
|
|
859
|
+
// would flash a loading state for a list that did not change.
|
|
860
|
+
},
|
|
861
|
+
setSkillVisibilityFailure(draft, action) {
|
|
862
|
+
draft.skillMutation.fetchState = 'Error';
|
|
863
|
+
draft.skillMutation.error = action.payload;
|
|
864
|
+
},
|
|
865
|
+
deleteSkill: {
|
|
866
|
+
reducer(draft) {
|
|
867
|
+
draft.skillMutation = {
|
|
868
|
+
fetchState: 'In-Progress',
|
|
869
|
+
error: undefined,
|
|
870
|
+
savedMacroId: undefined,
|
|
871
|
+
};
|
|
872
|
+
},
|
|
873
|
+
prepare(payload) {
|
|
874
|
+
return { payload };
|
|
875
|
+
},
|
|
876
|
+
},
|
|
877
|
+
deleteSkillSuccess(draft, action) {
|
|
878
|
+
draft.skillMutation.fetchState = 'Completed';
|
|
879
|
+
draft.skillMutation.error = undefined;
|
|
880
|
+
// Drop it from the list immediately rather than waiting for a refetch: the row
|
|
881
|
+
// the user just deleted staying on screen reads as the delete having failed.
|
|
882
|
+
draft.skills.skills = draft.skills.skills.filter((skill) => skill.macroId !== action.payload.macroId);
|
|
883
|
+
if (!draft.skills.deletedMacroIds.includes(action.payload.macroId)) {
|
|
884
|
+
draft.skills.deletedMacroIds.push(action.payload.macroId);
|
|
885
|
+
}
|
|
886
|
+
if (draft.skillDetail.macroId === action.payload.macroId) {
|
|
887
|
+
clearOpenSkillState(draft);
|
|
888
|
+
}
|
|
889
|
+
},
|
|
890
|
+
deleteSkillFailure(draft, action) {
|
|
891
|
+
draft.skillMutation.fetchState = 'Error';
|
|
892
|
+
draft.skillMutation.error = action.payload;
|
|
893
|
+
},
|
|
894
|
+
clearSkillMutation(draft) {
|
|
895
|
+
draft.skillMutation = {
|
|
896
|
+
fetchState: 'Not-Started',
|
|
897
|
+
error: undefined,
|
|
898
|
+
savedMacroId: undefined,
|
|
899
|
+
};
|
|
900
|
+
},
|
|
901
|
+
openSkillsBrowser(draft) {
|
|
902
|
+
draft.uiState.isSkillsBrowserOpen = true;
|
|
903
|
+
},
|
|
904
|
+
closeSkillsBrowser(draft) {
|
|
905
|
+
// Unguarded, unlike the implicit closes: an explicit close should clear a lingering
|
|
906
|
+
// detail even if the flag is already false.
|
|
907
|
+
closeSkillsBrowserState(draft);
|
|
908
|
+
},
|
|
506
909
|
updateCotCollapsedState(draft, action) {
|
|
507
910
|
const { isCollapsed, questionAnswerId } = action.payload;
|
|
508
911
|
draft.uiState.cotCollapsedByQuestionAnswerId[questionAnswerId] =
|
|
@@ -515,5 +918,5 @@ const aiCfoView = (0, toolkit_1.createSlice)({
|
|
|
515
918
|
});
|
|
516
919
|
},
|
|
517
920
|
});
|
|
518
|
-
_a = aiCfoView.actions, exports.submitQuestion = _a.submitQuestion, exports.submitQuestionSuccess = _a.submitQuestionSuccess, exports.submitQuestionFailure = _a.submitQuestionFailure, exports.updateResponseState = _a.updateResponseState, exports.updateAiCfoViewScrollPosition = _a.updateAiCfoViewScrollPosition, exports.updateCurrentInput = _a.updateCurrentInput, exports.submitFeedback = _a.submitFeedback, exports.submitFeedbackSuccess = _a.submitFeedbackSuccess, exports.submitFeedbackFailure = _a.submitFeedbackFailure, exports.setSession = _a.setSession, exports.createSession = _a.createSession, exports.createSessionSuccess = _a.createSessionSuccess, exports.createSessionFailure = _a.createSessionFailure, exports.createSessionAndSubmit = _a.createSessionAndSubmit, exports.initializeNewSessionState = _a.initializeNewSessionState, exports.createSessionAndSubmitSuccess = _a.createSessionAndSubmitSuccess, exports.createSessionAndSubmitFailure = _a.createSessionAndSubmitFailure, exports.fetchChatSessionsForUser = _a.fetchChatSessionsForUser, exports.fetchChatSessionsForUserSuccess = _a.fetchChatSessionsForUserSuccess, exports.fetchChatSessionsForUserFailure = _a.fetchChatSessionsForUserFailure, exports.fetchChatHistory = _a.fetchChatHistory, exports.fetchChatHistorySuccess = _a.fetchChatHistorySuccess, exports.fetchChatHistoryFailure = _a.fetchChatHistoryFailure, exports.clearCurrentSessionId = _a.clearCurrentSessionId, exports.clearLastContextMessage = _a.clearLastContextMessage, exports.stopSubmit = _a.stopSubmit, exports.stopSubmitSuccess = _a.stopSubmitSuccess, exports.stopSubmitFailure = _a.stopSubmitFailure, exports.stopSubmitQuestion = _a.stopSubmitQuestion, exports.stopSubmitQuestionSuccess = _a.stopSubmitQuestionSuccess, exports.stopSubmitQuestionFailure = _a.stopSubmitQuestionFailure, exports.acceptMasterTOS = _a.acceptMasterTOS, exports.acceptMasterTOSSuccess = _a.acceptMasterTOSSuccess, exports.acceptMasterTOSFailure = _a.acceptMasterTOSFailure, exports.deleteChatSession = _a.deleteChatSession, exports.deleteChatSessionSuccess = _a.deleteChatSessionSuccess, exports.deleteChatSessionFailure = _a.deleteChatSessionFailure, exports.clearDeleteChatSessionStatus = _a.clearDeleteChatSessionStatus, exports.updateCotCollapsedState = _a.updateCotCollapsedState, exports.fetchSuggestedQuestions = _a.fetchSuggestedQuestions, exports.fetchSuggestedQuestionsSuccess = _a.fetchSuggestedQuestionsSuccess, exports.fetchSuggestedQuestionsFailure = _a.fetchSuggestedQuestionsFailure, exports.fetchSkills = _a.fetchSkills, exports.fetchSkillsSuccess = _a.fetchSkillsSuccess, exports.fetchSkillsFailure = _a.fetchSkillsFailure, exports.applyAiCfoSidePanelHostPageTransition = _a.applyAiCfoSidePanelHostPageTransition, exports.clearAiCfoSidePanelHostPageContext = _a.clearAiCfoSidePanelHostPageContext;
|
|
921
|
+
_a = aiCfoView.actions, exports.submitQuestion = _a.submitQuestion, exports.submitQuestionSuccess = _a.submitQuestionSuccess, exports.submitQuestionFailure = _a.submitQuestionFailure, exports.updateResponseState = _a.updateResponseState, exports.updateAiCfoViewScrollPosition = _a.updateAiCfoViewScrollPosition, exports.updateCurrentInput = _a.updateCurrentInput, exports.submitFeedback = _a.submitFeedback, exports.submitFeedbackSuccess = _a.submitFeedbackSuccess, exports.submitFeedbackFailure = _a.submitFeedbackFailure, exports.setSession = _a.setSession, exports.createSession = _a.createSession, exports.createSessionSuccess = _a.createSessionSuccess, exports.createSessionFailure = _a.createSessionFailure, exports.createSessionAndSubmit = _a.createSessionAndSubmit, exports.initializeNewSessionState = _a.initializeNewSessionState, exports.createSessionAndSubmitSuccess = _a.createSessionAndSubmitSuccess, exports.createSessionAndSubmitFailure = _a.createSessionAndSubmitFailure, exports.fetchChatSessionsForUser = _a.fetchChatSessionsForUser, exports.fetchChatSessionsForUserSuccess = _a.fetchChatSessionsForUserSuccess, exports.fetchChatSessionsForUserFailure = _a.fetchChatSessionsForUserFailure, exports.fetchChatHistory = _a.fetchChatHistory, exports.fetchChatHistorySuccess = _a.fetchChatHistorySuccess, exports.fetchChatHistoryFailure = _a.fetchChatHistoryFailure, exports.clearCurrentSessionId = _a.clearCurrentSessionId, exports.clearLastContextMessage = _a.clearLastContextMessage, exports.stopSubmit = _a.stopSubmit, exports.stopSubmitSuccess = _a.stopSubmitSuccess, exports.stopSubmitFailure = _a.stopSubmitFailure, exports.stopSubmitQuestion = _a.stopSubmitQuestion, exports.stopSubmitQuestionSuccess = _a.stopSubmitQuestionSuccess, exports.stopSubmitQuestionFailure = _a.stopSubmitQuestionFailure, exports.acceptMasterTOS = _a.acceptMasterTOS, exports.acceptMasterTOSSuccess = _a.acceptMasterTOSSuccess, exports.acceptMasterTOSFailure = _a.acceptMasterTOSFailure, exports.deleteChatSession = _a.deleteChatSession, exports.deleteChatSessionSuccess = _a.deleteChatSessionSuccess, exports.deleteChatSessionFailure = _a.deleteChatSessionFailure, exports.clearDeleteChatSessionStatus = _a.clearDeleteChatSessionStatus, exports.updateCotCollapsedState = _a.updateCotCollapsedState, exports.fetchSuggestedQuestions = _a.fetchSuggestedQuestions, exports.fetchSuggestedQuestionsSuccess = _a.fetchSuggestedQuestionsSuccess, exports.fetchSuggestedQuestionsFailure = _a.fetchSuggestedQuestionsFailure, exports.fetchSkills = _a.fetchSkills, exports.fetchSkillsSuccess = _a.fetchSkillsSuccess, exports.fetchSkillsFailure = _a.fetchSkillsFailure, exports.fetchSkillDetail = _a.fetchSkillDetail, exports.fetchSkillDetailSuccess = _a.fetchSkillDetailSuccess, exports.fetchSkillDetailFailure = _a.fetchSkillDetailFailure, exports.clearSkillDetail = _a.clearSkillDetail, exports.clearSkillMutation = _a.clearSkillMutation, exports.deleteSkill = _a.deleteSkill, exports.deleteSkillSuccess = _a.deleteSkillSuccess, exports.deleteSkillFailure = _a.deleteSkillFailure, exports.fetchSkillVersionBody = _a.fetchSkillVersionBody, exports.fetchSkillVersionBodySuccess = _a.fetchSkillVersionBodySuccess, exports.fetchSkillVersionBodyFailure = _a.fetchSkillVersionBodyFailure, exports.fetchSkillVersions = _a.fetchSkillVersions, exports.fetchSkillVersionsSuccess = _a.fetchSkillVersionsSuccess, exports.fetchSkillVersionsFailure = _a.fetchSkillVersionsFailure, exports.saveSkill = _a.saveSkill, exports.saveSkillSuccess = _a.saveSkillSuccess, exports.saveSkillFailure = _a.saveSkillFailure, exports.setSkillVisibility = _a.setSkillVisibility, exports.setSkillVisibilitySuccess = _a.setSkillVisibilitySuccess, exports.setSkillVisibilityFailure = _a.setSkillVisibilityFailure, exports.openSkillsBrowser = _a.openSkillsBrowser, exports.closeSkillsBrowser = _a.closeSkillsBrowser, exports.applyAiCfoSidePanelHostPageTransition = _a.applyAiCfoSidePanelHostPageTransition, exports.clearAiCfoSidePanelHostPageContext = _a.clearAiCfoSidePanelHostPageContext;
|
|
519
922
|
exports.default = aiCfoView.reducer;
|
|
@@ -4,7 +4,7 @@ import { FetchStateAndError } from '../../commonStateTypes/common';
|
|
|
4
4
|
import { SelectorView } from '../../commonStateTypes/viewAndReport/viewAndReport';
|
|
5
5
|
import { AiCfoSelectorView } from '../../entity/aiCfo/aiCfoSelector';
|
|
6
6
|
import { RootState } from '../../rootStateTypes';
|
|
7
|
-
import { AiCfoViewUIState, SkillsState, SuggestedQuestionsForPageContext } from './aiCfoViewState';
|
|
7
|
+
import { AiCfoViewUIState, SkillDetailState, SkillMutationState, SkillVersionBodyState, SkillVersionsState, SkillsState, SuggestedQuestionsForPageContext } from './aiCfoViewState';
|
|
8
8
|
export interface AiCfoViewSelector extends SelectorView, AiCfoSelectorView {
|
|
9
9
|
createSessionAndSubmitState: FetchStateAndError;
|
|
10
10
|
createSessionState: FetchStateAndError;
|
|
@@ -24,3 +24,9 @@ export interface AiCfoViewSelector extends SelectorView, AiCfoSelectorView {
|
|
|
24
24
|
export declare const getAiCfoView: (state: RootState) => AiCfoViewSelector;
|
|
25
25
|
export declare function getSuggestedQuestionsForPageContext(state: RootState, pageContext: AiCfoSuggestedQuestionsPageContext): SuggestedQuestionsForPageContext | undefined;
|
|
26
26
|
export declare function getSkills(state: RootState): SkillsState;
|
|
27
|
+
export declare function getSkillDetail(state: RootState): SkillDetailState;
|
|
28
|
+
export declare function getSkillVersions(state: RootState): SkillVersionsState;
|
|
29
|
+
export declare function getSkillVersionBody(state: RootState): SkillVersionBodyState;
|
|
30
|
+
export declare function getSkillMutation(state: RootState): SkillMutationState;
|
|
31
|
+
/** True only when the server says the feature is on for this tenant. */
|
|
32
|
+
export declare function getSkillsEnabled(state: RootState): boolean;
|
|
@@ -3,6 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getAiCfoView = void 0;
|
|
4
4
|
exports.getSuggestedQuestionsForPageContext = getSuggestedQuestionsForPageContext;
|
|
5
5
|
exports.getSkills = getSkills;
|
|
6
|
+
exports.getSkillDetail = getSkillDetail;
|
|
7
|
+
exports.getSkillVersions = getSkillVersions;
|
|
8
|
+
exports.getSkillVersionBody = getSkillVersionBody;
|
|
9
|
+
exports.getSkillMutation = getSkillMutation;
|
|
10
|
+
exports.getSkillsEnabled = getSkillsEnabled;
|
|
6
11
|
const aiCfoReducer_1 = require("../../entity/aiCfo/aiCfoReducer");
|
|
7
12
|
const aiCfoSelector_1 = require("../../entity/aiCfo/aiCfoSelector");
|
|
8
13
|
const aiCfoViewReducer_1 = require("./aiCfoViewReducer");
|
|
@@ -35,7 +40,56 @@ const EMPTY_SKILLS_STATE = {
|
|
|
35
40
|
fetchState: 'Not-Started',
|
|
36
41
|
error: undefined,
|
|
37
42
|
skills: [],
|
|
43
|
+
// false, so the Skills entry stays hidden until the server confirms the feature
|
|
44
|
+
// is on. Defaulting true would flash a menu at tenants who never get one.
|
|
45
|
+
skillsEnabled: false,
|
|
46
|
+
// false, for the same reason as skillsEnabled: withhold the publish control until the
|
|
47
|
+
// server says this user may use it.
|
|
48
|
+
canPublish: false,
|
|
49
|
+
deletedMacroIds: [],
|
|
50
|
+
};
|
|
51
|
+
const EMPTY_SKILL_DETAIL_STATE = {
|
|
52
|
+
fetchState: 'Not-Started',
|
|
53
|
+
error: undefined,
|
|
54
|
+
detail: undefined,
|
|
55
|
+
macroId: undefined,
|
|
56
|
+
};
|
|
57
|
+
// Same stable-fallback reason as the two above: a selector that built a fresh object
|
|
58
|
+
// each call would re-render every subscriber on every unrelated state change.
|
|
59
|
+
const EMPTY_SKILL_VERSIONS_STATE = {
|
|
60
|
+
fetchState: 'Not-Started',
|
|
61
|
+
error: undefined,
|
|
62
|
+
versions: [],
|
|
63
|
+
macroId: undefined,
|
|
64
|
+
};
|
|
65
|
+
const EMPTY_SKILL_VERSION_BODY_STATE = {
|
|
66
|
+
fetchState: 'Not-Started',
|
|
67
|
+
error: undefined,
|
|
68
|
+
instructions: undefined,
|
|
69
|
+
macroId: undefined,
|
|
70
|
+
version: undefined,
|
|
71
|
+
};
|
|
72
|
+
const EMPTY_SKILL_MUTATION_STATE = {
|
|
73
|
+
fetchState: 'Not-Started',
|
|
74
|
+
error: undefined,
|
|
75
|
+
savedMacroId: undefined,
|
|
38
76
|
};
|
|
39
77
|
function getSkills(state) {
|
|
40
78
|
return state.aiCfoViewState?.skills ?? EMPTY_SKILLS_STATE;
|
|
41
79
|
}
|
|
80
|
+
function getSkillDetail(state) {
|
|
81
|
+
return state.aiCfoViewState?.skillDetail ?? EMPTY_SKILL_DETAIL_STATE;
|
|
82
|
+
}
|
|
83
|
+
function getSkillVersions(state) {
|
|
84
|
+
return state.aiCfoViewState?.skillVersions ?? EMPTY_SKILL_VERSIONS_STATE;
|
|
85
|
+
}
|
|
86
|
+
function getSkillVersionBody(state) {
|
|
87
|
+
return (state.aiCfoViewState?.skillVersionBody ?? EMPTY_SKILL_VERSION_BODY_STATE);
|
|
88
|
+
}
|
|
89
|
+
function getSkillMutation(state) {
|
|
90
|
+
return state.aiCfoViewState?.skillMutation ?? EMPTY_SKILL_MUTATION_STATE;
|
|
91
|
+
}
|
|
92
|
+
/** True only when the server says the feature is on for this tenant. */
|
|
93
|
+
function getSkillsEnabled(state) {
|
|
94
|
+
return getSkills(state).skillsEnabled;
|
|
95
|
+
}
|