@burdenoff/fe-libs 2026.928.2 → 2026.929.1

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 (142) hide show
  1. package/dist/shared/assistant/adminModeSendGate.d.ts +6 -5
  2. package/dist/shared/assistant/adminModeSendGate.d.ts.map +1 -1
  3. package/dist/shared/assistant/adminModeSendGate.js +11 -11
  4. package/dist/shared/assistant/api.d.ts +291 -28
  5. package/dist/shared/assistant/api.d.ts.map +1 -1
  6. package/dist/shared/assistant/api.js +351 -147
  7. package/dist/shared/assistant/autoRouting.d.ts +11 -3
  8. package/dist/shared/assistant/autoRouting.d.ts.map +1 -1
  9. package/dist/shared/assistant/autoRouting.js +7 -7
  10. package/dist/shared/assistant/capabilities.d.ts +28 -0
  11. package/dist/shared/assistant/capabilities.d.ts.map +1 -1
  12. package/dist/shared/assistant/capabilities.js +19 -10
  13. package/dist/shared/assistant/conversation.d.ts +24 -2
  14. package/dist/shared/assistant/conversation.d.ts.map +1 -1
  15. package/dist/shared/assistant/createSandboxAssistantTransport.d.ts.map +1 -1
  16. package/dist/shared/assistant/createSandboxAssistantTransport.js +67 -54
  17. package/dist/shared/assistant/history/historyList.js +1 -1
  18. package/dist/shared/assistant/history/historyMapping.d.ts.map +1 -1
  19. package/dist/shared/assistant/history/historyMapping.js +5 -1
  20. package/dist/shared/assistant/history/historyResume.js +7 -7
  21. package/dist/shared/assistant/i18nManifest.d.ts +53 -0
  22. package/dist/shared/assistant/i18nManifest.d.ts.map +1 -1
  23. package/dist/shared/assistant/i18nManifest.js +75 -16
  24. package/dist/shared/assistant/index.d.ts +15 -0
  25. package/dist/shared/assistant/index.d.ts.map +1 -1
  26. package/dist/shared/assistant/modeCapabilities.js +1 -1
  27. package/dist/shared/assistant/operations.d.ts +22 -0
  28. package/dist/shared/assistant/operations.d.ts.map +1 -1
  29. package/dist/shared/assistant/operations.js +2 -2
  30. package/dist/shared/assistant/prewarm.d.ts +7 -0
  31. package/dist/shared/assistant/prewarm.d.ts.map +1 -1
  32. package/dist/shared/assistant/prewarm.js +1 -1
  33. package/dist/shared/assistant/product.d.ts +80 -2
  34. package/dist/shared/assistant/product.d.ts.map +1 -1
  35. package/dist/shared/assistant/product.js +10 -6
  36. package/dist/shared/assistant/proposalWriteRules.d.ts +40 -0
  37. package/dist/shared/assistant/proposalWriteRules.d.ts.map +1 -0
  38. package/dist/shared/assistant/proposalWriteRules.js +14 -0
  39. package/dist/shared/assistant/store.d.ts +17 -0
  40. package/dist/shared/assistant/store.d.ts.map +1 -1
  41. package/dist/shared/assistant/store.js +50 -43
  42. package/dist/shared/assistant/turnOutcome.d.ts +34 -2
  43. package/dist/shared/assistant/turnOutcome.d.ts.map +1 -1
  44. package/dist/shared/assistant/turnOutcome.js +28 -17
  45. package/dist/shared/assistant/turnOutcomeCopy.d.ts +29 -7
  46. package/dist/shared/assistant/turnOutcomeCopy.d.ts.map +1 -1
  47. package/dist/shared/assistant/turnOutcomeCopy.js +18 -6
  48. package/dist/shared/assistant/types.d.ts +5 -1
  49. package/dist/shared/assistant/types.d.ts.map +1 -1
  50. package/dist/shared/assistant/ui/AssistantApiCallsConsentDialog.js +4 -4
  51. package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
  52. package/dist/shared/assistant/ui/AssistantChatArea.js +989 -718
  53. package/dist/shared/assistant/ui/AssistantConversationList.js +6 -6
  54. package/dist/shared/assistant/ui/AssistantLanguageMenu.js +6 -6
  55. package/dist/shared/assistant/ui/AssistantMessageItem.d.ts +8 -1
  56. package/dist/shared/assistant/ui/AssistantMessageItem.d.ts.map +1 -1
  57. package/dist/shared/assistant/ui/AssistantMessageItem.js +77 -76
  58. package/dist/shared/assistant/ui/AssistantMessageList.d.ts +13 -1
  59. package/dist/shared/assistant/ui/AssistantMessageList.d.ts.map +1 -1
  60. package/dist/shared/assistant/ui/AssistantMessageList.js +15 -13
  61. package/dist/shared/assistant/ui/AssistantReplyLanguageSelector.js +5 -5
  62. package/dist/shared/assistant/ui/AssistantSpeechProvider.js +209 -209
  63. package/dist/shared/assistant/ui/AssistantWriteConfirmDialog.d.ts +62 -0
  64. package/dist/shared/assistant/ui/AssistantWriteConfirmDialog.d.ts.map +1 -0
  65. package/dist/shared/assistant/ui/AssistantWriteConfirmDialog.js +253 -0
  66. package/dist/shared/assistant/ui/AssistantWriteProposalCard.d.ts +72 -0
  67. package/dist/shared/assistant/ui/AssistantWriteProposalCard.d.ts.map +1 -0
  68. package/dist/shared/assistant/ui/AssistantWriteProposalCard.js +439 -0
  69. package/dist/shared/assistant/ui/AssistantWriteProposalSlot.d.ts +40 -0
  70. package/dist/shared/assistant/ui/AssistantWriteProposalSlot.d.ts.map +1 -0
  71. package/dist/shared/assistant/ui/AssistantWriteProposalSlot.js +35 -0
  72. package/dist/shared/assistant/ui/composer/AssistantComposer.js +8 -8
  73. package/dist/shared/assistant/ui/useVoiceSession.d.ts +28 -0
  74. package/dist/shared/assistant/ui/useVoiceSession.d.ts.map +1 -1
  75. package/dist/shared/assistant/ui/useVoiceSession.js +159 -110
  76. package/dist/shared/assistant/ui/useWriteProposalConfirm.d.ts +61 -0
  77. package/dist/shared/assistant/ui/useWriteProposalConfirm.d.ts.map +1 -0
  78. package/dist/shared/assistant/ui/useWriteProposalConfirm.js +109 -0
  79. package/dist/shared/assistant/ui/useWriteProposals.d.ts +102 -0
  80. package/dist/shared/assistant/ui/useWriteProposals.d.ts.map +1 -0
  81. package/dist/shared/assistant/ui/useWriteProposals.js +230 -0
  82. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +17 -1
  83. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts.map +1 -1
  84. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +141 -109
  85. package/dist/shared/assistant/ui/writeProposalPresentation.d.ts +76 -0
  86. package/dist/shared/assistant/ui/writeProposalPresentation.d.ts.map +1 -0
  87. package/dist/shared/assistant/ui/writeProposalPresentation.js +110 -0
  88. package/dist/shared/assistant/usageReporting.d.ts +108 -0
  89. package/dist/shared/assistant/usageReporting.d.ts.map +1 -0
  90. package/dist/shared/assistant/usageReporting.js +155 -0
  91. package/dist/shared/assistant/useAssistantApiAccess.d.ts +49 -14
  92. package/dist/shared/assistant/useAssistantApiAccess.d.ts.map +1 -1
  93. package/dist/shared/assistant/useAssistantApiAccess.js +43 -25
  94. package/dist/shared/assistant/useAssistantHeartbeat.d.ts.map +1 -1
  95. package/dist/shared/assistant/useAssistantHeartbeat.js +5 -5
  96. package/dist/shared/assistant/useWorkspaceWriteAccess.d.ts +5 -6
  97. package/dist/shared/assistant/useWorkspaceWriteAccess.d.ts.map +1 -1
  98. package/dist/shared/assistant/voice/voiceSession.d.ts +46 -0
  99. package/dist/shared/assistant/voice/voiceSession.d.ts.map +1 -1
  100. package/dist/shared/assistant/voice/voiceSession.js +35 -2
  101. package/dist/shared/assistant/writeConfirmSeam.d.ts +32 -0
  102. package/dist/shared/assistant/writeConfirmSeam.d.ts.map +1 -0
  103. package/dist/shared/assistant/writeConfirmSeam.js +23 -0
  104. package/dist/shared/assistant/writeModeConsent.d.ts +16 -8
  105. package/dist/shared/assistant/writeModeConsent.d.ts.map +1 -1
  106. package/dist/shared/assistant/writeModeConsent.js +2 -2
  107. package/dist/shared/assistant/writeProposalDiscovery.d.ts +123 -0
  108. package/dist/shared/assistant/writeProposalDiscovery.d.ts.map +1 -0
  109. package/dist/shared/assistant/writeProposalDiscovery.js +210 -0
  110. package/dist/shared/assistant/writeProposalErrorCopy.d.ts +135 -0
  111. package/dist/shared/assistant/writeProposalErrorCopy.d.ts.map +1 -0
  112. package/dist/shared/assistant/writeProposalErrorCopy.js +135 -0
  113. package/dist/shared/assistant/writeProposalVoice.d.ts +133 -0
  114. package/dist/shared/assistant/writeProposalVoice.d.ts.map +1 -0
  115. package/dist/shared/assistant/writeProposalVoice.js +66 -0
  116. package/dist/shared/assistant/writeProposals.d.ts +268 -0
  117. package/dist/shared/assistant/writeProposals.d.ts.map +1 -0
  118. package/dist/shared/assistant/writeProposals.js +445 -0
  119. package/dist/shared/assistant/writeReplyBinder.d.ts +166 -0
  120. package/dist/shared/assistant/writeReplyBinder.d.ts.map +1 -0
  121. package/dist/shared/assistant/writeReplyBinder.js +233 -0
  122. package/dist/shared/assistant/writeReplySend.d.ts +110 -0
  123. package/dist/shared/assistant/writeReplySend.d.ts.map +1 -0
  124. package/dist/shared/assistant/writeReplySend.js +93 -0
  125. package/dist/shared/graphql/fetch.d.ts +12 -1
  126. package/dist/shared/graphql/fetch.d.ts.map +1 -1
  127. package/dist/shared/graphql/fetch.js +101 -80
  128. package/dist/shared/providers/shell/ActiveContextProvider.d.ts.map +1 -1
  129. package/dist/shared/providers/shell/ActiveContextProvider.js +28 -26
  130. package/dist/shared/providers/shell/PersonaSurfaceProvider.d.ts.map +1 -1
  131. package/dist/shared/providers/shell/PersonaSurfaceProvider.js +165 -193
  132. package/dist/shared/providers/shell/personaSurfaceRemote.d.ts +8 -2
  133. package/dist/shared/providers/shell/personaSurfaceRemote.d.ts.map +1 -1
  134. package/dist/shared/providers/shell/personaSurfaceRemote.js +37 -15
  135. package/dist/shared/providers/shell/useRemoteNavPreferences.d.ts +30 -0
  136. package/dist/shared/providers/shell/useRemoteNavPreferences.d.ts.map +1 -0
  137. package/dist/shared/providers/shell/useRemoteNavPreferences.js +43 -0
  138. package/dist/shared-assistant.js +167 -152
  139. package/dist/ui/modal-shell.d.ts +14 -1
  140. package/dist/ui/modal-shell.d.ts.map +1 -1
  141. package/dist/ui/modal-shell.js +8 -6
  142. package/package.json +2 -2
