@burdenoff/fe-libs 2026.904.12 → 2026.904.14

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.
@@ -0,0 +1,8 @@
1
+ import { Conversation } from './conversation';
2
+ export declare function exportConversation(conversation: Conversation, format: "json" | "markdown"): {
3
+ content: string;
4
+ filename: string;
5
+ mimeType: string;
6
+ };
7
+ export declare function downloadFile(content: string, filename: string, mimeType: string): void;
8
+ //# sourceMappingURL=exportConversation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exportConversation.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/exportConversation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,MAAM,GAAG,UAAU,GAC1B;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAuEzD;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,IAAI,CAUN"}
@@ -0,0 +1,47 @@
1
+ import { isVoiceTurn as e } from "./voice/turnVisibility.js";
2
+ //#region src/shared/assistant/exportConversation.ts
3
+ function t(t, n) {
4
+ let r = t.title.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-|-$/g, "").toLowerCase(), i = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
5
+ if (n === "json") {
6
+ let n = {
7
+ id: t.id,
8
+ title: t.title,
9
+ mode: t.mode,
10
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
11
+ backendSessionId: t.backendSessionId ?? null,
12
+ messages: t.messages.map((t) => ({
13
+ role: t.role,
14
+ channel: e(t) ? "voice" : "chat",
15
+ content: t.content,
16
+ timestamp: t.timestamp,
17
+ tokens: t.tokens
18
+ }))
19
+ };
20
+ return {
21
+ content: JSON.stringify(n, null, 2),
22
+ filename: `${r}-${i}.json`,
23
+ mimeType: "application/json"
24
+ };
25
+ }
26
+ let a = [
27
+ `# ${t.title}`,
28
+ "",
29
+ `> Mode: ${t.mode} | Exported: ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
30
+ ""
31
+ ];
32
+ for (let n of t.messages) {
33
+ let t = n.role === "system" ? "Note" : n.role === "user" ? "You" : "Assistant";
34
+ a.push(`## ${t}${e(n) ? " (spoken)" : ""}`), a.push(""), a.push(n.content), a.push("");
35
+ }
36
+ return {
37
+ content: a.join("\n"),
38
+ filename: `${r}-${i}.md`,
39
+ mimeType: "text/markdown"
40
+ };
41
+ }
42
+ function n(e, t, n) {
43
+ let r = new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
44
+ a.href = i, a.download = t, document.body.appendChild(a), a.click(), document.body.removeChild(a), URL.revokeObjectURL(i);
45
+ }
46
+ //#endregion
47
+ export { n as downloadFile, t as exportConversation };
@@ -25,10 +25,6 @@ import { ReactNode } from 'react';
25
25
  * without rendering anything.
26
26
  */
27
27
  export declare function assistantTranslationKey(namespace: string, key: string): string;
