@burdenoff/fe-libs 2026.1028.9 → 2026.1028.11

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.
@@ -149,6 +149,8 @@ export interface AssistantAttachment {
149
149
  * person can press Send again (that is the retry) or remove it. Draft-only.
150
150
  */
151
151
  saveError?: string;
152
+ /** Stable refusal code for translated chip copy; draft-only. */
153
+ saveErrorCode?: string;
152
154
  /**
153
155
  * True for a file that is deliberately NOT saved to Files (a non-image over the 5 MiB direct
154
156
  * upload limit whose text is still sent inline). `commitAttachments` passes it through
@@ -6,13 +6,14 @@ import { TURN_OUTCOME_COPY as i } from "./turnOutcomeCopy.js";
6
6
  import { INCOMPLETE_TURN_NOTICES as a } from "./streamBudget.js";
7
7
  import { STAGE_COPY as o, THINKING_PHRASES as s } from "./stageCopy.js";
8
8
  import { VOICE_MUTED_LABEL as c, VOICE_THINKING_LABEL as l } from "./voice/voiceStatus.js";
9
- import { ATTACHMENT_SOURCES as u } from "./attachmentSources.js";
10
- import { AVATAR_MINUTES_HOW_COUNTED as d } from "./avatar/useAvatarCopy.js";
11
- import { assistantProductCopyEntries as f } from "./productCopy.js";
12
- import { WRITE_PROPOSAL_ERROR_COPY as p } from "./writeProposalErrorCopy.js";
13
- import { WRITE_PROPOSAL_VOICE_COPY as m } from "./writeProposalVoice.js";
9
+ import { ATTACHMENT_EDITOR_ACCESS_COPY as u } from "./attachmentAccessCopy.js";
10
+ import { ATTACHMENT_SOURCES as d } from "./attachmentSources.js";
11
+ import { AVATAR_MINUTES_HOW_COUNTED as f } from "./avatar/useAvatarCopy.js";
12
+ import { assistantProductCopyEntries as p } from "./productCopy.js";
13
+ import { WRITE_PROPOSAL_ERROR_COPY as m } from "./writeProposalErrorCopy.js";
14
+ import { WRITE_PROPOSAL_VOICE_COPY as h } from "./writeProposalVoice.js";
14
15
  //#region src/shared/assistant/i18nManifest.ts
15
- var h = {
16
+ var g = {
16
17
  "apiCalls.consentBody": "In Take action mode the assistant can read AND change your data — creating records, logging activity, updating details, and more, on your behalf.",
17
18
  "apiCalls.consentBody2": "It will describe what it is about to do and ask you to confirm before making a change. Only continue if you want the assistant to take actions for you.",
18
19
  "apiCalls.consentCancel": "Stay in Ask",
@@ -572,35 +573,36 @@ var h = {
572
573
  "writeProposal.values": "Values",
573
574
  "writeProposal.variablesOmitted": "{{count}} more values not shown",
574
575
  "writeProposal.waitForTurn": "You can confirm once the assistant finishes replying."
575
- }, g = (e) => Object.fromEntries(e.map((e) => [e.key, e.fallback])), _ = Object.freeze({
576
- ...g(Object.values(o)),
577
- ...g(s),
578
- ...g([l, c]),
579
- ...g(a),
580
- ...g(Object.values(i)),
581
- ...g(Object.values(r)),
582
- ...g(Object.values(p)),
583
- ...g(Object.values(m)),
584
- ...g(Object.values(d)),
585
- ...Object.fromEntries(u.map((e) => [e.labelKey, e.labelFallback]))
586
- }), v = Object.freeze({
576
+ }, _ = (e) => Object.fromEntries(e.map((e) => [e.key, e.fallback])), v = Object.freeze({
577
+ ..._([u]),
578
+ ..._(Object.values(o)),
579
+ ..._(s),
580
+ ..._([l, c]),
581
+ ..._(a),
582
+ ..._(Object.values(i)),
583
+ ..._(Object.values(r)),
584
+ ..._(Object.values(m)),
585
+ ..._(Object.values(h)),
586
+ ..._(Object.values(f)),
587
+ ...Object.fromEntries(d.map((e) => [e.labelKey, e.labelFallback]))
588
+ }), y = Object.freeze({
587
589
  "attachments.retrying": "Retrying {{attempt}} of {{max}}",
588
590
  "attachments.waking": "File service is starting up — retry {{attempt}} of {{max}}",
589
591
  "outcome.usageDailyLimitReachedNoTime": "You've reached today's AI assistant limit. Try again tomorrow."
590
- }), y = Object.freeze({
591
- ...h,
592
- ..._,
593
- ...v
592
+ }), b = Object.freeze({
593
+ ...g,
594
+ ...v,
595
+ ...y
594
596
  });
595
- function b(e) {
597
+ function x(e) {
596
598
  let r = e.map((e) => e.id).filter((e) => !n(e));
597
599
  if (r.length > 0) throw Error(`assistantModeI18nCopy: malformed mode id ${r.map((e) => JSON.stringify(e)).join(", ")}. Declare product modes with declareAssistantMode().`);
598
600
  return Object.fromEntries(e.map((e) => [`mode.${e.id}`, e.label || t(e)]));
599
601
  }
600
- function x(t) {
602
+ function S(t) {
601
603
  let n = {
602
- ...y,
603
- ...b(t.modes)
604
+ ...b,
605
+ ...x(t.modes)
604
606
  }, r = Object.entries(t.overrides ?? {}), i = r.filter(([e]) => !Object.hasOwn(n, e)).map(([e]) => e);
605
607
  if (i.length > 0) throw Error(`assistantI18nSeedCopy: no shared assistant key ${i.join(", ")} to override. Check the spelling, or that the key is a mode this product offers; a key fe-libs no longer requests belongs with the product's own keys.`);
606
608
  let a = r.filter(([, e]) => e.trim() === "").map(([e]) => e);
@@ -608,7 +610,7 @@ function x(t) {
608
610
  let o = {
609
611
  ...n,
610
612
  ...Object.fromEntries(r),
611
- ...f({
613
+ ...p({
612
614
  modes: t.modes,
613
615
  pageLabels: t.pageLabels
614
616
  })
@@ -616,4 +618,4 @@ function x(t) {
616
618
  return Object.fromEntries(Object.entries(o).map(([n, r]) => [e(t.namespace, n), r]));
617
619
  }
618
620
  //#endregion
619
- export { _ as ASSISTANT_I18N_COMPUTED_COPY, h as ASSISTANT_I18N_LITERAL_COPY, y as ASSISTANT_I18N_MANIFEST, v as ASSISTANT_I18N_SEED_COMPAT_COPY, x as assistantI18nSeedCopy, b as assistantModeI18nCopy };
621
+ export { v as ASSISTANT_I18N_COMPUTED_COPY, g as ASSISTANT_I18N_LITERAL_COPY, b as ASSISTANT_I18N_MANIFEST, y as ASSISTANT_I18N_SEED_COMPAT_COPY, S as assistantI18nSeedCopy, x as assistantModeI18nCopy };
@@ -361,3 +361,5 @@ export * from './avatar/live/LiveAvatarMinutes';
361
361
  export * from './avatar/live/createLiveAvatarSeam';
362
362
  export * from './avatar/live/avatarVoice';
363
363
  export * from './promptDelivery';
364
+ export * from './attachmentAccess';
365
+ export * from './attachmentAccessCopy';
@@ -1,87 +1,90 @@
1
- import { useAssistantTr as e } from "../../i18n.js";
2
- import { formatBytes as t } from "../../attachments.js";
3
- import { AlertCircle as n, FileText as r, Loader2 as i, Paperclip as a, RotateCcw as o, X as s } from "lucide-react";
4
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
1
+ import { useI18n as e } from "../../../providers/shell/I18nProvider.js";
2
+ import { useAssistantTr as t } from "../../i18n.js";
3
+ import { attachmentEditorAccessMessage as n } from "../../attachmentAccessCopy.js";
4
+ import { formatBytes as r } from "../../attachments.js";
5
+ import { ATTACHMENT_COMMIT_CODES as i } from "../../attachmentCommit.js";
6
+ import { AlertCircle as a, FileText as o, Loader2 as s, Paperclip as c, RotateCcw as l, X as u } from "lucide-react";
7
+ import { jsx as d, jsxs as f } from "react/jsx-runtime";
5
8
  //#region src/shared/assistant/ui/composer/AssistantAttachmentChips.tsx
6
- var u = ({ attachments: u, onRemove: d, onRetry: f, preparingCount: p = 0, disabled: m = !1 }) => {
7
- let h = e();
8
- return u.length === 0 && p === 0 ? null : /* @__PURE__ */ l("ul", {
9
+ var p = ({ attachments: p, onRemove: m, onRetry: h, preparingCount: g = 0, disabled: _ = !1 }) => {
10
+ let v = t(), { locale: y } = e();
11
+ return p.length === 0 && g === 0 ? null : /* @__PURE__ */ f("ul", {
9
12
  className: "mb-1.5 flex flex-wrap gap-1.5 px-0.5",
10
- "aria-label": h("attachments.listLabel", "Attached files"),
13
+ "aria-label": v("attachments.listLabel", "Attached files"),
11
14
  "data-testid": "assistant-attachment-chips",
12
- children: [u.map((e) => {
13
- let u = e.status === "pending" || e.status === "uploading", p = e.status === "error" || !!e.saveError, g = e.status === "uploading", _ = Math.max(0, Math.min(100, Math.round(e.progress ?? 0))), v = p ? e.saveError ?? e.error ?? h("attachments.failed", "Upload failed") : g ? e.progressNote ?? h("attachments.savingProgress", "Saving {{percent}}%", { percent: _ }) : u ? h("attachments.uploading", "Uploading…") : e.inlineOnly ? h("attachments.inlineOnly", "Not saved to Files (over 5 MB). Its text is still included.") : t(e.size);
14
- return /* @__PURE__ */ l("li", {
15
+ children: [p.map((e) => {
16
+ let t = e.status === "pending" || e.status === "uploading", p = e.status === "error" || !!e.saveError, g = e.status === "uploading", b = Math.max(0, Math.min(100, Math.round(e.progress ?? 0))), x = p ? e.saveErrorCode === i.editorAccessRequired ? n(v, y) : e.saveError ?? e.error ?? v("attachments.failed", "Upload failed") : g ? e.progressNote ?? v("attachments.savingProgress", "Saving {{percent}}%", { percent: b }) : t ? v("attachments.uploading", "Uploading…") : e.inlineOnly ? v("attachments.inlineOnly", "Not saved to Files (over 5 MB). Its text is still included.") : r(e.size);
17
+ return /* @__PURE__ */ f("li", {
15
18
  className: `flex max-w-[220px] items-center gap-1.5 rounded-lg border py-1 pl-1 pr-1.5 ${p ? "border-status-error-text/40 bg-status-error-bg/10" : "border-border-subtle bg-bg-surface"}`,
16
19
  "data-testid": "assistant-attachment-chip",
17
20
  children: [
18
- /* @__PURE__ */ c("span", {
21
+ /* @__PURE__ */ d("span", {
19
22
  className: "flex size-7 flex-shrink-0 items-center justify-center overflow-hidden rounded-md bg-bg-sunken text-text-muted",
20
- children: e.previewUrl ? /* @__PURE__ */ c("img", {
23
+ children: e.previewUrl ? /* @__PURE__ */ d("img", {
21
24
  src: e.previewUrl,
22
25
  alt: "",
23
26
  className: "size-full object-cover"
24
- }) : p ? /* @__PURE__ */ c(n, { className: "size-3.5 text-status-error-text" }) : e.kind === "text" ? /* @__PURE__ */ c(r, { className: "size-3.5" }) : /* @__PURE__ */ c(a, { className: "size-3.5" })
27
+ }) : p ? /* @__PURE__ */ d(a, { className: "size-3.5 text-status-error-text" }) : e.kind === "text" ? /* @__PURE__ */ d(o, { className: "size-3.5" }) : /* @__PURE__ */ d(c, { className: "size-3.5" })
25
28
  }),
26
- /* @__PURE__ */ l("span", {
29
+ /* @__PURE__ */ f("span", {
27
30
  className: "min-w-0 flex-1",
28
31
  children: [
29
- /* @__PURE__ */ c("span", {
32
+ /* @__PURE__ */ d("span", {
30
33
  className: "block truncate text-[11px] font-medium leading-tight text-text-primary",
31
34
  children: e.filename
32
35
  }),
33
- /* @__PURE__ */ c("span", {
36
+ /* @__PURE__ */ d("span", {
34
37
  className: `block truncate text-[10px] leading-tight ${p ? "text-status-error-text" : "text-text-muted"}`,
35
- title: v,
36
- children: v
38
+ title: x,
39
+ children: x
37
40
  }),
38
- g ? /* @__PURE__ */ c("span", {
41
+ g ? /* @__PURE__ */ d("span", {
39
42
  role: "progressbar",
40
- "aria-label": h("attachments.saving", "Saving your attachments…"),
43
+ "aria-label": v("attachments.saving", "Saving your attachments…"),
41
44
  "aria-valuemin": 0,
42
45
  "aria-valuemax": 100,
43
- "aria-valuenow": _,
46
+ "aria-valuenow": b,
44
47
  className: "mt-0.5 block h-1 overflow-hidden rounded-full bg-bg-sunken",
45
48
  "data-testid": "assistant-attachment-progress",
46
- children: /* @__PURE__ */ c("span", {
49
+ children: /* @__PURE__ */ d("span", {
47
50
  className: "block h-full rounded-full bg-action-primary-bg transition-[width]",
48
- style: { width: `${_}%` }
51
+ style: { width: `${b}%` }
49
52
  })
50
53
  }) : null
51
54
  ]
52
55
  }),
53
- e.status === "error" && /* @__PURE__ */ c("button", {
56
+ e.status === "error" && /* @__PURE__ */ d("button", {
54
57
  type: "button",
55
- onClick: () => f(e.id),
56
- disabled: m,
58
+ onClick: () => h(e.id),
59
+ disabled: _,
57
60
  className: "flex size-5 flex-shrink-0 items-center justify-center rounded-full text-status-error-text transition-colors hover:bg-bg-sunken focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong disabled:cursor-not-allowed",
58
- "aria-label": h("attachments.retry", "Retry uploading {{name}}", { name: e.filename }),
61
+ "aria-label": v("attachments.retry", "Retry uploading {{name}}", { name: e.filename }),
59
62
  "data-testid": "assistant-attachment-retry",
60
- children: /* @__PURE__ */ c(o, { className: "size-3" })
63
+ children: /* @__PURE__ */ d(l, { className: "size-3" })
61
64
  }),
62
- u ? /* @__PURE__ */ c(i, {
65
+ t ? /* @__PURE__ */ d(s, {
63
66
  className: "size-3.5 flex-shrink-0 motion-safe:animate-spin text-text-muted",
64
- "aria-label": h("attachments.uploading", "Uploading…")
65
- }) : /* @__PURE__ */ c("button", {
67
+ "aria-label": v("attachments.uploading", "Uploading…")
68
+ }) : /* @__PURE__ */ d("button", {
66
69
  type: "button",
67
- onClick: () => d(e.id),
68
- disabled: m,
70
+ onClick: () => m(e.id),
71
+ disabled: _,
69
72
  className: "flex size-5 flex-shrink-0 items-center justify-center rounded-full text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong disabled:cursor-not-allowed",
70
- "aria-label": h("attachments.remove", "Remove {{name}}", { name: e.filename }),
73
+ "aria-label": v("attachments.remove", "Remove {{name}}", { name: e.filename }),
71
74
  "data-testid": "assistant-attachment-remove",
72
- children: /* @__PURE__ */ c(s, { className: "size-3" })
75
+ children: /* @__PURE__ */ d(u, { className: "size-3" })
73
76
  })
74
77
  ]
75
78
  }, e.id);
76
- }), Array.from({ length: p }, (e, t) => /* @__PURE__ */ l("li", {
79
+ }), Array.from({ length: g }, (e, t) => /* @__PURE__ */ f("li", {
77
80
  className: "flex items-center gap-1.5 rounded-lg border border-border-subtle bg-bg-sunken px-2 py-1 text-xs text-text-muted",
78
81
  "data-testid": "assistant-attachment-preparing",
79
- children: [/* @__PURE__ */ c(i, {
82
+ children: [/* @__PURE__ */ d(s, {
80
83
  className: "size-3 motion-safe:animate-spin",
81
84
  "aria-hidden": "true"
82
- }), h("attachments.preparing", "Reading file…")]
85
+ }), v("attachments.preparing", "Reading file…")]
83
86
  }, `preparing-${t}`))]
84
87
  });
85
88
  };
86
89
  //#endregion
87
- export { u as AssistantAttachmentChips };
90
+ export { p as AssistantAttachmentChips };