@@ -0,0 +1,76 @@
1
+ import { AssistantTr } from '../i18n';
2
+ import { SandboxWriteCapabilities, WriteProposalRiskKind, WriteProposalRootField, WriteProposalView } from '../writeProposals';
3
+ /**
4
+ * What a write proposal shows, and when it may be confirmed (BOFF-7803 5a).
5
+ * Shared by the card (FE4) and the confirmation dialog (FE5), so the two
6
+ * surfaces cannot drift: the dialog shows exactly the values, masking and
7
+ * countdown the card showed, and offers a confirm under exactly the same rule.
8
+ *
9
+ * ★★ 5a is a safety floor, not the final security boundary. Nothing here
10
+ * authorises a change. The issuing sandbox and wspace-sandbox-svc decide; these
11
+ * helpers only decide what a person is SHOWN and whether a press is OFFERED.
12
+ */
13
+ /** What a hidden value looks like. */
14
+ export declare const WRITE_PROPOSAL_MASK = "\u2022\u2022\u2022\u2022\u2022\u2022";
15
+ /** A value as the card writes it: a string as-is, anything else as JSON. */
16
+ export declare function formatWriteProposalValue(value: unknown): string;
17
+ /**
18
+ * The text of every sensitive value in the proposal. A gateway error can echo
19
+ * a variable's value ("got invalid value …"), so free text from the record is
20
+ * scrubbed of these before it is shown.
21
+ */
22
+ export declare function writeProposalSensitiveTexts(view: WriteProposalView): string[];
23
+ /**
24
+ * `text` with every one of `secrets` replaced by the mask: a long one wherever
25
+ * it appears, a short one where it stands alone. Pass the secrets longest
26
+ * first (`writeProposalSensitiveTexts` does), so a longer value is masked
27
+ * whole before a shorter one inside it is looked for. A blank one is skipped.
28
+ */
29
+ export declare function redactWriteProposalText(text: string, secrets: readonly string[]): string;
30
+ /** A risk kind in words, or null for one that says nothing a person can act on. */
31
+ export declare function writeProposalKindText(kind: WriteProposalRiskKind, tr: AssistantTr): string | null;
32
+ /** Which data the change touches, in words. */
33
+ export declare function writeProposalGatewayText(view: WriteProposalView, tr: AssistantTr): string;
34
+ /** One value a surface shows, keyed so a revision can be compared with it. */
35
+ export interface WriteProposalShownValue {
36
+ key: string;
37
+ label: string;
38
+ value: unknown;
39
+ sensitive: boolean;
40
+ }
41
+ /** A root field as written in the document: `alias: field`, or `field`. */
42
+ export declare function writeProposalRootFieldName(field: Pick<WriteProposalRootField, "alias" | "field">): string;
43
+ /** A root field's arguments, as the values that will be sent. */
44
+ export declare function writeProposalArgumentValues(field: WriteProposalRootField): WriteProposalShownValue[];
45
+ /** The operation's variables, as the values that will be sent. */
46
+ export declare function writeProposalVariableValues(view: WriteProposalView): WriteProposalShownValue[];
47
+ /** "Expires in 4:59", or, under reduced motion, words that move once a minute. */
48
+ export declare function writeProposalCountdownText(remainingMs: number, reducedMotion: boolean, tr: AssistantTr): string;
49
+ /**
50
+ * How long until `expiresAt`, on the ISSUING sandbox's clock.
51
+ *
52
+ * `serverNow` is that sandbox's clock when the record was read
53
+ * (`list().serverNow`); the difference from this device's clock is measured
54
+ * again whenever a fresh read arrives. While `ticking`, the value moves once a
55
+ * second.
56
+ */
57
+ export declare function useWriteProposalRemainingMs(expiresAt: number, serverNow: number, ticking: boolean): number;
58
+ /** Whether a proposal's controls, and its confirm, may be offered. */
59
+ export interface WriteProposalConfirmState {
60
+ /** The issuing sandbox speaks the v1 protocol and enforces it. */
61
+ available: boolean;
62
+ /** Execution is not enabled for this proposal or this sandbox (until 5b). */
63
+ fenced: boolean;
64
+ /** Pending, bound and on a v1 sandbox: Cancel (and maybe confirm) is shown. */
65
+ showControls: boolean;
66
+ /** A confirm press may be offered at all. */
67
+ offerConfirm: boolean;
68
+ }
69
+ /**
70
+ * The one rule both surfaces use to decide what to OFFER. It authorises
71
+ * nothing: the sandbox and wspace-sandbox-svc refuse anything this lets
72
+ * through that they would not run. An unknown sandbox is not available and an
73
+ * unknown execution state is fenced, so every doubt removes the button.
74
+ */
75
+ export declare function writeProposalConfirmState(view: WriteProposalView, capabilities: SandboxWriteCapabilities | null | undefined): WriteProposalConfirmState;
76
+ //# sourceMappingURL=writeProposalPresentation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writeProposalPresentation.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/writeProposalPresentation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EACV,wBAAwB,EACxB,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;GASG;AAEH,sCAAsC;AACtC,eAAO,MAAM,mBAAmB,yCAAW,CAAC;AAY5C,4EAA4E;AAC5E,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQ/D;AAkBD;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAW7E;AAqBD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,MAAM,CAUR;AAED,mFAAmF;AACnF,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,qBAAqB,EAC3B,EAAE,EAAE,WAAW,GACd,MAAM,GAAG,IAAI,CAkBf;AAED,+CAA+C;AAC/C,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,iBAAiB,EACvB,EAAE,EAAE,WAAW,GACd,MAAM,CAIR;AAED,8EAA8E;AAC9E,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,2EAA2E;AAC3E,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,IAAI,CAAC,sBAAsB,EAAE,OAAO,GAAG,OAAO,CAAC,GACrD,MAAM,CAER;AAED,iEAAiE;AACjE,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,sBAAsB,GAC5B,uBAAuB,EAAE,CAQ3B;AAED,kEAAkE;AAClE,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,iBAAiB,GACtB,uBAAuB,EAAE,CAO3B;AAED,kFAAkF;AAClF,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,OAAO,EACtB,EAAE,EAAE,WAAW,GACd,MAAM,CAeR;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,GACf,MAAM,CAmBR;AAED,sEAAsE;AACtE,MAAM,WAAW,yBAAyB;IACxC,kEAAkE;IAClE,SAAS,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,MAAM,EAAE,OAAO,CAAC;IAChB,+EAA+E;IAC/E,YAAY,EAAE,OAAO,CAAC;IACtB,6CAA6C;IAC7C,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,iBAAiB,EACvB,YAAY,EAAE,wBAAwB,GAAG,IAAI,GAAG,SAAS,GACxD,yBAAyB,CAY3B"}
@@ -0,0 +1,110 @@
1
+ import { useEffect as e, useState as t } from "react";
2
+ //#region src/shared/assistant/ui/writeProposalPresentation.ts
3
+ var n = "••••••", r = 4, i = /[\p{L}\p{N}]/u;
4
+ function a(e) {
5
+ if (typeof e == "string") return e === "" ? "\"\"" : e;
6
+ if (e === void 0) return "null";
7
+ try {
8
+ return JSON.stringify(e) ?? String(e);
9
+ } catch {
10
+ return String(e);
11
+ }
12
+ }
13
+ function o(e, t) {
14
+ if (e != null) {
15
+ if (Array.isArray(e)) {
16
+ for (let n of e) o(n, t);
17
+ return;
18
+ }
19
+ if (typeof e == "object") {
20
+ for (let n of Object.values(e)) o(n, t);
21
+ return;
22
+ }
23
+ t.push(String(e));
24
+ }
25
+ }
26
+ function s(e) {
27
+ let t = [];
28
+ for (let n of e.description.rootFields) for (let e of n.args) e.sensitive && o(e.value, t);
29
+ for (let n of e.description.variables) n.sensitive && o(n.value, t);
30
+ return [...new Set(t)].filter((e) => e.trim().length > 0).sort((e, t) => t.length - e.length);
31
+ }
32
+ function c(e, t) {
33
+ let r = "", a = 0, o = e.indexOf(t);
34
+ for (; o !== -1;) {
35
+ let s = o + t.length, c = !i.test(e.charAt(o - 1)) && !i.test(e.charAt(s));
36
+ c && (r += e.slice(a, o) + n, a = s), o = e.indexOf(t, c ? s : o + 1);
37
+ }
38
+ return r + e.slice(a);
39
+ }
40
+ function l(e, t) {
41
+ let i = e;
42
+ for (let e of t) e.trim() && (i = e.length >= r ? i.split(e).join(n) : c(i, e));
43
+ return i;
44
+ }
45
+ function u(e, t) {
46
+ switch (e) {
47
+ case "destructive": return t("writeProposal.kind.destructive", "Deletes data");
48
+ case "financial": return t("writeProposal.kind.financial", "Involves money");
49
+ case "bulk": return t("writeProposal.kind.bulk", "Changes several items");
50
+ case "permission": return t("writeProposal.kind.permission", "Changes access");
51
+ case "credential": return t("writeProposal.kind.credential", "Touches credentials");
52
+ case "irreversible": return t("writeProposal.kind.irreversible", "Can't be undone");
53
+ case "unclassified": return null;
54
+ }
55
+ }
56
+ function d(e, t) {
57
+ return e.gateway === "global" ? t("writeProposal.gateway.global", "Account and organization data") : t("writeProposal.gateway.workspace", "Workspace data");
58
+ }
59
+ function f(e) {
60
+ return e.alias ? `${e.alias}: ${e.field}` : e.field;
61
+ }
62
+ function p(e) {
63
+ let t = e.alias ?? e.field;
64
+ return e.args.map((e) => ({
65
+ key: `arg:${t}.${e.name}`,
66
+ label: e.name,
67
+ value: e.value,
68
+ sensitive: e.sensitive
69
+ }));
70
+ }
71
+ function m(e) {
72
+ return e.description.variables.map((e) => ({
73
+ key: `var:${e.path}`,
74
+ label: e.path,
75
+ value: e.value,
76
+ sensitive: e.sensitive
77
+ }));
78
+ }
79
+ function h(e, t, n) {
80
+ if (t) return e < 6e4 ? n("writeProposal.expiresSoon", "Expires in under a minute") : n("writeProposal.expiresInAbout", "Expires in about {{minutes}} min", { minutes: Math.ceil(e / 6e4) });
81
+ let r = Math.ceil(e / 1e3);
82
+ return n("writeProposal.expiresIn", "Expires in {{time}}", { time: `${Math.floor(r / 60)}:${String(r % 60).padStart(2, "0")}` });
83
+ }
84
+ function g(n, r, i) {
85
+ let [a, o] = t(() => ({
86
+ serverNow: r,
87
+ offset: Number.isFinite(r) ? r - Date.now() : 0
88
+ })), s = a.offset;
89
+ Object.is(a.serverNow, r) || (s = Number.isFinite(r) ? r - Date.now() : 0, o({
90
+ serverNow: r,
91
+ offset: s
92
+ }));
93
+ let [c, l] = t(() => Date.now());
94
+ return e(() => {
95
+ if (!i) return;
96
+ let e = setInterval(() => l(Date.now()), 1e3);
97
+ return () => clearInterval(e);
98
+ }, [i]), n - (c + s);
99
+ }
100
+ function _(e, t) {
101
+ let n = t?.proposals === !0 && t.writeApprovalMode === "proposal-v1", r = e.execution.enabled !== !0 || t?.writeExecution !== "enabled", i = e.status === "pending" && e.approvable && n;
102
+ return {
103
+ available: n,
104
+ fenced: r,
105
+ showControls: i,
106
+ offerConfirm: i && !r && e.allowedMethods.includes("button")
107
+ };
108
+ }
109
+ //#endregion
110
+ export { n as WRITE_PROPOSAL_MASK, a as formatWriteProposalValue, l as redactWriteProposalText, g as useWriteProposalRemainingMs, p as writeProposalArgumentValues, _ as writeProposalConfirmState, h as writeProposalCountdownText, d as writeProposalGatewayText, u as writeProposalKindText, f as writeProposalRootFieldName, s as writeProposalSensitiveTexts, m as writeProposalVariableValues };
@@ -0,0 +1,108 @@
1
+ import { AssistantSendRefusal } from './turnOutcome';
2
+ /** One finished turn's charge, as a product's `reportTokenUsage` receives it. */
3
+ export interface UsageReport {
4
+ workspaceId: string;
5
+ sessionId: string;
6
+ messageId?: string;
7
+ model?: string;
8
+ tokens: {
9
+ input: number;
10
+ output: number;
11
+ };
12
+ }
13
+ /** Sends one report to its ledger. Rejects when the ledger did not record it. */
14
+ export type UsageReporter = (report: UsageReport) => Promise<void>;
15
+ /**
16
+ * Why a report could not be recorded.
17
+ *
18
+ * - `permission`: the ledger refused this person (HTTP 403, or a FORBIDDEN /
19
+ * UNAUTHORIZED / PERMISSION_DENIED code). Retrying will not help until their
20
+ * role, or the ledger's rule, changes.
21
+ * - `unavailable`: anything else — a network drop, a timeout, a 5xx. Trying
22
+ * again can succeed.
23
+ */
24
+ export type UsageReportFailureKind = "permission" | "unavailable";
25
+ /** Set while at least one report is held: the assistant is paused. */
26
+ export interface UsageBlock {
27
+ readonly kind: UsageReportFailureKind;
28
+ }
29
+ export type UsageReportResult = {
30
+ readonly ok: true;
31
+ } | {
32
+ readonly ok: false;
33
+ readonly kind: UsageReportFailureKind;
34
+ };
35
+ export interface UsageReportingOptions {
36
+ /**
37
+ * Which ledger the report belongs to — see `assistantUsageLedger`. A held
38
+ * report is only ever retried through the reporter of its own ledger.
39
+ */
40
+ ledger?: string;
41
+ /** Waits between attempts. Defaults to `usageReportClock.sleep`. */
42
+ sleep?: (ms: number) => Promise<void>;
43
+ }
44
+ /** When each attempt starts, measured from the previous one's failure. */
45
+ export declare const USAGE_REPORT_RETRY_DELAYS_MS: readonly number[];
46
+ /**
47
+ * Dispatched on `window` when a report is given up on and the assistant pauses.
48
+ * The detail is the failure kind ONLY: no workspace, session, message or token.
49
+ */
50
+ export declare const USAGE_REPORT_FAILED_EVENT = "assistant.usage_report_failed";
51
+ export interface UsageReportFailedDetail {
52
+ readonly kind: UsageReportFailureKind;
53
+ }
54
+ /**
55
+ * The wait between attempts, as a property read at call time so a test can
56
+ * replace it (`spyOn(usageReportClock, "sleep")`) without waiting 4 s.
57
+ */
58
+ export declare const usageReportClock: {
59
+ sleep(ms: number): Promise<void>;
60
+ };
61
+ /**
62
+ * The ledger a charge site writes to.
63
+ *
64
+ * ★ Two sites, two ledgers, even within one product: the transport always
65
+ * charges through the shared `reportAiTokenUsage`, while the panel charges
66
+ * through the product's own seam (HealthyBowl's is a different mutation on a
67
+ * different row). A report held by one must never be retried through the
68
+ * other, or it would be billed to the wrong ledger.
69
+ */
70
+ export declare function assistantUsageLedger(source: "panel" | "transport", product: string): string;
71
+ /** Where a ledger's held reports are mirrored for this tab. */
72
+ export declare function usagePendingStorageKey(ledger: string, workspaceId: string): string;
73
+ /**
74
+ * Classify a failed report.
75
+ *
76
+ * ★ Decided by what the failure IS — an HTTP status or a GraphQL code — never
77
+ * by matching its words.
78
+ */
79
+ export declare function classifyUsageReportFailure(error: unknown): UsageReportFailureKind;
80
+ /**
81
+ * Send one report, retrying at 0 s, 1 s and 3 s.
82
+ *
83
+ * Never rejects. When every attempt fails, the report is held, the assistant is
84
+ * paused (`getUsageBlock`), and the result says why — the next send must call
85
+ * `retryPendingUsageReports` first and is refused while that still fails.
86
+ */
87
+ export declare function reportUsageWithRetry(report: UsageReport, fn: UsageReporter, options?: UsageReportingOptions): Promise<UsageReportResult>;
88
+ /** Whether any report is held for this ledger and workspace. */
89
+ export declare function hasPendingUsageReports(ledger: string, workspaceId: string): boolean;
90
+ /** Why the assistant is paused for this ledger and workspace, or null. */
91
+ export declare function getUsageBlock(ledger: string, workspaceId: string): UsageBlock | null;
92
+ /**
93
+ * Retry every held report once, oldest first, before a send.
94
+ *
95
+ * Resolves `ok` when nothing is held any more — the send may go ahead. Stops at
96
+ * the first report that still fails: the rest would meet the same refusal, and
97
+ * each attempt is a request.
98
+ */
99
+ export declare function retryPendingUsageReports(ledger: string, workspaceId: string, fn: UsageReporter): Promise<UsageReportResult>;
100
+ /**
101
+ * The refusal a send gets while a report is still held.
102
+ *
103
+ * Thrown as an `AssistantSendRefusal`, so the panel says it in the reader's
104
+ * language (`outcome.usageNotPermitted` / `outcome.usageNotRecorded`) and a
105
+ * widget that shows `error.message` shows the same English.
106
+ */
107
+ export declare function usageSendRefusal(kind: UsageReportFailureKind): AssistantSendRefusal;
108
+ //# sourceMappingURL=usageReporting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usageReporting.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/usageReporting.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAGrD,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAED,iFAAiF;AACjF,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnE;;;;;;;;GAQG;AACH,MAAM,MAAM,sBAAsB,GAAG,YAAY,GAAG,aAAa,CAAC;AAElE,sEAAsE;AACtE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;CACvC;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GACrB;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAA;CAAE,CAAC;AAElE,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,0EAA0E;AAC1E,eAAO,MAAM,4BAA4B,EAAE,SAAS,MAAM,EAEzD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,yBAAyB,kCAAkC,CAAC;AAEzE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;CACvC;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB;cACjB,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGjC,CAAC;AAMF;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,OAAO,GAAG,WAAW,EAC7B,OAAO,EAAE,MAAM,GACd,MAAM,CAER;AAED,+DAA+D;AAC/D,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,MAAM,CAER;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,GACb,sBAAsB,CAmBxB;AA0KD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,WAAW,EACnB,EAAE,EAAE,aAAa,EACjB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,iBAAiB,CAAC,CAuB5B;AAED,gEAAgE;AAChE,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAET;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,UAAU,GAAG,IAAI,CAGnB;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,aAAa,GAChB,OAAO,CAAC,iBAAiB,CAAC,CAwB5B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,sBAAsB,GAC3B,oBAAoB,CAUtB"}
@@ -0,0 +1,155 @@
1
+ import { extensionObjectsIn as e } from "./quota.js";
2
+ import { TURN_OUTCOME_COPY as t } from "./turnOutcomeCopy.js";
3
+ import { AssistantSendRefusal as n } from "./turnOutcome.js";
4
+ //#region src/shared/assistant/usageReporting.ts
5
+ var r = [
6
+ 0,
7
+ 1e3,
8
+ 3e3
9
+ ], i = "assistant.usage_report_failed", a = { sleep(e) {
10
+ return new Promise((t) => setTimeout(t, e));
11
+ } }, o = Object.freeze({ ok: !0 }), s = "default", c = "bf-assistant:usage-pending:v1:";
12
+ function l(e, t) {
13
+ return `${e}:${t}`;
14
+ }
15
+ function u(e, t) {
16
+ return `${c}${encodeURIComponent(e)}:${encodeURIComponent(t)}`;
17
+ }
18
+ function d(t) {
19
+ if (f(t)) return "permission";
20
+ for (let n of e(t)) {
21
+ let e = n.code;
22
+ if (e === "FORBIDDEN" || e === "UNAUTHORIZED" || e === "PERMISSION_DENIED") return "permission";
23
+ let t = n.http;
24
+ if (t && typeof t == "object" && t.status === 403) return "permission";
25
+ }
26
+ return "unavailable";
27
+ }
28
+ function f(e) {
29
+ return !e || typeof e != "object" ? !1 : [
30
+ e,
31
+ e.networkError,
32
+ e.response
33
+ ].some((e) => {
34
+ if (!e || typeof e != "object") return !1;
35
+ let { status: t, statusCode: n } = e;
36
+ return t === 403 || n === 403;
37
+ });
38
+ }
39
+ var p = /* @__PURE__ */ new Map(), m = /* @__PURE__ */ new Map(), h = (e, t) => `${e}\u0000${t}`, g = (e) => `${e.sessionId}\u0000${e.messageId ?? ""}`;
40
+ function _() {
41
+ try {
42
+ return typeof window > "u" ? null : window.sessionStorage ?? null;
43
+ } catch {
44
+ return null;
45
+ }
46
+ }
47
+ var v = (e) => typeof e == "number" && Number.isFinite(e) && e >= 0, y = (e) => e === void 0 || typeof e == "string";
48
+ function b(e, t) {
49
+ if (!e || typeof e != "object") return null;
50
+ let n = e, r = n.tokens;
51
+ return n.workspaceId !== t || typeof n.sessionId != "string" || n.sessionId.length === 0 || !y(n.messageId) || !y(n.model) || !r || typeof r != "object" || !v(r.input) || !v(r.output) ? null : {
52
+ workspaceId: t,
53
+ sessionId: n.sessionId,
54
+ ...typeof n.messageId == "string" ? { messageId: n.messageId } : {},
55
+ ...typeof n.model == "string" ? { model: n.model } : {},
56
+ tokens: {
57
+ input: r.input,
58
+ output: r.output
59
+ }
60
+ };
61
+ }
62
+ function x(e, t) {
63
+ let n = {
64
+ kind: "unavailable",
65
+ reports: /* @__PURE__ */ new Map()
66
+ };
67
+ try {
68
+ let r = _()?.getItem(u(e, t));
69
+ if (!r) return n;
70
+ let i = JSON.parse(r);
71
+ if (i?.v !== 1 || !Array.isArray(i.reports)) return n;
72
+ i.kind === "permission" && (n.kind = "permission");
73
+ for (let e of i.reports) {
74
+ let r = b(e, t);
75
+ r && n.reports.set(g(r), r);
76
+ }
77
+ } catch {}
78
+ return n;
79
+ }
80
+ function S(e, t) {
81
+ let n = h(e, t), r = p.get(n);
82
+ return r || (r = x(e, t), p.set(n, r)), r;
83
+ }
84
+ function C(e, t, n) {
85
+ try {
86
+ let r = _();
87
+ if (!r) return;
88
+ let i = u(e, t);
89
+ if (n.reports.size === 0) {
90
+ r.removeItem(i);
91
+ return;
92
+ }
93
+ r.setItem(i, JSON.stringify({
94
+ v: 1,
95
+ kind: n.kind,
96
+ reports: [...n.reports.values()]
97
+ }));
98
+ } catch {}
99
+ }
100
+ function w(e) {
101
+ try {
102
+ if (console.error("[assistant] a turn's usage could not be recorded; the assistant is paused until it is", { kind: e }), typeof window > "u" || typeof CustomEvent != "function") return;
103
+ window.dispatchEvent(new CustomEvent(i, { detail: { kind: e } }));
104
+ } catch {}
105
+ }
106
+ async function T(e, t, n = {}) {
107
+ let i = n.ledger ?? s, c = n.sleep ?? ((e) => a.sleep(e)), l = "unavailable";
108
+ for (let n of r) {
109
+ n > 0 && await c(n);
110
+ try {
111
+ await t(e);
112
+ let n = S(i, e.workspaceId);
113
+ return n.reports.delete(g(e)) && C(i, e.workspaceId, n), o;
114
+ } catch (e) {
115
+ l = d(e);
116
+ }
117
+ }
118
+ let u = S(i, e.workspaceId);
119
+ return u.reports.set(g(e), e), u.kind = l, C(i, e.workspaceId, u), w(l), {
120
+ ok: !1,
121
+ kind: l
122
+ };
123
+ }
124
+ function E(e, t) {
125
+ return S(e, t).reports.size > 0;
126
+ }
127
+ function D(e, t) {
128
+ let n = S(e, t);
129
+ return n.reports.size > 0 ? { kind: n.kind } : null;
130
+ }
131
+ function O(e, t, n) {
132
+ let r = h(e, t), i = m.get(r);
133
+ if (i) return i;
134
+ let a = (async () => {
135
+ let r = S(e, t);
136
+ for (let [i, a] of [...r.reports]) try {
137
+ await n(a), r.reports.delete(i);
138
+ } catch (n) {
139
+ return r.kind = d(n), C(e, t, r), {
140
+ ok: !1,
141
+ kind: r.kind
142
+ };
143
+ }
144
+ return C(e, t, r), r.reports.size === 0 ? o : {
145
+ ok: !1,
146
+ kind: r.kind
147
+ };
148
+ })().finally(() => m.delete(r));
149
+ return m.set(r, a), a;
150
+ }
151
+ function k(e) {
152
+ return e === "permission" ? new n("usage-not-permitted", t.usageNotPermitted.fallback) : new n("usage-not-recorded", t.usageNotRecorded.fallback);
153
+ }
154
+ //#endregion
155
+ export { i as USAGE_REPORT_FAILED_EVENT, r as USAGE_REPORT_RETRY_DELAYS_MS, l as assistantUsageLedger, d as classifyUsageReportFailure, D as getUsageBlock, E as hasPendingUsageReports, T as reportUsageWithRetry, O as retryPendingUsageReports, u as usagePendingStorageKey, a as usageReportClock, k as usageSendRefusal };
@@ -1,23 +1,58 @@
1
1
  /**
2
- * Resolves whether the current user may use the write-capable `api-calls`
3
- * assistant mode.
2
+ * Resolves whether the current user may use an ADMIN-ONLY assistant mode: a
3
+ * mode a product declares with `requiresAdmin` (today only FluidGrids'
4
+ * `fluidgrids-node`).
4
5
  *
5
- * That mode mints a per-sandbox OAuth app under the caller's identity
6
- * (createApp/createApplication in wspace-sandbox-svc), which is RBAC-gated to a
7
- * global Owner/Admin — a non-admin would only discover this as a FORBIDDEN at
8
- * provision time. So we gate the UI on the same signal up front, via the global
9
- * gateway's `myRoles(scopeId)` query (`@rbac(public: true)`, auth-only, returns
10
- * `isAdmin`/`isOwner` directly — no extra provider wiring needed).
6
+ * ★★ WORKSPACE-scoped, the same question the server asks (OD-2, BOFF-7803 /
7
+ * BOFF-7800). wspace-sandbox-svc refuses an admin-only mode unless
8
+ * `checkPermission` grants `sandbox:admin` at the WORKSPACE scope
9
+ * (`SandboxProvider.assertAssistantModeAllowed`): Workspace Owner and Workspace
10
+ * Admin pass; Editor, Viewer and Guest do not. This hook used to ask
11
+ * `myRoles` at ORG scope, which is a different question with different
12
+ * answers: an org admin who is only a member of this workspace was offered the
13
+ * mode and then refused when it provisioned, and a workspace admin who is not
14
+ * an org admin was never offered it at all.
11
15
  *
12
- * Fails CLOSED: an error, an empty org scope, or the master flag being off all
13
- * resolve to `canUseApiCalls = false`, so the mode stays hidden unless the user
14
- * is provably an org admin.
16
+ * So it asks the workspace gateway's `checkPermissions` for exactly that pair,
17
+ * for the signed-in user in this workspace. The resolver only answers for the
18
+ * caller's own actor id in the workspace the request is scoped to, which is why
19
+ * the request carries `workspaceId` explicitly and the actor is the user's own
20
+ * id (the token's `sub`).
21
+ *
22
+ * ★ It is a UI gate, not the authority. The server re-checks on every
23
+ * provisioning; this only keeps the mode out of the list for someone the server
24
+ * would refuse, so they are not offered a mode that can only fail.
25
+ *
26
+ * Fails CLOSED: no workspace, no user, a transport error, a GraphQL error, an
27
+ * empty or malformed answer, anything but a single `allowed: true` — all
28
+ * resolve to `canUseApiCalls = false`. An answer is also only ever used for the
29
+ * workspace and user it was asked about: after a switch the hook reports
30
+ * `loading` (and `false`) until the new answer lands, never the previous
31
+ * workspace's yes.
32
+ *
33
+ * ★ It runs only when the product declares an admin-only mode. A product with
34
+ * none has nothing to gate, and no query is sent.
35
+ */
36
+ /** The server's own pair: `sandbox:admin` (see the header). */
37
+ export declare const ASSISTANT_ADMIN_RESOURCE_TYPE = "sandbox";
38
+ export declare const ASSISTANT_ADMIN_ACTION = "admin";
39
+ export declare const WORKSPACE_ASSISTANT_ADMIN_QUERY = "query AssistantWorkspaceAdmin($inputs: [PermissionCheckInput!]!) {\n checkPermissions(inputs: $inputs) {\n allowed\n }\n}";
40
+ /**
41
+ * Asks whether `userId` holds `sandbox:admin` in `workspaceId`.
42
+ *
43
+ * Resolves `true` only for a clean answer of exactly one `allowed: true`;
44
+ * every other outcome, including a thrown error, resolves `false`. Never
45
+ * rejects.
15
46
  */
