@burdenoff/fe-libs 2026.920.1 → 2026.920.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/shared/assistant/api.d.ts +17 -0
  2. package/dist/shared/assistant/api.d.ts.map +1 -1
  3. package/dist/shared/assistant/api.js +88 -66
  4. package/dist/shared/assistant/attachmentTurn.d.ts +21 -0
  5. package/dist/shared/assistant/attachmentTurn.d.ts.map +1 -0
  6. package/dist/shared/assistant/attachmentTurn.js +48 -0
  7. package/dist/shared/assistant/attachments.d.ts +85 -6
  8. package/dist/shared/assistant/attachments.d.ts.map +1 -1
  9. package/dist/shared/assistant/attachments.js +165 -112
  10. package/dist/shared/assistant/conversation.d.ts +21 -0
  11. package/dist/shared/assistant/conversation.d.ts.map +1 -1
  12. package/dist/shared/assistant/documentExtract.d.ts +11 -2
  13. package/dist/shared/assistant/documentExtract.d.ts.map +1 -1
  14. package/dist/shared/assistant/documentExtract.js +39 -37
  15. package/dist/shared/assistant/gatewayLimits.d.ts +10 -0
  16. package/dist/shared/assistant/gatewayLimits.d.ts.map +1 -1
  17. package/dist/shared/assistant/gatewayLimits.js +2 -2
  18. package/dist/shared/assistant/index.d.ts +1 -0
  19. package/dist/shared/assistant/index.d.ts.map +1 -1
  20. package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
  21. package/dist/shared/assistant/ui/AssistantChatArea.js +342 -325
  22. package/dist/shared/assistant/ui/composer/AssistantComposer.d.ts +12 -0
  23. package/dist/shared/assistant/ui/composer/AssistantComposer.d.ts.map +1 -1
  24. package/dist/shared/assistant/ui/composer/AssistantComposer.js +57 -57
  25. package/dist/shared/assistant/useAssistantAttachments.d.ts +12 -1
  26. package/dist/shared/assistant/useAssistantAttachments.d.ts.map +1 -1
  27. package/dist/shared/assistant/useAssistantAttachments.js +98 -98
  28. package/dist/shared-assistant.js +116 -115
  29. package/package.json +1 -1
