@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
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The conversation: transcript, confirmation cards, composer, and in the
3
+ * classic form the microphone.
4
+ *
5
+ * Built once and updated. The composer and the microphone buttons in
6
+ * particular are never rebuilt: a rebuilt input loses what the user was
7
+ * typing, and a push-to-talk button replaced mid-press loses its pointer
8
+ * capture, so the release lands elsewhere and the microphone stays open.
9
+ */
10
+ import type { VoiceMode } from "@mihe-dev/protocol";
11
+ import { type Mihe, type MiheState } from "../mihe.js";
12
+ export declare const DEFAULT_VOICE_MODES: VoiceMode[];
13
+ export interface PanelOptions {
14
+ /** Header title; the assistant's name from the app's settings otherwise. */
15
+ title?: string;
16
+ placeholder?: string;
17
+ showClose: boolean;
18
+ /** The microphone beside the input. Off when the orb owns voice. */
19
+ showVoice: boolean;
20
+ }
21
+ export declare class Panel {
22
+ private readonly mihe;
23
+ private options;
24
+ readonly root: HTMLElement;
25
+ private readonly heading;
26
+ private readonly dot;
27
+ private readonly closeButton;
28
+ private readonly transcript;
29
+ private readonly input;
30
+ private readonly sendButton;
31
+ private readonly voiceControl;
32
+ /** What the transcript was last drawn from, so it is redrawn only on change. */
33
+ private drawn;
34
+ constructor(mihe: Mihe, options: PanelOptions);
35
+ setOptions(options: PanelOptions): void;
36
+ update(state: MiheState): void;
37
+ private syncSend;
38
+ private drawTranscript;
39
+ }
40
+ //# sourceMappingURL=panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../../../js/src/widget/panel.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAsB,KAAK,IAAI,EAAE,KAAK,SAAS,EAAsB,MAAM,SAAS,CAAC;AAI5F,eAAO,MAAM,mBAAmB,EAAE,SAAS,EAA2B,CAAC;AAEvE,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,KAAK;IAad,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,OAAO;IAbjB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAO;IAC/B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoB;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,gFAAgF;IAChF,OAAO,CAAC,KAAK,CAAiB;gBAGX,IAAI,EAAE,IAAI,EACnB,OAAO,EAAE,YAAY;IAiD/B,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIvC,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAiC9B,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,cAAc;CA6CvB"}
@@ -0,0 +1,240 @@
1
+ /**
2
+ * The conversation: transcript, confirmation cards, composer, and in the
3
+ * classic form the microphone.
4
+ *
5
+ * Built once and updated. The composer and the microphone buttons in
6
+ * particular are never rebuilt: a rebuilt input loses what the user was
7
+ * typing, and a push-to-talk button replaced mid-press loses its pointer
8
+ * capture, so the release lands elsewhere and the microphone stays open.
9
+ */
10
+ import { ASSISTANT_PANEL_ID } from "../mihe.js";
11
+ import { confirmationCard } from "./card.js";
12
+ import { h, replace, setAttrs } from "./dom.js";
13
+ export const DEFAULT_VOICE_MODES = ["hands-free", "hold"];
14
+ export class Panel {
15
+ mihe;
16
+ options;
17
+ root;
18
+ heading;
19
+ dot;
20
+ closeButton;
21
+ transcript;
22
+ input;
23
+ sendButton;
24
+ voiceControl;
25
+ /** What the transcript was last drawn from, so it is redrawn only on change. */
26
+ drawn = [];
27
+ constructor(mihe, options) {
28
+ this.mihe = mihe;
29
+ this.options = options;
30
+ this.heading = document.createTextNode("");
31
+ this.dot = h("span", { class: "status-dot", attrs: { "aria-hidden": "true" } });
32
+ this.closeButton = h("button", {
33
+ class: "icon-button",
34
+ attrs: { type: "button", "aria-label": "Close assistant" },
35
+ on: { click: () => this.mihe.close() },
36
+ }, "✕");
37
+ this.transcript = h("div", { class: "transcript" });
38
+ this.input = h("input", {
39
+ class: "input",
40
+ attrs: { "aria-label": "Message" },
41
+ on: { input: () => this.syncSend(this.mihe.getState()) },
42
+ });
43
+ this.sendButton = h("button", { class: "send", attrs: { type: "submit" } }, "Send");
44
+ this.voiceControl = new VoiceControl(mihe);
45
+ const composer = h("form", {
46
+ class: "composer",
47
+ on: {
48
+ submit: (event) => {
49
+ event.preventDefault();
50
+ this.mihe.send(this.input.value);
51
+ this.input.value = "";
52
+ this.syncSend(this.mihe.getState());
53
+ },
54
+ },
55
+ }, this.voiceControl.root, this.input, this.sendButton);
56
+ this.root = h("section", { class: "panel", attrs: { id: ASSISTANT_PANEL_ID } }, h("header", { class: "header" }, h("div", { class: "header-title" }, this.dot, this.heading), this.closeButton), this.transcript, composer);
57
+ }
58
+ setOptions(options) {
59
+ this.options = options;
60
+ }
61
+ update(state) {
62
+ const heading = this.options.title ?? state.assistantName ?? "Assistant";
63
+ this.heading.data = heading;
64
+ this.root.setAttribute("aria-label", heading);
65
+ this.dot.classList.toggle("open", state.connection === "open");
66
+ this.closeButton.hidden = !this.options.showClose;
67
+ this.input.placeholder = this.options.placeholder ?? "Ask me anything about this app…";
68
+ this.input.disabled = state.connection !== "open";
69
+ this.syncSend(state);
70
+ // The modes the app allows. Offering one it does not would be a button
71
+ // the runtime refuses.
72
+ const modes = state.widgetSettings?.voiceModes ?? DEFAULT_VOICE_MODES;
73
+ const showVoice = this.options.showVoice && state.voice.available && modes.length > 0;
74
+ this.voiceControl.root.hidden = !showVoice;
75
+ if (showVoice) {
76
+ this.voiceControl.update(state.voice, state.connection !== "open", modes);
77
+ }
78
+ const inputs = [
79
+ state.messages,
80
+ state.proposals,
81
+ state.cardViews,
82
+ state.voice.state === "connecting",
83
+ state.voice.notice,
84
+ state.lastError,
85
+ state.connection,
86
+ ];
87
+ if (inputs.every((value, index) => value === this.drawn[index]))
88
+ return;
89
+ this.drawn = inputs;
90
+ this.drawTranscript(state);
91
+ }
92
+ syncSend(state) {
93
+ this.sendButton.disabled = state.busy || !this.input.value.trim() || state.connection !== "open";
94
+ }
95
+ drawTranscript(state) {
96
+ replace(this.transcript, state.messages.length === 0 &&
97
+ h("p", { class: "empty" }, "Ask where something is, what a screen does, or for help getting something done."), ...state.messages.map((message) => h("div", { class: message.role === "user" ? "bubble-user" : "bubble-assistant" }, message.text, message.streaming && message.text === "" && h("span", { class: "thinking" }, "thinking…"), message.sources && message.sources.length > 0 &&
98
+ // Titles only. The snippet is what the model read, not something
99
+ // a reader needs.
100
+ h("div", { class: "sources" }, ...message.sources.map((source) => h("span", { class: "source" }, source.url && /^https?:\/\//i.test(source.url)
101
+ ? h("a", { attrs: { href: source.url, target: "_blank", rel: "noreferrer noopener" } }, source.title)
102
+ : source.title))))), ...state.proposals.map((proposal) => confirmationCard(proposal, this.mihe.respondToProposal, state.cardViews[proposal.proposalId])),
103
+ // Setting up a voice session takes a moment, and the microphone stays
104
+ // shut until it finishes (amendment 32). Without a word here the user
105
+ // talks into a session that is not listening yet.
106
+ state.voice.state === "connecting" && h("div", { class: "voice-notice" }, "Setting up the microphone…"), state.voice.notice && h("div", { class: "voice-notice" }, state.voice.notice), state.lastError && h("div", { class: "error" }, state.lastError), state.connection !== "open" &&
107
+ h("div", { class: "notice" }, state.connection === "closed" ? "Disconnected." : "Connecting…"));
108
+ this.transcript.scrollTo?.({ top: this.transcript.scrollHeight, behavior: "smooth" });
109
+ }
110
+ }
111
+ /**
112
+ * The microphone, in whichever of its two modes is running.
113
+ *
114
+ * Idle, it offers both: hold to talk, or hands-free. Once a session is live
115
+ * only the running one is shown, with a way out.
116
+ */
117
+ class VoiceControl {
118
+ mihe;
119
+ root;
120
+ hold;
121
+ handsFree;
122
+ stopHandsFree;
123
+ pulse;
124
+ constructor(mihe) {
125
+ this.mihe = mihe;
126
+ this.hold = pushToTalk(mihe);
127
+ this.handsFree = h("button", {
128
+ class: "hands-free",
129
+ attrs: {
130
+ type: "button",
131
+ "aria-label": "Start hands-free voice",
132
+ title: "Hands-free — talk without holding anything",
133
+ },
134
+ on: { click: () => this.mihe.voice.start({ handsFree: true }) },
135
+ }, "∞");
136
+ this.pulse = h("span", { class: "pulse" });
137
+ this.stopHandsFree = h("button", {
138
+ class: "mic live",
139
+ attrs: { type: "button", "aria-label": "Stop hands-free voice", "aria-pressed": "true" },
140
+ on: { click: () => this.mihe.voice.stop() },
141
+ }, this.pulse);
142
+ this.root = h("span", { attrs: { style: "display: contents" } }, this.hold, this.handsFree, this.stopHandsFree);
143
+ }
144
+ update(voice, disabled, modes) {
145
+ // Connecting is not live: the microphone is shut until the provider
146
+ // accepts its configuration, and a live-looking button invites talking
147
+ // into a session that cannot hear yet.
148
+ const live = voice.state !== "idle" && voice.state !== "error" && voice.state !== "connecting";
149
+ const liveHandsFree = live && voice.handsFree;
150
+ this.stopHandsFree.hidden = !liveHandsFree;
151
+ this.hold.hidden = liveHandsFree || (!live && !modes.includes("hold"));
152
+ this.handsFree.hidden = live || !modes.includes("hands-free");
153
+ this.stopHandsFree.disabled = disabled;
154
+ this.handsFree.disabled = disabled;
155
+ this.stopHandsFree.title =
156
+ voice.state === "speaking" ? "Speaking — just talk to interrupt" : "Listening — say anything";
157
+ // Speaking and listening pulse at different rates: a hands-free user
158
+ // cannot tell from a still icon whether the microphone is open.
159
+ this.pulse.classList.toggle("fast", voice.state === "speaking");
160
+ const connecting = voice.state === "connecting";
161
+ const recording = voice.state === "recording";
162
+ setAttrs(this.hold, {
163
+ "aria-label": connecting
164
+ ? "Setting up the microphone"
165
+ : !live
166
+ ? "Start voice"
167
+ : recording
168
+ ? "Release to send"
169
+ : "Hold to speak",
170
+ "aria-busy": connecting ? "true" : undefined,
171
+ "aria-pressed": recording ? "true" : "false",
172
+ title: voice.state === "thinking" ? "Thinking…" : voice.state === "speaking" ? "Speaking — press to interrupt" : undefined,
173
+ });
174
+ this.hold.disabled = disabled || connecting;
175
+ this.hold.classList.toggle("recording", recording);
176
+ this.hold.classList.toggle("live", live && !recording);
177
+ this.hold.textContent = voice.state === "thinking" ? "…" : "\u{1F399}";
178
+ }
179
+ }
180
+ /**
181
+ * The push-to-talk button: hold to speak, release to send, the same gesture
182
+ * on a mouse, a touchscreen and a keyboard.
183
+ *
184
+ * - **Pointer down, not click,** because the press begins the utterance and
185
+ * the release ends it. It is also the gesture iOS Safari needs before any
186
+ * audio, which is why the first press opens the session.
187
+ * - **Pointer capture,** so a finger that slides off still ends the
188
+ * utterance on release.
189
+ * - **Space and Enter, held,** with key repeat ignored.
190
+ *
191
+ * State is read at the moment of each event, never captured.
192
+ */
193
+ function pushToTalk(mihe) {
194
+ const phase = () => {
195
+ const state = mihe.getState().voice.state;
196
+ const connecting = state === "connecting";
197
+ return { connecting, live: state !== "idle" && state !== "error" && !connecting };
198
+ };
199
+ const begin = (button, pointerId) => {
200
+ const { connecting, live } = phase();
201
+ if (connecting)
202
+ return;
203
+ if (!live) {
204
+ mihe.voice.start();
205
+ return;
206
+ }
207
+ if (pointerId !== undefined)
208
+ button.setPointerCapture?.(pointerId);
209
+ mihe.voice.press();
210
+ };
211
+ const end = () => {
212
+ if (phase().live)
213
+ mihe.voice.release();
214
+ };
215
+ const button = h("button", {
216
+ class: "mic",
217
+ attrs: { type: "button" },
218
+ on: {
219
+ pointerdown: (event) => begin(button, event.pointerId),
220
+ pointerup: end,
221
+ pointercancel: end,
222
+ keydown: (event) => {
223
+ if (event.repeat)
224
+ return;
225
+ if (event.key === " " || event.key === "Enter") {
226
+ event.preventDefault();
227
+ begin(button);
228
+ }
229
+ },
230
+ keyup: (event) => {
231
+ if (event.key === " " || event.key === "Enter") {
232
+ event.preventDefault();
233
+ end();
234
+ }
235
+ },
236
+ },
237
+ }, "\u{1F399}");
238
+ return button;
239
+ }
240
+ //# sourceMappingURL=panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel.js","sourceRoot":"","sources":["../../../../js/src/widget/panel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The widget's stylesheet, inside its shadow root.
3
+ *
4
+ * The shadow root is what keeps the host page out: a Tailwind reset or a
5
+ * site's `button { … }` cannot select anything in here, and nothing here can
6
+ * select the page. Inherited properties still cross the boundary, which is
7
+ * why `:host` resets them all.
8
+ *
9
+ * Theming is through custom properties set on the element, the one styling
10
+ * hook a shadow root lets through by design:
11
+ *
12
+ * ```css
13
+ * mihe-assistant { --mihe-accent: #0a7d5a; --mihe-radius: 10px; }
14
+ * ```
15
+ *
16
+ * The values match the React widget's.
17
+ */
18
+ export declare const LAUNCHER_BG = "#221f1b";
19
+ export declare const LAUNCHER_INK = "#eae7e4";
20
+ export declare const LAUNCHER_VOICE = "#5ac8cd";
21
+ export declare const STYLES = "\n:host {\n all: initial;\n --mihe-accent: #4f7cff;\n --mihe-radius: 14px;\n --mihe-font: system-ui, -apple-system, 'Segoe UI', sans-serif;\n --mihe-z: 2147482000;\n}\n:host([layout=\"inline\"]) { display: block; width: 100%; height: 100%; }\n*, *::before, *::after { box-sizing: border-box; }\n[hidden] { display: none !important; }\nbutton { font: inherit; color: inherit; margin: 0; }\n\n.panel {\n display: flex; flex-direction: column; width: 100%; height: 100%;\n background: #fff; color: #0f172a;\n border-radius: var(--mihe-radius); border: 1px solid #e2e8f0;\n box-shadow: 0 20px 50px rgba(15,23,42,0.22);\n font: 14px/1.5 var(--mihe-font); overflow: hidden;\n}\n.floating {\n position: fixed; bottom: 20px;\n width: min(380px, calc(100vw - 40px)); height: min(560px, calc(100vh - 40px));\n z-index: var(--mihe-z);\n}\n.floating.right { right: 20px; }\n.floating.left { left: 20px; }\n.header {\n display: flex; align-items: center; justify-content: space-between;\n padding: 12px 14px; border-bottom: 1px solid #e2e8f0; font-weight: 600;\n}\n.header-title { display: flex; align-items: center; gap: 8px; }\n.status-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; background: #f59e0b; }\n.status-dot.open { background: #22c55e; }\n.icon-button { border: none; background: transparent; cursor: pointer; font-size: 14px; color: #64748b; }\n.transcript { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 10px; }\n.empty { color: #64748b; margin: 0; }\n.bubble-user, .bubble-assistant { max-width: 85%; padding: 8px 12px; white-space: pre-wrap; overflow-wrap: anywhere; }\n.bubble-user { align-self: flex-end; background: var(--mihe-accent); color: #fff; border-radius: 12px 12px 2px 12px; }\n.bubble-assistant { align-self: flex-start; background: #f1f5f9; border-radius: 12px 12px 12px 2px; }\n.thinking { color: #64748b; font-style: italic; }\n.sources { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; padding-top: 8px; border-top: 1px solid #e2e8f0; }\n.source { font-size: 11px; color: #475569; background: #f1f5f9; padding: 2px 8px; border-radius: 999px; }\n.source a { color: inherit; text-decoration: none; }\n.error { background: #fef2f2; color: #991b1b; padding: 8px 10px; border-radius: 8px; font-size: 13px; }\n.notice { color: #64748b; font-size: 13px; text-align: center; }\n.voice-notice { background: #f1f5f9; color: #475569; padding: 8px 10px; border-radius: 8px; font-size: 13px; }\n.composer { display: flex; gap: 8px; padding: 12px; border-top: 1px solid #e2e8f0; }\n.input {\n flex: 1; min-width: 0; padding: 9px 12px; border-radius: 8px; border: 1px solid #cbd5e1;\n font: 14px var(--mihe-font); color: #0f172a; background: #fff; outline: none;\n}\n.send {\n padding: 9px 16px; border-radius: 8px; border: none; background: var(--mihe-accent);\n color: #fff; cursor: pointer; font: 600 13px var(--mihe-font);\n}\n.send:disabled { opacity: 0.6; cursor: default; }\n.mic {\n width: 38px; border-radius: 8px; border: 1px solid #cbd5e1; background: #fff; cursor: pointer;\n font-size: 16px; user-select: none; -webkit-user-select: none; touch-action: none;\n}\n.mic.live { border-color: var(--mihe-accent); }\n.mic.recording { border-color: #dc2626; background: #fef2f2; }\n.hands-free {\n width: 30px; border-radius: 8px; border: 1px solid #cbd5e1; background: #fff; color: #475569;\n cursor: pointer; font-size: 15px; user-select: none; -webkit-user-select: none;\n}\n.pulse {\n display: block; width: 12px; height: 12px; margin: 0 auto; border-radius: 50%;\n background: var(--mihe-accent); animation: mihe-pulse 2s ease-in-out infinite;\n}\n.pulse.fast { animation-duration: 0.8s; }\n@keyframes mihe-pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(0.6); opacity: 0.45; } }\n\n.card {\n border: 1px solid #e2e8f0; border-radius: 10px; padding: 12px; background: #fff; color: #0f172a;\n box-shadow: 0 2px 8px rgba(15,23,42,0.06); font: 14px/1.5 var(--mihe-font);\n}\n.card-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }\n.risk { font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 999px; white-space: nowrap; background: #fef3c7; color: #92400e; }\n.risk-high { background: #fee2e2; color: #991b1b; }\n.card-description { margin: 0 0 10px; color: #475569; font-size: 13px; }\n.card-input { margin: 0 0 12px; display: flex; flex-direction: column; gap: 8px; max-height: 40vh; overflow-y: auto; }\n.card-row { display: flex; flex-wrap: wrap; gap: 8px; font-size: 13px; }\n.card-key { color: #64748b; min-width: 90px; margin: 0; }\n.card-value { margin: 0; font-weight: 500; overflow-wrap: anywhere; min-width: 0; flex: 1 1 160px; }\n.input-list { margin: 0; padding-left: 20px; display: grid; gap: 8px; }\n.input-text { white-space: pre-wrap; }\n.card-actions { display: flex; gap: 8px; justify-content: flex-end; }\n.card-summary { margin: 0 0 10px; font-size: 14px; font-weight: 600; color: #0f172a; }\n.card-note { margin: 0 0 12px; font-size: 12px; color: #64748b; }\n.card-more { margin: 0 0 12px; font-size: 12px; color: #64748b; }\n.card-more summary { cursor: pointer; }\n.card-more .card-description { margin: 6px 0 0; }\n.card-value-wide { flex-basis: 100%; }\n.card-images { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; }\n.card-images img { width: 44px; height: 44px; object-fit: cover; border-radius: 6px; background: #f1f5f9; }\n.card-before { color: #94a3b8; font-weight: 400; }\n.card-arrow { color: #94a3b8; }\n.button-primary:disabled { opacity: 0.5; cursor: default; }\n.button-secondary {\n padding: 7px 14px; border-radius: 8px; border: 1px solid #cbd5e1; background: #fff;\n cursor: pointer; font: 500 13px var(--mihe-font);\n}\n.button-primary {\n padding: 7px 14px; border-radius: 8px; border: none; background: var(--mihe-accent); color: #fff;\n cursor: pointer; font: 600 13px var(--mihe-font);\n}\n\n.launcher {\n position: fixed; right: 20px; bottom: 20px; width: 52px; height: 52px; border-radius: 50%;\n border: none; padding: 0; display: grid; place-items: center; overflow: hidden;\n background: #221f1b; color: #eae7e4; cursor: pointer;\n box-shadow: 0 8px 24px rgba(15,23,42,0.25); z-index: var(--mihe-z);\n}\n.launcher-image { width: 100%; height: 100%; object-fit: cover; display: block; }\n\n.orb {\n position: fixed; width: 56px; height: 56px; padding: 0; border: none; border-radius: 50%;\n background: #221f1b; color: #eae7e4; box-shadow: 0 8px 24px rgba(15,23,42,0.25);\n z-index: var(--mihe-z); cursor: pointer; transition: left 180ms ease, top 180ms ease;\n touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;\n -webkit-tap-highlight-color: transparent;\n}\n.orb.dragging { cursor: grabbing; transition: none; }\n.orb:disabled { cursor: default; }\n.face { position: absolute; inset: 0; display: grid; place-items: center; border-radius: 50%; overflow: hidden; pointer-events: none; }\n.ring {\n position: absolute; inset: -6px; border-radius: 50%; border: 2px solid #5ac8cd;\n pointer-events: none; transform-origin: center; will-change: transform;\n}\n.ring.idle { border-color: transparent; }\n.ring.recording { border-color: #e5484d; border-width: 3px; }\n.ring.thinking, .ring.connecting { border-style: dashed; }\n.ring.listening { animation: mihe-orb-breathe 2.4s ease-in-out infinite; }\n.ring.thinking { animation: mihe-orb-spin 1.2s linear infinite; }\n.ring.connecting { animation: mihe-orb-spin 2.4s linear infinite; }\n@keyframes mihe-orb-breathe { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }\n@keyframes mihe-orb-spin { to { rotate: 360deg; } }\n.stop {\n position: fixed; width: 44px; height: 44px; border-radius: 50%; border: 1px solid rgba(15,23,42,0.12);\n background: #fff; box-shadow: 0 4px 14px rgba(15,23,42,0.18); display: grid; place-items: center;\n cursor: pointer; z-index: var(--mihe-z);\n}\n.stop-square { width: 12px; height: 12px; border-radius: 2px; background: #0f172a; }\n.popover {\n position: fixed; max-width: min(340px, calc(100vw - 40px)); z-index: calc(var(--mihe-z) + 1);\n display: flex; flex-direction: column; gap: 8px; font: 14px/1.45 var(--mihe-font);\n}\n.popover.cards { width: 320px; }\n.menu-item {\n display: inline-flex; align-items: center; gap: 10px; min-height: 44px; padding: 0 16px 0 6px;\n border-radius: 999px; border: 1px solid rgba(15,23,42,0.1); background: #fff; color: #0f172a;\n box-shadow: 0 6px 18px rgba(15,23,42,0.16); cursor: pointer; font: 500 14px var(--mihe-font);\n}\n.menu-icon {\n display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%;\n background: #221f1b; color: #5ac8cd;\n}\n.orb-bubble {\n padding: 8px 12px; border-radius: 12px; background: #fff; color: #0f172a;\n border: 1px solid rgba(15,23,42,0.1); box-shadow: 0 6px 18px rgba(15,23,42,0.16);\n}\n.orb-bubble.error { background: #fef2f2; color: #991b1b; border-color: #fecaca; }\n\n@media (prefers-reduced-motion: reduce) {\n .pulse, .ring { animation: none !important; }\n .ring { transform: none !important; }\n .orb { transition: none; }\n}\n";
22
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../js/src/widget/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAO,MAAM,WAAW,YAAY,CAAC;AACrC,eAAO,MAAM,YAAY,YAAY,CAAC;AACtC,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC,eAAO,MAAM,MAAM,i+RA0KlB,CAAC"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * The widget's stylesheet, inside its shadow root.
3
+ *
4
+ * The shadow root is what keeps the host page out: a Tailwind reset or a
5
+ * site's `button { … }` cannot select anything in here, and nothing here can
6
+ * select the page. Inherited properties still cross the boundary, which is
7
+ * why `:host` resets them all.
8
+ *
9
+ * Theming is through custom properties set on the element, the one styling
10
+ * hook a shadow root lets through by design:
11
+ *
12
+ * ```css
13
+ * mihe-assistant { --mihe-accent: #0a7d5a; --mihe-radius: 10px; }
14
+ * ```
15
+ *
16
+ * The values match the React widget's.
17
+ */
18
+ export const LAUNCHER_BG = "#221f1b";
19
+ export const LAUNCHER_INK = "#eae7e4";
20
+ export const LAUNCHER_VOICE = "#5ac8cd";
21
+ export const STYLES = `
22
+ :host {
23
+ all: initial;
24
+ --mihe-accent: #4f7cff;
25
+ --mihe-radius: 14px;
26
+ --mihe-font: system-ui, -apple-system, 'Segoe UI', sans-serif;
27
+ --mihe-z: 2147482000;
28
+ }
29
+ :host([layout="inline"]) { display: block; width: 100%; height: 100%; }
30
+ *, *::before, *::after { box-sizing: border-box; }
31
+ [hidden] { display: none !important; }
32
+ button { font: inherit; color: inherit; margin: 0; }
33
+
34
+ .panel {
35
+ display: flex; flex-direction: column; width: 100%; height: 100%;
36
+ background: #fff; color: #0f172a;
37
+ border-radius: var(--mihe-radius); border: 1px solid #e2e8f0;
38
+ box-shadow: 0 20px 50px rgba(15,23,42,0.22);
39
+ font: 14px/1.5 var(--mihe-font); overflow: hidden;
40
+ }
41
+ .floating {
42
+ position: fixed; bottom: 20px;
43
+ width: min(380px, calc(100vw - 40px)); height: min(560px, calc(100vh - 40px));
44
+ z-index: var(--mihe-z);
45
+ }
46
+ .floating.right { right: 20px; }
47
+ .floating.left { left: 20px; }
48
+ .header {
49
+ display: flex; align-items: center; justify-content: space-between;
50
+ padding: 12px 14px; border-bottom: 1px solid #e2e8f0; font-weight: 600;
51
+ }
52
+ .header-title { display: flex; align-items: center; gap: 8px; }
53
+ .status-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; background: #f59e0b; }
54
+ .status-dot.open { background: #22c55e; }
55
+ .icon-button { border: none; background: transparent; cursor: pointer; font-size: 14px; color: #64748b; }
56
+ .transcript { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 10px; }
57
+ .empty { color: #64748b; margin: 0; }
58
+ .bubble-user, .bubble-assistant { max-width: 85%; padding: 8px 12px; white-space: pre-wrap; overflow-wrap: anywhere; }
59
+ .bubble-user { align-self: flex-end; background: var(--mihe-accent); color: #fff; border-radius: 12px 12px 2px 12px; }
60
+ .bubble-assistant { align-self: flex-start; background: #f1f5f9; border-radius: 12px 12px 12px 2px; }
61
+ .thinking { color: #64748b; font-style: italic; }
62
+ .sources { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; padding-top: 8px; border-top: 1px solid #e2e8f0; }
63
+ .source { font-size: 11px; color: #475569; background: #f1f5f9; padding: 2px 8px; border-radius: 999px; }
64
+ .source a { color: inherit; text-decoration: none; }
65
+ .error { background: #fef2f2; color: #991b1b; padding: 8px 10px; border-radius: 8px; font-size: 13px; }
66
+ .notice { color: #64748b; font-size: 13px; text-align: center; }
67
+ .voice-notice { background: #f1f5f9; color: #475569; padding: 8px 10px; border-radius: 8px; font-size: 13px; }
68
+ .composer { display: flex; gap: 8px; padding: 12px; border-top: 1px solid #e2e8f0; }
69
+ .input {
70
+ flex: 1; min-width: 0; padding: 9px 12px; border-radius: 8px; border: 1px solid #cbd5e1;
71
+ font: 14px var(--mihe-font); color: #0f172a; background: #fff; outline: none;
72
+ }
73
+ .send {
74
+ padding: 9px 16px; border-radius: 8px; border: none; background: var(--mihe-accent);
75
+ color: #fff; cursor: pointer; font: 600 13px var(--mihe-font);
76
+ }
77
+ .send:disabled { opacity: 0.6; cursor: default; }
78
+ .mic {
79
+ width: 38px; border-radius: 8px; border: 1px solid #cbd5e1; background: #fff; cursor: pointer;
80
+ font-size: 16px; user-select: none; -webkit-user-select: none; touch-action: none;
81
+ }
82
+ .mic.live { border-color: var(--mihe-accent); }
83
+ .mic.recording { border-color: #dc2626; background: #fef2f2; }
84
+ .hands-free {
85
+ width: 30px; border-radius: 8px; border: 1px solid #cbd5e1; background: #fff; color: #475569;
86
+ cursor: pointer; font-size: 15px; user-select: none; -webkit-user-select: none;
87
+ }
88
+ .pulse {
89
+ display: block; width: 12px; height: 12px; margin: 0 auto; border-radius: 50%;
90
+ background: var(--mihe-accent); animation: mihe-pulse 2s ease-in-out infinite;
91
+ }
92
+ .pulse.fast { animation-duration: 0.8s; }
93
+ @keyframes mihe-pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(0.6); opacity: 0.45; } }
94
+
95
+ .card {
96
+ border: 1px solid #e2e8f0; border-radius: 10px; padding: 12px; background: #fff; color: #0f172a;
97
+ box-shadow: 0 2px 8px rgba(15,23,42,0.06); font: 14px/1.5 var(--mihe-font);
98
+ }
99
+ .card-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
100
+ .risk { font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 999px; white-space: nowrap; background: #fef3c7; color: #92400e; }
101
+ .risk-high { background: #fee2e2; color: #991b1b; }
102
+ .card-description { margin: 0 0 10px; color: #475569; font-size: 13px; }
103
+ .card-input { margin: 0 0 12px; display: flex; flex-direction: column; gap: 8px; max-height: 40vh; overflow-y: auto; }
104
+ .card-row { display: flex; flex-wrap: wrap; gap: 8px; font-size: 13px; }
105
+ .card-key { color: #64748b; min-width: 90px; margin: 0; }
106
+ .card-value { margin: 0; font-weight: 500; overflow-wrap: anywhere; min-width: 0; flex: 1 1 160px; }
107
+ .input-list { margin: 0; padding-left: 20px; display: grid; gap: 8px; }
108
+ .input-text { white-space: pre-wrap; }
109
+ .card-actions { display: flex; gap: 8px; justify-content: flex-end; }
110
+ .card-summary { margin: 0 0 10px; font-size: 14px; font-weight: 600; color: #0f172a; }
111
+ .card-note { margin: 0 0 12px; font-size: 12px; color: #64748b; }
112
+ .card-more { margin: 0 0 12px; font-size: 12px; color: #64748b; }
113
+ .card-more summary { cursor: pointer; }
114
+ .card-more .card-description { margin: 6px 0 0; }
115
+ .card-value-wide { flex-basis: 100%; }
116
+ .card-images { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; }
117
+ .card-images img { width: 44px; height: 44px; object-fit: cover; border-radius: 6px; background: #f1f5f9; }
118
+ .card-before { color: #94a3b8; font-weight: 400; }
119
+ .card-arrow { color: #94a3b8; }
120
+ .button-primary:disabled { opacity: 0.5; cursor: default; }
121
+ .button-secondary {
122
+ padding: 7px 14px; border-radius: 8px; border: 1px solid #cbd5e1; background: #fff;
123
+ cursor: pointer; font: 500 13px var(--mihe-font);
124
+ }
125
+ .button-primary {
126
+ padding: 7px 14px; border-radius: 8px; border: none; background: var(--mihe-accent); color: #fff;
127
+ cursor: pointer; font: 600 13px var(--mihe-font);
128
+ }
129
+
130
+ .launcher {
131
+ position: fixed; right: 20px; bottom: 20px; width: 52px; height: 52px; border-radius: 50%;
132
+ border: none; padding: 0; display: grid; place-items: center; overflow: hidden;
133
+ background: ${LAUNCHER_BG}; color: ${LAUNCHER_INK}; cursor: pointer;
134
+ box-shadow: 0 8px 24px rgba(15,23,42,0.25); z-index: var(--mihe-z);
135
+ }
136
+ .launcher-image { width: 100%; height: 100%; object-fit: cover; display: block; }
137
+
138
+ .orb {
139
+ position: fixed; width: 56px; height: 56px; padding: 0; border: none; border-radius: 50%;
140
+ background: ${LAUNCHER_BG}; color: ${LAUNCHER_INK}; box-shadow: 0 8px 24px rgba(15,23,42,0.25);
141
+ z-index: var(--mihe-z); cursor: pointer; transition: left 180ms ease, top 180ms ease;
142
+ touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
143
+ -webkit-tap-highlight-color: transparent;
144
+ }
145
+ .orb.dragging { cursor: grabbing; transition: none; }
146
+ .orb:disabled { cursor: default; }
147
+ .face { position: absolute; inset: 0; display: grid; place-items: center; border-radius: 50%; overflow: hidden; pointer-events: none; }
148
+ .ring {
149
+ position: absolute; inset: -6px; border-radius: 50%; border: 2px solid ${LAUNCHER_VOICE};
150
+ pointer-events: none; transform-origin: center; will-change: transform;
151
+ }
152
+ .ring.idle { border-color: transparent; }
153
+ .ring.recording { border-color: #e5484d; border-width: 3px; }
154
+ .ring.thinking, .ring.connecting { border-style: dashed; }
155
+ .ring.listening { animation: mihe-orb-breathe 2.4s ease-in-out infinite; }
156
+ .ring.thinking { animation: mihe-orb-spin 1.2s linear infinite; }
157
+ .ring.connecting { animation: mihe-orb-spin 2.4s linear infinite; }
158
+ @keyframes mihe-orb-breathe { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }
159
+ @keyframes mihe-orb-spin { to { rotate: 360deg; } }
160
+ .stop {
161
+ position: fixed; width: 44px; height: 44px; border-radius: 50%; border: 1px solid rgba(15,23,42,0.12);
162
+ background: #fff; box-shadow: 0 4px 14px rgba(15,23,42,0.18); display: grid; place-items: center;
163
+ cursor: pointer; z-index: var(--mihe-z);
164
+ }
165
+ .stop-square { width: 12px; height: 12px; border-radius: 2px; background: #0f172a; }
166
+ .popover {
167
+ position: fixed; max-width: min(340px, calc(100vw - 40px)); z-index: calc(var(--mihe-z) + 1);
168
+ display: flex; flex-direction: column; gap: 8px; font: 14px/1.45 var(--mihe-font);
169
+ }
170
+ .popover.cards { width: 320px; }
171
+ .menu-item {
172
+ display: inline-flex; align-items: center; gap: 10px; min-height: 44px; padding: 0 16px 0 6px;
173
+ border-radius: 999px; border: 1px solid rgba(15,23,42,0.1); background: #fff; color: #0f172a;
174
+ box-shadow: 0 6px 18px rgba(15,23,42,0.16); cursor: pointer; font: 500 14px var(--mihe-font);
175
+ }
176
+ .menu-icon {
177
+ display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%;
178
+ background: ${LAUNCHER_BG}; color: ${LAUNCHER_VOICE};
179
+ }
180
+ .orb-bubble {
181
+ padding: 8px 12px; border-radius: 12px; background: #fff; color: #0f172a;
182
+ border: 1px solid rgba(15,23,42,0.1); box-shadow: 0 6px 18px rgba(15,23,42,0.16);
183
+ }
184
+ .orb-bubble.error { background: #fef2f2; color: #991b1b; border-color: #fecaca; }
185
+
186
+ @media (prefers-reduced-motion: reduce) {
187
+ .pulse, .ring { animation: none !important; }
188
+ .ring { transform: none !important; }
189
+ .orb { transition: none; }
190
+ }
191
+ `;
192
+ //# sourceMappingURL=styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../../js/src/widget/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AACrC,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC;AACtC,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;AAExC,MAAM,CAAC,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAgHN,WAAW,YAAY,YAAY;;;;;;;gBAOnC,WAAW,YAAY,YAAY;;;;;;;;;2EASwB,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA6BzE,WAAW,YAAY,cAAc;;;;;;;;;;;;;CAapD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,45 @@
1
1
  {
2
2
  "name": "@mihe-dev/js",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.0",
4
+ "description": "Embed an app-aware AI assistant in any web app, with or without a framework.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./mihe.min.js": "./dist/mihe.min.js",
17
+ "./mihe.iife.min.js": "./dist/mihe.iife.min.js",
18
+ "./package.json": "./package.json"
19
+ },
20
+ "jsdelivr": "./dist/mihe.iife.min.js",
21
+ "unpkg": "./dist/mihe.iife.min.js",
22
+ "files": [
23
+ "dist",
24
+ "README.md",
25
+ "LICENSE"
26
+ ],
27
+ "sideEffects": false,
28
+ "homepage": "https://mihe.dev/docs",
29
+ "keywords": [
30
+ "ai",
31
+ "assistant",
32
+ "copilot",
33
+ "agent",
34
+ "vanilla",
35
+ "javascript",
36
+ "voice",
37
+ "mihe"
38
+ ],
39
+ "dependencies": {
40
+ "@mihe-dev/protocol": "0.1.0"
41
+ },
42
+ "publishConfig": {
43
+ "access": "public"
44
+ }
45
+ }