47
+ export declare function probeWorkspaceAssistantAdmin(workspaceId: string, userId: string): Promise<boolean>;
16
48
  export interface AssistantApiAccess {
17
- /** True only for a confirmed global Owner/Admin (and when the mode is enabled). */
49
+ /**
50
+ * True only for a confirmed workspace admin (`sandbox:admin` in this
51
+ * workspace), and only when the product declares an admin-only mode.
52
+ */
18
53
  canUseApiCalls: boolean;
19
- /** True while the role check is in flight. */
54
+ /** True while the check for the CURRENT workspace and user is in flight. */
20
55
  loading: boolean;
21
56
  }
22
- export declare function useAssistantApiAccess(scopeId: string): AssistantApiAccess;
57
+ export declare function useAssistantApiAccess(workspaceId: string, userId: string | null): AssistantApiAccess;
23
58
  //# sourceMappingURL=useAssistantApiAccess.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAssistantApiAccess.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/useAssistantApiAccess.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAiBH,MAAM,WAAW,kBAAkB;IACjC,mFAAmF;IACnF,cAAc,EAAE,OAAO,CAAC;IACxB,8CAA8C;IAC9C,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,CAkDzE"}
1
+ {"version":3,"file":"useAssistantApiAccess.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/useAssistantApiAccess.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAMH,+DAA+D;AAC/D,eAAO,MAAM,6BAA6B,YAAY,CAAC;AACvD,eAAO,MAAM,sBAAsB,UAAU,CAAC;AAE9C,eAAO,MAAM,+BAA+B,mIAI1C,CAAC;AAMH;;;;;;GAMG;AACH,wBAAsB,4BAA4B,CAChD,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CAiClB;AAED,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAC;CAClB;AAQD,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,kBAAkB,CAgCpB"}
@@ -3,35 +3,53 @@ import "../../shared-graphql.js";
3
3
  import { useAssistantProduct as t } from "./product.js";