@@ -20,6 +20,18 @@ interface Props {
20
20
  mode: AssistantMode;
21
21
  /** Role-filtered list of modes the user may pick. */
22
22
  availableModes: AssistantModeConfig[];
23
+ /**
24
+ * How many characters of an attached text or document file to KEEP — the
25
+ * largest per-file limit among ALL the product's modes (BOFF-7334). The send
26
+ * cuts each file to the sending mode's own limit.
27
+ *
28
+ * ★ All modes, not `availableModes`. That list is role-filtered, and while the
29
+ * role check loads it omits an admin-only mode — so a file attached in that
30
+ * window was cut to 8,000 characters for good, and the Build mode the admin
31
+ * switched to a moment later received 8,000 of the 100,000 it asks for.
32
+ * Absent: the shared default, `MAX_INLINE_CHARS_PER_FILE`.
33
+ */
34
+ attachmentCharsPerFile?: number;
23
35
  onModeChange: (mode: AssistantMode) => void;
24
36
  /**
25
37
  * Opens the hands-free voice conversation. Omitted where a voice session
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantComposer.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/composer/AssistantComposer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,EAAE,EAER,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAG9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAQjD,OAAO,EAGL,KAAK,mBAAmB,EAEzB,MAAM,mBAAmB,CAAC;AAO3B,UAAU,KAAK;IACb;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE,KAAK,IAAI,CAAC;IACtE,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,aAAa,CAAC;IACpB,qDAAqD;IACrD,cAAc,EAAE,mBAAmB,EAAE,CAAC;IACtC,YAAY,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC5C;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAID;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,KAAK,CAuZvC,CAAC"}
1
+ {"version":3,"file":"AssistantComposer.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/composer/AssistantComposer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,EAAE,EAER,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAG9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAQjD,OAAO,EAGL,KAAK,mBAAmB,EAEzB,MAAM,mBAAmB,CAAC;AAO3B,UAAU,KAAK;IACb;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE,KAAK,IAAI,CAAC;IACtE,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,aAAa,CAAC;IACpB,qDAAqD;IACrD,cAAc,EAAE,mBAAmB,EAAE,CAAC;IACtC;;;;;;;;;;OAUG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,YAAY,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC5C;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAID;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,KAAK,CA6ZvC,CAAC"}
@@ -11,44 +11,44 @@ import { AssistantModeSelector as c } from "./AssistantModeSelector.js";
11
11
  import { AssistantVoiceButton as te } from "./AssistantVoiceButton.js";
12
12
  import { AssistantVoiceSessionButton as ne } from "../voice/AssistantVoiceSessionButton.js";
13
13
  import { useAssistantAttachments as re } from "../../useAssistantAttachments.js";
14
- import { useCallback as l, useLayoutEffect as ie, useMemo as u, useRef as d, useState as f } from "react";
15
- import { ArrowUp as p, Loader2 as m } from "lucide-react";
16
- import { jsx as h, jsxs as g } from "react/jsx-runtime";
14
+ import { useCallback as l, useLayoutEffect as u, useMemo as d, useRef as f, useState as p } from "react";
15
+ import { ArrowUp as m, Loader2 as h } from "lucide-react";
16
+ import { jsx as g, jsxs as _ } from "react/jsx-runtime";
17
17
  //#region src/shared/assistant/ui/composer/AssistantComposer.tsx
18
- var _ = 200, v = ({ writeAccessDenied: v = !1, onSend: y, disabled: b = !1, placeholder: x, mode: S, availableModes: C, onModeChange: ae, onStartVoiceSession: w }) => {
19
- let T = ee(), { locale: E } = e(), D = d(null), [O, k] = f(""), [A, j] = f(!1), M = d(0), { attachments: N, isBusy: P, preparingCount: F, sendBlocker: I, rejection: L, addFiles: R, remove: z, retry: B, clear: V, clearRejection: H, canAddMore: U } = re(), oe = l((e) => {
18
+ var v = 200, y = ({ writeAccessDenied: y = !1, onSend: b, disabled: x = !1, placeholder: S, mode: ie, availableModes: C, attachmentCharsPerFile: ae, onModeChange: oe, onStartVoiceSession: w }) => {
19
+ let T = ee(), { locale: E } = e(), D = f(null), [O, k] = p(""), [A, j] = p(!1), M = f(0), { attachments: N, isBusy: P, preparingCount: F, sendBlocker: I, rejection: L, addFiles: R, remove: z, retry: B, clear: V, clearRejection: H, canAddMore: se } = re({ perFileChars: ae }), U = l((e) => {
20
20
  k((t) => t ? `${t.replace(/\s+$/, "")} ${e}` : e);
21
21
  }, []), W = a((e) => e.assistantLanguage), G = t({
22
- onFinalize: oe,
23
- language: u(() => r(W, E), [W, E]).tag
24
- }), K = x ?? T("composer.placeholder", "Ask me anything…"), q = O.trim(), J = i(N), Y = N.filter((e) => e.status === "error"), X = (q.length > 0 || J.length > 0) && !b && I === null;
25
- ie(() => {
22
+ onFinalize: U,
23
+ language: d(() => r(W, E), [W, E]).tag
24
+ }), K = S ?? T("composer.placeholder", "Ask me anything…"), q = O.trim(), J = i(N), Y = N.filter((e) => e.status === "error"), X = (q.length > 0 || J.length > 0) && !x && I === null;
25
+ u(() => {
26
26
  let e = D.current;
27
- e && (e.style.height = "auto", e.style.height = `${Math.min(e.scrollHeight, _)}px`);
27
+ e && (e.style.height = "auto", e.style.height = `${Math.min(e.scrollHeight, v)}px`);
28
28
  }, [O]);
29
29
  let Z = l(() => {
30
- X && (G.isActive && G.stop(), y(O.trim(), J), k(""), V());
30
+ X && (G.isActive && G.stop(), b(O.trim(), J), k(""), V());
31
31
  }, [
32
32
  X,
33
- y,
33
+ b,
34
34
  O,
35
35
  J,
36
36
  V,
37
37
  G
38
- ]), se = l((e) => {
38
+ ]), ce = l((e) => {
39
39
  e.key === "Enter" && !e.shiftKey && (e.preventDefault(), Z());
40
- }, [Z]), ce = l((e) => {
40
+ }, [Z]), le = l((e) => {
41
41
  let t = Array.from(e.clipboardData?.files ?? []);
42
42
  t.length !== 0 && (e.preventDefault(), R(t));
43
- }, [R]), le = l((e) => {
43
+ }, [R]), ue = l((e) => {
44
44
  Array.from(e.dataTransfer?.types ?? []).includes("Files") && (M.current += 1, j(!0));
45
- }, []), ue = l(() => {
45
+ }, []), Q = l(() => {
46
46
  M.current = Math.max(0, M.current - 1), M.current === 0 && j(!1);
47
- }, []), Q = l((e) => {
48
- Array.from(e.dataTransfer?.types ?? []).includes("Files") && e.preventDefault();
49
47
  }, []), de = l((e) => {
48
+ Array.from(e.dataTransfer?.types ?? []).includes("Files") && e.preventDefault();
49
+ }, []), fe = l((e) => {
50
50
  e.preventDefault(), M.current = 0, j(!1), R(e.dataTransfer?.files ?? null);
51
- }, [R]), fe = (e) => {
51
+ }, [R]), pe = (e) => {
52
52
  switch (e) {
53
53
  case "too-many": return T("attachments.tooMany", "You can attach up to {{max}} files per message.", { max: 5 });
54
54
  case "too-large": return T("attachments.tooLarge", "That file is larger than 10 MB.");
@@ -66,107 +66,107 @@ var _ = 200, v = ({ writeAccessDenied: v = !1, onSend: y, disabled: b = !1, plac
66
66
  default: return null;
67
67
  }
68
68
  })();
69
- return /* @__PURE__ */ g("div", {
69
+ return /* @__PURE__ */ _("div", {
70
70
  className: "flex-shrink-0 px-3 pb-3 pt-1.5",
71
71
  children: [
72
- /* @__PURE__ */ g("div", {
73
- onDragEnter: le,
74
- onDragLeave: ue,
75
- onDragOver: Q,
76
- onDrop: de,
72
+ /* @__PURE__ */ _("div", {
73
+ onDragEnter: ue,
74
+ onDragLeave: Q,
75
+ onDragOver: de,
76
+ onDrop: fe,
77
77
  className: `rounded-2xl border p-2 shadow-sm transition-colors focus-within:border-action-primary-bg focus-within:ring-2 focus-within:ring-action-primary-bg/15 ${A ? "border-action-primary-bg border-dashed bg-action-primary-bg/5" : "border-border-default bg-bg-sunken"}`,
78
78
  "data-testid": "assistant-composer",
79
79
  children: [
80
- /* @__PURE__ */ h(s, {
80
+ /* @__PURE__ */ g(s, {
81
81
  attachments: N,
82
82
  onRemove: z,
83
83
  onRetry: B,
84
- disabled: b,
84
+ disabled: x,
85
85
  preparingCount: F
86
86
  }),
87
- /* @__PURE__ */ g("div", {
87
+ /* @__PURE__ */ _("div", {
88
88
  className: "flex items-end gap-2",
89
89
  children: [
90
- /* @__PURE__ */ h(o, {
90
+ /* @__PURE__ */ g(o, {
91
91
  onFiles: R,
92
- canAddMore: U,
93
- disabled: b
92
+ canAddMore: se,
93
+ disabled: x
94
94
  }),
95
- /* @__PURE__ */ h("textarea", {
95
+ /* @__PURE__ */ g("textarea", {
96
96
  ref: D,
97
97
  value: O,
98
98
  onChange: (e) => k(e.target.value),
99
- onKeyDown: se,
100
- onPaste: ce,
101
- disabled: b,
99
+ onKeyDown: ce,
100
+ onPaste: le,
101
+ disabled: x,
102
102
  placeholder: A ? T("composer.dropHere", "Drop files to attach") : K,
103
103
  rows: 1,
104
104
  className: "min-h-[36px] flex-1 resize-none self-center bg-transparent px-1 py-2 text-[15px] leading-relaxed text-text-primary placeholder:text-text-muted focus:outline-none disabled:opacity-50",
105
105
  "aria-label": T("chatInput.ariaLabel", "Message input"),
106
106
  "data-testid": "assistant-input"
107
107
  }),
108
- G.isSupported && /* @__PURE__ */ h(te, {
108
+ G.isSupported && /* @__PURE__ */ g(te, {
109
109
  isListening: G.isListening,
110
110
  isStarting: G.isStarting,
111
111
  onToggle: G.toggle,
112
- disabled: b
112
+ disabled: x
113
113
  }),
114
- w && q.length === 0 && N.length === 0 && !G.isActive ? /* @__PURE__ */ h(ne, {
114
+ w && q.length === 0 && N.length === 0 && !G.isActive ? /* @__PURE__ */ g(ne, {
115
115
  onStart: w,
116
- disabled: b
117
- }) : /* @__PURE__ */ h("button", {
116
+ disabled: x
117
+ }) : /* @__PURE__ */ g("button", {
118
118
  type: "button",
119
119
  onClick: Z,
120
120
  disabled: !X,
121
121
  className: `flex size-9 flex-shrink-0 items-center justify-center rounded-full shadow-sm transition-all focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${X ? "bg-action-primary-bg text-action-primary-text hover:scale-105 hover:bg-action-primary-bg-hover" : "bg-bg-elevated text-text-muted"}`,
122
122
  "aria-label": T("chatInput.send", "Send message"),
123
123
  "data-testid": "assistant-send",
124
- children: b || P ? /* @__PURE__ */ h(m, { className: "size-4 motion-safe:animate-spin" }) : /* @__PURE__ */ h(p, { className: "size-4" })
124
+ children: x || P ? /* @__PURE__ */ g(h, { className: "size-4 motion-safe:animate-spin" }) : /* @__PURE__ */ g(m, { className: "size-4" })
125
125
  })
126
126
  ]
127
127
  }),
128
- C.length > 1 && /* @__PURE__ */ h("div", {
128
+ C.length > 1 && /* @__PURE__ */ g("div", {
129
129
  className: "mt-2 px-0.5",
130
- children: /* @__PURE__ */ h(c, {
131
- mode: S,
130
+ children: /* @__PURE__ */ g(c, {
131
+ mode: ie,
132
132
  availableModes: C,
133
- onModeChange: ae,
134
- disabled: b
133
+ onModeChange: oe,
134
+ disabled: x
135
135
  })
136
136
  })
137
137
  ]
138
138
  }),
139
- v ? /* @__PURE__ */ h("p", {
139
+ y ? /* @__PURE__ */ g("p", {
140
140
  className: "mt-1.5 px-1 text-center text-[11px] text-status-warning",
141
141
  "data-testid": "assistant-write-access-warning",
142
142
  children: T("composer.writeAccessDenied", "Changes may not save — your role in this workspace does not currently allow edits. You can still plan and review an action.")
143
143
  }) : null,
144
- /* @__PURE__ */ h("div", {
144
+ /* @__PURE__ */ g("div", {
145
145
  className: "mt-1.5 px-1 text-center text-[11px]",
146
146
  "aria-live": "polite",
147
- children: G.isStarting && !G.isListening ? /* @__PURE__ */ h("p", {
147
+ children: G.isStarting && !G.isListening ? /* @__PURE__ */ g("p", {
148
148
  className: "text-text-muted",
149
149
  "data-testid": "assistant-voice-starting",
150
150
  children: T("voice.starting", "Starting the microphone…")
151
- }) : G.isListening ? /* @__PURE__ */ g("p", {
151
+ }) : G.isListening ? /* @__PURE__ */ _("p", {
152
152
  className: "text-status-error-text",
153
153
  "data-testid": "assistant-voice-status",
154
- children: [/* @__PURE__ */ h("span", { className: "mr-1 inline-block size-1.5 rounded-full bg-status-error-text align-middle motion-safe:animate-pulse" }), G.interim || T("voice.listening", "Listening… speak now, tap the square to stop")]
155
- }) : $ ? /* @__PURE__ */ h("p", {
154
+ children: [/* @__PURE__ */ g("span", { className: "mr-1 inline-block size-1.5 rounded-full bg-status-error-text align-middle motion-safe:animate-pulse" }), G.interim || T("voice.listening", "Listening… speak now, tap the square to stop")]
155
+ }) : $ ? /* @__PURE__ */ g("p", {
156
156
  className: "text-status-error-text",
157
157
  "data-testid": "assistant-voice-error",
158
158
  children: $
159
- }) : L ? /* @__PURE__ */ h("button", {
159
+ }) : L ? /* @__PURE__ */ g("button", {
160
160
  type: "button",
161
161
  onClick: H,
162
162
  className: "text-status-error-text underline-offset-2 hover:underline",
163
163
  "data-testid": "assistant-attachment-rejection",
164
- children: fe(L)
165
- }) : I === "failed" ? /* @__PURE__ */ h("p", {
164
+ children: pe(L)
165
+ }) : I === "failed" ? /* @__PURE__ */ g("p", {
166
166
  className: "text-status-error-text",
167
167
  "data-testid": "assistant-attachment-blocked",
168
168
  children: Y.length === 1 ? T("attachments.blockedOne", "{{name}} didn't upload. Retry or remove it before sending.", { name: Y[0].filename }) : T("attachments.blockedMany", "{{count}} attachments didn't upload. Retry or remove them before sending.", { count: Y.length })
169
- }) : /* @__PURE__ */ h("p", {
169
+ }) : /* @__PURE__ */ g("p", {
170
170
  className: "text-text-muted",
171
171
  children: T("composer.hint", "Enter to send · Shift+Enter for newline · drag or paste files to attach")
172
172
  })
@@ -175,4 +175,4 @@ var _ = 200, v = ({ writeAccessDenied: v = !1, onSend: y, disabled: b = !1, plac
175
175
  });
176
176
  };
177
177
  //#endregion
178
- export { v as AssistantComposer };
178
+ export { y as AssistantComposer };
@@ -22,5 +22,16 @@ export interface UseAssistantAttachmentsResult {
22
22
  clearRejection: () => void;
23
23
  canAddMore: boolean;
24
24
  }
25
- export declare function useAssistantAttachments(): UseAssistantAttachmentsResult;
25
+ export interface UseAssistantAttachmentsOptions {
26
+ /**
27
+ * How many characters of a text or document file to keep when it is attached
28
+ * (BOFF-7334). Pass `largestInlineCharsPerFile(availableModes)`: the send cuts
29
+ * each file again to the SENDING mode's limit, so keeping the largest is what
30
+ * lets a file attached in one mode be sent in another without having been cut
31
+ * to the smaller limit first. Absent: the shared default,
32
+ * `MAX_INLINE_CHARS_PER_FILE`. Bounded like a mode's own limit.
33
+ */
34
+ perFileChars?: number;
35
+ }
36
+ export declare function useAssistantAttachments(options?: UseAssistantAttachmentsOptions): UseAssistantAttachmentsResult;
26
37
  //# sourceMappingURL=useAssistantAttachments.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAssistantAttachments.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/useAssistantAttachments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAOH,OAAO,EAYL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC3B,MAAM,eAAe,CAAC;AAkJvB,MAAM,WAAW,6BAA6B;IAC5C,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,qEAAqE;IACrE,MAAM,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,WAAW,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC1C,6DAA6D;IAC7D,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,EAAE,GAAG,IAAI,GAAG,SAAS,KAAK,IAAI,CAAC;IAChE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,gFAAgF;IAChF,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,uBAAuB,IAAI,6BAA6B,CAqQvE"}
1
+ {"version":3,"file":"useAssistantAttachments.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/useAssistantAttachments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAOH,OAAO,EAYL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC3B,MAAM,eAAe,CAAC;AAsJvB,MAAM,WAAW,6BAA6B;IAC5C,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,qEAAqE;IACrE,MAAM,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,WAAW,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC1C,6DAA6D;IAC7D,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,EAAE,GAAG,IAAI,GAAG,SAAS,KAAK,IAAI,CAAC;IAChE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,gFAAgF;IAChF,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,8BAA8B;IAC7C;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,8BAAmC,GAC3C,6BAA6B,CAyQ/B"}
@@ -3,7 +3,7 @@ import "../../shared-graphql.js";
3
3
  import { downscaleImage as t } from "../utils/imageDownscale.js";
4
4
  import { useAssistantStorageFolders as n } from "./product.js";
5
5
  import { useAssistantTr as r } from "./i18n.js";
6
- import { AttachmentRejectedError as i, INLINE_IMAGE_QUALITY as a, MAX_INLINE_CHARS_PER_FILE as o, classifyAttachment as s, detectDocumentFormat as c, getAttachmentSendBlocker as l, truncateForInline as u, validateFile as d } from "./attachments.js";
6
+ import { AttachmentRejectedError as i, INLINE_IMAGE_QUALITY as a, classifyAttachment as o, detectDocumentFormat as s, getAttachmentSendBlocker as c, resolveAssistantInlineLimits as l, truncateForInline as u, validateFile as d } from "./attachments.js";
7
7
  import { getWorkspaceId as f } from "./context.js";
8
8
  import { useSaveToFiles as p } from "../../storage/useSaveToFiles.js";
9
9
  import "../../storage/index.js";
@@ -30,58 +30,58 @@ var x = 0;
30
30
  function S() {
31
31
  return x += 1, `att-${Date.now()}-${x}`;
32
32
  }
33
- async function C(e) {
34
- let n = s(e.type, e.name), r = {
33
+ async function C(e, n) {
34
+ let r = o(e.type, e.name), c = {
35
35
  id: S(),
36
36
  status: "pending"
37
37
  };
38
- if (n === "image") {
39
- let o = await t(e, {
38
+ if (r === "image") {
39
+ let n = await t(e, {
40
40
  encodeFallback: !1,
41
41
  inline: {
42
42
  maxDim: 768,
43
43
  quality: a
44
44
  }
45
45
  });
46
- if (!o.downscaled && o.blob.size > 10485760) throw new i("unsupported-image");
46
+ if (!n.downscaled && n.blob.size > 10485760) throw new i("unsupported-image");
47
47
  return {
48
48
  attachment: {
49
- ...r,
50
- filename: o.filename,
51
- mimeType: o.mimeType,
52
- size: o.blob.size,
53
- kind: n,
54
- previewUrl: o.dataUrl || void 0,
55
- inlineDataUrl: o.inlineDataUrl
49
+ ...c,
50
+ filename: n.filename,
51
+ mimeType: n.mimeType,
52
+ size: n.blob.size,
53
+ kind: r,
54
+ previewUrl: n.dataUrl || void 0,
55
+ inlineDataUrl: n.inlineDataUrl
56
56
  },
57
- blob: o.blob
57
+ blob: n.blob
58
58
  };
59
59
  }
60
- if (n === "text") {
61
- let { text: t, truncated: i } = u(await e.text(), o);
60
+ if (r === "text") {
61
+ let { text: t, truncated: i } = u(await e.text(), n);
62
62
  return {
63
63
  attachment: {
64
- ...r,
64
+ ...c,
65
65
  filename: e.name,
66
66
  mimeType: e.type || "text/plain",
67
67
  size: e.size,
68
- kind: n,
68
+ kind: r,
69
69
  textContent: t,
70
70
  textTruncated: i
71
71
  },
72
72
  blob: e
73
73
  };
74
74
  }
75
- let l = c(e.type, e.name);
75
+ let l = s(e.type, e.name);
76
76
  if (l) {
77
- let t = await m(e, l);
77
+ let t = await m(e, l, n);
78
78
  return {
79
79
  attachment: {
80
- ...r,
80
+ ...c,
81
81
  filename: e.name,
82
82
  mimeType: e.type || "application/octet-stream",
83
83
  size: e.size,
84
- kind: n,
84
+ kind: r,
85
85
  extraction: t.extraction,
86
86
  textContent: t.textContent,
87
87
  textTruncated: t.textTruncated,
@@ -92,131 +92,131 @@ async function C(e) {
92
92
  }
93
93
  return {
94
94
  attachment: {
95
- ...r,
95
+ ...c,
96
96
  filename: e.name,
97
97
  mimeType: e.type || "application/octet-stream",
98
98
  size: e.size,
99
- kind: n
99
+ kind: r
100
100
  },
101
101
  blob: e
102
102
  };
103
103
  }
104
- function w() {
105
- let e = r(), t = n(), { save: a } = p(), [o, s] = v([]), [c, u] = v(null), m = _(Promise.resolve()), [y, x] = v(0), S = _(0), w = _(/* @__PURE__ */ new Map()), T = _(/* @__PURE__ */ new Set()), E = _(0), D = _(!0);
104
+ function w(e = {}) {
105
+ let t = r(), a = l({ maxInlineCharsPerFile: e.perFileChars }).perFileChars, o = n(), { save: s } = p(), [u, m] = v([]), [y, x] = v(null), S = _(Promise.resolve()), [w, T] = v(0), E = _(0), D = _(/* @__PURE__ */ new Map()), O = _(/* @__PURE__ */ new Set()), k = _(0), A = _(!0);
106
106
  g(() => () => {
107
- D.current = !1;
107
+ A.current = !1;
108
108
  }, []);
109
- let O = _([]);
109
+ let j = _([]);
110
110
  g(() => {
111
- O.current = o;
112
- }, [o]);
113
- let k = h((e, t) => {
114
- D.current && s((n) => n.map((n) => n.id === e ? {
111
+ j.current = u;
112
+ }, [u]);
113
+ let M = h((e, t) => {
114
+ A.current && m((n) => n.map((n) => n.id === e ? {
115
115
  ...n,
116
116
  ...t
117
117
  } : n));
118
- }, []), A = h(async ({ attachment: n, blob: r }) => {
119
- if (!T.current.has(n.id)) {
120
- k(n.id, {
118
+ }, []), N = h(async ({ attachment: e, blob: n }) => {
119
+ if (!O.current.has(e.id)) {
120
+ M(e.id, {
121
121
  status: "uploading",
122
122
  progressNote: void 0
123
123
  });
124
124
  try {
125
- let i = await a({
125
+ let r = await s({
126
126
  source: {
127
127
  kind: "blob",
128
- filename: n.filename,
129
- mimeType: n.mimeType,
128
+ filename: e.filename,
129
+ mimeType: e.mimeType,
130
130
  getBlob: async () => ({
131
- blob: r,
132
- filename: n.filename,
133
- mimeType: n.mimeType
131
+ blob: n,
132
+ filename: e.filename,
133
+ mimeType: e.mimeType
134
134
  })
135
135
  },
136
- folderPath: t.attachments,
137
- onRetry: (t) => {
138
- T.current.has(n.id) || k(n.id, { progressNote: t.kind === "cold-start" ? e("attachments.waking", "File service is starting up — retry {{attempt}} of {{max}}", {
139
- attempt: String(t.attempt),
140
- max: String(t.maxAttempts)
141
- }) : e("attachments.retrying", "Retrying {{attempt}} of {{max}}", {
142
- attempt: String(t.attempt),
143
- max: String(t.maxAttempts)
136
+ folderPath: o.attachments,
137
+ onRetry: (n) => {
138
+ O.current.has(e.id) || M(e.id, { progressNote: n.kind === "cold-start" ? t("attachments.waking", "File service is starting up — retry {{attempt}} of {{max}}", {
139
+ attempt: String(n.attempt),
140
+ max: String(n.maxAttempts)
141
+ }) : t("attachments.retrying", "Retrying {{attempt}} of {{max}}", {
142
+ attempt: String(n.attempt),
143
+ max: String(n.maxAttempts)
144
144
  }) });
145
145
  }
146
146
  });
147
- if (T.current.has(n.id)) return;
148
- let o = i?.id ? await b(i.id, f()) : null;
149
- if (T.current.has(n.id)) return;
150
- k(n.id, {
147
+ if (O.current.has(e.id)) return;
148
+ let i = r?.id ? await b(r.id, f()) : null;
149
+ if (O.current.has(e.id)) return;
150
+ M(e.id, {
151
151
  status: "ready",
152
- fileId: i?.id,
153
- downloadUrl: o ?? void 0,
152
+ fileId: r?.id,
153
+ downloadUrl: i ?? void 0,
154
154
  progressNote: void 0
155
155
  });
156
- } catch (e) {
157
- if (T.current.has(n.id)) return;
158
- if (n.kind === "text" || n.textContent) {
159
- k(n.id, {
156
+ } catch (t) {
157
+ if (O.current.has(e.id)) return;
158
+ if (e.kind === "text" || e.textContent) {
159
+ M(e.id, {
160
160
  status: "ready",
161
161
  progressNote: void 0
162
162
  });
163
163
  return;
164
164
  }
165
- k(n.id, {
165
+ M(e.id, {
166
166
  status: "error",
167
- error: e instanceof Error ? e.message : "Upload failed",
167
+ error: t instanceof Error ? t.message : "Upload failed",
168
168
  progressNote: void 0
169
169
  });
170
170
  }
171
171
  }
172
172
  }, [
173
- k,
174
- a,
175
- e
176
- ]), j = h((e) => {
173
+ M,
174
+ s,
175
+ t
176
+ ]), P = h((e) => {
177
177
  if (!e) return;
178
178
  let t = Array.from(e);
179
179
  if (t.length === 0) return;
180
- u(null);
180
+ x(null);
181
181
  let n = [];
182
182
  for (let e of t) {
183
- let t = d(e, E.current);
183
+ let t = d(e, k.current);
184
184
  if (t) {
185
- u(t);
185
+ x(t);
186
186
  continue;
187
187
  }
188
- n.push(e), E.current += 1;
188
+ n.push(e), k.current += 1;
189
189
  }
190
190
  if (n.length !== 0) {
191
- x((e) => e + n.length);
191
+ T((e) => e + n.length);
192
192
  for (let e of n) {
193
- let t = S.current;
194
- m.current = m.current.then(async () => {
193
+ let t = E.current;
194
+ S.current = S.current.then(async () => {
195
195
  let n = null;
196
196
  try {
197
- n = await C(e);
197
+ n = await C(e, a);
198
198
  } catch (e) {
199
- E.current = Math.max(0, E.current - 1), D.current && u(e instanceof i ? e.reason : "unreadable");
199
+ k.current = Math.max(0, k.current - 1), A.current && x(e instanceof i ? e.reason : "unreadable");
200
200
  }
201
- if (!D.current || (x((e) => Math.max(0, e - 1)), !n)) return;
202
- if (t !== S.current) {
203
- E.current = Math.max(0, E.current - 1);
201
+ if (!A.current || (T((e) => Math.max(0, e - 1)), !n)) return;
202
+ if (t !== E.current) {
203
+ k.current = Math.max(0, k.current - 1);
204
204
  return;
205
205
  }
206
206
  let r = n;
207
- w.current.set(r.attachment.id, r.blob), s((e) => [...e, r.attachment]), await A(r);
207
+ D.current.set(r.attachment.id, r.blob), m((e) => [...e, r.attachment]), await N(r);
208
208
  });
209
209
  }
210
210
  }
211
- }, [A]), M = h((e) => {
212
- T.current.add(e), w.current.delete(e), E.current = Math.max(0, E.current - 1), s((t) => t.filter((t) => t.id !== e));
213
- }, []), N = h((e) => {
214
- let t = O.current.find((t) => t.id === e), n = w.current.get(e);
215
- !t || t.status !== "error" || !n || (T.current.delete(e), k(e, {
211
+ }, [N, a]), F = h((e) => {
212
+ O.current.add(e), D.current.delete(e), k.current = Math.max(0, k.current - 1), m((t) => t.filter((t) => t.id !== e));
213
+ }, []), I = h((e) => {
214
+ let t = j.current.find((t) => t.id === e), n = D.current.get(e);
215
+ !t || t.status !== "error" || !n || (O.current.delete(e), M(e, {
216
216
  status: "pending",
217
217
  error: void 0,
218
218
  progressNote: void 0
219
- }), m.current = m.current.then(() => A({
219
+ }), S.current = S.current.then(() => N({
220
220
  attachment: {
221
221
  ...t,
222
222
  status: "pending",
@@ -224,21 +224,21 @@ function w() {
224
224
  },
225
225
  blob: n
226
226
  })));
227
- }, [k, A]), P = h(() => {
228
- S.current += 1, E.current = 0, O.current.forEach((e) => T.current.add(e.id)), w.current.clear(), s([]);
229
- }, []), F = l(y, o);
227
+ }, [M, N]), L = h(() => {
228
+ E.current += 1, k.current = 0, j.current.forEach((e) => O.current.add(e.id)), D.current.clear(), m([]);
229
+ }, []), R = c(w, u);
230
230
  return {
231
- attachments: o,
232
- isBusy: F === "in-flight",
233
- preparingCount: y,
234
- sendBlocker: F,
235
- rejection: c,
236
- addFiles: j,
237
- remove: M,
238
- retry: N,
239
- clear: P,
240
- clearRejection: h(() => u(null), []),
241
- canAddMore: E.current < 5
231
+ attachments: u,
232
+ isBusy: R === "in-flight",
233
+ preparingCount: w,
234
+ sendBlocker: R,
235
+ rejection: y,
236
+ addFiles: P,
237
+ remove: F,
238
+ retry: I,
239
+ clear: L,
240
+ clearRejection: h(() => x(null), []),
241
+ canAddMore: k.current < 5
242
242
  };
243
243
  }
244
244
  //#endregion