@mihe-dev/js 0.0.0-stage → 0.2.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.
Files changed (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +114 -2
  3. package/dist/audio.d.ts +121 -0
  4. package/dist/audio.d.ts.map +1 -0
  5. package/dist/audio.js +377 -0
  6. package/dist/audio.js.map +1 -0
  7. package/dist/card-view.d.ts +79 -0
  8. package/dist/card-view.d.ts.map +1 -0
  9. package/dist/card-view.js +99 -0
  10. package/dist/card-view.js.map +1 -0
  11. package/dist/chart.d.ts +15 -0
  12. package/dist/chart.d.ts.map +1 -0
  13. package/dist/chart.js +58 -0
  14. package/dist/chart.js.map +1 -0
  15. package/dist/client.d.ts +226 -0
  16. package/dist/client.d.ts.map +1 -0
  17. package/dist/client.js +358 -0
  18. package/dist/client.js.map +1 -0
  19. package/dist/commands.d.ts +70 -0
  20. package/dist/commands.d.ts.map +1 -0
  21. package/dist/commands.js +295 -0
  22. package/dist/commands.js.map +1 -0
  23. package/dist/debug.d.ts +17 -0
  24. package/dist/debug.d.ts.map +1 -0
  25. package/dist/debug.js +29 -0
  26. package/dist/debug.js.map +1 -0
  27. package/dist/declarations.d.ts +160 -0
  28. package/dist/declarations.d.ts.map +1 -0
  29. package/dist/declarations.js +171 -0
  30. package/dist/declarations.js.map +1 -0
  31. package/dist/highlight.d.ts +77 -0
  32. package/dist/highlight.d.ts.map +1 -0
  33. package/dist/highlight.js +233 -0
  34. package/dist/highlight.js.map +1 -0
  35. package/dist/index.d.ts +41 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +32 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/mihe.d.ts +364 -0
  40. package/dist/mihe.d.ts.map +1 -0
  41. package/dist/mihe.iife.min.js +217 -0
  42. package/dist/mihe.iife.min.js.map +7 -0
  43. package/dist/mihe.js +758 -0
  44. package/dist/mihe.js.map +1 -0
  45. package/dist/mihe.min.js +217 -0
  46. package/dist/mihe.min.js.map +7 -0
  47. package/dist/store.d.ts +175 -0
  48. package/dist/store.d.ts.map +1 -0
  49. package/dist/store.js +208 -0
  50. package/dist/store.js.map +1 -0
  51. package/dist/voice.d.ts +192 -0
  52. package/dist/voice.d.ts.map +1 -0
  53. package/dist/voice.js +443 -0
  54. package/dist/voice.js.map +1 -0
  55. package/dist/widget/card.d.ts +17 -0
  56. package/dist/widget/card.d.ts.map +1 -0
  57. package/dist/widget/card.js +31 -0
  58. package/dist/widget/card.js.map +1 -0
  59. package/dist/widget/dom.d.ts +24 -0
  60. package/dist/widget/dom.d.ts.map +1 -0
  61. package/dist/widget/dom.js +49 -0
  62. package/dist/widget/dom.js.map +1 -0
  63. package/dist/widget/element.d.ts +88 -0
  64. package/dist/widget/element.d.ts.map +1 -0
  65. package/dist/widget/element.js +285 -0
  66. package/dist/widget/element.js.map +1 -0
  67. package/dist/widget/format.d.ts +24 -0
  68. package/dist/widget/format.d.ts.map +1 -0
  69. package/dist/widget/format.js +64 -0
  70. package/dist/widget/format.js.map +1 -0
  71. package/dist/widget/icons.d.ts +5 -0
  72. package/dist/widget/icons.d.ts.map +1 -0
  73. package/dist/widget/icons.js +19 -0
  74. package/dist/widget/icons.js.map +1 -0
  75. package/dist/widget/launcher.d.ts +13 -0
  76. package/dist/widget/launcher.d.ts.map +1 -0
  77. package/dist/widget/launcher.js +27 -0
  78. package/dist/widget/launcher.js.map +1 -0
  79. package/dist/widget/mark.d.ts +10 -0
  80. package/dist/widget/mark.d.ts.map +1 -0
  81. package/dist/widget/mark.js +20 -0
  82. package/dist/widget/mark.js.map +1 -0
  83. package/dist/widget/orb.d.ts +92 -0
  84. package/dist/widget/orb.d.ts.map +1 -0
  85. package/dist/widget/orb.js +500 -0
  86. package/dist/widget/orb.js.map +1 -0
  87. package/dist/widget/panel.d.ts +40 -0
  88. package/dist/widget/panel.d.ts.map +1 -0
  89. package/dist/widget/panel.js +240 -0
  90. package/dist/widget/panel.js.map +1 -0
  91. package/dist/widget/styles.d.ts +22 -0
  92. package/dist/widget/styles.d.ts.map +1 -0
  93. package/dist/widget/styles.js +192 -0
  94. package/dist/widget/styles.js.map +1 -0
  95. package/package.json +43 -4
package/dist/client.js ADDED
@@ -0,0 +1,358 @@
1
+ /**
2
+ * The WebSocket client (doc 02).
3
+ *
4
+ * One persistent socket per session carries chat, commands, and
5
+ * confirmations. Two properties drive the design:
6
+ *
7
+ * - A frontend action is a tool call that round-trips through the browser, so
8
+ * the runtime pushes a command and blocks until this client acks it. Every
9
+ * command MUST be answered, including on failure — an unanswered command
10
+ * stalls the assistant's turn until the runtime's timeout fires.
11
+ * - Confirming an action needs server-to-client push, which is why this is a
12
+ * socket rather than a request per message.
13
+ *
14
+ * The client owns transport only. It never decides what a command means; the
15
+ * provider does that and hands back a result.
16
+ */
17
+ import { PROTOCOL_VERSION, } from "@mihe-dev/protocol";
18
+ const MAX_RECONNECT_DELAY_MS = 30_000;
19
+ export class AssistantClient {
20
+ options;
21
+ socket = null;
22
+ state = "idle";
23
+ attempt = 0;
24
+ reconnectTimer = null;
25
+ heartbeatTimer = null;
26
+ /** Set when the caller closed deliberately, so we do not reconnect. */
27
+ stopped = false;
28
+ conversationId = null;
29
+ /** Re-sent after every reconnect, so the runtime is never blind to context. */
30
+ lastScreen = null;
31
+ constructor(options) {
32
+ this.options = options;
33
+ }
34
+ get connectionState() {
35
+ return this.state;
36
+ }
37
+ async connect() {
38
+ if (this.state === "connecting" || this.state === "open")
39
+ return;
40
+ this.stopped = false;
41
+ await this.open();
42
+ }
43
+ close() {
44
+ this.stopped = true;
45
+ this.clearTimers();
46
+ this.socket?.close();
47
+ this.socket = null;
48
+ this.setState("closed");
49
+ }
50
+ /** Send a user message. Silently dropped when offline — the widget shows the state. */
51
+ sendMessage(text, clientMsgId) {
52
+ this.send({ type: "message", data: { text, clientMsgId } });
53
+ }
54
+ /**
55
+ * Publish the current screen. Idempotent: a full snapshot that replaces
56
+ * whatever the runtime held.
57
+ */
58
+ /**
59
+ * Tell the runtime where the user is, or that they are somewhere it does not
60
+ * know about.
61
+ *
62
+ * `null` matters as much as a screen. The host app registers the screens it
63
+ * chooses to; every other page is one the runtime must be told it cannot
64
+ * see. Left unsaid, the runtime keeps the last screen it heard about, and
65
+ * the assistant names a page the user left — which is worse than admitting
66
+ * it does not know, and quietly keeps that screen's scoped actions callable.
67
+ */
68
+ updateScreen(screen) {
69
+ this.lastScreen = screen;
70
+ this.send({ type: "screen_update", data: { screen } });
71
+ }
72
+ /**
73
+ * Answer a command. Must be called for every command received, including
74
+ * failures — the runtime is blocking a turn on this.
75
+ */
76
+ ackCommand(commandId, ok, result, error) {
77
+ this.send({
78
+ type: "command_result",
79
+ data: {
80
+ commandId,
81
+ ok,
82
+ result: (result ?? null),
83
+ error: error ?? null,
84
+ },
85
+ });
86
+ }
87
+ confirmAction(proposalId, confirmed, editedInput) {
88
+ this.send({
89
+ type: "action_confirm",
90
+ data: {
91
+ proposalId,
92
+ confirmed,
93
+ editedInput: (editedInput ?? null),
94
+ },
95
+ });
96
+ }
97
+ cancelTurn(turnId) {
98
+ this.send({ type: "cancel", data: { turnId } });
99
+ }
100
+ /**
101
+ * Ask for a permit to open the voice socket.
102
+ *
103
+ * Requested on the chat socket rather than fetched over HTTP because this
104
+ * session is what the permit is scoped to: the runtime hands back a token
105
+ * bound to the very session actor holding this connection, so the voice
106
+ * socket joins the conversation already in progress instead of starting a
107
+ * second one beside it.
108
+ *
109
+ * Answered by a `voice_token` event, or by an `error` when voice is not
110
+ * available for this app — which is the signal to hide the microphone
111
+ * rather than offer one that fails on the first press.
112
+ */
113
+ requestVoiceToken() {
114
+ this.send({ type: "voice_token_request" });
115
+ }
116
+ // ------------------------------------------------------------- internals
117
+ async open() {
118
+ this.setState(this.attempt === 0 ? "connecting" : "reconnecting");
119
+ let token;
120
+ try {
121
+ token = await this.options.getUserToken();
122
+ }
123
+ catch (cause) {
124
+ if (this.stopped)
125
+ return;
126
+ // The host app's token endpoint is down. Retrying is right — this is
127
+ // usually transient — but the user should be told why it is quiet.
128
+ this.emit({
129
+ type: "error",
130
+ code: "user_token_unavailable",
131
+ message: "Could not get a session token from the app.",
132
+ recoverable: true,
133
+ });
134
+ this.scheduleReconnect();
135
+ return;
136
+ }
137
+ // Closed while the token was on its way. Opening anyway left a socket
138
+ // nothing would ever close: a second live session, which React's
139
+ // StrictMode made on every development mount by connecting, closing and
140
+ // connecting again.
141
+ if (this.stopped)
142
+ return;
143
+ const factory = this.options.socketFactory ??
144
+ ((url) => new WebSocket(url));
145
+ const socket = factory(this.options.url);
146
+ this.socket = socket;
147
+ socket.onopen = () => {
148
+ const auth = {
149
+ type: "auth",
150
+ data: {
151
+ publicKey: this.options.publicKey,
152
+ userToken: token,
153
+ sdkVersion: this.options.sdkVersion,
154
+ protocolVersion: PROTOCOL_VERSION,
155
+ conversationId: this.conversationId,
156
+ ...(this.options.debug ? { debug: true } : {}),
157
+ },
158
+ };
159
+ socket.send(JSON.stringify(auth));
160
+ };
161
+ socket.onmessage = (event) => {
162
+ if (typeof event.data !== "string")
163
+ return;
164
+ let message;
165
+ try {
166
+ message = JSON.parse(event.data);
167
+ }
168
+ catch {
169
+ return;
170
+ }
171
+ this.handle(message);
172
+ };
173
+ socket.onclose = () => {
174
+ this.clearTimers();
175
+ if (this.stopped) {
176
+ this.setState("closed");
177
+ return;
178
+ }
179
+ this.scheduleReconnect();
180
+ };
181
+ socket.onerror = () => {
182
+ // `onclose` always follows, and that is where reconnect is handled.
183
+ };
184
+ }
185
+ handle(message) {
186
+ switch (message.type) {
187
+ case "auth_ok": {
188
+ this.attempt = 0;
189
+ this.conversationId = message.data.conversationId;
190
+ this.emit({
191
+ type: "voice_available",
192
+ available: message.data.voiceAvailable ?? false,
193
+ });
194
+ // Only when the runtime actually sent one. An older runtime omits the
195
+ // field, and overwriting a good name with "" would rename the panel to
196
+ // nothing — worse than leaving the SDK's own default in place.
197
+ if (message.data.assistantName) {
198
+ this.emit({ type: "assistant_name", name: message.data.assistantName });
199
+ }
200
+ this.emit({
201
+ type: "launcher_icon",
202
+ url: message.data.launcherIconUrl ?? null,
203
+ });
204
+ this.emit({ type: "widget_settings", settings: message.data.widget ?? null });
205
+ this.setState("open");
206
+ this.startHeartbeat(message.data.heartbeatIntervalMs);
207
+ // The runtime replays nothing, so re-publish context immediately.
208
+ if (this.lastScreen)
209
+ this.updateScreen(this.lastScreen);
210
+ break;
211
+ }
212
+ case "auth_error": {
213
+ this.emit({
214
+ type: "error",
215
+ code: message.data.code,
216
+ message: message.data.message,
217
+ // A bad key or an unsupported protocol version will not fix itself.
218
+ recoverable: false,
219
+ });
220
+ this.stopped = true;
221
+ break;
222
+ }
223
+ case "auth_expired": {
224
+ // Re-authenticate in place rather than tearing down the socket.
225
+ void this.options
226
+ .getUserToken()
227
+ .then((token) => this.send({
228
+ type: "auth",
229
+ data: {
230
+ publicKey: this.options.publicKey,
231
+ userToken: token,
232
+ sdkVersion: this.options.sdkVersion,
233
+ protocolVersion: PROTOCOL_VERSION,
234
+ conversationId: this.conversationId,
235
+ ...(this.options.debug ? { debug: true } : {}),
236
+ },
237
+ }))
238
+ .catch(() => this.socket?.close());
239
+ break;
240
+ }
241
+ case "turn_start":
242
+ this.emit({ type: "turn_start", turnId: message.data.turnId });
243
+ break;
244
+ case "delta":
245
+ this.emit({
246
+ type: "delta",
247
+ turnId: message.data.turnId,
248
+ text: message.data.text,
249
+ });
250
+ break;
251
+ case "complete":
252
+ this.emit({
253
+ type: "complete",
254
+ turnId: message.data.turnId,
255
+ message: message.data.message,
256
+ sources: message.data.sources ?? [],
257
+ });
258
+ break;
259
+ case "command":
260
+ this.emit({
261
+ type: "command",
262
+ commandId: message.data.commandId,
263
+ command: message.data.command,
264
+ });
265
+ break;
266
+ case "action_proposal":
267
+ this.emit({
268
+ type: "proposal",
269
+ proposal: message.data,
270
+ });
271
+ break;
272
+ case "action_status":
273
+ this.emit({
274
+ type: "action_status",
275
+ proposalId: message.data.proposalId,
276
+ status: message.data.status,
277
+ result: message.data.result ?? undefined,
278
+ error: message.data.error ?? undefined,
279
+ });
280
+ break;
281
+ case "error":
282
+ this.emit({
283
+ type: "error",
284
+ code: message.data.code,
285
+ message: message.data.message,
286
+ recoverable: message.data.recoverable,
287
+ });
288
+ break;
289
+ case "voice_token":
290
+ this.emit({
291
+ type: "voice_token",
292
+ token: message.data.token,
293
+ expiresAt: message.data.expiresAt,
294
+ });
295
+ break;
296
+ case "context_report":
297
+ this.emit({ type: "context_report", report: message.data });
298
+ break;
299
+ case "pong":
300
+ break;
301
+ }
302
+ }
303
+ send(message) {
304
+ if (this.state !== "open" && message.type !== "auth")
305
+ return;
306
+ try {
307
+ this.socket?.send(JSON.stringify(message));
308
+ }
309
+ catch {
310
+ // A send on a closing socket throws; `onclose` handles recovery.
311
+ }
312
+ }
313
+ scheduleReconnect() {
314
+ this.setState("reconnecting");
315
+ const delay = this.options.reconnectDelay?.(this.attempt) ?? backoff(this.attempt);
316
+ this.attempt += 1;
317
+ this.reconnectTimer = setTimeout(() => void this.open(), delay);
318
+ }
319
+ startHeartbeat(intervalMs) {
320
+ this.clearHeartbeat();
321
+ this.heartbeatTimer = setInterval(() => {
322
+ this.send({ type: "ping" });
323
+ }, intervalMs);
324
+ }
325
+ clearHeartbeat() {
326
+ if (this.heartbeatTimer !== null) {
327
+ clearInterval(this.heartbeatTimer);
328
+ this.heartbeatTimer = null;
329
+ }
330
+ }
331
+ clearTimers() {
332
+ this.clearHeartbeat();
333
+ if (this.reconnectTimer !== null) {
334
+ clearTimeout(this.reconnectTimer);
335
+ this.reconnectTimer = null;
336
+ }
337
+ }
338
+ setState(state) {
339
+ if (this.state === state)
340
+ return;
341
+ this.state = state;
342
+ this.emit({ type: "state", state });
343
+ }
344
+ emit(event) {
345
+ this.options.onEvent(event);
346
+ }
347
+ }
348
+ /**
349
+ * Exponential backoff with jitter, capped.
350
+ *
351
+ * Jitter matters more than it looks: without it, every tab of every customer
352
+ * reconnects in lockstep after a runtime restart and stampedes it.
353
+ */
354
+ function backoff(attempt) {
355
+ const base = Math.min(1000 * 2 ** attempt, MAX_RECONNECT_DELAY_MS);
356
+ return base / 2 + Math.random() * (base / 2);
357
+ }
358
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../js/src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Executing the commands the runtime sends.
3
+ *
4
+ * Every command names a registered target — a route the runtime resolved from
5
+ * its screen catalogue, or a component key the app declared. Nothing here
6
+ * takes a CSS selector or a coordinate, so there is no path by which the model
7
+ * drives the UI directly (spec §5.2).
8
+ *
9
+ * Every branch returns a result, including failures, because the runtime is
10
+ * blocking a turn on the ack and the model needs to learn the truth. Reporting
11
+ * "the element was not on screen" is far better than reporting nothing.
12
+ */
13
+ import type { AssistantCommand } from "@mihe-dev/protocol";
14
+ import type { HighlightEngine } from "./highlight.js";
15
+ import type { AssistantStore, QueryParamDeclaration } from "./store.js";
16
+ /** When a frontend action is warned about as slow. */
17
+ export declare const ACTION_SLOW_MS = 5000;
18
+ /**
19
+ * How long the runtime waits for a command's answer (`COMMAND_ACK_TIMEOUT`
20
+ * in the runtime's session.rs). Past it, the assistant is told the command
21
+ * failed.
22
+ */
23
+ export declare const RUNTIME_ACK_WAIT_MS = 10000;
24
+ export interface CommandResult {
25
+ ok: boolean;
26
+ result?: unknown;
27
+ error?: string;
28
+ }
29
+ export interface CommandContext {
30
+ store: AssistantStore;
31
+ highlighter: HighlightEngine;
32
+ /**
33
+ * How the host app changes route. Supplied by the customer, because only
34
+ * they know whether that is Next.js's router, React Router, or something
35
+ * else. Defaults to a full page load, which works everywhere and is
36
+ * noticeably worse — the docs should push people to wire this up.
37
+ */
38
+ navigate: (route: string) => void;
39
+ /**
40
+ * Resolves once the screen at `route` has published its context to the
41
+ * runtime, or `false` if it has not done so within the timeout.
42
+ *
43
+ * Navigating is the one command whose effects are not finished when the
44
+ * function returns: the router swaps the tree, React mounts the destination,
45
+ * its hooks register, and only then does the new context travel. The runtime
46
+ * re-reads the screen after every tool call to decide what the next step may
47
+ * do, so acking before that lands would tell it the user is still on the
48
+ * screen they just left — and the action they navigated *for* would be
49
+ * filtered out as off-screen.
50
+ *
51
+ * Optional so a hand-built context still works; the provider always supplies
52
+ * it.
53
+ */
54
+ screenPublished?: (route: string, options?: {
55
+ fresh?: boolean;
56
+ }) => Promise<boolean>;
57
+ /**
58
+ * Resolves once a published screen shows `controlKey` set to `value`, or
59
+ * `false` if none does within the timeout. A switch is acked only then, for
60
+ * `screenPublished`'s reason: the runtime's next step reads the screen.
61
+ */
62
+ viewPublished?: (controlKey: string, value: string) => Promise<boolean>;
63
+ /** Opens a registered modal, when the host app has modals to open. */
64
+ /** Return `false` when the key is not one this app can open. */
65
+ openModal?: (modalKey: string) => void | boolean;
66
+ }
67
+ /** Why a set of search parameters is not what the table declared, or null. */
68
+ export declare function checkQueryParams(declared: QueryParamDeclaration[], params: Record<string, string>): string | null;
69
+ export declare function executeCommand(command: AssistantCommand, ctx: CommandContext): Promise<CommandResult>;
70
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../js/src/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAY,MAAM,SAAS,CAAC;AAE/E,sDAAsD;AACtD,eAAO,MAAM,cAAc,OAAQ,CAAC;AAEpC;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,cAAc,CAAC;IACtB,WAAW,EAAE,eAAe,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;;;;;;;;;;;;;OAcG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACrF;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxE,sEAAsE;IACtE,gEAAgE;IAChE,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC;CAClD;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,qBAAqB,EAAE,EACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,MAAM,GAAG,IAAI,CAgBf;AAqBD,wBAAsB,cAAc,CAClC,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,aAAa,CAAC,CAgPxB"}