4
4
  import { useEffect as n, useState as r } from "react";
5
5
  //#region src/shared/assistant/useAssistantApiAccess.ts
6
- var i = "query AssistantMyRoles($scopeId: String!) {\n myRoles(scopeId: $scopeId) {\n isAdmin\n isOwner\n }\n}";
7
- function a(a) {
8
- let { modes: o } = t(), s = o.some((e) => e.requiresAdmin) && !!a, [c, l] = r(!1), [u, d] = r(s);
9
- return n(() => {
10
- if (!s) {
11
- l(!1), d(!1);
12
- return;
13
- }
14
- let t = !1;
15
- return d(!0), e({
16
- gateway: "global",
17
- query: i,
18
- variables: { scopeId: a },
6
+ var i = "sandbox", a = "admin", o = "query AssistantWorkspaceAdmin($inputs: [PermissionCheckInput!]!) {\n checkPermissions(inputs: $inputs) {\n allowed\n }\n}";
7
+ async function s(t, n) {
8
+ if (!t || !n) return !1;
9
+ try {
10
+ let r = await e({
11
+ gateway: "workspace",
12
+ query: o,
13
+ variables: { inputs: [{
14
+ actorId: n,
15
+ actorType: "USER",
16
+ scopeId: t,
17
+ resourceType: i,
18
+ action: a
19
+ }] },
20
+ workspaceId: t,
19
21
  suppressGlobalErrorEvent: !0
20
- }).then((e) => {
21
- if (t) return;
22
- let n = e.data?.myRoles;
23
- l(!!(n?.isOwner || n?.isAdmin));
24
- }).catch(() => {
25
- t || l(!1);
26
- }).finally(() => {
27
- t || d(!1);
22
+ });
23
+ if (r.errors?.length) return !1;
24
+ let s = r.data?.checkPermissions;
25
+ return Array.isArray(s) && s.length === 1 && s[0]?.allowed === !0;
26
+ } catch {
27
+ return !1;
28
+ }
29
+ }
30
+ function c(e, i) {
31
+ let { modes: a } = t(), o = a.some((e) => e.requiresAdmin) && e && i ? JSON.stringify([e, i]) : null, [c, l] = r(null);
32
+ n(() => {
33
+ if (o === null || !i) return;
34
+ let t = !1;
35
+ return s(e, i).then((e) => {
36
+ t || l({
37
+ key: o,
38
+ allowed: e
39
+ });
28
40
  }), () => {
29
41
  t = !0;
30
42
  };
31
- }, [s, a]), {
32
- canUseApiCalls: c,
33
- loading: u
43
+ }, [
44
+ o,
45
+ e,
46
+ i
47
+ ]);
48
+ let u = o !== null && c?.key === o;
49
+ return {
50
+ canUseApiCalls: u && c.allowed,
51
+ loading: o !== null && !u
34
52
  };
35
53
  }
36
54
  //#endregion
37
- export { a as useAssistantApiAccess };
55
+ export { a as ASSISTANT_ADMIN_ACTION, i as ASSISTANT_ADMIN_RESOURCE_TYPE, o as WORKSPACE_ASSISTANT_ADMIN_QUERY, s as probeWorkspaceAssistantAdmin, c as useAssistantApiAccess };
@@ -1 +1 @@
1
- {"version":3,"file":"useAssistantHeartbeat.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/useAssistantHeartbeat.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAK7C;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,IAAI,EAAE,aAAa,GAAG,IAAI,EAC1B,MAAM,EAAE,OAAO,GACd,IAAI,CAkCN"}
1
+ {"version":3,"file":"useAssistantHeartbeat.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/useAssistantHeartbeat.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAK7C;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,IAAI,EAAE,aAAa,GAAG,IAAI,EAC1B,MAAM,EAAE,OAAO,GACd,IAAI,CAmCN"}
@@ -1,7 +1,7 @@
1
1
  import { useAuthToken as e } from "../providers/shell/AuthTokenProvider.js";
2
2
  import "../../shared-providers-shell.js";
3
- import { extendAssistantSandboxTTL as t, sendHeartbeat as n } from "./api.js";
4
- import { useAssistantStore as r } from "./store.js";
3
+ import { useAssistantStore as t } from "./store.js";
4
+ import { extendAssistantSandboxTTL as n, sendHeartbeat as r } from "./api.js";
5
5
  import { getWorkspaceId as i } from "./context.js";
6
6
  import { useEffect as a } from "react";
7
7
  //#region src/shared/assistant/useAssistantHeartbeat.ts
@@ -10,16 +10,16 @@ function s(s, c, l) {
10
10
  let { getAccessToken: u, getWorkspaceToken: d } = e();
11
11
  a(() => {
12
12
  if (!s || !c || !l) return;
13
- let e = c, a = r.getState().sandboxesByMode[e]?.sandboxId;
13
+ let e = c, a = t.getState().sandboxesByMode[e]?.sandboxId;
14
14
  if (!a) return;
15
15
  let f = i();
16
16
  if (!f) return;
17
17
  let p = () => {
18
- let r = {
18
+ let t = {
19
19
  accessToken: u(),
20
20
  workspaceToken: d()
21
21
  };
22
- Promise.all([n(a, f, s, e, r), t(a, f, 600, r)]).catch((e) => {
22
+ Promise.all([r(a, f, s, e, t), n(a, f, 600, t)]).catch((e) => {
23
23
  console.warn("[heartbeat] Failed:", e);
24
24
  });
25
25
  };