28
- export interface AssistantI18nValue {
29
- /** Product id, e.g. `healthybowl`. Matches the id in shared/config/products. */
30
- namespace: string;
31
- }
32
28
  export interface AssistantI18nProviderProps {
33
29
  namespace: string;
34
30
  children: ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/i18n.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,MAAM,CAER;AAED,MAAM,WAAW,kBAAkB;IACjC,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,QAAQ,GACT,EAAE,0BAA0B,2CAO5B;AAED,mEAAmE;AACnE,wBAAgB,yBAAyB,IAAI,MAAM,GAAG,IAAI,CAEzD;AAED,MAAM,MAAM,WAAW,GAAG,CACxB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KACrC,MAAM,CAAC;AAIZ;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,IAAI,WAAW,CA4B5C"}
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/i18n.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAKpD;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,MAAM,CAER;AAED,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,QAAQ,GACT,EAAE,0BAA0B,2CAa5B;AAED,mEAAmE;AACnE,wBAAgB,yBAAyB,IAAI,MAAM,GAAG,IAAI,CAEzD;AAED,MAAM,MAAM,WAAW,GAAG,CACxB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KACrC,MAAM,CAAC;AAIZ;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,IAAI,WAAW,CA4B5C"}
@@ -1,32 +1,32 @@
1
1
  import { useI18n as e } from "../providers/shell/I18nProvider.js";
2
- import { createContext as t, useCallback as n, useContext as r, useMemo as i } from "react";
3
- import { jsx as a } from "react/jsx-runtime";
2
+ import { AssistantProductProvider as t, useAssistantProductOrNull as n } from "./product.js";
3
+ import { useCallback as r } from "react";
4
+ import { jsx as i } from "react/jsx-runtime";
4
5
  //#region src/shared/assistant/i18n.tsx
5
- function o(e, t) {
6
+ function a(e, t) {
6
7
  return `${e}.assistant.${t}`;
7
8
  }
8
- var s = t(null);
9
- function c({ namespace: e, children: t }) {
10
- let n = i(() => ({ namespace: e }), [e]);
11
- return /* @__PURE__ */ a(s.Provider, {
12
- value: n,
13
- children: t
9
+ function o({ namespace: e, children: n }) {
10
+ return /* @__PURE__ */ i(t, {
11
+ product: e,
12
+ modes: [],
13
+ children: n
14
14
  });
15
15
  }
16
- function l() {
17
- return r(s)?.namespace ?? null;
16
+ function s() {
17
+ return n()?.product ?? null;
18
18
  }
19
- var u = !1;
20
- function d() {
21
- let { t } = e(), r = l();
22
- return r === null && !u && (u = !0, console.error("[assistant] No AssistantI18nProvider mounted — assistant copy will render in English for every locale. Wrap the assistant in <AssistantI18nProvider namespace=\"<product>\">.")), n((e, n, i) => {
23
- if (r === null) return f(n, i);
24
- let a = o(r, e), s = t(a);
25
- return f(s === a ? n : s, i);
26
- }, [t, r]);
19
+ var c = !1;
20
+ function l() {
21
+ let { t } = e(), n = s();
22
+ return n === null && !c && (c = !0, console.error("[assistant] No AssistantI18nProvider mounted — assistant copy will render in English for every locale. Wrap the assistant in <AssistantI18nProvider namespace=\"<product>\">.")), r((e, r, i) => {
23
+ if (n === null) return u(r, i);
24
+ let o = a(n, e), s = t(o);
25
+ return u(s === o ? r : s, i);
26
+ }, [t, n]);
27
27
  }
28
- function f(e, t) {
28
+ function u(e, t) {
29
29
  return t ? Object.entries(t).reduce((e, [t, n]) => e.replace(RegExp(`\\{\\{${t}\\}\\}`, "g"), String(n)), e) : e;
30
30
  }
31
31
  //#endregion
32
- export { c as AssistantI18nProvider, o as assistantTranslationKey, l as useAssistantI18nNamespace, d as useAssistantTr };
32
+ export { o as AssistantI18nProvider, a as assistantTranslationKey, s as useAssistantI18nNamespace, l as useAssistantTr };
@@ -98,4 +98,10 @@ export * from './ui/voice/VoiceMiniController';
98
98
  export * from './ui/voice/VoiceStage';
99
99
  export * from './ui/voice/VoiceTranscriptDrawer';
100
100
  export * from './ui/voice/VoiceWaveform';
101
+ export * from './product';
102
+ export * from './ui/AssistantMoreMenu';
103
+ export * from './ui/AssistantHeader';
104
+ export * from './ui/AssistantConversationList';
105
+ export * from './ui/AssistantEmptyState';
106
+ export * from './exportConversation';
101
107
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mCAAmC,CAAC;AAClD,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AAGxB,cAAc,wBAAwB,CAAC;AAKvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAG9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,gBAAgB,CAAC;AAK/B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,4BAA4B,CAAC;AAG3C,cAAc,QAAQ,CAAC;AAEvB,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AAGrC,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qCAAqC,CAAC;AACpD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,yCAAyC,CAAC;AACxD,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,oCAAoC,CAAC;AACnD,cAAc,sCAAsC,CAAC;AACrD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wCAAwC,CAAC;AACvD,cAAc,yBAAyB,CAAC;AACxC,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,kCAAkC,CAAC;AACjD,cAAc,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mCAAmC,CAAC;AAClD,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AAGxB,cAAc,wBAAwB,CAAC;AAKvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAG9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,gBAAgB,CAAC;AAK/B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,4BAA4B,CAAC;AAG3C,cAAc,QAAQ,CAAC;AAEvB,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AAGrC,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qCAAqC,CAAC;AACpD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,yCAAyC,CAAC;AACxD,cAAc,wCAAwC,CAAC;AACvD,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,oCAAoC,CAAC;AACnD,cAAc,sCAAsC,CAAC;AACrD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wCAAwC,CAAC;AACvD,cAAc,yBAAyB,CAAC;AACxC,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,kCAAkC,CAAC;AACjD,cAAc,0BAA0B,CAAC;AAGzC,cAAc,WAAW,CAAC;AAE1B,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,81 @@
1
+ import { ReactNode } from 'react';
2
+ import { AssistantModeConfig } from './conversation';
3
+ /**
4
+ * What a product tells the shared assistant about ITSELF.
5
+ *
6
+ * ★★ Deliberately tiny, and it should stay that way. The obvious design here is
7
+ * a broad capabilities object — transport, RBAC, export, artifact download,
8
+ * quota, branding — and it would have been wrong. Every one of those turned out
9
+ * to be either already shared or shareable once looked at:
10
+ *
11
+ * - `downloadAssistantArtifact` already exists in `./api`; the product's copy
12
+ * was a five-line adapter dropping a vestigial argument.
13
+ * - the conversation export service had ZERO product references.
14
+ * - modes, RBAC and quota are consumed by the product's own orchestrator,
15
+ * which composes this library rather than living inside it.
16
+ *
17
+ * What genuinely varies by product, and cannot be derived, is two things: WHICH
18
+ * MODES it offers, and WHAT IT CALLS THE PAGE the user is on. A field is only
19
+ * added here when a shared component cannot work without it and no product can
20
+ * supply it by any other means. An interface that grows to fit one product is
21
+ * how HealthyBowl's shape ends up baked into every other product's library.
22
+ */
23
+ export interface AssistantProductCapabilities {
24
+ /**
25
+ * The modes this product offers, in display order.
26
+ *
27
+ * fe-libs owns the SHAPE (`AssistantModeConfig`); the product owns the LIST.
28
+ * FluidGrids offers "Build a node", HealthyBowl offers "Take action", and
29
+ * neither should be able to render the other's.
30
+ */
31
+ modes: readonly AssistantModeConfig[];
32
+ /**
33
+ * A human label for where the user is right now — "Crop planning", "Workflow
34
+ * editor" — or null when there is nothing useful to say.
35
+ *
36
+ * Optional because it is genuinely optional: a product with no route model
37
+ * simply has no answer, and the empty state drops the sentence rather than
38
+ * inventing one. Resolving a route to an entity is deep product knowledge and
39
+ * a wrong answer is worse than none.
40
+ */
41
+ describeCurrentPage?: () => string | null;
42
+ }
43
+ export interface AssistantProductValue extends AssistantProductCapabilities {
44
+ /**
45
+ * Product id, e.g. `healthybowl`. The SAME value the transport sends as
46
+ * `AI_ASSISTANT_PRODUCT` and the prefix for `<product>.assistant.*` keys, so
47
+ * "which product is this?" has exactly one answer rather than two that drift.
48
+ */
49
+ product: string;
50
+ }
51
+ export interface AssistantProductProviderProps extends AssistantProductCapabilities {
52
+ product: string;
53
+ children: ReactNode;
54
+ }
55
+ /**
56
+ * Mount once, above the assistant. Everything below can ask what product it is
57
+ * running inside and what that product offers.
58
+ */
59
+ export declare function AssistantProductProvider({ product, modes, describeCurrentPage, children, }: AssistantProductProviderProps): import("react/jsx-runtime").JSX.Element;
60
+ /** The product in force, or null when no provider is mounted. */
61
+ export declare function useAssistantProductOrNull(): AssistantProductValue | null;
62
+ /**
63
+ * The product in force.
64
+ *
65
+ * ★ Returns an empty descriptor rather than throwing when no provider is
66
+ * mounted. A missing provider is a configuration mistake, but a throw inside
67
+ * render is a white screen, and a mode selector with nothing in it is a visible,
68
+ * survivable failure that says exactly what is wrong. `useAssistantTr` complains
69
+ * to the console on the same condition, so it is still findable.
70
+ */
71
+ export declare function useAssistantProduct(): AssistantProductValue;
72
+ /**
73
+ * The mode a product would show for an id, falling back to its first.
74
+ *
75
+ * Shared because two components need exactly this and got it slightly
76
+ * differently: a persisted mode can name something the product no longer offers
77
+ * — a flag turned off, or a conversation restored from another build — and
78
+ * `undefined` there renders an empty panel rather than a usable one.
79
+ */
80
+ export declare function resolveModeConfig(modes: readonly AssistantModeConfig[], mode: string | undefined): AssistantModeConfig | undefined;
81
+ //# sourceMappingURL=product.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/product.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;;;;;OAMG;IACH,KAAK,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACtC;;;;;;;;OAQG;IACH,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,qBAAsB,SAAQ,4BAA4B;IACzE;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,MAAM,WAAW,6BAA8B,SAAQ,4BAA4B;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,OAAO,EACP,KAAK,EACL,mBAAmB,EACnB,QAAQ,GACT,EAAE,6BAA6B,2CAU/B;AAED,iEAAiE;AACjE,wBAAgB,yBAAyB,IAAI,qBAAqB,GAAG,IAAI,CAExE;AAID;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,IAAI,qBAAqB,CAE3D;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,mBAAmB,EAAE,EACrC,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB,mBAAmB,GAAG,SAAS,CAEjC"}
@@ -0,0 +1,34 @@
1
+ import { createContext as e, useContext as t, useMemo as n } from "react";
2
+ import { jsx as r } from "react/jsx-runtime";
3
+ //#region src/shared/assistant/product.tsx
4
+ var i = e(null);
5
+ function a({ product: e, modes: t, describeCurrentPage: a, children: o }) {
6
+ let s = n(() => ({
7
+ product: e,
8
+ modes: t,
9
+ describeCurrentPage: a
10
+ }), [
11
+ e,
12
+ t,
13
+ a
14
+ ]);
15
+ return /* @__PURE__ */ r(i.Provider, {
16
+ value: s,
17
+ children: o
18
+ });
19
+ }
20
+ function o() {
21
+ return t(i);
22
+ }
23
+ var s = {
24
+ product: "",
25
+ modes: []
26
+ };
27
+ function c() {
28
+ return t(i) ?? s;
29
+ }
30
+ function l(e, t) {
31
+ return e.find((e) => e.id === t) ?? e[0];
32
+ }
33
+ //#endregion
34
+ export { a as AssistantProductProvider, l as resolveModeConfig, c as useAssistantProduct, o as useAssistantProductOrNull };
@@ -0,0 +1,3 @@
1
+ import { FC } from 'react';
2
+ export declare const AssistantConversationList: FC;
3
+ //# sourceMappingURL=AssistantConversationList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssistantConversationList.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantConversationList.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAc1C,eAAO,MAAM,yBAAyB,EAAE,EAgPvC,CAAC"}
@@ -0,0 +1,159 @@
1
+ import { chatTurns as e } from "../voice/turnVisibility.js";
2
+ import { useAssistantProduct as t } from "../product.js";
3
+ import { useAssistantTr as n } from "../i18n.js";
4
+ import { useAssistantStore as r } from "../store.js";
5
+ import { useState as i } from "react";
6
+ import { Check as a, MessageSquare as o, PanelLeftClose as s, Pencil as c, Plus as l, Trash2 as u } from "lucide-react";
7
+ import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
8
+ //#region src/shared/assistant/ui/AssistantConversationList.tsx
9
+ var m = () => {
10
+ let m = n(), { modes: h } = t(), { conversations: g, activeConversationId: _, processingByConversationId: v, setActiveConversation: y, setMode: b, createConversation: x, deleteConversation: S, renameConversation: C, setConversationListOpen: w } = r(), [T, E] = i(null), [D, O] = i(""), k = () => {
11
+ x(), w(!1);
12
+ }, A = (e) => {
13
+ let t = g.find((t) => t.id === e);
14
+ y(e), t && b(t.mode), w(!1);
15
+ }, j = (e, t) => {
16
+ E(e), O(t);
17
+ }, M = () => {
18
+ T && D.trim() && C(T, D.trim()), E(null);
19
+ }, N = (e, t) => {
20
+ e.stopPropagation(), S(t);
21
+ };
22
+ return /* @__PURE__ */ p("div", {
23
+ className: "absolute inset-0 z-10 flex flex-col bg-bg-surface animate-in slide-in-from-left-2 fade-in duration-200",
24
+ "data-testid": "conversation-list",
25
+ children: [/* @__PURE__ */ p("div", {
26
+ className: "flex items-center justify-between px-4 py-3 border-b border-border-default bg-bg-elevated",
27
+ children: [/* @__PURE__ */ f("span", {
28
+ className: "text-[13px] font-semibold text-text-primary",
29
+ children: m("conversations.title", "History")
30
+ }), /* @__PURE__ */ p("div", {
31
+ className: "flex items-center gap-0.5",
32
+ children: [/* @__PURE__ */ f("button", {
33
+ type: "button",
34
+ onClick: k,
35
+ className: "p-1.5 rounded-lg text-text-secondary hover:bg-bg-sunken transition-colors",
36
+ "aria-label": m("conversations.new", "New conversation"),
37
+ "data-testid": "new-conversation",
38
+ children: /* @__PURE__ */ f(l, { className: "size-4" })
39
+ }), /* @__PURE__ */ p("button", {
40
+ type: "button",
41
+ onClick: () => w(!1),
42
+ className: "flex items-center gap-1 px-2 py-1.5 rounded-lg text-text-secondary hover:bg-bg-sunken transition-colors",
43
+ "aria-label": m("conversations.collapse", "Collapse history"),
44
+ "data-testid": "collapse-conversation-list",
45
+ children: [/* @__PURE__ */ f(s, { className: "size-4" }), /* @__PURE__ */ f("span", {
46
+ className: "text-[11px] font-medium",
47
+ children: m("conversations.collapseLabel", "Collapse")
48
+ })]
49
+ })]
50
+ })]
51
+ }), /* @__PURE__ */ f("div", {
52
+ className: "flex-1 overflow-y-auto",
53
+ children: g.length === 0 ? /* @__PURE__ */ p("div", {
54
+ className: "flex flex-col items-center justify-center h-full text-center px-4",
55
+ children: [
56
+ /* @__PURE__ */ f(o, { className: "size-6 text-text-muted mb-2" }),
57
+ /* @__PURE__ */ f("p", {
58
+ className: "text-xs text-text-muted",
59
+ children: m("conversations.empty", "No conversations yet")
60
+ }),
61
+ /* @__PURE__ */ f("button", {
62
+ type: "button",
63
+ onClick: k,
64
+ className: "mt-2 text-xs text-action-primary-bg hover:underline",
65
+ children: m("conversations.startNew", "Start a new conversation")
66
+ })
67
+ ]
68
+ }) : /* @__PURE__ */ f("div", {
69
+ className: "py-1",
70
+ children: g.map((t) => {
71
+ let n = t.id === _, r = t.id === T, i = h.find((e) => e.id === t.mode), o = e(t.messages), s = o[o.length - 1], l = o.length === 0 && t.messages.length > 0, g = v[t.id];
72
+ return /* @__PURE__ */ f("div", {
73
+ role: "button",
74
+ tabIndex: 0,
75
+ onKeyDown: (e) => {
76
+ (e.key === "Enter" || e.key === " ") && (e.preventDefault(), !r && A(t.id));
77
+ },
78
+ onClick: () => !r && A(t.id),
79
+ className: `group px-3 py-2 cursor-pointer hover:bg-bg-elevated transition-colors ${n ? "bg-bg-elevated border-l-2 border-action-primary-bg" : ""}`,
80
+ children: r ? /* @__PURE__ */ p("div", {
81
+ className: "flex items-center gap-1",
82
+ children: [/* @__PURE__ */ f("input", {
83
+ "aria-label": m("conversations.renameLabel", "Conversation title"),
84
+ value: D,
85
+ onChange: (e) => O(e.target.value),
86
+ onKeyDown: (e) => {
87
+ e.key === "Enter" && M(), e.key === "Escape" && E(null);
88
+ },
89
+ className: "flex-1 text-xs bg-bg-sunken border border-border-default rounded px-2 py-1 text-text-primary focus:outline-none focus:border-action-primary-bg",
90
+ onClick: (e) => e.stopPropagation()
91
+ }), /* @__PURE__ */ f("button", {
92
+ type: "button",
93
+ onClick: (e) => {
94
+ e.stopPropagation(), M();
95
+ },
96
+ className: "p-1 hover:bg-bg-sunken rounded",
97
+ "aria-label": m("conversations.saveTitle", "Save title"),
98
+ children: /* @__PURE__ */ f(a, { className: "size-3 text-status-success-text" })
99
+ })]
100
+ }) : /* @__PURE__ */ p(d, { children: [
101
+ /* @__PURE__ */ p("div", {
102
+ className: "flex items-center justify-between",
103
+ children: [/* @__PURE__ */ f("span", {
104
+ className: "text-xs font-medium text-text-primary truncate flex-1",
105
+ children: t.title
106
+ }), /* @__PURE__ */ p("div", {
107
+ className: "hidden group-hover:flex group-focus-within:flex items-center gap-0.5 ml-1",
108
+ children: [/* @__PURE__ */ f("button", {
109
+ type: "button",
110
+ onClick: (e) => {
111
+ e.stopPropagation(), j(t.id, t.title);
112
+ },
113
+ className: "p-0.5 hover:bg-bg-sunken rounded",
114
+ "aria-label": m("conversations.rename", "Rename conversation"),
115
+ children: /* @__PURE__ */ f(c, { className: "size-3 text-text-muted" })
116
+ }), /* @__PURE__ */ f("button", {
117
+ type: "button",
118
+ onClick: (e) => N(e, t.id),
119
+ className: "p-0.5 hover:bg-bg-sunken rounded",
120
+ "aria-label": m("conversations.delete", "Delete conversation"),
121
+ "data-testid": "delete-conversation",
122
+ children: /* @__PURE__ */ f(u, { className: "size-3 text-status-error-text" })
123
+ })]
124
+ })]
125
+ }),
126
+ /* @__PURE__ */ p("div", {
127
+ className: "flex items-center gap-1.5 mt-0.5",
128
+ children: [
129
+ /* @__PURE__ */ f("span", {
130
+ className: "text-[10px] text-text-muted px-1 py-0.5 bg-bg-sunken rounded",
131
+ children: i?.label ?? t.mode
132
+ }),
133
+ /* @__PURE__ */ p("span", {
134
+ className: "text-[10px] text-text-muted",
135
+ children: [o.length, " msgs"]
136
+ }),
137
+ g && g.status !== "idle" && /* @__PURE__ */ f("span", {
138
+ className: "text-[10px] text-action-primary-bg px-1 py-0.5 bg-bg-sunken rounded",
139
+ children: g.status
140
+ })
141
+ ]
142
+ }),
143
+ s && /* @__PURE__ */ f("p", {
144
+ className: "text-[10px] text-text-muted truncate mt-0.5",
145
+ children: s.content.slice(0, 60)
146
+ }),
147
+ l && /* @__PURE__ */ f("p", {
148
+ className: "text-[10px] text-text-muted truncate mt-0.5",
149
+ children: m("conversationList.voiceOnly", "Spoken conversation")
150
+ })
151
+ ] })
152
+ }, t.id);
153
+ })
154
+ })
155
+ })]
156
+ });
157
+ };
158
+ //#endregion
159
+ export { m as AssistantConversationList };
@@ -0,0 +1,16 @@
1
+ import { FC } from 'react';
2
+ import { AssistantMode } from '../types';
3
+ interface Props {
4
+ mode: AssistantMode;
5
+ onSuggestionClick: (suggestion: string) => void;
6
+ }
7
+ /**
8
+ * AssistantEmptyState — the v2 zero-message surface (per the "panel-welcome"
9
+ * mockup): a centered gradient sparkle mark, one headline, one contextual
10
+ * sentence, and 3–4 rounded suggestion chips. Shown only while a conversation
11
+ * has no messages (AssistantChatArea swaps it for the transcript once messages
12
+ * exist). Derived from the former AssistantWelcome.
13
+ */
14
+ export declare const AssistantEmptyState: FC<Props>;
15
+ export {};
16
+ //# sourceMappingURL=AssistantEmptyState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssistantEmptyState.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantEmptyState.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAEzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAI9C,UAAU,KAAK;IACb,IAAI,EAAE,aAAa,CAAC;IACpB,iBAAiB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAAC,KAAK,CA2DzC,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { resolveModeConfig as e, useAssistantProduct as t } from "../product.js";
2
+ import { useAssistantTr as n } from "../i18n.js";
3
+ import { useMemo as r } from "react";
4
+ import { Sparkles as i } from "lucide-react";
5
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
6
+ //#region src/shared/assistant/ui/AssistantEmptyState.tsx
7
+ var s = ({ mode: s, onSuggestionClick: c }) => {
8
+ let l = n(), { modes: u, describeCurrentPage: d } = t(), f = e(u, s), p = r(() => d?.() ?? null, [d]), m = f?.suggestions.slice(0, 4) ?? [];
9
+ return /* @__PURE__ */ o("div", {
10
+ className: "flex flex-1 flex-col items-center justify-center overflow-y-auto px-6 py-8 text-center",
11
+ children: [
12
+ /* @__PURE__ */ a("div", {
13
+ className: "flex size-12 items-center justify-center rounded-2xl bg-gradient-to-br from-action-primary-bg/25 to-action-primary-bg/5 text-action-primary-bg shadow-sm",
14
+ children: /* @__PURE__ */ a(i, { className: "size-6" })
15
+ }),
16
+ /* @__PURE__ */ a("h2", {
17
+ className: "mt-5 text-2xl font-semibold leading-tight tracking-tight text-text-primary",
18
+ children: l("empty.title", "How can I help?")
19
+ }),
20
+ /* @__PURE__ */ a("p", {
21
+ className: "mt-2 max-w-[16rem] text-[13px] leading-relaxed text-text-muted",
22
+ children: p ? l("empty.subtitle", "You're viewing {{page}}. Ask about it, or pick a suggestion below.", { page: p }) : l("empty.subtitleNoPage", "Ask me anything, or pick a suggestion below.")
23
+ }),
24
+ /* @__PURE__ */ a("div", {
25
+ className: "mt-6 flex flex-wrap items-center justify-center gap-2",
26
+ children: m.map((e) => /* @__PURE__ */ a("button", {
27
+ type: "button",
28
+ onClick: () => c(e),
29
+ className: "rounded-full border border-border-subtle bg-bg-surface px-3.5 py-2 text-[13px] leading-tight text-text-primary shadow-sm transition-all hover:border-action-primary-bg/40 hover:bg-bg-elevated hover:shadow-md",
30
+ "data-testid": "assistant-suggestion",
31
+ children: e
32
+ }, e))
33
+ })
34
+ ]
35
+ });
36
+ };
37
+ //#endregion
38
+ export { s as AssistantEmptyState };
@@ -0,0 +1,25 @@
1
+ import { FC } from 'react';
2
+ interface Props {
3
+ /** Friendly label for the page the user is on (e.g. "Inventory"). */
4
+ contextLabel: string;
5
+ onNewConversation: () => void;
6
+ onOpenHistory: () => void;
7
+ /** True when the history drawer is currently open (drives the toggle state). */
8
+ historyOpen: boolean;
9
+ onClose: () => void;
10
+ docked?: boolean;
11
+ onToggleDock?: () => void;
12
+ }
13
+ /**
14
+ * AssistantHeader — the v2 identity bar (per the ai-assistant-v2 mockups):
15
+ * a ✦ brand mark + "HealthyBowl AI", a small availability/context subtitle
16
+ * ("Ready · Context: <page>"), and a row of icon actions: New conversation,
17
+ * History (opens the conversation list as an overlay drawer — NOT an accordion),
18
+ * Export, Dock toggle, Close.
19
+ *
20
+ * Replaces the old "Conversation History" accordion header. HB semantic tokens
21
+ * only; copy via useAssistantTr.
22
+ */
23
+ export declare const AssistantHeader: FC<Props>;
24
+ export {};
25
+ //# sourceMappingURL=AssistantHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssistantHeader.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAYhC,UAAU,KAAK;IACb,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,gFAAgF;IAChF,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,KAAK,CA8FrC,CAAC"}
@@ -0,0 +1,75 @@
1
+ import { useAssistantTr as e } from "../i18n.js";
2
+ import { AssistantMoreMenu as t } from "./AssistantMoreMenu.js";
3
+ import { History as n, PanelBottom as r, PanelRight as i, Plus as a, Sparkles as o, X as s } from "lucide-react";
4
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
5
+ //#region src/shared/assistant/ui/AssistantHeader.tsx
6
+ var u = ({ contextLabel: u, onNewConversation: d, onOpenHistory: f, historyOpen: p, onClose: m, docked: h, onToggleDock: g }) => {
7
+ let _ = e();
8
+ return /* @__PURE__ */ l("div", {
9
+ className: "flex items-center gap-2 border-b border-border-default bg-bg-elevated px-3 py-2.5",
10
+ children: [/* @__PURE__ */ l("div", {
11
+ className: "flex min-w-0 flex-1 items-center gap-2",
12
+ children: [/* @__PURE__ */ c("span", {
13
+ className: "flex size-7 flex-shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-action-primary-bg/25 to-action-primary-bg/5 text-action-primary-bg",
14
+ children: /* @__PURE__ */ c(o, { className: "size-4" })
15
+ }), /* @__PURE__ */ l("span", {
16
+ className: "min-w-0 flex-1",
17
+ children: [/* @__PURE__ */ c("span", {
18
+ className: "block truncate text-[14px] font-semibold leading-tight text-text-primary",
19
+ children: _("header.title", "HealthyBowl AI")
20
+ }), /* @__PURE__ */ l("span", {
21
+ className: "block truncate text-[11px] leading-tight text-text-muted",
22
+ children: [
23
+ _("header.ready", "Ready"),
24
+ /* @__PURE__ */ c("span", {
25
+ "aria-hidden": "true",
26
+ children: " · "
27
+ }),
28
+ _("header.context", "Context: {{page}}", { page: u })
29
+ ]
30
+ })]
31
+ })]
32
+ }), /* @__PURE__ */ l("div", {
33
+ className: "flex flex-shrink-0 items-center gap-0.5",
34
+ children: [
35
+ /* @__PURE__ */ c("button", {
36
+ type: "button",
37
+ onClick: d,
38
+ className: "rounded-lg p-1.5 text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary",
39
+ "aria-label": _("header.newConversation", "New conversation"),
40
+ "data-testid": "assistant-new-conversation",
41
+ children: /* @__PURE__ */ c(a, { className: "size-4" })
42
+ }),
43
+ /* @__PURE__ */ c("button", {
44
+ type: "button",
45
+ onClick: f,
46
+ className: `rounded-lg p-1.5 transition-colors ${p ? "bg-action-primary-bg/15 text-action-primary-bg" : "text-text-secondary hover:bg-bg-sunken hover:text-text-primary"}`,
47
+ "aria-label": _("header.history", "Conversation history"),
48
+ "aria-pressed": p,
49
+ "data-testid": "assistant-open-history",
50
+ children: /* @__PURE__ */ c(n, { className: "size-4" })
51
+ }),
52
+ /* @__PURE__ */ c(t, {}),
53
+ g && /* @__PURE__ */ c("button", {
54
+ type: "button",
55
+ onClick: g,
56
+ className: "hidden rounded-lg p-1.5 text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary sm:inline-flex",
57
+ "aria-label": h ? _("header.float", "Float chat window") : _("header.dock", "Dock to side panel"),
58
+ "aria-pressed": h,
59
+ "data-testid": "assistant-toggle-dock",
60
+ children: c(h ? r : i, { className: "size-4" })
61
+ }),
62
+ /* @__PURE__ */ c("button", {
63
+ type: "button",
64
+ onClick: m,
65
+ className: "rounded-lg p-1.5 text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary",
66
+ "aria-label": _("header.close", "Close assistant"),
67
+ "data-testid": "assistant-close",
68
+ children: /* @__PURE__ */ c(s, { className: "size-4" })
69
+ })
70
+ ]
71
+ })]
72
+ });
73
+ };
74
+ //#endregion
75
+ export { u as AssistantHeader };
@@ -0,0 +1,32 @@
1
+ import { FC } from 'react';
2
+ /**
3
+ * The header's secondary surface — everything that CONFIGURES the assistant.
4
+ *
5
+ * ★ `+` supplies content, `⋯` configures. Keeping those two meanings apart is
6
+ * the point: the header carried seven controls, and three of them
7
+ * (auto-read, the voice picker, export) render null under conditions the user
8
+ * cannot see — no speech support, fewer than two voices, an empty conversation —
9
+ * so the row silently changed width between devices and between the first and
10
+ * second message of the same session.
11
+ *
12
+ * Now four primary controls, always present, and one menu that absorbs the
13
+ * conditional ones. A menu ROW may still hide itself; a menu that keeps its
14
+ * position while its contents vary is a much smaller surprise than a toolbar
15
+ * that reflows.
16
+ *
17
+ * ★ Export is FLATTENED into this menu rather than nested inside it. It was
18
+ * itself a dropdown, and a dropdown inside a dropdown is two Escape presses and
19
+ * two outside-click regions for two menu items.
20
+ *
21
+ * ★ The voice picker keeps its native `<select>`. It is deliberate — see that
22
+ * component — and a custom listbox would look tidier in a screenshot while being
23
+ * worse on the phones this product is used on. Because the select lives inside
24
+ * the menu's own subtree, the outside-click handler ignores clicks on it.
25
+ *
26
+ * Not included, deliberately: Live captions and Assistant settings have nothing
27
+ * behind them yet, and a Transcript entry needs a product decision first (the
28
+ * voice transcript is session-scoped, while the chat thread is always visible —
29
+ * one menu label cannot honestly mean both).
30
+ */
31
+ export declare const AssistantMoreMenu: FC;
32
+ //# sourceMappingURL=AssistantMoreMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssistantMoreMenu.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantMoreMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAgB7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,iBAAiB,EAAE,EAgM/B,CAAC"}
@@ -0,0 +1,121 @@
1
+ import { useAssistantTr as e } from "../i18n.js";
2
+ import { useAssistantStore as t } from "../store.js";
3
+ import { useAssistantSpeech as n } from "./AssistantSpeechProvider.js";
4
+ import { AssistantReplyLanguageSelector as r } from "./AssistantReplyLanguageSelector.js";
5
+ import { AssistantVoiceSelector as i } from "./composer/AssistantVoiceSelector.js";
6
+ import { downloadFile as a, exportConversation as o } from "../exportConversation.js";
7
+ import { useEffect as s, useRef as c, useState as l } from "react";
8
+ import { Check as u, FileJson as d, FileText as f, MoreHorizontal as p, Play as m, Volume2 as h } from "lucide-react";
9
+ import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
10
+ //#region src/shared/assistant/ui/AssistantMoreMenu.tsx
11
+ var y = () => {
12
+ let y = e(), [b, x] = l(!1), S = c(null), C = c(null), { conversations: w, activeConversationId: T } = t(), E = w.find((e) => e.id === T), D = !!(E && E.messages.length > 0), { isSupported: O, isBlocked: k, disabledReason: A, autoSpeakEnabled: j, setAutoSpeak: M, stop: N, previewVoice: P, activeVoiceName: F } = n(), I = k && !j;
13
+ s(() => {
14
+ if (!b) return;
15
+ let e = (e) => {
16
+ e.key === "Escape" && (x(!1), C.current?.focus());
17
+ }, t = (e) => {
18
+ let t = e.target;
19
+ S.current?.contains(t) || C.current?.contains(t) || x(!1);
20
+ };
21
+ return window.addEventListener("keydown", e), document.addEventListener("mousedown", t), () => {
22
+ window.removeEventListener("keydown", e), document.removeEventListener("mousedown", t);
23
+ };
24
+ }, [b]);
25
+ let L = (e) => {
26
+ if (!E) return;
27
+ let { content: t, filename: n, mimeType: r } = o(E, e);
28
+ a(t, n, r), x(!1);
29
+ }, R = () => {
30
+ j && N(), M(!j);
31
+ }, z = y("header.more", "More options");
32
+ return /* @__PURE__ */ v("div", {
33
+ className: "relative",
34
+ children: [/* @__PURE__ */ _("button", {
35
+ ref: C,
36
+ type: "button",
37
+ onClick: () => x((e) => !e),
38
+ className: "rounded p-1 transition-colors hover:bg-bg-elevated",
39
+ "aria-label": z,
40
+ "aria-haspopup": "menu",
41
+ "aria-expanded": b,
42
+ "data-testid": "assistant-more",
43
+ children: /* @__PURE__ */ _(p, { className: "size-4 text-text-secondary" })
44
+ }), b ? /* @__PURE__ */ v("div", {
45
+ ref: S,
46
+ role: "menu",
47
+ "aria-label": z,
48
+ className: "absolute right-0 top-full z-50 mt-1 min-w-56 overflow-hidden rounded-xl border border-border-default bg-bg-surface py-1 shadow-lg",
49
+ "data-testid": "assistant-more-menu",
50
+ children: [
51
+ O ? /* @__PURE__ */ v("button", {
52
+ type: "button",
53
+ role: "menuitemcheckbox",
54
+ "aria-checked": j,
55
+ onClick: R,
56
+ disabled: I,
57
+ title: I ? A ?? void 0 : void 0,
58
+ className: "flex w-full items-center gap-2.5 px-3 py-2 text-left text-xs text-text-primary transition-colors hover:bg-bg-elevated disabled:cursor-not-allowed disabled:text-text-muted disabled:hover:bg-transparent",
59
+ "data-testid": "assistant-auto-speak",
60
+ children: [
61
+ /* @__PURE__ */ _(h, {
62
+ className: "size-3.5 flex-shrink-0 text-text-secondary",
63
+ "aria-hidden": "true"
64
+ }),
65
+ /* @__PURE__ */ _("span", {
66
+ className: "flex-1",
67
+ children: y("header.autoRead", "Auto-read replies")
68
+ }),
69
+ j ? /* @__PURE__ */ _(u, { className: "size-3.5 flex-shrink-0 text-action-primary-bg" }) : null
70
+ ]
71
+ }) : null,
72
+ /* @__PURE__ */ _(r, {}),
73
+ /* @__PURE__ */ v("div", {
74
+ className: "flex items-center gap-1 px-3 py-1.5",
75
+ "data-testid": "assistant-more-voice",
76
+ children: [/* @__PURE__ */ _(i, {}), F ? /* @__PURE__ */ v("button", {
77
+ type: "button",
78
+ onClick: () => P(F),
79
+ className: "flex items-center gap-1 rounded-md px-1.5 py-1 text-[11px] text-text-muted transition-colors hover:bg-bg-elevated hover:text-text-secondary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong",
80
+ "aria-label": y("voice.preview", "Hear this voice"),
81
+ "data-testid": "assistant-voice-preview",
82
+ children: [/* @__PURE__ */ _(m, {
83
+ className: "size-3",
84
+ "aria-hidden": "true"
85
+ }), y("voice.previewShort", "Preview")]
86
+ }) : null]
87
+ }),
88
+ D ? /* @__PURE__ */ v(g, { children: [
89
+ /* @__PURE__ */ _("div", {
90
+ className: "my-1 border-t border-border-subtle",
91
+ role: "separator"
92
+ }),
93
+ /* @__PURE__ */ v("button", {
94
+ type: "button",
95
+ role: "menuitem",
96
+ onClick: () => L("json"),
97
+ className: "flex w-full items-center gap-2.5 px-3 py-2 text-left text-xs text-text-primary transition-colors hover:bg-bg-elevated",
98
+ "data-testid": "export-json",
99
+ children: [/* @__PURE__ */ _(d, {
100
+ className: "size-3.5 flex-shrink-0 text-text-secondary",
101
+ "aria-hidden": "true"
102
+ }), y("export.json", "Export as JSON")]
103
+ }),
104
+ /* @__PURE__ */ v("button", {
105
+ type: "button",
106
+ role: "menuitem",
107
+ onClick: () => L("markdown"),
108
+ className: "flex w-full items-center gap-2.5 px-3 py-2 text-left text-xs text-text-primary transition-colors hover:bg-bg-elevated",
109
+ "data-testid": "export-markdown",
110
+ children: [/* @__PURE__ */ _(f, {
111
+ className: "size-3.5 flex-shrink-0 text-text-secondary",
112
+ "aria-hidden": "true"
113
+ }), y("export.markdown", "Export as Markdown")]
114
+ })
115
+ ] }) : null
116
+ ]
117
+ }) : null]
118
+ });
119
+ };
120
+ //#endregion
121
+ export { y as AssistantMoreMenu };
@@ -26,42 +26,48 @@ import { toCaptionText as kt } from "./shared/assistant/voice/captionText.js";
26
26
  import { ASSISTANT_LANGUAGES as At, DEFAULT_SPEECH_RATE as jt, findAssistantLanguage as Mt, resolveAssistantLanguage as Nt } from "./shared/assistant/voice/languages.js";
27
27
  import { replyFollowsInput as Pt, resolveLanguagePair as Ft } from "./shared/assistant/voice/languagePair.js";
28
28
  import { findPendingWrite as It, parseConfirmationRefusal as Lt } from "./shared/assistant/pendingWrite.js";
29
- import { AssistantI18nProvider as Rt, assistantTranslationKey as zt, useAssistantI18nNamespace as Bt, useAssistantTr as Vt } from "./shared/assistant/i18n.js";
30
- import { SPOKEN_LABEL_LANGUAGES as Ht, speechLabelsFor as Ut } from "./shared/assistant/voice/speechLabels.js";
31
- import { detectScriptLocale as Wt, resolveSpeechLocale as Gt } from "./shared/assistant/voice/replyLanguage.js";
32
- import { IDLE_PLAYBACK as Kt, isSpeakingMessage as qt, requiresCancel as Jt, speechPlaybackReducer as Yt } from "./shared/assistant/voice/speechPlayback.js";
33
- import { MAX_INLINE_IMAGE_BASE64_BYTES as Xt, MAX_REQUEST_BODY_BYTES as Zt } from "./shared/assistant/gatewayLimits.js";
34
- import { BOILERPLATE_PAGE_SHARE as Qt, MAX_BOILERPLATE_LINE_CHARS as $t, MAX_EXTRACTED_CHARS as en, MAX_PDF_PAGES_SCANNED as tn, MIN_PAGE_TEXT_CHARS as nn, MIN_TEXT_PAGE_SHARE as rn, columnLetterToIndex as an, decodeXmlEntities as on, docxXmlToText as sn, fitPdfPages as cn, formatPageRanges as ln, isMostlyImagePages as un, joinSheets as dn, pageMarker as fn, parseSharedStrings as pn, parseWorkbookSheets as mn, pdfTextItemsToPage as hn, sheetXmlToRows as gn, summarisePageText as _n, truncatePagesForInline as vn } from "./shared/assistant/documentText.js";
35
- import { ATTACHMENT_ACCEPT as yn, AttachmentRejectedError as bn, INLINE_IMAGE_MAX_DIM as xn, INLINE_IMAGE_QUALITY as Sn, MAX_ATTACHMENTS as Cn, MAX_FILE_BYTES as wn, MAX_INLINE_CHARS_PER_FILE as Tn, MAX_INLINE_CHARS_TOTAL as En, MAX_INLINE_IMAGE_BASE64_CHARS as Dn, MAX_INLINE_IMAGE_PARTS as On, MAX_INLINE_TURN_BODY_BYTES as kn, MAX_TURN_BODY_BYTES as An, PROMPT_ENVELOPE_RESERVE_BYTES as jn, TURN_BODY_HEADROOM_BYTES as Mn, buildAttachmentPromptBlock as Nn, buildPromptParts as Pn, buildPromptWithAttachments as Fn, classifyAttachment as In, countInlineImageCandidates as Ln, countInlinedImageParts as Rn, detectDocumentFormat as zn, estimateTurnBodyBytes as Bn, formatBytes as Vn, getAttachmentSendBlocker as Hn, getExtension as Un, getSendableAttachments as Wn, hasAttachmentWorkInFlight as Gn, parseDataUrl as Kn, toMessageAttachment as qn, truncateForInline as Jn, validateFile as Yn } from "./shared/assistant/attachments.js";
36
- import { useAssistantStore as Xn } from "./shared/assistant/store.js";
37
- import { isTurnInFlight as Zn } from "./shared/assistant/turnState.js";
38
- import { AssistantToolActivity as Qn, parseToolActivity as $n } from "./shared/assistant/ui/AssistantToolActivity.js";
39
- import { AssistantSpeechProvider as er, useAssistantSpeech as tr } from "./shared/assistant/ui/AssistantSpeechProvider.js";
40
- import { useVoiceSession as nr } from "./shared/assistant/ui/useVoiceSession.js";
41
- import { copyToClipboard as rr } from "./shared/assistant/clipboard.js";
42
- import { getActorId as ir, getOrganizationId as ar, getWorkspaceId as or } from "./shared/assistant/context.js";
43
- import { ATTACHMENT_SOURCES as sr, availableAttachmentSources as cr, deviceHasCamera as lr } from "./shared/assistant/attachmentSources.js";
44
- import { SANDBOX_READY_TTL_MS as ur, createReadinessTracker as dr, isRecentlyVerified as fr } from "./shared/assistant/sandboxReadiness.js";
45
- import { AssistantAutoSpeakToggle as pr } from "./shared/assistant/ui/AssistantAutoSpeakToggle.js";
46
- import { AssistantMarkdownImage as mr, imageHostLabel as hr, isRemoteImageSrc as gr } from "./shared/assistant/ui/AssistantMarkdownImage.js";
47
- import { AssistantMarkdownRenderer as _r, assistantUrlTransform as vr } from "./shared/assistant/ui/AssistantMarkdownRenderer.js";
48
- import { AssistantMessageAttachments as yr } from "./shared/assistant/ui/AssistantMessageAttachments.js";
49
- import { AssistantPendingWriteCard as br } from "./shared/assistant/ui/AssistantPendingWriteCard.js";
50
- import { AssistantReplyLanguageSelector as xr } from "./shared/assistant/ui/AssistantReplyLanguageSelector.js";
51
- import { AssistantSpeakButton as Sr } from "./shared/assistant/ui/AssistantSpeakButton.js";
52
- import { AssistantSpokenTurnsNotice as Cr } from "./shared/assistant/ui/AssistantSpokenTurnsNotice.js";
53
- import { AssistantAttachmentButton as wr } from "./shared/assistant/ui/composer/AssistantAttachmentButton.js";
54
- import { AssistantAttachmentChips as Tr } from "./shared/assistant/ui/composer/AssistantAttachmentChips.js";
55
- import { AssistantLanguageSelector as Er, FOLLOW_APP_LOCALE as Dr } from "./shared/assistant/ui/composer/AssistantLanguageSelector.js";
56
- import { ASSISTANT_MODE_META as Or, AssistantModeSelector as kr, nextModeIndex as Ar } from "./shared/assistant/ui/composer/AssistantModeSelector.js";
57
- import { AssistantVoiceButton as jr } from "./shared/assistant/ui/composer/AssistantVoiceButton.js";
58
- import { AUTO_VOICE as Mr, AssistantVoiceSelector as Nr } from "./shared/assistant/ui/composer/AssistantVoiceSelector.js";
59
- import { AssistantVoiceOrb as Pr } from "./shared/assistant/ui/voice/AssistantVoiceOrb.js";
60
- import { AssistantVoiceSessionButton as Fr } from "./shared/assistant/ui/voice/AssistantVoiceSessionButton.js";
61
- import { VoiceCaption as Ir } from "./shared/assistant/ui/voice/VoiceCaption.js";
62
- import { VoiceConversationView as Lr } from "./shared/assistant/ui/voice/VoiceConversationView.js";
63
- import { VoiceWaveform as Rr } from "./shared/assistant/ui/voice/VoiceWaveform.js";
64
- import { VoiceMiniController as zr } from "./shared/assistant/ui/voice/VoiceMiniController.js";
65
- import { VoiceStage as Br } from "./shared/assistant/ui/voice/VoiceStage.js";
66
- import { VoiceTranscriptDrawer as Vr } from "./shared/assistant/ui/voice/VoiceTranscriptDrawer.js";
67
- export { p as ASSISTANT_API_AUTH_STRATEGY, At as ASSISTANT_LANGUAGES, Or as ASSISTANT_MODE_META, yn as ATTACHMENT_ACCEPT, sr as ATTACHMENT_SOURCES, Mr as AUTO_VOICE, wr as AssistantAttachmentButton, Tr as AssistantAttachmentChips, pr as AssistantAutoSpeakToggle, Rt as AssistantI18nProvider, Er as AssistantLanguageSelector, mr as AssistantMarkdownImage, _r as AssistantMarkdownRenderer, yr as AssistantMessageAttachments, kr as AssistantModeSelector, br as AssistantPendingWriteCard, xr as AssistantReplyLanguageSelector, U as AssistantRuntimeManager, Sr as AssistantSpeakButton, er as AssistantSpeechProvider, Cr as AssistantSpokenTurnsNotice, Qn as AssistantToolActivity, jr as AssistantVoiceButton, Pr as AssistantVoiceOrb, Nr as AssistantVoiceSelector, Fr as AssistantVoiceSessionButton, bn as AttachmentRejectedError, Qt as BOILERPLATE_PAGE_SHARE, i as CHECK_AI_CREDITS, a as CREATE_SANDBOX, dt as DEFAULT_SPEAKABLE_LABELS, jt as DEFAULT_SPEECH_RATE, Re as ENDPOINT_GRACE_MS, o as EXTEND_SANDBOX_TTL, Dr as FOLLOW_APP_LOCALE, s as GET_ACTIVE_SANDBOXES, c as GET_SANDBOX, me as HOSTED_TTS_MAX_CHARS, ue as HOSTED_TTS_TIER, de as HOSTED_VOICES, Kt as IDLE_PLAYBACK, ze as INITIAL_SESSION, xn as INLINE_IMAGE_MAX_DIM, Sn as INLINE_IMAGE_QUALITY, Be as INTERRUPT_MAX_MS, Ve as INTERRUPT_MIN_MS, Cn as MAX_ATTACHMENTS, $t as MAX_BOILERPLATE_LINE_CHARS, en as MAX_EXTRACTED_CHARS, wn as MAX_FILE_BYTES, Tn as MAX_INLINE_CHARS_PER_FILE, En as MAX_INLINE_CHARS_TOTAL, Xt as MAX_INLINE_IMAGE_BASE64_BYTES, Dn as MAX_INLINE_IMAGE_BASE64_CHARS, On as MAX_INLINE_IMAGE_PARTS, kn as MAX_INLINE_TURN_BODY_BYTES, tn as MAX_PDF_PAGES_SCANNED, Zt as MAX_REQUEST_BODY_BYTES, ft as MAX_SPEAKABLE_CHARS, pt as MAX_SPOKEN_TABLE_ROWS, An as MAX_TURN_BODY_BYTES, nn as MIN_PAGE_TEXT_CHARS, rn as MIN_TEXT_PAGE_SHARE, Ct as POLL_FAST_MS, wt as POLL_FAST_UNTIL_MS, Tt as POLL_SLOW_MS, Et as POLL_STEADY_MS, Dt as POLL_STEADY_UNTIL_MS, xt as PREVIEW_LANGUAGES, jn as PROMPT_ENVELOPE_RESERVE_BYTES, l as PROXY_SANDBOX_REQUEST, u as REPORT_AI_TOKEN_USAGE, ur as SANDBOX_READY_TTL_MS, He as SILENCE_SUBMIT_MS, he as SPEAKING_RATE_MAX, ge as SPEAKING_RATE_MAX_STREAMING, _e as SPEAKING_RATE_MAX_SYNC, ve as SPEAKING_RATE_MIN, mt as SPEECH_CHUNK_CHARS, ht as SPEECH_CHUNK_CJK_CHARS, Xe as SPEECH_LANG, Ht as SPOKEN_LABEL_LANGUAGES, d as STOP_ASSISTANT_SANDBOX, Mn as TURN_BODY_HEADROOM_BYTES, Ze as VOICE_LIST_TIMEOUT_MS, Ir as VoiceCaption, Lr as VoiceConversationView, zr as VoiceMiniController, Br as VoiceStage, Vr as VoiceTranscriptDrawer, Rr as VoiceWaveform, f as WAIT_FOR_SANDBOX_RUNNING, zt as assistantTranslationKey, vr as assistantUrlTransform, cr as availableAttachmentSources, ye as base64ToBytes, le as browserSpeechEngine, C as buildAssistantSandboxEnv, Nn as buildAttachmentPromptBlock, ct as buildContinuedFromVoiceNote, W as buildProgress, Pn as buildPromptParts, w as buildPromptRequestBody, Fn as buildPromptWithAttachments, be as buildRequest, t as buildSandboxContextInput, lt as buildVoiceTranscriptMarkdown, ne as chatTurns, T as checkAssistantAiCredits, gt as chunkForSpeech, In as classifyAttachment, xe as classifyHttpFailure, an as columnLetterToIndex, De as configureSpeechEngine, _t as containsCjk, rr as copyToClipboard, Ln as countInlineImageCandidates, Rn as countInlinedImageParts, E as createAssistantSandbox, D as createAssistantSession, Te as createHostedTtsEngine, dr as createReadinessTracker, Ee as createRoutingSpeechEngine, ee as createSandboxAssistantTransport, Oe as createSpeechEngines, Se as decodeAudioResponse, on as decodeXmlEntities, zn as detectDocumentFormat, Wt as detectScriptLocale, lr as deviceHasCamera, sn as docxXmlToText, O as downloadAssistantArtifact, Bn as estimateTurnBodyBytes, n as executeSandboxGraphQL, k as extendAssistantSandboxTTL, Mt as findAssistantLanguage, A as findExistingSandbox, It as findPendingWrite, cn as fitPdfPages, Vn as formatBytes, ln as formatPageRanges, ir as getActorId, j as getAssistantArtifacts, G as getAssistantMedia, M as getAssistantMessages, N as getAssistantSession, P as getAssistantStreamAccess, K as getAssistantText, Hn as getAttachmentSendBlocker, y as getCapability, Un as getExtension, m as getImageForMode, h as getImageTagForMode, ar as getOrganizationId, q as getRawMessageCreatedAt, g as getResourcesForMode, _ as getSandboxImageRegistry, Wn as getSendableAttachments, ke as getSpeechEngine, J as getToolProgress, or as getWorkspaceId, re as groupBySession, ie as groupConsecutiveBySession, Gn as hasAttachmentWorkInFlight, fe as hostedLocaleFor, pe as hostedSupportsLanguage, hr as imageHostLabel, Ue as isCapturing, We as isEcho, un as isMostlyImagePages, r as isQuotaExhaustedError, Y as isReapedSandboxConnectionError, fr as isRecentlyVerified, X as isRecoverable, gr as isRemoteImageSrc, qt as isSpeakingMessage, Qe as isSpeechBlocked, Ge as isSubmittable, Zn as isTurnInFlight, b as isUnknownFieldError, ae as isVoiceTurn, dn as joinSheets, $e as languageDisplayName, Z as mapSessionToHistory, x as markSupported, S as markUnsupported, Q as mergeMessagesById, Me as micIsInterrupt, F as modeRequiresConfirmWrites, Ar as nextModeIndex, et as normalizeLangTag, Ke as orbMode, fn as pageMarker, Lt as parseConfirmationRefusal, Kn as parseDataUrl, pn as parseSharedStrings, $n as parseToolActivity, mn as parseWorkbookSheets, hn as pdfTextItemsToPage, qe as planReplyConsumption, Ot as pollDelayMs, tt as primaryLanguageSubtag, Ae as readSpeechEngineConfig, Pt as replyFollowsInput, I as reportAssistantAiTokenUsage, Jt as requiresCancel, je as resetSpeechEngine, Nt as resolveAssistantLanguage, Ft as resolveLanguagePair, v as resolveSandboxAssistantMode, Gt as resolveSpeechLocale, $ as sanitize, L as selectExistingAssistantSandbox, nt as selectVoiceForLocale, R as sendAssistantPromptAsync, z as sendHeartbeat, gn as sheetXmlToRows, Ce as shouldDisableEngine, Ne as showsAssistantCaption, Pe as showsUserCaption, vt as speakableEmail, rt as speechGate, Ut as speechLabelsFor, it as speechLangForLocale, Yt as speechPlaybackReducer, we as splitForVendor, yt as splitTableRow, Je as spokenSoFar, B as stopReapedAssistantSandbox, _n as summarisePageText, kt as toCaptionText, qn as toMessageAttachment, bt as toSpeakableText, Jn as truncateForInline, vn as truncatePagesForInline, Bt as useAssistantI18nNamespace, tr as useAssistantSpeech, Xn as useAssistantStore, Vt as useAssistantTr, te as useSandboxAssistantTransport, e as useVoiceInput, nr as useVoiceSession, Yn as validateFile, at as voiceAvailability, oe as voiceMarker, St as voicePreviewText, ot as voiceQualityRank, se as voiceSessionIdOf, Ye as voiceSessionReducer, Fe as voiceStageState, ut as voiceTranscriptFilename, ce as voiceTurnsOnly, st as voicesForLocale, V as waitForAssistantServiceReady, H as waitForSandboxRunning, Ie as waveformIsActive, Le as waveformIsSettled };
29
+ import { AssistantProductProvider as Rt, resolveModeConfig as zt, useAssistantProduct as Bt, useAssistantProductOrNull as Vt } from "./shared/assistant/product.js";
30
+ import { AssistantI18nProvider as Ht, assistantTranslationKey as Ut, useAssistantI18nNamespace as Wt, useAssistantTr as Gt } from "./shared/assistant/i18n.js";
31
+ import { SPOKEN_LABEL_LANGUAGES as Kt, speechLabelsFor as qt } from "./shared/assistant/voice/speechLabels.js";
32
+ import { detectScriptLocale as Jt, resolveSpeechLocale as Yt } from "./shared/assistant/voice/replyLanguage.js";
33
+ import { IDLE_PLAYBACK as Xt, isSpeakingMessage as Zt, requiresCancel as Qt, speechPlaybackReducer as $t } from "./shared/assistant/voice/speechPlayback.js";
34
+ import { MAX_INLINE_IMAGE_BASE64_BYTES as en, MAX_REQUEST_BODY_BYTES as tn } from "./shared/assistant/gatewayLimits.js";
35
+ import { BOILERPLATE_PAGE_SHARE as nn, MAX_BOILERPLATE_LINE_CHARS as rn, MAX_EXTRACTED_CHARS as an, MAX_PDF_PAGES_SCANNED as on, MIN_PAGE_TEXT_CHARS as sn, MIN_TEXT_PAGE_SHARE as cn, columnLetterToIndex as ln, decodeXmlEntities as un, docxXmlToText as dn, fitPdfPages as fn, formatPageRanges as pn, isMostlyImagePages as mn, joinSheets as hn, pageMarker as gn, parseSharedStrings as _n, parseWorkbookSheets as vn, pdfTextItemsToPage as yn, sheetXmlToRows as bn, summarisePageText as xn, truncatePagesForInline as Sn } from "./shared/assistant/documentText.js";
36
+ import { ATTACHMENT_ACCEPT as Cn, AttachmentRejectedError as wn, INLINE_IMAGE_MAX_DIM as Tn, INLINE_IMAGE_QUALITY as En, MAX_ATTACHMENTS as Dn, MAX_FILE_BYTES as On, MAX_INLINE_CHARS_PER_FILE as kn, MAX_INLINE_CHARS_TOTAL as An, MAX_INLINE_IMAGE_BASE64_CHARS as jn, MAX_INLINE_IMAGE_PARTS as Mn, MAX_INLINE_TURN_BODY_BYTES as Nn, MAX_TURN_BODY_BYTES as Pn, PROMPT_ENVELOPE_RESERVE_BYTES as Fn, TURN_BODY_HEADROOM_BYTES as In, buildAttachmentPromptBlock as Ln, buildPromptParts as Rn, buildPromptWithAttachments as zn, classifyAttachment as Bn, countInlineImageCandidates as Vn, countInlinedImageParts as Hn, detectDocumentFormat as Un, estimateTurnBodyBytes as Wn, formatBytes as Gn, getAttachmentSendBlocker as Kn, getExtension as qn, getSendableAttachments as Jn, hasAttachmentWorkInFlight as Yn, parseDataUrl as Xn, toMessageAttachment as Zn, truncateForInline as Qn, validateFile as $n } from "./shared/assistant/attachments.js";
37
+ import { useAssistantStore as er } from "./shared/assistant/store.js";
38
+ import { isTurnInFlight as tr } from "./shared/assistant/turnState.js";
39
+ import { AssistantToolActivity as nr, parseToolActivity as rr } from "./shared/assistant/ui/AssistantToolActivity.js";
40
+ import { AssistantSpeechProvider as ir, useAssistantSpeech as ar } from "./shared/assistant/ui/AssistantSpeechProvider.js";
41
+ import { useVoiceSession as or } from "./shared/assistant/ui/useVoiceSession.js";
42
+ import { copyToClipboard as sr } from "./shared/assistant/clipboard.js";
43
+ import { getActorId as cr, getOrganizationId as lr, getWorkspaceId as ur } from "./shared/assistant/context.js";
44
+ import { ATTACHMENT_SOURCES as dr, availableAttachmentSources as fr, deviceHasCamera as pr } from "./shared/assistant/attachmentSources.js";
45
+ import { SANDBOX_READY_TTL_MS as mr, createReadinessTracker as hr, isRecentlyVerified as gr } from "./shared/assistant/sandboxReadiness.js";
46
+ import { AssistantAutoSpeakToggle as _r } from "./shared/assistant/ui/AssistantAutoSpeakToggle.js";
47
+ import { AssistantMarkdownImage as vr, imageHostLabel as yr, isRemoteImageSrc as br } from "./shared/assistant/ui/AssistantMarkdownImage.js";
48
+ import { AssistantMarkdownRenderer as xr, assistantUrlTransform as Sr } from "./shared/assistant/ui/AssistantMarkdownRenderer.js";
49
+ import { AssistantMessageAttachments as Cr } from "./shared/assistant/ui/AssistantMessageAttachments.js";
50
+ import { AssistantPendingWriteCard as wr } from "./shared/assistant/ui/AssistantPendingWriteCard.js";
51
+ import { AssistantReplyLanguageSelector as Tr } from "./shared/assistant/ui/AssistantReplyLanguageSelector.js";
52
+ import { AssistantSpeakButton as Er } from "./shared/assistant/ui/AssistantSpeakButton.js";
53
+ import { AssistantSpokenTurnsNotice as Dr } from "./shared/assistant/ui/AssistantSpokenTurnsNotice.js";
54
+ import { AssistantAttachmentButton as Or } from "./shared/assistant/ui/composer/AssistantAttachmentButton.js";
55
+ import { AssistantAttachmentChips as kr } from "./shared/assistant/ui/composer/AssistantAttachmentChips.js";
56
+ import { AssistantLanguageSelector as Ar, FOLLOW_APP_LOCALE as jr } from "./shared/assistant/ui/composer/AssistantLanguageSelector.js";
57
+ import { ASSISTANT_MODE_META as Mr, AssistantModeSelector as Nr, nextModeIndex as Pr } from "./shared/assistant/ui/composer/AssistantModeSelector.js";
58
+ import { AssistantVoiceButton as Fr } from "./shared/assistant/ui/composer/AssistantVoiceButton.js";
59
+ import { AUTO_VOICE as Ir, AssistantVoiceSelector as Lr } from "./shared/assistant/ui/composer/AssistantVoiceSelector.js";
60
+ import { AssistantVoiceOrb as Rr } from "./shared/assistant/ui/voice/AssistantVoiceOrb.js";
61
+ import { AssistantVoiceSessionButton as zr } from "./shared/assistant/ui/voice/AssistantVoiceSessionButton.js";
62
+ import { VoiceCaption as Br } from "./shared/assistant/ui/voice/VoiceCaption.js";
63
+ import { VoiceConversationView as Vr } from "./shared/assistant/ui/voice/VoiceConversationView.js";
64
+ import { VoiceWaveform as Hr } from "./shared/assistant/ui/voice/VoiceWaveform.js";
65
+ import { VoiceMiniController as Ur } from "./shared/assistant/ui/voice/VoiceMiniController.js";
66
+ import { VoiceStage as Wr } from "./shared/assistant/ui/voice/VoiceStage.js";
67
+ import { VoiceTranscriptDrawer as Gr } from "./shared/assistant/ui/voice/VoiceTranscriptDrawer.js";
68
+ import { downloadFile as Kr, exportConversation as qr } from "./shared/assistant/exportConversation.js";
69
+ import { AssistantMoreMenu as Jr } from "./shared/assistant/ui/AssistantMoreMenu.js";
70
+ import { AssistantHeader as Yr } from "./shared/assistant/ui/AssistantHeader.js";
71
+ import { AssistantConversationList as Xr } from "./shared/assistant/ui/AssistantConversationList.js";
72
+ import { AssistantEmptyState as Zr } from "./shared/assistant/ui/AssistantEmptyState.js";
73
+ export { p as ASSISTANT_API_AUTH_STRATEGY, At as ASSISTANT_LANGUAGES, Mr as ASSISTANT_MODE_META, Cn as ATTACHMENT_ACCEPT, dr as ATTACHMENT_SOURCES, Ir as AUTO_VOICE, Or as AssistantAttachmentButton, kr as AssistantAttachmentChips, _r as AssistantAutoSpeakToggle, Xr as AssistantConversationList, Zr as AssistantEmptyState, Yr as AssistantHeader, Ht as AssistantI18nProvider, Ar as AssistantLanguageSelector, vr as AssistantMarkdownImage, xr as AssistantMarkdownRenderer, Cr as AssistantMessageAttachments, Nr as AssistantModeSelector, Jr as AssistantMoreMenu, wr as AssistantPendingWriteCard, Rt as AssistantProductProvider, Tr as AssistantReplyLanguageSelector, U as AssistantRuntimeManager, Er as AssistantSpeakButton, ir as AssistantSpeechProvider, Dr as AssistantSpokenTurnsNotice, nr as AssistantToolActivity, Fr as AssistantVoiceButton, Rr as AssistantVoiceOrb, Lr as AssistantVoiceSelector, zr as AssistantVoiceSessionButton, wn as AttachmentRejectedError, nn as BOILERPLATE_PAGE_SHARE, i as CHECK_AI_CREDITS, a as CREATE_SANDBOX, dt as DEFAULT_SPEAKABLE_LABELS, jt as DEFAULT_SPEECH_RATE, Re as ENDPOINT_GRACE_MS, o as EXTEND_SANDBOX_TTL, jr as FOLLOW_APP_LOCALE, s as GET_ACTIVE_SANDBOXES, c as GET_SANDBOX, me as HOSTED_TTS_MAX_CHARS, ue as HOSTED_TTS_TIER, de as HOSTED_VOICES, Xt as IDLE_PLAYBACK, ze as INITIAL_SESSION, Tn as INLINE_IMAGE_MAX_DIM, En as INLINE_IMAGE_QUALITY, Be as INTERRUPT_MAX_MS, Ve as INTERRUPT_MIN_MS, Dn as MAX_ATTACHMENTS, rn as MAX_BOILERPLATE_LINE_CHARS, an as MAX_EXTRACTED_CHARS, On as MAX_FILE_BYTES, kn as MAX_INLINE_CHARS_PER_FILE, An as MAX_INLINE_CHARS_TOTAL, en as MAX_INLINE_IMAGE_BASE64_BYTES, jn as MAX_INLINE_IMAGE_BASE64_CHARS, Mn as MAX_INLINE_IMAGE_PARTS, Nn as MAX_INLINE_TURN_BODY_BYTES, on as MAX_PDF_PAGES_SCANNED, tn as MAX_REQUEST_BODY_BYTES, ft as MAX_SPEAKABLE_CHARS, pt as MAX_SPOKEN_TABLE_ROWS, Pn as MAX_TURN_BODY_BYTES, sn as MIN_PAGE_TEXT_CHARS, cn as MIN_TEXT_PAGE_SHARE, Ct as POLL_FAST_MS, wt as POLL_FAST_UNTIL_MS, Tt as POLL_SLOW_MS, Et as POLL_STEADY_MS, Dt as POLL_STEADY_UNTIL_MS, xt as PREVIEW_LANGUAGES, Fn as PROMPT_ENVELOPE_RESERVE_BYTES, l as PROXY_SANDBOX_REQUEST, u as REPORT_AI_TOKEN_USAGE, mr as SANDBOX_READY_TTL_MS, He as SILENCE_SUBMIT_MS, he as SPEAKING_RATE_MAX, ge as SPEAKING_RATE_MAX_STREAMING, _e as SPEAKING_RATE_MAX_SYNC, ve as SPEAKING_RATE_MIN, mt as SPEECH_CHUNK_CHARS, ht as SPEECH_CHUNK_CJK_CHARS, Xe as SPEECH_LANG, Kt as SPOKEN_LABEL_LANGUAGES, d as STOP_ASSISTANT_SANDBOX, In as TURN_BODY_HEADROOM_BYTES, Ze as VOICE_LIST_TIMEOUT_MS, Br as VoiceCaption, Vr as VoiceConversationView, Ur as VoiceMiniController, Wr as VoiceStage, Gr as VoiceTranscriptDrawer, Hr as VoiceWaveform, f as WAIT_FOR_SANDBOX_RUNNING, Ut as assistantTranslationKey, Sr as assistantUrlTransform, fr as availableAttachmentSources, ye as base64ToBytes, le as browserSpeechEngine, C as buildAssistantSandboxEnv, Ln as buildAttachmentPromptBlock, ct as buildContinuedFromVoiceNote, W as buildProgress, Rn as buildPromptParts, w as buildPromptRequestBody, zn as buildPromptWithAttachments, be as buildRequest, t as buildSandboxContextInput, lt as buildVoiceTranscriptMarkdown, ne as chatTurns, T as checkAssistantAiCredits, gt as chunkForSpeech, Bn as classifyAttachment, xe as classifyHttpFailure, ln as columnLetterToIndex, De as configureSpeechEngine, _t as containsCjk, sr as copyToClipboard, Vn as countInlineImageCandidates, Hn as countInlinedImageParts, E as createAssistantSandbox, D as createAssistantSession, Te as createHostedTtsEngine, hr as createReadinessTracker, Ee as createRoutingSpeechEngine, ee as createSandboxAssistantTransport, Oe as createSpeechEngines, Se as decodeAudioResponse, un as decodeXmlEntities, Un as detectDocumentFormat, Jt as detectScriptLocale, pr as deviceHasCamera, dn as docxXmlToText, O as downloadAssistantArtifact, Kr as downloadFile, Wn as estimateTurnBodyBytes, n as executeSandboxGraphQL, qr as exportConversation, k as extendAssistantSandboxTTL, Mt as findAssistantLanguage, A as findExistingSandbox, It as findPendingWrite, fn as fitPdfPages, Gn as formatBytes, pn as formatPageRanges, cr as getActorId, j as getAssistantArtifacts, G as getAssistantMedia, M as getAssistantMessages, N as getAssistantSession, P as getAssistantStreamAccess, K as getAssistantText, Kn as getAttachmentSendBlocker, y as getCapability, qn as getExtension, m as getImageForMode, h as getImageTagForMode, lr as getOrganizationId, q as getRawMessageCreatedAt, g as getResourcesForMode, _ as getSandboxImageRegistry, Jn as getSendableAttachments, ke as getSpeechEngine, J as getToolProgress, ur as getWorkspaceId, re as groupBySession, ie as groupConsecutiveBySession, Yn as hasAttachmentWorkInFlight, fe as hostedLocaleFor, pe as hostedSupportsLanguage, yr as imageHostLabel, Ue as isCapturing, We as isEcho, mn as isMostlyImagePages, r as isQuotaExhaustedError, Y as isReapedSandboxConnectionError, gr as isRecentlyVerified, X as isRecoverable, br as isRemoteImageSrc, Zt as isSpeakingMessage, Qe as isSpeechBlocked, Ge as isSubmittable, tr as isTurnInFlight, b as isUnknownFieldError, ae as isVoiceTurn, hn as joinSheets, $e as languageDisplayName, Z as mapSessionToHistory, x as markSupported, S as markUnsupported, Q as mergeMessagesById, Me as micIsInterrupt, F as modeRequiresConfirmWrites, Pr as nextModeIndex, et as normalizeLangTag, Ke as orbMode, gn as pageMarker, Lt as parseConfirmationRefusal, Xn as parseDataUrl, _n as parseSharedStrings, rr as parseToolActivity, vn as parseWorkbookSheets, yn as pdfTextItemsToPage, qe as planReplyConsumption, Ot as pollDelayMs, tt as primaryLanguageSubtag, Ae as readSpeechEngineConfig, Pt as replyFollowsInput, I as reportAssistantAiTokenUsage, Qt as requiresCancel, je as resetSpeechEngine, Nt as resolveAssistantLanguage, Ft as resolveLanguagePair, zt as resolveModeConfig, v as resolveSandboxAssistantMode, Yt as resolveSpeechLocale, $ as sanitize, L as selectExistingAssistantSandbox, nt as selectVoiceForLocale, R as sendAssistantPromptAsync, z as sendHeartbeat, bn as sheetXmlToRows, Ce as shouldDisableEngine, Ne as showsAssistantCaption, Pe as showsUserCaption, vt as speakableEmail, rt as speechGate, qt as speechLabelsFor, it as speechLangForLocale, $t as speechPlaybackReducer, we as splitForVendor, yt as splitTableRow, Je as spokenSoFar, B as stopReapedAssistantSandbox, xn as summarisePageText, kt as toCaptionText, Zn as toMessageAttachment, bt as toSpeakableText, Qn as truncateForInline, Sn as truncatePagesForInline, Wt as useAssistantI18nNamespace, Bt as useAssistantProduct, Vt as useAssistantProductOrNull, ar as useAssistantSpeech, er as useAssistantStore, Gt as useAssistantTr, te as useSandboxAssistantTransport, e as useVoiceInput, or as useVoiceSession, $n as validateFile, at as voiceAvailability, oe as voiceMarker, St as voicePreviewText, ot as voiceQualityRank, se as voiceSessionIdOf, Ye as voiceSessionReducer, Fe as voiceStageState, ut as voiceTranscriptFilename, ce as voiceTurnsOnly, st as voicesForLocale, V as waitForAssistantServiceReady, H as waitForSandboxRunning, Ie as waveformIsActive, Le as waveformIsSettled };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/fe-libs",
3
- "version": "2026.904.12",
3
+ "version": "2026.904.14",
4
4
  "description": "Burdenoff frontend primitives and domain libraries",
5
5
  "type": "module",
6
6
  "bin": {