@miso.ai/client-sdk-core 1.13.2-beta.0 → 1.14.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/api/ask.js +16 -0
- package/dist/cjs/api/base.js +0 -2
- package/dist/cjs/api/history.0.js +212 -0
- package/dist/cjs/api/history.js +61 -0
- package/dist/cjs/api/index.js +14 -0
- package/dist/cjs/api/iterable.js +9 -0
- package/dist/cjs/plugin/context.js +3 -1
- package/dist/cjs/utils.js +6 -0
- package/dist/cjs/version.js +1 -1
- package/package.json +4 -4
- package/src/api/ask.js +14 -0
- package/src/api/base.js +0 -2
- package/src/api/history.0.js +119 -0
- package/src/api/history.js +56 -0
- package/src/api/index.js +2 -0
- package/src/api/iterable.js +9 -0
- package/src/plugin/context.js +3 -1
- package/src/utils.js +1 -1
- package/src/version.js +1 -1
package/dist/cjs/api/ask.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _commons = require("@miso.ai/commons");
|
|
8
8
|
var _base = _interopRequireDefault(require("./base.js"));
|
|
9
|
+
var _history = _interopRequireDefault(require("./history.0.js"));
|
|
9
10
|
var _iterable = require("./iterable.js");
|
|
10
11
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
12
|
const {
|
|
@@ -15,6 +16,9 @@ const {
|
|
|
15
16
|
class Ask extends _base.default {
|
|
16
17
|
constructor(api) {
|
|
17
18
|
super(api, GROUP.ASK);
|
|
19
|
+
// the deployed (v0) user history API; switch back to UserHistory
|
|
20
|
+
// (history.js) when the resource-style API ships
|
|
21
|
+
this.userHistory = new _history.default(api);
|
|
18
22
|
}
|
|
19
23
|
async questions(payload, options = {}) {
|
|
20
24
|
if (isId(payload)) {
|
|
@@ -36,6 +40,18 @@ class Ask extends _base.default {
|
|
|
36
40
|
method: 'GET'
|
|
37
41
|
}));
|
|
38
42
|
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Retrieve multiple question-answer pairs at once.
|
|
46
|
+
*/
|
|
47
|
+
async answers(payload, options = {}) {
|
|
48
|
+
if (Array.isArray(payload)) {
|
|
49
|
+
payload = {
|
|
50
|
+
question_ids: payload
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return this._run(NAME.ANSWERS, payload, options);
|
|
54
|
+
}
|
|
39
55
|
async relatedQuestions(payload, options = {}) {
|
|
40
56
|
return this._run(NAME.RELATED_QUESTIONS, payload, options);
|
|
41
57
|
}
|
package/dist/cjs/api/base.js
CHANGED
|
@@ -8,8 +8,6 @@ var _commons = require("@miso.ai/commons");
|
|
|
8
8
|
const _excluded = ["bulk"];
|
|
9
9
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
10
10
|
class ApiBase extends _commons.Component {
|
|
11
|
-
// TODO: use private fields (may encounter issues with rollup)
|
|
12
|
-
|
|
13
11
|
constructor(api, apiPath) {
|
|
14
12
|
super(apiPath, api);
|
|
15
13
|
this._apiPath = apiPath;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _history = _interopRequireDefault(require("./history.js"));
|
|
8
|
+
const _excluded = ["thread_ids"],
|
|
9
|
+
_excluded2 = ["threads"],
|
|
10
|
+
_excluded3 = ["id", "question_id", "time"],
|
|
11
|
+
_excluded4 = ["question_ids"];
|
|
12
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
|
+
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
14
|
+
/**
|
|
15
|
+
* The user history API as deployed today (version 0): a flat, POST-only
|
|
16
|
+
* surface where a thread is addressed by the `question_id` of its root
|
|
17
|
+
* question, with its own request/response shapes.
|
|
18
|
+
* @see https://miso-docs.apidocumentation.com/api/genai/user-history
|
|
19
|
+
*
|
|
20
|
+
* It adapts the v0 wire format behind the interface of UserHistory in
|
|
21
|
+
* history.js — the resource-style API the SDK is written against, not
|
|
22
|
+
* released yet. All calls funnel through `_run`, where the resource-style
|
|
23
|
+
* (name, payload, method) is translated to its v0 form and the response
|
|
24
|
+
* value back to the resource-style shape, so the workflow layer stays
|
|
25
|
+
* version-agnostic. When the resource-style API ships, switching the SDK
|
|
26
|
+
* over means using UserHistory in ask.js again.
|
|
27
|
+
*/
|
|
28
|
+
class UserHistoryV0 extends _history.default {
|
|
29
|
+
async _run(apiName, payload, options = {}) {
|
|
30
|
+
const {
|
|
31
|
+
name,
|
|
32
|
+
payload: v0Payload,
|
|
33
|
+
adapt
|
|
34
|
+
} = translate(apiName, payload, options);
|
|
35
|
+
const value = await super._run(name, v0Payload, Object.assign({}, options, {
|
|
36
|
+
method: 'POST'
|
|
37
|
+
}));
|
|
38
|
+
return adapt ? adapt(value) : value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Translate a resource-style (name, payload, method) call to its v0 form.
|
|
44
|
+
* The v0 payload is always an object — even when the resource-style call
|
|
45
|
+
* carries none (a GET) — so the context plugin's payload pass attaches the
|
|
46
|
+
* user info (user_id/anonymous_id) that v0 endpoints require.
|
|
47
|
+
*/
|
|
48
|
+
exports.default = UserHistoryV0;
|
|
49
|
+
function translate(apiName, payload, {
|
|
50
|
+
method = 'POST'
|
|
51
|
+
} = {}) {
|
|
52
|
+
switch (apiName) {
|
|
53
|
+
case 'threads':
|
|
54
|
+
// GET threads -> POST list
|
|
55
|
+
return {
|
|
56
|
+
name: 'list',
|
|
57
|
+
payload: Object.assign({}, payload),
|
|
58
|
+
adapt: adaptThreadList
|
|
59
|
+
};
|
|
60
|
+
case 'threads/_delete':
|
|
61
|
+
{
|
|
62
|
+
const _ref = payload || {},
|
|
63
|
+
{
|
|
64
|
+
thread_ids: question_ids = []
|
|
65
|
+
} = _ref,
|
|
66
|
+
rest = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
67
|
+
return {
|
|
68
|
+
name: 'delete',
|
|
69
|
+
payload: Object.assign({}, rest, {
|
|
70
|
+
question_ids
|
|
71
|
+
})
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
case 'threads/_delete_all':
|
|
75
|
+
return {
|
|
76
|
+
name: 'delete_all',
|
|
77
|
+
payload: Object.assign({}, payload)
|
|
78
|
+
};
|
|
79
|
+
case 'notifications':
|
|
80
|
+
// GET notifications -> POST thread/updates
|
|
81
|
+
return {
|
|
82
|
+
name: 'thread/updates',
|
|
83
|
+
payload: Object.assign({}, payload)
|
|
84
|
+
};
|
|
85
|
+
case 'notifications/dismiss':
|
|
86
|
+
return {
|
|
87
|
+
name: 'thread/updates/dismiss_overall',
|
|
88
|
+
payload: Object.assign({}, payload)
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const segments = apiName.split('/');
|
|
92
|
+
if (segments[0] === 'threads' && segments.length === 2) {
|
|
93
|
+
const thread_id = segments[1]; // the thread id is its root question id
|
|
94
|
+
switch (method) {
|
|
95
|
+
case 'GET':
|
|
96
|
+
// GET threads/{id} -> POST thread
|
|
97
|
+
return {
|
|
98
|
+
name: 'thread',
|
|
99
|
+
payload: Object.assign({}, payload, {
|
|
100
|
+
thread_id
|
|
101
|
+
}),
|
|
102
|
+
adapt: value => adaptThreadDetail(thread_id, value)
|
|
103
|
+
};
|
|
104
|
+
case 'PUT':
|
|
105
|
+
// PUT threads/{id} { title } -> POST thread/rename
|
|
106
|
+
return {
|
|
107
|
+
name: 'thread/rename',
|
|
108
|
+
payload: Object.assign({}, payload, {
|
|
109
|
+
thread_id
|
|
110
|
+
})
|
|
111
|
+
};
|
|
112
|
+
case 'DELETE':
|
|
113
|
+
// DELETE threads/{id} -> POST delete
|
|
114
|
+
return {
|
|
115
|
+
name: 'delete',
|
|
116
|
+
payload: {
|
|
117
|
+
question_ids: [thread_id]
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (segments[0] === 'threads' && segments.length === 3) {
|
|
123
|
+
const thread_id = segments[1];
|
|
124
|
+
switch (segments[2]) {
|
|
125
|
+
case 'read':
|
|
126
|
+
// POST threads/{id}/read -> POST thread/updates/dismiss_thread
|
|
127
|
+
return {
|
|
128
|
+
name: 'thread/updates/dismiss_thread',
|
|
129
|
+
payload: Object.assign({}, payload, {
|
|
130
|
+
thread_id
|
|
131
|
+
})
|
|
132
|
+
};
|
|
133
|
+
case 'subscribe':
|
|
134
|
+
return {
|
|
135
|
+
name: 'thread/updates/subscribe',
|
|
136
|
+
payload: Object.assign({}, payload, {
|
|
137
|
+
thread_id
|
|
138
|
+
})
|
|
139
|
+
};
|
|
140
|
+
case 'unsubscribe':
|
|
141
|
+
return {
|
|
142
|
+
name: 'thread/updates/unsubscribe',
|
|
143
|
+
payload: Object.assign({}, payload, {
|
|
144
|
+
thread_id
|
|
145
|
+
})
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
throw new Error(`Unknown user history API: ${method} ${apiName}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* A v0 list response nests the entries under `threads`, alongside the paging
|
|
154
|
+
* fields (has_more, start, rows), which pass through untouched.
|
|
155
|
+
*/
|
|
156
|
+
function adaptThreadList(value) {
|
|
157
|
+
if (!value || typeof value !== 'object') {
|
|
158
|
+
return value;
|
|
159
|
+
}
|
|
160
|
+
if (Array.isArray(value)) {
|
|
161
|
+
return value.map(adaptThreadEntry);
|
|
162
|
+
}
|
|
163
|
+
const {
|
|
164
|
+
threads = []
|
|
165
|
+
} = value,
|
|
166
|
+
rest = _objectWithoutPropertiesLoose(value, _excluded2);
|
|
167
|
+
return Object.assign({}, rest, {
|
|
168
|
+
threads: threads.map(adaptThreadEntry)
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* A v0 thread entry carries (id, time, question_id, title, subscribed,
|
|
174
|
+
* has_new); the resource-style records read (thread_id, title, updated_at).
|
|
175
|
+
* A thread is keyed by its root question, so question_id serves as the
|
|
176
|
+
* thread id.
|
|
177
|
+
*/
|
|
178
|
+
function adaptThreadEntry(entry) {
|
|
179
|
+
if (!entry || typeof entry !== 'object') {
|
|
180
|
+
return entry;
|
|
181
|
+
}
|
|
182
|
+
const {
|
|
183
|
+
id,
|
|
184
|
+
question_id = id,
|
|
185
|
+
time
|
|
186
|
+
} = entry,
|
|
187
|
+
rest = _objectWithoutPropertiesLoose(entry, _excluded3);
|
|
188
|
+
return Object.assign({}, rest, {
|
|
189
|
+
thread_id: question_id,
|
|
190
|
+
question_id,
|
|
191
|
+
updated_at: rest.updated_at !== undefined ? rest.updated_at : time
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* The v0 open-thread response carries the question ids (and a has_more flag,
|
|
197
|
+
* passed through) but no thread metadata: synthesize the thread record around
|
|
198
|
+
* them, keyed by the requested thread id.
|
|
199
|
+
*/
|
|
200
|
+
function adaptThreadDetail(thread_id, value) {
|
|
201
|
+
if (!value || typeof value !== 'object') {
|
|
202
|
+
return value;
|
|
203
|
+
}
|
|
204
|
+
const {
|
|
205
|
+
question_ids = []
|
|
206
|
+
} = value,
|
|
207
|
+
rest = _objectWithoutPropertiesLoose(value, _excluded4);
|
|
208
|
+
return Object.assign({}, rest, {
|
|
209
|
+
thread_id,
|
|
210
|
+
questions_ids: question_ids
|
|
211
|
+
});
|
|
212
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _commons = require("@miso.ai/commons");
|
|
8
|
+
var _base = _interopRequireDefault(require("./base.js"));
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
const {
|
|
11
|
+
GROUP
|
|
12
|
+
} = _commons.API;
|
|
13
|
+
class UserHistory extends _base.default {
|
|
14
|
+
constructor(api) {
|
|
15
|
+
super(api, GROUP.ASK_USER_HISTORY);
|
|
16
|
+
}
|
|
17
|
+
async getThreads(options) {
|
|
18
|
+
return this._run('threads', undefined, Object.assign({}, options, {
|
|
19
|
+
method: 'GET'
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
async getThread(threadId, options) {
|
|
23
|
+
return this._run(`threads/${threadId}`, undefined, Object.assign({}, options, {
|
|
24
|
+
method: 'GET'
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
async updateThread(threadId, payload, options) {
|
|
28
|
+
return this._run(`threads/${threadId}`, payload, Object.assign({}, options, {
|
|
29
|
+
method: 'PUT'
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
async deleteThreads(payload, options) {
|
|
33
|
+
return this._run('threads/_delete', payload, options);
|
|
34
|
+
}
|
|
35
|
+
async deleteAllThreads(options) {
|
|
36
|
+
return this._run('threads/_delete_all', undefined, options);
|
|
37
|
+
}
|
|
38
|
+
async deleteThread(threadId, options) {
|
|
39
|
+
return this._run(`threads/${threadId}`, undefined, Object.assign({}, options, {
|
|
40
|
+
method: 'DELETE'
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
async markThreadAsRead(threadId, options) {
|
|
44
|
+
return this._run(`threads/${threadId}/read`, undefined, options);
|
|
45
|
+
}
|
|
46
|
+
async subscribeThread(threadId, options) {
|
|
47
|
+
return this._run(`threads/${threadId}/subscribe`, undefined, options);
|
|
48
|
+
}
|
|
49
|
+
async unsubscribeThread(threadId, options) {
|
|
50
|
+
return this._run(`threads/${threadId}/unsubscribe`, undefined, options);
|
|
51
|
+
}
|
|
52
|
+
async getNotifications(options) {
|
|
53
|
+
return this._run('notifications', undefined, Object.assign({}, options, {
|
|
54
|
+
method: 'GET'
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
async dismissNotifications(options) {
|
|
58
|
+
return this._run('notifications/dismiss', undefined, options);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.default = UserHistory;
|
package/dist/cjs/api/index.js
CHANGED
|
@@ -45,11 +45,25 @@ Object.defineProperty(exports, "Search", {
|
|
|
45
45
|
return _search.default;
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
|
+
Object.defineProperty(exports, "UserHistory", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () {
|
|
51
|
+
return _history.default;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
Object.defineProperty(exports, "UserHistoryV0", {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function () {
|
|
57
|
+
return _history2.default;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
48
60
|
var _api = _interopRequireDefault(require("./api.js"));
|
|
49
61
|
var _base = _interopRequireDefault(require("./base.js"));
|
|
50
62
|
var _helpers = _interopRequireDefault(require("./helpers.js"));
|
|
51
63
|
var _interactions = _interopRequireDefault(require("./interactions.js"));
|
|
52
64
|
var _ask = _interopRequireDefault(require("./ask.js"));
|
|
65
|
+
var _history = _interopRequireDefault(require("./history.js"));
|
|
66
|
+
var _history2 = _interopRequireDefault(require("./history.0.js"));
|
|
53
67
|
var _search = _interopRequireDefault(require("./search.js"));
|
|
54
68
|
var _recommendation = _interopRequireDefault(require("./recommendation.js"));
|
|
55
69
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
package/dist/cjs/api/iterable.js
CHANGED
|
@@ -41,6 +41,15 @@ class IterableApiStub {
|
|
|
41
41
|
options = _objectWithoutPropertiesLoose(_this$_options, _excluded);
|
|
42
42
|
const stac = new _commons.StallTimeoutAbortController(stallTimeout);
|
|
43
43
|
signal = _commons.signals.any(this._ac.signal, stac.signal, signal);
|
|
44
|
+
// the stall timer must die with the stream: a timer armed past an abort
|
|
45
|
+
// would keep a Node process alive for the full stall timeout. The signal
|
|
46
|
+
// may have aborted before this iterator was created (it is captured at
|
|
47
|
+
// request time), so the already-aborted case has to be handled as well.
|
|
48
|
+
if (signal.aborted) {
|
|
49
|
+
stac.clear();
|
|
50
|
+
} else {
|
|
51
|
+
signal.addEventListener('abort', () => stac.clear());
|
|
52
|
+
}
|
|
44
53
|
let prevResponse;
|
|
45
54
|
const onResponse = (response, finished) => {
|
|
46
55
|
if (finished) {
|
|
@@ -167,7 +167,9 @@ class ClientContext {
|
|
|
167
167
|
// helpers //
|
|
168
168
|
_set(key, value) {
|
|
169
169
|
this._props[key] = value;
|
|
170
|
-
|
|
170
|
+
// never emit credentials: the event may end up in the debug console
|
|
171
|
+
const displayed = key === 'auth' && value ? '****' : value;
|
|
172
|
+
this._plugin._events.emit('set', `${key} = '${displayed}'`);
|
|
171
173
|
}
|
|
172
174
|
_requireString(key, value) {
|
|
173
175
|
if (typeof value !== 'string' && typeof value !== 'undefined') {
|
package/dist/cjs/utils.js
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
Object.defineProperty(exports, "centered", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _commons.centered;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
6
12
|
Object.defineProperty(exports, "debounce", {
|
|
7
13
|
enumerable: true,
|
|
8
14
|
get: function () {
|
package/dist/cjs/version.js
CHANGED
package/package.json
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"access": "public"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
-
"build:clean": "
|
|
16
|
-
"build:cjs": "BABEL_ENV=cjs
|
|
15
|
+
"build:clean": "rimraf dist",
|
|
16
|
+
"build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir dist/cjs",
|
|
17
17
|
"build": "npm run build:clean && npm run build:cjs"
|
|
18
18
|
},
|
|
19
19
|
"repository": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"url": "https://github.com/MisoAI/miso-client-js-sdk/issues"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@miso.ai/commons": "1.
|
|
33
|
+
"@miso.ai/commons": "1.14.0-beta.0"
|
|
34
34
|
},
|
|
35
|
-
"version": "1.
|
|
35
|
+
"version": "1.14.0-beta.0"
|
|
36
36
|
}
|
package/src/api/ask.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { API, defineValues, trimObj } from '@miso.ai/commons';
|
|
2
2
|
import ApiBase from './base.js';
|
|
3
|
+
import UserHistoryV0 from './history.0.js';
|
|
3
4
|
import { IdBasedIterableApiStub } from './iterable.js';
|
|
4
5
|
|
|
5
6
|
const { GROUP, NAME } = API;
|
|
@@ -8,6 +9,9 @@ export default class Ask extends ApiBase {
|
|
|
8
9
|
|
|
9
10
|
constructor(api) {
|
|
10
11
|
super(api, GROUP.ASK);
|
|
12
|
+
// the deployed (v0) user history API; switch back to UserHistory
|
|
13
|
+
// (history.js) when the resource-style API ships
|
|
14
|
+
this.userHistory = new UserHistoryV0(api);
|
|
11
15
|
}
|
|
12
16
|
|
|
13
17
|
async questions(payload, options = {}) {
|
|
@@ -29,6 +33,16 @@ export default class Ask extends ApiBase {
|
|
|
29
33
|
return this._run(`${NAME.QUESTIONS}/${questionId}/answer`, undefined, { ...options, method: 'GET' });
|
|
30
34
|
}
|
|
31
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Retrieve multiple question-answer pairs at once.
|
|
38
|
+
*/
|
|
39
|
+
async answers(payload, options = {}) {
|
|
40
|
+
if (Array.isArray(payload)) {
|
|
41
|
+
payload = { question_ids: payload };
|
|
42
|
+
}
|
|
43
|
+
return this._run(NAME.ANSWERS, payload, options);
|
|
44
|
+
}
|
|
45
|
+
|
|
32
46
|
async relatedQuestions(payload, options = {}) {
|
|
33
47
|
return this._run(NAME.RELATED_QUESTIONS, payload, options);
|
|
34
48
|
}
|
package/src/api/base.js
CHANGED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import UserHistory from './history.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The user history API as deployed today (version 0): a flat, POST-only
|
|
5
|
+
* surface where a thread is addressed by the `question_id` of its root
|
|
6
|
+
* question, with its own request/response shapes.
|
|
7
|
+
* @see https://miso-docs.apidocumentation.com/api/genai/user-history
|
|
8
|
+
*
|
|
9
|
+
* It adapts the v0 wire format behind the interface of UserHistory in
|
|
10
|
+
* history.js — the resource-style API the SDK is written against, not
|
|
11
|
+
* released yet. All calls funnel through `_run`, where the resource-style
|
|
12
|
+
* (name, payload, method) is translated to its v0 form and the response
|
|
13
|
+
* value back to the resource-style shape, so the workflow layer stays
|
|
14
|
+
* version-agnostic. When the resource-style API ships, switching the SDK
|
|
15
|
+
* over means using UserHistory in ask.js again.
|
|
16
|
+
*/
|
|
17
|
+
export default class UserHistoryV0 extends UserHistory {
|
|
18
|
+
|
|
19
|
+
async _run(apiName, payload, options = {}) {
|
|
20
|
+
const { name, payload: v0Payload, adapt } = translate(apiName, payload, options);
|
|
21
|
+
const value = await super._run(name, v0Payload, { ...options, method: 'POST' });
|
|
22
|
+
return adapt ? adapt(value) : value;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Translate a resource-style (name, payload, method) call to its v0 form.
|
|
29
|
+
* The v0 payload is always an object — even when the resource-style call
|
|
30
|
+
* carries none (a GET) — so the context plugin's payload pass attaches the
|
|
31
|
+
* user info (user_id/anonymous_id) that v0 endpoints require.
|
|
32
|
+
*/
|
|
33
|
+
function translate(apiName, payload, { method = 'POST' } = {}) {
|
|
34
|
+
switch (apiName) {
|
|
35
|
+
case 'threads': // GET threads -> POST list
|
|
36
|
+
return { name: 'list', payload: { ...payload }, adapt: adaptThreadList };
|
|
37
|
+
case 'threads/_delete': {
|
|
38
|
+
const { thread_ids: question_ids = [], ...rest } = payload || {};
|
|
39
|
+
return { name: 'delete', payload: { ...rest, question_ids } };
|
|
40
|
+
}
|
|
41
|
+
case 'threads/_delete_all':
|
|
42
|
+
return { name: 'delete_all', payload: { ...payload } };
|
|
43
|
+
case 'notifications': // GET notifications -> POST thread/updates
|
|
44
|
+
return { name: 'thread/updates', payload: { ...payload } };
|
|
45
|
+
case 'notifications/dismiss':
|
|
46
|
+
return { name: 'thread/updates/dismiss_overall', payload: { ...payload } };
|
|
47
|
+
}
|
|
48
|
+
const segments = apiName.split('/');
|
|
49
|
+
if (segments[0] === 'threads' && segments.length === 2) {
|
|
50
|
+
const thread_id = segments[1]; // the thread id is its root question id
|
|
51
|
+
switch (method) {
|
|
52
|
+
case 'GET': // GET threads/{id} -> POST thread
|
|
53
|
+
return { name: 'thread', payload: { ...payload, thread_id }, adapt: value => adaptThreadDetail(thread_id, value) };
|
|
54
|
+
case 'PUT': // PUT threads/{id} { title } -> POST thread/rename
|
|
55
|
+
return { name: 'thread/rename', payload: { ...payload, thread_id } };
|
|
56
|
+
case 'DELETE': // DELETE threads/{id} -> POST delete
|
|
57
|
+
return { name: 'delete', payload: { question_ids: [thread_id] } };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (segments[0] === 'threads' && segments.length === 3) {
|
|
61
|
+
const thread_id = segments[1];
|
|
62
|
+
switch (segments[2]) {
|
|
63
|
+
case 'read': // POST threads/{id}/read -> POST thread/updates/dismiss_thread
|
|
64
|
+
return { name: 'thread/updates/dismiss_thread', payload: { ...payload, thread_id } };
|
|
65
|
+
case 'subscribe':
|
|
66
|
+
return { name: 'thread/updates/subscribe', payload: { ...payload, thread_id } };
|
|
67
|
+
case 'unsubscribe':
|
|
68
|
+
return { name: 'thread/updates/unsubscribe', payload: { ...payload, thread_id } };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
throw new Error(`Unknown user history API: ${method} ${apiName}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* A v0 list response nests the entries under `threads`, alongside the paging
|
|
76
|
+
* fields (has_more, start, rows), which pass through untouched.
|
|
77
|
+
*/
|
|
78
|
+
function adaptThreadList(value) {
|
|
79
|
+
if (!value || typeof value !== 'object') {
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
if (Array.isArray(value)) {
|
|
83
|
+
return value.map(adaptThreadEntry);
|
|
84
|
+
}
|
|
85
|
+
const { threads = [], ...rest } = value;
|
|
86
|
+
return { ...rest, threads: threads.map(adaptThreadEntry) };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A v0 thread entry carries (id, time, question_id, title, subscribed,
|
|
91
|
+
* has_new); the resource-style records read (thread_id, title, updated_at).
|
|
92
|
+
* A thread is keyed by its root question, so question_id serves as the
|
|
93
|
+
* thread id.
|
|
94
|
+
*/
|
|
95
|
+
function adaptThreadEntry(entry) {
|
|
96
|
+
if (!entry || typeof entry !== 'object') {
|
|
97
|
+
return entry;
|
|
98
|
+
}
|
|
99
|
+
const { id, question_id = id, time, ...rest } = entry;
|
|
100
|
+
return {
|
|
101
|
+
...rest,
|
|
102
|
+
thread_id: question_id,
|
|
103
|
+
question_id,
|
|
104
|
+
updated_at: rest.updated_at !== undefined ? rest.updated_at : time,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The v0 open-thread response carries the question ids (and a has_more flag,
|
|
110
|
+
* passed through) but no thread metadata: synthesize the thread record around
|
|
111
|
+
* them, keyed by the requested thread id.
|
|
112
|
+
*/
|
|
113
|
+
function adaptThreadDetail(thread_id, value) {
|
|
114
|
+
if (!value || typeof value !== 'object') {
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
const { question_ids = [], ...rest } = value;
|
|
118
|
+
return { ...rest, thread_id, questions_ids: question_ids };
|
|
119
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { API } from '@miso.ai/commons';
|
|
2
|
+
import ApiBase from './base.js';
|
|
3
|
+
|
|
4
|
+
const { GROUP } = API;
|
|
5
|
+
|
|
6
|
+
export default class UserHistory extends ApiBase {
|
|
7
|
+
|
|
8
|
+
constructor(api) {
|
|
9
|
+
super(api, GROUP.ASK_USER_HISTORY);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async getThreads(options) {
|
|
13
|
+
return this._run('threads', undefined, { ...options, method: 'GET' });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async getThread(threadId, options) {
|
|
17
|
+
return this._run(`threads/${threadId}`, undefined, { ...options, method: 'GET' });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async updateThread(threadId, payload, options) {
|
|
21
|
+
return this._run(`threads/${threadId}`, payload, { ...options, method: 'PUT' });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async deleteThreads(payload, options) {
|
|
25
|
+
return this._run('threads/_delete', payload, options);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async deleteAllThreads(options) {
|
|
29
|
+
return this._run('threads/_delete_all', undefined, options);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async deleteThread(threadId, options) {
|
|
33
|
+
return this._run(`threads/${threadId}`, undefined, { ...options, method: 'DELETE' });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async markThreadAsRead(threadId, options) {
|
|
37
|
+
return this._run(`threads/${threadId}/read`, undefined, options);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async subscribeThread(threadId, options) {
|
|
41
|
+
return this._run(`threads/${threadId}/subscribe`, undefined, options);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async unsubscribeThread(threadId, options) {
|
|
45
|
+
return this._run(`threads/${threadId}/unsubscribe`, undefined, options);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async getNotifications(options) {
|
|
49
|
+
return this._run('notifications', undefined, { ...options, method: 'GET' });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async dismissNotifications(options) {
|
|
53
|
+
return this._run('notifications/dismiss', undefined, options);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
}
|
package/src/api/index.js
CHANGED
|
@@ -3,5 +3,7 @@ export { default as ApiBase } from './base.js';
|
|
|
3
3
|
export { default as ApiHelpers } from './helpers.js';
|
|
4
4
|
export { default as Interactions } from './interactions.js';
|
|
5
5
|
export { default as Ask } from './ask.js';
|
|
6
|
+
export { default as UserHistory } from './history.js';
|
|
7
|
+
export { default as UserHistoryV0 } from './history.0.js';
|
|
6
8
|
export { default as Search } from './search.js';
|
|
7
9
|
export { default as Recommendation } from './recommendation.js';
|
package/src/api/iterable.js
CHANGED
|
@@ -33,6 +33,15 @@ export class IterableApiStub {
|
|
|
33
33
|
let { pollingInterval: interval, signal, stallTimeout = 120000, ...options } = this._options;
|
|
34
34
|
const stac = new StallTimeoutAbortController(stallTimeout);
|
|
35
35
|
signal = signals.any(this._ac.signal, stac.signal, signal);
|
|
36
|
+
// the stall timer must die with the stream: a timer armed past an abort
|
|
37
|
+
// would keep a Node process alive for the full stall timeout. The signal
|
|
38
|
+
// may have aborted before this iterator was created (it is captured at
|
|
39
|
+
// request time), so the already-aborted case has to be handled as well.
|
|
40
|
+
if (signal.aborted) {
|
|
41
|
+
stac.clear();
|
|
42
|
+
} else {
|
|
43
|
+
signal.addEventListener('abort', () => stac.clear());
|
|
44
|
+
}
|
|
36
45
|
|
|
37
46
|
let prevResponse;
|
|
38
47
|
const onResponse = (response, finished) => {
|
package/src/plugin/context.js
CHANGED
|
@@ -140,7 +140,9 @@ class ClientContext {
|
|
|
140
140
|
// helpers //
|
|
141
141
|
_set(key, value) {
|
|
142
142
|
this._props[key] = value;
|
|
143
|
-
|
|
143
|
+
// never emit credentials: the event may end up in the debug console
|
|
144
|
+
const displayed = key === 'auth' && value ? '****' : value;
|
|
145
|
+
this._plugin._events.emit('set', `${key} = '${displayed}'`);
|
|
144
146
|
}
|
|
145
147
|
|
|
146
148
|
_requireString(key, value) {
|
package/src/utils.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { viewable, debounce } from '@miso.ai/commons';
|
|
1
|
+
export { viewable, centered, debounce } from '@miso.ai/commons';
|
package/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '1.
|
|
1
|
+
export default '1.14.0-beta.0';
|