@miso.ai/client-sdk-ui 1.13.0-beta.0 → 1.13.0-beta.2

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.
@@ -68,6 +68,12 @@ class Tracker {
68
68
  value
69
69
  });
70
70
  }
71
+ heartbeat() {
72
+ this._syncSession();
73
+ this._sendToHub({
74
+ type: _constants.EVENT_TYPE.HEARTBEAT
75
+ });
76
+ }
71
77
  _sendToHub(args) {
72
78
  this._hub.trigger(fields.tracker(), Object.freeze((0, _commons.trimObj)(Object.assign({
73
79
  role: this._role
@@ -52,9 +52,10 @@ const EVENT_TYPE = exports.EVENT_TYPE = Object.freeze({
52
52
  VIEWABLE: 'viewable',
53
53
  CLICK: 'click',
54
54
  SUBMIT: 'submit',
55
- FEEDBACK: 'feedback'
55
+ FEEDBACK: 'feedback',
56
+ HEARTBEAT: 'heartbeat'
56
57
  });
57
- const TRACKING_EVENT_TYPES = exports.TRACKING_EVENT_TYPES = [EVENT_TYPE.IMPRESSION, EVENT_TYPE.VIEWABLE, EVENT_TYPE.CLICK, EVENT_TYPE.SUBMIT, EVENT_TYPE.FEEDBACK];
58
+ const TRACKING_EVENT_TYPES = exports.TRACKING_EVENT_TYPES = [EVENT_TYPE.IMPRESSION, EVENT_TYPE.VIEWABLE, EVENT_TYPE.CLICK, EVENT_TYPE.SUBMIT, EVENT_TYPE.FEEDBACK, EVENT_TYPE.HEARTBEAT];
58
59
  const PERFORMANCE_EVENT_TYPES = exports.PERFORMANCE_EVENT_TYPES = [EVENT_TYPE.IMPRESSION, EVENT_TYPE.VIEWABLE, EVENT_TYPE.CLICK];
59
60
  const PERFORMANCE_EVENT_TYPE_SET = new Set(PERFORMANCE_EVENT_TYPES);
60
61
  function isPerformanceEventType(type) {
@@ -4,4 +4,4 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _default = exports.default = '1.13.0-beta.0';
7
+ var _default = exports.default = '1.13.0-beta.2';
@@ -57,6 +57,9 @@ class Workflow extends _commons.Component {
57
57
  onEmit: event => this._onHubEmit(event)
58
58
  });
59
59
  this._sessionContext = new WeakMap();
60
+ this._pluginContext = {
61
+ processInteractionPasses: []
62
+ };
60
63
  client._events.emit('workflow', this);
61
64
  this._initProperties(args);
62
65
  this._initActors(args);
@@ -298,6 +301,9 @@ class Workflow extends _commons.Component {
298
301
  _buildInteraction(args) {
299
302
  let payload = (0, _processors.buildBaseInteraction)(args);
300
303
  payload = this._defaultProcessInteraction(payload, args);
304
+ for (const p of this._pluginContext.processInteractionPasses) {
305
+ payload = p(payload, args);
306
+ }
301
307
  const {
302
308
  preprocess = []
303
309
  } = this._options.resolved.interactions;
@@ -41,17 +41,21 @@ function autoQuery(options = {}) {
41
41
  const searchParams = new URLSearchParams(window.location.search);
42
42
  const q = searchParams.get(param);
43
43
  const qs = searchParams.get(sourceParam) || undefined;
44
- for (const view of this._views.getAll(_constants.ROLE.QUERY)) {
45
- const {
46
- layout
47
- } = view;
48
- if (q && setValue) {
49
- layout.value = q;
50
- }
51
- if (!q && focus) {
52
- layout.focus();
44
+
45
+ // because it's probably not there yet, but this is an ad-hoc solution
46
+ setTimeout(() => {
47
+ for (const view of this._views.getAll(_constants.ROLE.QUERY)) {
48
+ const {
49
+ layout
50
+ } = view;
51
+ if (q && setValue) {
52
+ layout.value = q;
53
+ }
54
+ if (!q && focus) {
55
+ layout.focus();
56
+ }
53
57
  }
54
- }
58
+ });
55
59
  if (q) {
56
60
  this.query((0, _commons.trimObj)({
57
61
  q,
@@ -429,6 +429,10 @@ function buildBaseInteraction(args) {
429
429
  payload.context.custom_context.value = payload.value = args.value;
430
430
  payload.context.custom_context.result_type = payload.result_type = args.result_type;
431
431
  break;
432
+ case _constants.EVENT_TYPE.HEARTBEAT:
433
+ payload.type = 'custom';
434
+ payload.custom_action_name = 'heartbeat';
435
+ break;
432
436
  }
433
437
  return (0, _commons.trimObj)(payload);
434
438
  }
package/package.json CHANGED
@@ -26,7 +26,7 @@
26
26
  "url": "https://github.com/MisoAI/miso-client-js-sdk/issues"
27
27
  },
28
28
  "dependencies": {
29
- "@miso.ai/commons": "1.13.0-beta.0"
29
+ "@miso.ai/commons": "1.13.0-beta.2"
30
30
  },
31
- "version": "1.13.0-beta.0"
31
+ "version": "1.13.0-beta.2"
32
32
  }
package/src/CLAUDE.md ADDED
@@ -0,0 +1,134 @@
1
+ # Client SDK UI
2
+
3
+ The UI package (`std:ui` plugin) provides the presentation layer for Miso SDK, including custom elements, workflows, and rendering infrastructure.
4
+
5
+ ## Architecture Overview
6
+
7
+ // TODO: wrong concept
8
+
9
+ ```
10
+ ┌─────────────────────────────────────────────────────────────────┐
11
+ │ UiPlugin │
12
+ │ - Registered as 'std:ui' │
13
+ │ - Injects client.ui on each MisoClient instance │
14
+ │ - Manages layouts, combo, and extensions │
15
+ └─────────────────────────────────────────────────────────────────┘
16
+ │
17
+ ┌─────────────────────┼─────────────────────┐
18
+ ▼ ▼ ▼
19
+ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
20
+ │ Workflows │ │ Elements │ │ Layouts │
21
+ │ │◄────►│ │◄────►│ │
22
+ │ (Logic) │ │ (Custom El) │ │ (Rendering) │
23
+ └─────────────┘ └─────────────┘ └─────────────┘
24
+ │
25
+ ▼
26
+ ┌─────────────┐
27
+ │ Actors │
28
+ │ (Hub I/O) │
29
+ └─────────────┘
30
+ ```
31
+
32
+ ## Core Directories
33
+
34
+ // TODO: wrong concept
35
+
36
+ | Directory | Purpose |
37
+ |-----------|---------|
38
+ | `workflow/` | Orchestration logic for features (Ask, Search, Explore, etc.) |
39
+ | `element/` | Custom HTML elements (`<miso-*>` tags) |
40
+ | `actor/` | Hub-connected actors for data, views, tracking, interactions |
41
+ | `layout/` | Rendering templates for different UI roles |
42
+ | `combo/` | Pre-built composite UI configurations (deprecated) |
43
+ | `trait/` | Reusable behavior mixins |
44
+ | `defaults/` | Default configurations |
45
+
46
+ ## Key Concepts
47
+
48
+ ### Workflows (`workflow/`)
49
+
50
+ // TODO: wrong concept
51
+
52
+ State machines that orchestrate API calls and UI updates. Each workflow manages:
53
+ - Session lifecycle (restart, query, response)
54
+ - Data flow via Hub
55
+ - View state synchronization
56
+ - Interaction tracking
57
+
58
+ **Available workflows**: `Ask`, `Search`, `HybridSearch`, `Explore`, `Recommendation`
59
+
60
+ ### Elements (`element/`)
61
+
62
+ Web Components following the `<miso-*>` naming convention:
63
+
64
+ - **Containers**: Top-level elements that own a workflow
65
+ - `<miso-ask>`, `<miso-search>`, `<miso-explore>`, `<miso-recommendation>`, `<miso-hybrid-search>`
66
+
67
+ - **Roles**: Child elements bound to specific data roles
68
+ - Query: `<miso-query>`
69
+ - Results: `<miso-answer>`, `<miso-sources>`, `<miso-products>`, `<miso-results>`
70
+ - Navigation: `<miso-follow-up-questions>`, `<miso-related-questions>`
71
+ - Utility: `<miso-feedback>`, `<miso-error>`, `<miso-facets>`, `<miso-total>`
72
+
73
+ - **Combos**: Pre-configured composite elements (deprecated)
74
+ - `<miso-ask-combo>`
75
+
76
+ ### Actors (`actor/`)
77
+
78
+ Components that subscribe to and publish on the Hub:
79
+ - `DataActor` - Fetches data from API based on requests
80
+ - `ViewsActor` - Manages view state for each role
81
+ - `TrackersActor` - Handles impression/click/viewable tracking
82
+ - `InteractionsActor` - Sends interaction events to API
83
+ - `SessionMaker` - Manages session lifecycle
84
+
85
+ ### Hub
86
+
87
+ Central pub/sub state manager connecting workflows and actors. Fields include:
88
+ - `session` - Current session object
89
+ - `request` - API request parameters
90
+ - `data` - Response data
91
+ - `view(role)` - View state per role
92
+ - `tracker(role, event)` - Tracking state
93
+
94
+ ### Layouts (`layout/`)
95
+
96
+ Rendering strategies for each role. Registered via `plugin.layouts.register()`.
97
+
98
+ Types: `input`, `list`, `text`, `container`, `error`, `button`, etc.
99
+
100
+ ### Roles & Status
101
+
102
+ **Roles** (from `constants.js`): Define what data a view displays
103
+ - Content: `answer`, `question`, `sources`, `products`, `results`
104
+ - Navigation: `follow_up_questions`, `related_questions`, `query_suggestions`
105
+ - Meta: `feedback`, `error`, `total`, `facets`
106
+
107
+ **Status**: Workflow/view lifecycle states
108
+ - `initial` → `loading` → `ready` / `erroneous`
109
+ - `ongoing` (streaming) → `done`
110
+
111
+ ## Entry Point
112
+
113
+ ```javascript
114
+ // plugin.js exports UiPlugin
115
+ // Installed automatically with full SDK, or manually:
116
+ MisoClient.plugins.use('std:ui');
117
+
118
+ // Access via client instance:
119
+ const client = new MisoClient({ apiKey });
120
+ client.ui.ask; // Ask workflow
121
+ client.ui.search; // Search workflow
122
+ client.ui.recommendations; // Recommendations
123
+ ```
124
+
125
+ ## Event Flow
126
+
127
+ 1. User interacts with `<miso-query>` element (ask, hybrid-search, search, etc.), or start by calling `start()` on the workflow instance (explore, recommendations).
128
+ 2. Container element triggers workflow request
129
+ 3. Workflow publishes request to Hub
130
+ 4. `DataActor` fetches from API, publishes response
131
+ 5. `ViewsActor` updates view states per role
132
+ 6. Layout renders updated content in elements
133
+ 7. `TrackersActor` observes visibility, triggers interactions
134
+ 8. `InteractionsActor` sends tracking data to API
@@ -63,6 +63,13 @@ export default class Tracker {
63
63
  });
64
64
  }
65
65
 
66
+ heartbeat() {
67
+ this._syncSession();
68
+ this._sendToHub({
69
+ type: EVENT_TYPE.HEARTBEAT,
70
+ });
71
+ }
72
+
66
73
  _sendToHub(args) {
67
74
  this._hub.trigger(fields.tracker(), Object.freeze(trimObj({ role: this._role, ...args })));
68
75
  }
package/src/constants.js CHANGED
@@ -71,6 +71,7 @@ export const EVENT_TYPE = Object.freeze({
71
71
  CLICK: 'click',
72
72
  SUBMIT: 'submit',
73
73
  FEEDBACK: 'feedback',
74
+ HEARTBEAT: 'heartbeat',
74
75
  });
75
76
 
76
77
  export const TRACKING_EVENT_TYPES = [
@@ -79,6 +80,7 @@ export const TRACKING_EVENT_TYPES = [
79
80
  EVENT_TYPE.CLICK,
80
81
  EVENT_TYPE.SUBMIT,
81
82
  EVENT_TYPE.FEEDBACK,
83
+ EVENT_TYPE.HEARTBEAT,
82
84
  ];
83
85
 
84
86
  export const PERFORMANCE_EVENT_TYPES = [
package/src/version.js CHANGED
@@ -1 +1 @@
1
- export default '1.13.0-beta.0';
1
+ export default '1.13.0-beta.2';
@@ -1,4 +1,4 @@
1
- import { API, mergeInteractions } from '@miso.ai/commons';
1
+ import { API } from '@miso.ai/commons';
2
2
  import Workflow from './base.js';
3
3
  import { fields, FeedbackActor } from '../actor/index.js';
4
4
  import { ROLE, STATUS, QUESTION_SOURCE } from '../constants.js';
@@ -59,6 +59,9 @@ export default class Workflow extends Component {
59
59
  onEmit: event => this._onHubEmit(event),
60
60
  });
61
61
  this._sessionContext = new WeakMap();
62
+ this._pluginContext = {
63
+ processInteractionPasses: [],
64
+ };
62
65
 
63
66
  client._events.emit('workflow', this);
64
67
 
@@ -286,6 +289,9 @@ export default class Workflow extends Component {
286
289
  _buildInteraction(args) {
287
290
  let payload = buildBaseInteraction(args);
288
291
  payload = this._defaultProcessInteraction(payload, args);
292
+ for (const p of this._pluginContext.processInteractionPasses) {
293
+ payload = p(payload, args);
294
+ }
289
295
  const { preprocess = [] } = this._options.resolved.interactions;
290
296
  for (const p of preprocess) {
291
297
  payload = p(payload, args);
@@ -22,15 +22,18 @@ export function autoQuery(options = {}) {
22
22
  const q = searchParams.get(param);
23
23
  const qs = searchParams.get(sourceParam) || undefined;
24
24
 
25
- for (const view of this._views.getAll(ROLE.QUERY)) {
26
- const { layout } = view;
27
- if (q && setValue) {
28
- layout.value = q;
25
+ // because it's probably not there yet, but this is an ad-hoc solution
26
+ setTimeout(() => {
27
+ for (const view of this._views.getAll(ROLE.QUERY)) {
28
+ const { layout } = view;
29
+ if (q && setValue) {
30
+ layout.value = q;
31
+ }
32
+ if (!q && focus) {
33
+ layout.focus();
34
+ }
29
35
  }
30
- if (!q && focus) {
31
- layout.focus();
32
- }
33
- }
36
+ });
34
37
 
35
38
  if (q) {
36
39
  this.query(trimObj({ q, qs }));
@@ -329,6 +329,10 @@ export function buildBaseInteraction(args) {
329
329
  payload.context.custom_context.value = payload.value = args.value;
330
330
  payload.context.custom_context.result_type = payload.result_type = args.result_type;
331
331
  break;
332
+ case EVENT_TYPE.HEARTBEAT:
333
+ payload.type = 'custom';
334
+ payload.custom_action_name = 'heartbeat';
335
+ break;
332
336
  }
333
337
 
334
338
  return trimObj(payload);