@miso.ai/client-sdk-ui 1.11.0-beta.2 → 1.11.0-beta.4
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/cjs/actor/data.js +6 -7
- package/dist/cjs/actor/hub.js +1 -2
- package/dist/cjs/actor/sessions.js +4 -5
- package/dist/cjs/actor/views.js +3 -0
- package/dist/cjs/defaults/hybrid-search/answer-box.js +2 -2
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/workflow/answer-based.js +20 -7
- package/dist/cjs/workflow/ask.js +1 -0
- package/dist/cjs/workflow/base.js +16 -13
- package/dist/cjs/workflow/hybrid-search-answer.js +86 -0
- package/dist/cjs/workflow/hybrid-search-results.js +88 -0
- package/dist/cjs/workflow/hybrid-search.js +184 -60
- package/dist/cjs/workflow/processors.js +0 -19
- package/package.json +2 -2
- package/src/actor/data.js +2 -4
- package/src/actor/hub.js +1 -2
- package/src/actor/sessions.js +4 -3
- package/src/actor/views.js +4 -0
- package/src/defaults/hybrid-search/answer-box.js +4 -4
- package/src/layout/trackable.js +1 -1
- package/src/version.js +1 -1
- package/src/workflow/answer-based.js +21 -5
- package/src/workflow/ask.js +2 -1
- package/src/workflow/base.js +13 -11
- package/src/workflow/hybrid-search-answer.js +78 -0
- package/src/workflow/hybrid-search-results.js +79 -0
- package/src/workflow/hybrid-search.js +194 -43
- package/src/workflow/processors.js +0 -21
|
@@ -5,19 +5,18 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _commons = require("@miso.ai/commons");
|
|
8
|
-
var _answerBased = _interopRequireDefault(require("./answer-based.js"));
|
|
9
|
-
var _options = require("./options.js");
|
|
10
8
|
var _index = require("../actor/index.js");
|
|
9
|
+
var _base = _interopRequireDefault(require("./base.js"));
|
|
10
|
+
var _answerBased = _interopRequireDefault(require("./answer-based.js"));
|
|
11
11
|
var _constants = require("../constants.js");
|
|
12
12
|
var _index2 = require("../layout/index.js");
|
|
13
|
-
var
|
|
14
|
-
|
|
13
|
+
var _hybridSearchAnswer = _interopRequireDefault(require("./hybrid-search-answer.js"));
|
|
14
|
+
var _hybridSearchResults = _interopRequireDefault(require("./hybrid-search-results.js"));
|
|
15
15
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
|
-
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
|
|
17
16
|
const DEFAULT_API_OPTIONS = Object.freeze(Object.assign({}, _answerBased.default.DEFAULT_API_OPTIONS, {
|
|
18
17
|
name: _commons.API.NAME.SEARCH,
|
|
19
18
|
payload: Object.assign({}, _answerBased.default.DEFAULT_API_OPTIONS.payload, {
|
|
20
|
-
|
|
19
|
+
fl: ['cover_image', 'url', 'created_at', 'updated_at', 'published_at']
|
|
21
20
|
})
|
|
22
21
|
}));
|
|
23
22
|
const DEFAULT_LAYOUTS = Object.freeze(Object.assign({}, _answerBased.default.DEFAULT_LAYOUTS, {
|
|
@@ -47,7 +46,23 @@ const ROLES_CONFIG = Object.freeze({
|
|
|
47
46
|
mapping: 'facet_counts'
|
|
48
47
|
}
|
|
49
48
|
});
|
|
50
|
-
|
|
49
|
+
const SUBWORKFLOW = Object.freeze({
|
|
50
|
+
ANSWER: 'answer',
|
|
51
|
+
RESULTS: 'results'
|
|
52
|
+
});
|
|
53
|
+
function getSubworkflowByRole(role) {
|
|
54
|
+
// TODO: ROLE.ERROR
|
|
55
|
+
switch (role) {
|
|
56
|
+
case _constants.ROLE.PRODUCTS:
|
|
57
|
+
case _constants.ROLE.HITS:
|
|
58
|
+
case _constants.ROLE.FACETS:
|
|
59
|
+
case _constants.ROLE.KEYWORDS:
|
|
60
|
+
return SUBWORKFLOW.RESULTS;
|
|
61
|
+
default:
|
|
62
|
+
return SUBWORKFLOW.ANSWER;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
class HybridSearch extends _base.default {
|
|
51
66
|
constructor(plugin, client) {
|
|
52
67
|
super({
|
|
53
68
|
name: 'hybrid-search',
|
|
@@ -58,68 +73,177 @@ class HybridSearch extends _answerBased.default {
|
|
|
58
73
|
defaults: DEFAULT_OPTIONS
|
|
59
74
|
});
|
|
60
75
|
}
|
|
61
|
-
|
|
62
|
-
super.
|
|
63
|
-
this.
|
|
76
|
+
_initProperties(args) {
|
|
77
|
+
super._initProperties(args);
|
|
78
|
+
this._subworkflows = [this._answer = new _hybridSearchAnswer.default(this), this._results = new _hybridSearchResults.default(this)];
|
|
64
79
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
_getSubworkflow(name) {
|
|
81
|
+
switch (name) {
|
|
82
|
+
case SUBWORKFLOW.ANSWER:
|
|
83
|
+
return this._answer;
|
|
84
|
+
case SUBWORKFLOW.RESULTS:
|
|
85
|
+
return this._results;
|
|
86
|
+
default:
|
|
87
|
+
throw new Error(`Invalid subworkflow: ${name}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
_initActors() {
|
|
91
|
+
const hub = this._hub;
|
|
92
|
+
const client = this._client;
|
|
93
|
+
const options = this._options;
|
|
94
|
+
this._views = new HybridSearchViewsActor(this);
|
|
95
|
+
this._interactions = new _index.InteractionsActor(hub, {
|
|
96
|
+
client,
|
|
97
|
+
options
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
_initReset() {
|
|
101
|
+
this._results.reset();
|
|
102
|
+
this._answer.reset();
|
|
103
|
+
}
|
|
104
|
+
restart() {
|
|
69
105
|
let {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
payload = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
75
|
-
const fq = (0, _processors.composeFq)(filters); // TODO: combine with fq in payload?
|
|
76
|
-
return (0, _commons.trimObj)(Object.assign({}, payload, {
|
|
77
|
-
q,
|
|
78
|
-
// q, not question
|
|
79
|
-
fq,
|
|
80
|
-
_meta: Object.assign({}, payload._meta, {
|
|
81
|
-
question_source: qs || _constants.ORGANIC_QUESTION_SOURCE // might be null, not undefined
|
|
82
|
-
})
|
|
83
|
-
}));
|
|
84
|
-
}
|
|
85
|
-
_refine(filters) {
|
|
86
|
-
const query = this._hub.states[_index.fields.query()];
|
|
87
|
-
const payload = this._buildPayload(Object.assign({}, query, {
|
|
88
|
-
filters,
|
|
89
|
-
answer: false
|
|
90
|
-
}));
|
|
106
|
+
answer = true
|
|
107
|
+
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
108
|
+
const previousSession = this.session;
|
|
109
|
+
this._sessions.restart();
|
|
91
110
|
const {
|
|
92
111
|
session
|
|
93
112
|
} = this;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this._request(event);
|
|
113
|
+
if (!answer) {
|
|
114
|
+
session._answer = previousSession._answer || previousSession;
|
|
115
|
+
}
|
|
116
|
+
return this;
|
|
117
|
+
}
|
|
100
118
|
|
|
101
|
-
|
|
102
|
-
|
|
119
|
+
// properties //
|
|
120
|
+
get questionId() {
|
|
121
|
+
return this._answer.questionId;
|
|
122
|
+
}
|
|
123
|
+
get filters() {
|
|
124
|
+
return this._results._views.filters;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// query //
|
|
128
|
+
autoQuery(options) {
|
|
129
|
+
this._answer.autoQuery(options);
|
|
130
|
+
}
|
|
131
|
+
query(args) {
|
|
132
|
+
this._answer.query(args);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// interactions //
|
|
136
|
+
_preprocessInteraction(payload) {
|
|
137
|
+
return this._answer._preprocessInteraction(payload);
|
|
103
138
|
}
|
|
104
139
|
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
140
|
+
// destroy //
|
|
141
|
+
_destroy() {
|
|
142
|
+
for (const subworkflow of this._subworkflows) {
|
|
143
|
+
subworkflow.destroy();
|
|
144
|
+
}
|
|
145
|
+
super._destroy();
|
|
111
146
|
}
|
|
112
147
|
}
|
|
113
148
|
exports.default = HybridSearch;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
149
|
+
class HybridSearchViewsActor {
|
|
150
|
+
constructor(workflow) {
|
|
151
|
+
this._workflow = workflow;
|
|
152
|
+
this._containers = new Set();
|
|
153
|
+
}
|
|
154
|
+
get(role) {
|
|
155
|
+
return this._getSubviews(role).get(role);
|
|
156
|
+
}
|
|
157
|
+
addContainer(element) {
|
|
158
|
+
if (this._containers.has(element)) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
this._containers.add(element);
|
|
162
|
+
const {
|
|
163
|
+
components
|
|
164
|
+
} = element;
|
|
165
|
+
for (const component of components) {
|
|
166
|
+
this.addComponent(component);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
removeContainer(element) {
|
|
170
|
+
for (const subworkflow of this._workflow._subworkflows) {
|
|
171
|
+
subworkflow._views.removeContainer(element);
|
|
172
|
+
}
|
|
173
|
+
this._containers.delete(element);
|
|
174
|
+
}
|
|
175
|
+
addComponent(element) {
|
|
176
|
+
this._getViewByElement(element).element = element;
|
|
177
|
+
this._addContainerToSubviews(element._container, element);
|
|
178
|
+
}
|
|
179
|
+
removeComponent(element) {
|
|
180
|
+
this._getViewByElement(element).element = undefined;
|
|
181
|
+
this._removeContainerFromSubviewsIfNecessary(element._container);
|
|
182
|
+
}
|
|
183
|
+
updateComponentRole(element, oldRole, newRole) {
|
|
184
|
+
// TODO
|
|
185
|
+
}
|
|
186
|
+
refreshElement(element) {
|
|
187
|
+
const view = element.isContainer ? this._containers.get(element) : this._getViewByElement(element);
|
|
188
|
+
view && view.refresh({
|
|
189
|
+
force: true
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// helpers //
|
|
194
|
+
_getSubworkflow(role) {
|
|
195
|
+
return this._workflow._getSubworkflow(getSubworkflowByRole(role));
|
|
196
|
+
}
|
|
197
|
+
_getAllSubviews() {
|
|
198
|
+
return this._workflow._subworkflows.flatMap(subworkflow => subworkflow._views);
|
|
199
|
+
}
|
|
200
|
+
_getSubviews(role) {
|
|
201
|
+
return this._getSubworkflow(role)._views;
|
|
202
|
+
}
|
|
203
|
+
_getViewByElement(element) {
|
|
204
|
+
let {
|
|
205
|
+
role
|
|
206
|
+
} = element;
|
|
207
|
+
if (!role) {
|
|
208
|
+
throw new Error('Component must have a role');
|
|
209
|
+
}
|
|
210
|
+
return this.get(role);
|
|
211
|
+
}
|
|
212
|
+
_addContainerToSubviews(container, child) {
|
|
213
|
+
if (!container) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const {
|
|
217
|
+
role
|
|
218
|
+
} = child;
|
|
219
|
+
const subviews = this._getSubviews(role);
|
|
220
|
+
if (subviews._containers.has(container)) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
// check if the container is in other subviews
|
|
224
|
+
for (const otherSubviews of this._getAllSubviews()) {
|
|
225
|
+
if (otherSubviews === subviews) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (otherSubviews._containers.has(container)) {
|
|
229
|
+
// find the conflicting element
|
|
230
|
+
for (const component of container.components) {
|
|
231
|
+
if (otherSubviews.containsElement(component)) {
|
|
232
|
+
throw new Error(`<${container.tagName}> cannot contain both <${component.tagName}> and <${child.tagName}>, for they don't share the same data lifecycle.`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
throw new Error(`Failed to add container <${container.tagName}> with child component <${child.tagName}>.`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
// add the container to the subviews
|
|
239
|
+
subviews.addContainer(container);
|
|
240
|
+
}
|
|
241
|
+
_removeContainerFromSubviewsIfNecessary(container) {
|
|
242
|
+
if (!container || container.components.length > 0) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
for (const subviews of this._getAllSubviews()) {
|
|
246
|
+
subviews.removeContainer(container);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
125
249
|
}
|
|
@@ -3,17 +3,13 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.addDataInstructions = addDataInstructions;
|
|
7
6
|
exports.composeFq = composeFq;
|
|
8
|
-
exports.removeDataInstructions = removeDataInstructions;
|
|
9
7
|
exports.writeAnswerStageToMeta = writeAnswerStageToMeta;
|
|
10
8
|
exports.writeDataStatus = writeDataStatus;
|
|
11
9
|
exports.writeKeywordsToData = writeKeywordsToData;
|
|
12
10
|
exports.writeMisoIdToMeta = writeMisoIdToMeta;
|
|
13
11
|
var _commons = require("@miso.ai/commons");
|
|
14
12
|
var _constants = require("../constants.js");
|
|
15
|
-
const _excluded = ["_inst"];
|
|
16
|
-
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
|
|
17
13
|
function writeDataStatus(data) {
|
|
18
14
|
const status = getStatus(data);
|
|
19
15
|
const ongoing = status === _constants.STATUS.READY ? !!data.ongoing : undefined;
|
|
@@ -97,21 +93,6 @@ function writeAnswerStageToMeta(data) {
|
|
|
97
93
|
})
|
|
98
94
|
});
|
|
99
95
|
}
|
|
100
|
-
function addDataInstructions(data, instructions) {
|
|
101
|
-
if (!instructions) {
|
|
102
|
-
return data;
|
|
103
|
-
}
|
|
104
|
-
return Object.assign({
|
|
105
|
-
_inst: Object.assign({}, data._inst, instructions)
|
|
106
|
-
}, data);
|
|
107
|
-
}
|
|
108
|
-
function removeDataInstructions(data) {
|
|
109
|
-
if (typeof data !== 'object') {
|
|
110
|
-
return data;
|
|
111
|
-
}
|
|
112
|
-
const rest = _objectWithoutPropertiesLoose(data, _excluded);
|
|
113
|
-
return rest;
|
|
114
|
-
}
|
|
115
96
|
function composeFq(filters) {
|
|
116
97
|
if (!filters) {
|
|
117
98
|
return undefined;
|
package/package.json
CHANGED
package/src/actor/data.js
CHANGED
|
@@ -50,10 +50,8 @@ export default class DataActor {
|
|
|
50
50
|
const { session } = this._hub.states;
|
|
51
51
|
const { session: _, ...request } = event;
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this._emitResponse({ session, request });
|
|
56
|
-
}
|
|
53
|
+
// emit response to update request
|
|
54
|
+
this._emitResponse({ session, request });
|
|
57
55
|
|
|
58
56
|
try {
|
|
59
57
|
const { signal } = this._ac || {};
|
package/src/actor/hub.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { defineValues, EventEmitter } from '@miso.ai/commons';
|
|
2
|
-
import { removeDataInstructions } from '../workflow/processors.js';
|
|
3
2
|
|
|
4
3
|
export default class Hub {
|
|
5
4
|
|
|
@@ -14,7 +13,7 @@ export default class Hub {
|
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
update(name, state, { silent = false } = {}) {
|
|
17
|
-
this._states[name] = Object.freeze(
|
|
16
|
+
this._states[name] = Object.freeze(state);
|
|
18
17
|
if (!silent) {
|
|
19
18
|
this._events.emit(name, state);
|
|
20
19
|
}
|
package/src/actor/sessions.js
CHANGED
|
@@ -10,12 +10,13 @@ export default class SessionMaker {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
get active() {
|
|
13
|
-
|
|
13
|
+
// TODO: may eliminate active flag?
|
|
14
|
+
const session = this._hub.states[fields.session()];
|
|
14
15
|
return !!(session && session.active);
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
new({ force = false } = {}) {
|
|
18
|
-
const currentSession = this._hub.states.session;
|
|
19
|
+
const currentSession = this._hub.states[fields.session()];
|
|
19
20
|
if (currentSession && !currentSession.active && !force) {
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
@@ -24,7 +25,7 @@ export default class SessionMaker {
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
start() {
|
|
27
|
-
const session = this._hub.states.session || this._create();
|
|
28
|
+
const session = this._hub.states[fields.session()] || this._create();
|
|
28
29
|
if (session.active) {
|
|
29
30
|
return;
|
|
30
31
|
}
|
package/src/actor/views.js
CHANGED
|
@@ -99,6 +99,10 @@ export default class ViewsActor {
|
|
|
99
99
|
// TODO
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
containsElement(element) {
|
|
103
|
+
return this._containers.has(element) || this._views[element.role];
|
|
104
|
+
}
|
|
105
|
+
|
|
102
106
|
refreshElement(element) {
|
|
103
107
|
const view = element.isContainer ? this._containers.get(element) : this._getViewByElement(element);
|
|
104
108
|
view && view.refresh({ force: true });
|
|
@@ -35,9 +35,9 @@ export default class AnswerBox {
|
|
|
35
35
|
|
|
36
36
|
this._unsubscribes = [
|
|
37
37
|
() => element.removeEventListener('click', callback),
|
|
38
|
-
workflow.on('loading', () => this.hide()),
|
|
39
|
-
workflow.on('error', () => this.show()),
|
|
40
|
-
workflow.on('ready', () => this.show()),
|
|
38
|
+
workflow._answer.on('loading', () => this.hide()),
|
|
39
|
+
workflow._answer.on('error', () => this.show()),
|
|
40
|
+
workflow._answer.on('ready', () => this.show()),
|
|
41
41
|
];
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -52,7 +52,7 @@ export default class AnswerBox {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
_syncWofkflowStatus() {
|
|
55
|
-
const { status } = this._workflow;
|
|
55
|
+
const { status } = this._workflow._answer;
|
|
56
56
|
switch (status) {
|
|
57
57
|
case STATUS.ERRONEOUS:
|
|
58
58
|
case STATUS.READY:
|
package/src/layout/trackable.js
CHANGED
package/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '1.11.0-beta.
|
|
1
|
+
export default '1.11.0-beta.4';
|
|
@@ -133,16 +133,21 @@ export default class AnswerBasedWorkflow extends Workflow {
|
|
|
133
133
|
// start a new session
|
|
134
134
|
this.restart();
|
|
135
135
|
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
// TODO: move to ask workflow
|
|
137
|
+
// keep track of question source on this session, for suggested questions interactions
|
|
138
|
+
this._writeQuestionSourceToSession(args);
|
|
139
139
|
|
|
140
140
|
// build payload and trigger request
|
|
141
|
+
const { session } = this;
|
|
141
142
|
const payload = this._buildPayload(args);
|
|
142
143
|
const event = mergeApiOptions(this._options.resolved.api, { payload, session });
|
|
143
144
|
this._request(event);
|
|
144
145
|
}
|
|
145
146
|
|
|
147
|
+
_writeQuestionSourceToSession(args) {
|
|
148
|
+
this.session.meta.question_source = args.questionSource || ORGANIC_QUESTION_SOURCE; // might be null, not undefined
|
|
149
|
+
}
|
|
150
|
+
|
|
146
151
|
_request(event) {
|
|
147
152
|
this._hub.update(fields.request(), event);
|
|
148
153
|
}
|
|
@@ -164,11 +169,22 @@ export default class AnswerBasedWorkflow extends Workflow {
|
|
|
164
169
|
*/
|
|
165
170
|
|
|
166
171
|
// data //
|
|
167
|
-
|
|
168
|
-
|
|
172
|
+
_updateData(data) {
|
|
173
|
+
// if it's the head response, write question id and return
|
|
174
|
+
if (data.value && !data.value.answer_stage) {
|
|
175
|
+
this._handleHeadResponse(data);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
super._updateData(data);
|
|
179
|
+
}
|
|
169
180
|
|
|
181
|
+
_handleHeadResponse(data) {
|
|
170
182
|
// capture question ID and register at context
|
|
171
183
|
this._writeQuestionIdFromData(data);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
_defaultProcessData(data) {
|
|
187
|
+
data = super._defaultProcessData(data);
|
|
172
188
|
|
|
173
189
|
// update URL if autoQuery.updateUrl is not false
|
|
174
190
|
this._updateUrlIfNecessary(data);
|
package/src/workflow/ask.js
CHANGED
|
@@ -2,7 +2,7 @@ import { defineValues, trimObj, API } from '@miso.ai/commons';
|
|
|
2
2
|
import AnswerBasedWorkflow from './answer-based.js';
|
|
3
3
|
import { fields } from '../actor/index.js';
|
|
4
4
|
import { ROLE, ORGANIC_QUESTION_SOURCE } from '../constants.js';
|
|
5
|
-
import { OptionListLayout, ListLayout
|
|
5
|
+
import { OptionListLayout, ListLayout } from '../layout/index.js';
|
|
6
6
|
|
|
7
7
|
const DEFAULT_API_OPTIONS = Object.freeze({
|
|
8
8
|
...AnswerBasedWorkflow.DEFAULT_API_OPTIONS,
|
|
@@ -64,6 +64,7 @@ export default class Ask extends AnswerBasedWorkflow {
|
|
|
64
64
|
if (!previous) {
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
67
|
+
// TODO: write question_source from payload._meta, so we don't need to write it to session.meta
|
|
67
68
|
const values = previous.states[fields.data()].value;
|
|
68
69
|
const value = values.suggested_followup_questions || values.followup_questions || [];
|
|
69
70
|
this._hub.update(fields.suggestions(), { value: value.map(text => ({ text })) });
|
package/src/workflow/base.js
CHANGED
|
@@ -5,7 +5,7 @@ import { STATUS, ROLE } from '../constants.js';
|
|
|
5
5
|
import { ContainerLayout, ErrorLayout } from '../layout/index.js';
|
|
6
6
|
import { injectLogger } from './utils.js';
|
|
7
7
|
import { WorkflowOptions, mergeLayoutsOptions, mergeInteractionsOptions, makeConfigurable } from './options.js';
|
|
8
|
-
import { writeDataStatus, writeMisoIdToMeta
|
|
8
|
+
import { writeDataStatus, writeMisoIdToMeta } from './processors.js';
|
|
9
9
|
|
|
10
10
|
const DEFAULT_LAYOUTS = Object.freeze({
|
|
11
11
|
[ROLE.CONTAINER]: ContainerLayout.type,
|
|
@@ -38,7 +38,7 @@ export default class Workflow extends Component {
|
|
|
38
38
|
constructor(args) {
|
|
39
39
|
super(args.name || 'workflow', args.plugin);
|
|
40
40
|
|
|
41
|
-
let { context, plugin, client } = args;
|
|
41
|
+
let { context, plugin, client, options } = args;
|
|
42
42
|
this._context = context;
|
|
43
43
|
this._plugin = plugin = plugin || context._plugin;
|
|
44
44
|
this._client = client = client || context._client;
|
|
@@ -49,7 +49,7 @@ export default class Workflow extends Component {
|
|
|
49
49
|
this._rolesConfig = { ...ROLES_CONFIG, ...args.rolesConfig };
|
|
50
50
|
|
|
51
51
|
this._extensions = plugin._getExtensions(client);
|
|
52
|
-
this._options = new WorkflowOptions(context && context._options, mergeDefaults(this, args.defaults));
|
|
52
|
+
this._options = options || new WorkflowOptions(context && context._options, mergeDefaults(this, args.defaults));
|
|
53
53
|
this._hub = injectLogger(new Hub(), (...args) => this._log(...args));
|
|
54
54
|
|
|
55
55
|
this._initProperties(args);
|
|
@@ -90,7 +90,7 @@ export default class Workflow extends Component {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
get session() {
|
|
93
|
-
return this._hub.states.session;
|
|
93
|
+
return this._hub.states[fields.session()];
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
get active() {
|
|
@@ -128,7 +128,7 @@ export default class Workflow extends Component {
|
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
// states //
|
|
131
|
-
updateData(data
|
|
131
|
+
updateData(data) {
|
|
132
132
|
if (!data) {
|
|
133
133
|
throw new Error(`Data is required.`);
|
|
134
134
|
}
|
|
@@ -152,6 +152,12 @@ export default class Workflow extends Component {
|
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
this._updateData(data);
|
|
156
|
+
|
|
157
|
+
return this;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
_updateData(data) {
|
|
155
161
|
this._sessions.start(); // in case session not started yet
|
|
156
162
|
|
|
157
163
|
data = writeDataStatus(data);
|
|
@@ -160,19 +166,14 @@ export default class Workflow extends Component {
|
|
|
160
166
|
data = process(data);
|
|
161
167
|
}
|
|
162
168
|
|
|
163
|
-
// write data instructions from function args
|
|
164
|
-
data = addDataInstructions(data, instructions);
|
|
165
|
-
data = this._mergeDataIfNecessary(data);
|
|
166
|
-
|
|
167
169
|
this._hub.update(fields.data(), data);
|
|
168
|
-
|
|
169
|
-
return this;
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
_defaultProcessData(data) {
|
|
173
173
|
return writeMisoIdToMeta(data);
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
/*
|
|
176
177
|
_mergeDataIfNecessary(data) {
|
|
177
178
|
if (!data._inst || !data._inst.merge) {
|
|
178
179
|
return data;
|
|
@@ -184,6 +185,7 @@ export default class Workflow extends Component {
|
|
|
184
185
|
}
|
|
185
186
|
|
|
186
187
|
_handleResponseObject() {}
|
|
188
|
+
*/
|
|
187
189
|
|
|
188
190
|
// TODO: notifyViewUpdateAll()
|
|
189
191
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import AnswerBasedWorkflow from './answer-based.js';
|
|
2
|
+
import { ROLE, STATUS, ORGANIC_QUESTION_SOURCE } from '../constants.js';
|
|
3
|
+
import { writeKeywordsToData } from './processors.js';
|
|
4
|
+
|
|
5
|
+
const ROLES_CONFIG = Object.freeze({
|
|
6
|
+
[ROLE.QUESTION]: {
|
|
7
|
+
mapping: ROLE.KEYWORDS,
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export default class HybridSearchAnswer extends AnswerBasedWorkflow {
|
|
12
|
+
|
|
13
|
+
constructor(superworkflow) {
|
|
14
|
+
super({
|
|
15
|
+
name: 'hybrid-search/answer',
|
|
16
|
+
plugin: superworkflow._plugin,
|
|
17
|
+
client: superworkflow._client,
|
|
18
|
+
options: superworkflow._options,
|
|
19
|
+
roles: Object.keys(AnswerBasedWorkflow.DEFAULT_LAYOUTS),
|
|
20
|
+
rolesConfig: ROLES_CONFIG,
|
|
21
|
+
superworkflow,
|
|
22
|
+
});
|
|
23
|
+
this.useInteractions(false);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
_initProperties(args) {
|
|
27
|
+
super._initProperties(args);
|
|
28
|
+
this._superworkflow = args.superworkflow;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_initReset() {} // no reset here, will manually reset later
|
|
32
|
+
|
|
33
|
+
restart() {
|
|
34
|
+
super.restart();
|
|
35
|
+
// cascade restart to the sibling
|
|
36
|
+
const results = this._superworkflow._results;
|
|
37
|
+
results.restart();
|
|
38
|
+
this._resultsSession = results.session; // keep track of the session
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// query //
|
|
42
|
+
_buildPayload({ q, qs, ...payload } = {}) {
|
|
43
|
+
return {
|
|
44
|
+
...payload,
|
|
45
|
+
q, // q, not question
|
|
46
|
+
_meta: {
|
|
47
|
+
...payload._meta,
|
|
48
|
+
question_source: qs || ORGANIC_QUESTION_SOURCE, // might be null, not undefined
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// data //
|
|
54
|
+
_updateData(data) {
|
|
55
|
+
// we want this to be available everywhere
|
|
56
|
+
data = writeKeywordsToData(data);
|
|
57
|
+
|
|
58
|
+
switch (data.status) {
|
|
59
|
+
case STATUS.INITIAL:
|
|
60
|
+
case STATUS.LOADING:
|
|
61
|
+
// share the initial/loading status with its sibling
|
|
62
|
+
this._dispatchDataToSibling(data);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
super._updateData(data);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
_handleHeadResponse(data) {
|
|
69
|
+
super._handleHeadResponse(data);
|
|
70
|
+
// share the search results with its sibling
|
|
71
|
+
this._dispatchDataToSibling(data);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
_dispatchDataToSibling(data) {
|
|
75
|
+
this._superworkflow._results.updateData({ ...data, session: this._resultsSession });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
}
|