@burdenoff/fe-libs 2026.1017.1 → 2026.1017.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.
package/README.md CHANGED
@@ -21,7 +21,7 @@ This is a **Layer 1 package** - a monolithic package with subpath exports for al
21
21
 
22
22
  ```typescript
23
23
  import { Button } from '@burdenoff/fe-libs/button';
24
- import { WorkflowNode, WorkflowCanvas } from '@burdenoff/fe-libs/workflow';
24
+ import { mockProducts } from '@burdenoff/fe-libs/shared/utils/mockData';
25
25
  import { cn } from '@burdenoff/fe-libs/shared';
26
26
  ```
27
27
 
@@ -129,3 +129,27 @@ plain browser (persisted in `sessionStorage`, cleared with `off`). It is
129
129
  - TailwindCSS v4
130
130
  - Radix UI (for accessible primitives)
131
131
  - Vite 7 (for building)
132
+
133
+ ## Export migration (BOFF-9417)
134
+
135
+ Beginning with the first CalVer release containing BOFF-9417, the already
136
+ nonfunctional `@burdenoff/fe-libs/workflow` export metadata is explicitly retired. Both advertised
137
+ targets (`dist/workflow.js` and `dist/workflow.d.ts`) are absent from the verified
138
+ published 2026.1016.3 package. The former WorkflowCanvas/WorkflowNode implementation
139
+ was deliberately removed in source commit `f0920f9a` on 2026-01-15; this change does
140
+ not remove a working runtime implementation or restore that obsolete UI. Existing
141
+ published releases are unchanged. Usage outside the bounded local repository
142
+ inventory is unknown; this is not a claim that external consumers do not exist.
143
+
144
+ Current workflow-builder functionality belongs to `@burdenoff/fluidgrids-fe-sdk`
145
+ (WorkflowBuilder and WorkflowBuilderCore), not another microfrontend import. Those
146
+ APIs differ from the deleted generic canvas/node props and require an explicit
147
+ consumer migration; they are not a drop-in compatibility adapter. Consumers should
148
+ review their intended workflow behavior before choosing that API.
149
+
150
+ The existing `@burdenoff/fe-libs/shared/utils/mockData` subpath is retained. Its five
151
+ fixture arrays now have an explicit runtime build entry alongside their declarations.
152
+ The archive verifier checks literal export/bin targets in the actual npm tar before
153
+ publication; wildcard export patterns and universal consumer compatibility are not
154
+ certified by that existence check. Normal release automation assigns the concrete
155
+ CalVer version; this source note does not claim publication or host adoption.
@@ -1,13 +1,5 @@
1
- /**
2
- * AiPage Component
3
- *
4
- * Simple branded placeholder page for the /ai route across all app shells.
5
- * Shows product-specific AI branding with a "coming soon" state.
6
- */
7
1
  export interface AiPageProps {
8
- /** Display name of the product (e.g., "VibeControls", "FluidGrids") */
9
2
  productName: string;
10
- /** Machine-readable product identifier (e.g., "vibecontrols", "fluidgrids") */
11
3
  productId: string;
12
4
  }
13
5
  export declare function AiPage({ productName, productId }: AiPageProps): import('react/jsx-runtime').JSX.Element;
@@ -1,78 +1,132 @@
1
- import { Bot as e, Brain as t, Sparkles as n, Zap as r } from "lucide-react";
2
- import { jsx as i, jsxs as a } from "react/jsx-runtime";
1
+ import { useSafeGatewayClient as e } from "../graphql/GatewayContext.js";
2
+ import { useAuth as t } from "../providers/shell/AuthProvider.js";
3
+ import { useActiveContext as n } from "../providers/shell/ActiveContextProvider.js";
4
+ import { useI18n as r } from "../providers/shell/I18nProvider.js";
5
+ import { PermissionProvider as i, usePermissions as a, useSafePermissions as o } from "../providers/shell/PermissionProvider.js";
6
+ import { MODELS as s, PROVIDERS as c, SUMMARY as l, catalog as u, sevenDays as d, summary as f } from "./ai/contracts.js";
7
+ import { useAiTr as p } from "./ai/i18n.js";
8
+ import { CatalogPanel as m } from "./ai/CatalogPanel.js";
9
+ import { SummaryPanel as h } from "./ai/SummaryPanel.js";
10
+ import { useAiRead as g } from "./ai/useAiRead.js";
11
+ import { useCallback as _, useMemo as v, useState as y } from "react";
12
+ import { Fragment as b, jsx as x, jsxs as S } from "react/jsx-runtime";
3
13
  //#region src/shared/pages/AiPage.tsx
4
- var o = [
5
- {
6
- icon: t,
7
- title: "Intelligent Automation",
8
- description: "AI-powered workflows that adapt to your needs"
9
- },
10
- {
11
- icon: n,
12
- title: "Smart Suggestions",
13
- description: "Context-aware recommendations and insights"
14
- },
15
- {
16
- icon: r,
17
- title: "Instant Analysis",
18
- description: "Real-time data processing and pattern recognition"
19
- }
20
- ];
21
- function s({ productName: t, productId: n }) {
22
- return /* @__PURE__ */ i("div", {
23
- className: "flex flex-col items-center justify-center min-h-[calc(100vh-4rem)] px-4 py-12",
14
+ function C({ productName: t, productId: n }) {
15
+ let r = p(), i = e("workspace");
16
+ return /* @__PURE__ */ S("main", {
17
+ className: "mx-auto w-full max-w-6xl space-y-6 px-4 py-6 sm:px-6",
24
18
  "data-product-id": n,
25
- children: /* @__PURE__ */ a("div", {
26
- className: "max-w-2xl w-full text-center space-y-8",
27
- children: [
28
- /* @__PURE__ */ i("div", {
29
- className: "flex justify-center",
30
- children: /* @__PURE__ */ i("div", {
31
- className: "rounded-2xl bg-action-primary-bg/10 p-4",
32
- children: /* @__PURE__ */ i(e, { className: "size-12 text-action-primary-bg" })
33
- })
34
- }),
35
- /* @__PURE__ */ a("div", {
36
- className: "space-y-3",
37
- children: [/* @__PURE__ */ a("h1", {
38
- className: "text-3xl font-bold tracking-tight text-foreground",
39
- children: [t, " AI"]
40
- }), /* @__PURE__ */ a("p", {
41
- className: "text-lg text-muted-foreground",
42
- children: [
43
- "AI-powered features for ",
44
- t,
45
- " are on the way. Stay tuned for intelligent capabilities that will transform how you work."
46
- ]
47
- })]
48
- }),
49
- /* @__PURE__ */ i("div", {
50
- className: "grid grid-cols-1 sm:grid-cols-3 gap-4 pt-4",
51
- children: o.map((e) => /* @__PURE__ */ a("div", {
52
- className: "rounded-xl border border-border bg-card p-5 text-left space-y-2",
53
- children: [
54
- /* @__PURE__ */ i(e.icon, { className: "size-5 text-action-primary-bg" }),
55
- /* @__PURE__ */ i("h3", {
56
- className: "text-sm font-semibold text-foreground",
57
- children: e.title
58
- }),
59
- /* @__PURE__ */ i("p", {
60
- className: "text-xs text-muted-foreground",
61
- children: e.description
62
- })
63
- ]
64
- }, e.title))
65
- }),
66
- /* @__PURE__ */ i("div", {
67
- className: "flex justify-center pt-2",
68
- children: /* @__PURE__ */ a("span", {
69
- className: "inline-flex items-center gap-1.5 rounded-full bg-amber-500/10 px-3 py-1 text-xs font-medium text-amber-600 dark:text-amber-400",
70
- children: [/* @__PURE__ */ i("span", { className: "size-1.5 rounded-full bg-amber-500 animate-pulse" }), "Coming Soon"]
71
- })
19
+ children: [/* @__PURE__ */ S("header", {
20
+ className: "space-y-2",
21
+ children: [/* @__PURE__ */ x("h1", {
22
+ className: "text-2xl font-semibold text-foreground",
23
+ children: r("title", "{product} AI operations", { product: t })
24
+ }), /* @__PURE__ */ x("p", {
25
+ className: "max-w-3xl text-sm text-muted-foreground",
26
+ children: r("intro", "Review the workspace model catalog and recorded AI usage.")
27
+ })]
28
+ }), i ? /* @__PURE__ */ x(w, { children: /* @__PURE__ */ x(T, {
29
+ productId: n,
30
+ client: i
31
+ }) }) : /* @__PURE__ */ x("p", {
32
+ role: "status",
33
+ children: r("unavailable", "AI operations are unavailable in this context.")
34
+ })]
35
+ });
36
+ }
37
+ function w({ children: e }) {
38
+ let t = o(), { workspaceId: r } = n();
39
+ return t ? e : /* @__PURE__ */ x(i, {
40
+ scopeId: r ?? null,
41
+ gateway: "workspace",
42
+ children: e
43
+ });
44
+ }
45
+ function T({ productId: e, client: i }) {
46
+ let o = t(), { workspaceId: C } = n(), w = a(), { locale: T } = r(), E = p(), D = v(() => ({
47
+ workspaceId: C ?? "",
48
+ actorId: o.user?.id ?? "",
49
+ profileId: o.activeProfileId,
50
+ accessToken: o.tokens?.accessToken ?? null,
51
+ workspaceToken: o.workspaceToken
52
+ }), [
53
+ C,
54
+ o.user?.id,
55
+ o.activeProfileId,
56
+ o.tokens?.accessToken,
57
+ o.workspaceToken
58
+ ]), [O, k] = y(d), [A, j] = y({
59
+ scope: D,
60
+ models: 0,
61
+ providers: 0,
62
+ revision: 0
63
+ }), M = A.scope === D ? A.models : 0, N = A.scope === D ? A.providers : 0, P = A.scope === D ? A.revision : 0, F = (e) => o.isLoading ? "loading" : !o.isAuthenticated || !D.workspaceId || !D.actorId || !D.accessToken ? "unavailable" : w.isLoading || w.scopeId !== D.workspaceId ? "loading" : w.error ? "unavailable" : !w.isSuperAdmin && w.permissions?.actorId !== D.actorId ? "loading" : w.hasPermission(e) ? "ready" : "denied", I = v(() => ({ pagination: {
64
+ limit: 20,
65
+ offset: M
66
+ } }), [M]), L = v(() => ({ pagination: {
67
+ limit: 20,
68
+ offset: N
69
+ } }), [N]), R = v(() => ({
70
+ ...O,
71
+ productKey: e
72
+ }), [O, e]), z = _((e) => u(e, "models"), []), B = _((e) => u(e, "providers"), []), V = _((t) => f(t, D.workspaceId, e, O), [
73
+ D.workspaceId,
74
+ e,
75
+ O
76
+ ]), H = g(i, D, F("prompt-model:read"), s, I, z, P), U = g(i, D, F("prompt-provider:read"), c, L, B, P), W = g(i, D, F("prompt-invocation:read"), l, R, V, P);
77
+ function G() {
78
+ k(d()), j({
79
+ scope: D,
80
+ models: M,
81
+ providers: N,
82
+ revision: P + 1
83
+ });
84
+ }
85
+ return /* @__PURE__ */ S(b, { children: [
86
+ /* @__PURE__ */ S("div", {
87
+ className: "flex flex-wrap items-center justify-between gap-3",
88
+ children: [/* @__PURE__ */ x("p", {
89
+ className: "text-sm text-muted-foreground",
90
+ children: E("readonly", "Read-only workspace view")
91
+ }), /* @__PURE__ */ x("button", {
92
+ type: "button",
93
+ onClick: G,
94
+ className: "rounded-md border border-border px-3 py-2 text-sm font-medium focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
95
+ children: E("refresh", "Refresh")
96
+ })]
97
+ }),
98
+ /* @__PURE__ */ x(h, {
99
+ state: W,
100
+ window: O,
101
+ locale: T
102
+ }),
103
+ /* @__PURE__ */ S("div", {
104
+ className: "grid gap-6 lg:grid-cols-2",
105
+ children: [/* @__PURE__ */ x(m, {
106
+ kind: "models",
107
+ state: H,
108
+ offset: M,
109
+ locale: T,
110
+ onPage: (e) => j({
111
+ scope: D,
112
+ models: e,
113
+ providers: N,
114
+ revision: P
72
115
  })
73
- ]
116
+ }), /* @__PURE__ */ x(m, {
117
+ kind: "providers",
118
+ state: U,
119
+ offset: N,
120
+ locale: T,
121
+ onPage: (e) => j({
122
+ scope: D,
123
+ models: M,
124
+ providers: e,
125
+ revision: P
126
+ })
127
+ })]
74
128
  })
75
- });
129
+ ] });
76
130
  }
77
131
  //#endregion
78
- export { s as AiPage };
132
+ export { C as AiPage };
@@ -0,0 +1,9 @@
1
+ import { CatalogPage } from './contracts';
2
+ import { ReadState } from './useAiRead';
3
+ export declare function CatalogPanel({ kind, state, offset, locale, onPage, }: {
4
+ kind: 'models' | 'providers';
5
+ state: ReadState<CatalogPage>;
6
+ offset: number;
7
+ locale: string;
8
+ onPage: (offset: number) => void;
9
+ }): import('react/jsx-runtime').JSX.Element;
@@ -0,0 +1,80 @@
1
+ import { exactInteger as e } from "./contracts.js";
2
+ import { useAiTr as t } from "./i18n.js";
3
+ import { ReadNotice as n } from "./ReadNotice.js";
4
+ import { Fragment as r, jsx as i, jsxs as a } from "react/jsx-runtime";
5
+ //#region src/shared/pages/ai/CatalogPanel.tsx
6
+ function o({ kind: o, state: s, offset: c, locale: l, onPage: u }) {
7
+ let d = t(), f = o === "models" ? d("models", "Model catalog") : d("providers", "Provider catalog");
8
+ return /* @__PURE__ */ a("section", {
9
+ "aria-label": f,
10
+ className: "min-w-0 rounded-xl border border-border bg-card p-4 sm:p-5",
11
+ children: [
12
+ /* @__PURE__ */ i("h2", {
13
+ className: "mb-2 text-lg font-semibold",
14
+ children: f
15
+ }),
16
+ /* @__PURE__ */ i("p", {
17
+ className: "mb-4 text-sm text-muted-foreground",
18
+ children: o === "models" ? d("modelsDescription", "Models registered for this workspace") : d("providersDescription", "Providers registered for this workspace")
19
+ }),
20
+ s.status === "ready" ? /* @__PURE__ */ a(r, { children: [
21
+ /* @__PURE__ */ i("p", {
22
+ className: "mb-3 text-sm text-muted-foreground",
23
+ children: d("catalogTotal", "{count} catalog entries", { count: e(String(s.data.total), l) })
24
+ }),
25
+ s.data.items.length === 0 ? /* @__PURE__ */ i("p", {
26
+ className: "text-sm",
27
+ children: d("emptyCatalog", "No entries on this page.")
28
+ }) : /* @__PURE__ */ i("ul", {
29
+ tabIndex: 0,
30
+ "aria-label": d("catalogEntries", "{section} entries", { section: f }),
31
+ className: "max-h-96 overflow-y-auto divide-y divide-border rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
32
+ children: s.data.items.map((e) => /* @__PURE__ */ a("li", {
33
+ className: "space-y-1 py-3",
34
+ children: [
35
+ /* @__PURE__ */ i("h3", {
36
+ className: "break-words font-medium",
37
+ children: e.displayName
38
+ }),
39
+ /* @__PURE__ */ a("p", {
40
+ className: "break-all text-sm text-muted-foreground",
41
+ children: [
42
+ /* @__PURE__ */ i("bdi", { children: e.key }),
43
+ " · ",
44
+ /* @__PURE__ */ i("bdi", { children: e.detail })
45
+ ]
46
+ }),
47
+ /* @__PURE__ */ a("p", {
48
+ className: "text-xs text-muted-foreground",
49
+ children: [e.isActive ? d("active", "Active catalog entry") : d("inactive", "Inactive catalog entry"), e.deprecated ? ` · ${d("deprecated", "Deprecated")}` : ""]
50
+ })
51
+ ]
52
+ }, e.id))
53
+ }),
54
+ /* @__PURE__ */ i("p", {
55
+ className: "mt-3 text-xs text-muted-foreground",
56
+ children: d("registrationNotice", "Registration does not guarantee live availability.")
57
+ }),
58
+ /* @__PURE__ */ a("nav", {
59
+ "aria-label": d("pagination", "{section} pages", { section: f }),
60
+ className: "mt-4 flex flex-wrap gap-2",
61
+ children: [/* @__PURE__ */ i("button", {
62
+ type: "button",
63
+ disabled: c === 0,
64
+ onClick: () => u(Math.max(0, c - 20)),
65
+ className: "rounded-md border border-border px-3 py-2 text-sm disabled:opacity-50",
66
+ children: d("previous", "Previous")
67
+ }), /* @__PURE__ */ i("button", {
68
+ type: "button",
69
+ disabled: !s.data.hasMore,
70
+ onClick: () => u(c + 20),
71
+ className: "rounded-md border border-border px-3 py-2 text-sm disabled:opacity-50",
72
+ children: d("next", "Next")
73
+ })]
74
+ })
75
+ ] }) : /* @__PURE__ */ i(n, { status: s.status })
76
+ ]
77
+ });
78
+ }
79
+ //#endregion
80
+ export { o as CatalogPanel };
@@ -0,0 +1,4 @@
1
+ import { ReadState } from './useAiRead';
2
+ export declare function ReadNotice({ status }: {
3
+ status: Exclude<ReadState<unknown>['status'], 'ready'>;
4
+ }): import('react/jsx-runtime').JSX.Element;
@@ -0,0 +1,18 @@
1
+ import { useAiTr as e } from "./i18n.js";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ //#region src/shared/pages/ai/ReadNotice.tsx
4
+ function n({ status: n }) {
5
+ let r = e();
6
+ return /* @__PURE__ */ t("p", {
7
+ role: "status",
8
+ className: "text-sm text-muted-foreground",
9
+ children: {
10
+ loading: r("loading", "Loading this workspace…"),
11
+ denied: r("denied", "You do not have permission to read this section."),
12
+ unavailable: r("unavailable", "AI operations are unavailable in this context."),
13
+ error: r("error", "This read could not be completed. Refresh to try again.")
14
+ }[n]
15
+ });
16
+ }
17
+ //#endregion
18
+ export { n as ReadNotice };
@@ -0,0 +1,7 @@
1
+ import { UsageSummary, UsageWindow } from './contracts';
2
+ import { ReadState } from './useAiRead';
3
+ export declare function SummaryPanel({ state, window, locale, }: {
4
+ state: ReadState<UsageSummary>;
5
+ window: UsageWindow;
6
+ locale: string;
7
+ }): import('react/jsx-runtime').JSX.Element;
@@ -0,0 +1,135 @@
1
+ import { exactInteger as e, exactUsd as t } from "./contracts.js";
2
+ import { useAiTr as n } from "./i18n.js";
3
+ import { ReadNotice as r } from "./ReadNotice.js";
4
+ import { useMemo as i } from "react";
5
+ import { Fragment as a, jsx as o, jsxs as s } from "react/jsx-runtime";
6
+ //#region src/shared/pages/ai/SummaryPanel.tsx
7
+ function c({ label: r, value: i, cost: a, locale: c }) {
8
+ let l = n();
9
+ return /* @__PURE__ */ s("div", {
10
+ className: "min-w-0 rounded-lg bg-muted/40 p-3",
11
+ children: [
12
+ /* @__PURE__ */ o("dt", {
13
+ className: "text-sm text-muted-foreground",
14
+ children: r
15
+ }),
16
+ /* @__PURE__ */ o("dd", {
17
+ className: "mt-1 break-all text-xl font-semibold tabular-nums",
18
+ children: i.knownSubtotal === null ? l("unknown", "Unknown") : a ? t(i.knownSubtotal, c) : e(i.knownSubtotal, c)
19
+ }),
20
+ /* @__PURE__ */ o("dd", {
21
+ className: "mt-2 text-xs text-muted-foreground",
22
+ children: l("coverage", "{known} attempts reported; {missing} missing", {
23
+ known: e(i.knownAttempts, c),
24
+ missing: e(i.missingAttempts, c)
25
+ })
26
+ })
27
+ ]
28
+ });
29
+ }
30
+ function l({ state: t, window: l, locale: u }) {
31
+ let d = n(), f = d("summary", "Recorded usage"), p = i(() => new Intl.DateTimeFormat(u, {
32
+ year: "numeric",
33
+ month: "short",
34
+ day: "numeric",
35
+ hour: "2-digit",
36
+ minute: "2-digit",
37
+ timeZone: "UTC"
38
+ }), [u]), m = t.status === "ready" ? [
39
+ [d("operations", "Operations"), t.data.operations],
40
+ [d("attempts", "Recorded attempts"), t.data.attempts],
41
+ [d("known", "Known"), t.data.knownAttempts],
42
+ [d("partial", "Partial"), t.data.partialAttempts],
43
+ [d("unknownAttempts", "Unknown"), t.data.unknownAttempts],
44
+ [d("pending", "Pending (included in unknown)"), t.data.pendingAttempts]
45
+ ] : [];
46
+ return /* @__PURE__ */ s("section", {
47
+ "aria-label": f,
48
+ className: "min-w-0 rounded-xl border border-border bg-card p-4 sm:p-5",
49
+ children: [
50
+ /* @__PURE__ */ o("h2", {
51
+ className: "text-lg font-semibold",
52
+ children: f
53
+ }),
54
+ /* @__PURE__ */ o("p", {
55
+ className: "mt-2 break-words text-sm text-muted-foreground",
56
+ children: d("window", "{from} to {to} UTC", {
57
+ from: p.format(new Date(l.from)),
58
+ to: p.format(new Date(l.to))
59
+ })
60
+ }),
61
+ /* @__PURE__ */ o("p", {
62
+ className: "mt-2 text-sm text-muted-foreground",
63
+ children: d("summaryNotice", "Recorded attempts for this product. Usage may be incomplete; costs are estimated subtotals.")
64
+ }),
65
+ /* @__PURE__ */ o("div", {
66
+ className: "mt-4",
67
+ "aria-live": "polite",
68
+ children: t.status === "ready" ? /* @__PURE__ */ s(a, { children: [
69
+ t.data.attempts === "0" && /* @__PURE__ */ o("p", {
70
+ className: "mb-4 text-sm",
71
+ children: d("emptySummary", "No recorded attempts in this window. Unknown subtotals are not zero usage.")
72
+ }),
73
+ /* @__PURE__ */ o("dl", {
74
+ className: "grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-6",
75
+ children: m.map(([t, n]) => /* @__PURE__ */ s("div", {
76
+ className: "min-w-0",
77
+ children: [/* @__PURE__ */ o("dt", {
78
+ className: "text-xs text-muted-foreground",
79
+ children: t
80
+ }), /* @__PURE__ */ o("dd", {
81
+ className: "break-all text-xl font-semibold tabular-nums",
82
+ children: e(n, u)
83
+ })]
84
+ }, t))
85
+ }),
86
+ /* @__PURE__ */ s("dl", {
87
+ className: "mt-5 grid gap-3 sm:grid-cols-2 2xl:grid-cols-4",
88
+ children: [
89
+ /* @__PURE__ */ o(c, {
90
+ label: d("input", "Known input tokens"),
91
+ value: t.data.inputTokens,
92
+ locale: u
93
+ }),
94
+ /* @__PURE__ */ o(c, {
95
+ label: d("output", "Known output tokens"),
96
+ value: t.data.outputTokens,
97
+ locale: u
98
+ }),
99
+ /* @__PURE__ */ o(c, {
100
+ label: d("total", "Known total tokens"),
101
+ value: t.data.totalTokens,
102
+ locale: u
103
+ }),
104
+ /* @__PURE__ */ o(c, {
105
+ label: d("cost", "Known estimated cost subtotal"),
106
+ value: t.data.costMicroUsd,
107
+ cost: !0,
108
+ locale: u
109
+ })
110
+ ]
111
+ }),
112
+ /* @__PURE__ */ s("details", {
113
+ className: "mt-4 text-sm text-muted-foreground",
114
+ children: [/* @__PURE__ */ o("summary", {
115
+ className: "cursor-pointer",
116
+ children: d("usageHelp", "About these figures")
117
+ }), /* @__PURE__ */ s("div", {
118
+ className: "mt-2 space-y-2 text-xs",
119
+ children: [
120
+ /* @__PURE__ */ o("p", { children: d("coverageHelp", "Unknown means no supplied value; zero is a reported value. Missing counts show incomplete coverage. Pending attempts are included in unknown.") }),
121
+ /* @__PURE__ */ o("p", { children: d("recordedHelp", "These are recorded attempts, not all provider traffic or an invoice. Legacy records are excluded. Failed or timed-out attempts may still report usage. Cached input is included in input tokens.") }),
122
+ /* @__PURE__ */ o("p", { children: d("exactWindow", "Exact UTC range: {from} (inclusive) to {to} (exclusive).", {
123
+ from: l.from,
124
+ to: l.to
125
+ }) })
126
+ ]
127
+ })]
128
+ })
129
+ ] }) : /* @__PURE__ */ o(r, { status: t.status })
130
+ })
131
+ ]
132
+ });
133
+ }
134
+ //#endregion
135
+ export { l as SummaryPanel };
@@ -0,0 +1,45 @@
1
+ /** Read-only operations owned by Prompts; deliberately exclude credentials and V1. */
2
+ export declare const MODELS: import('graphql').DocumentNode;
3
+ export declare const PROVIDERS: import('graphql').DocumentNode;
4
+ export declare const SUMMARY: import('graphql').DocumentNode;
5
+ export interface CatalogItem {
6
+ id: string;
7
+ key: string;
8
+ displayName: string;
9
+ isActive: boolean;
10
+ detail: string;
11
+ deprecated: boolean;
12
+ }
13
+ export interface CatalogPage {
14
+ items: CatalogItem[];
15
+ total: number;
16
+ hasMore: boolean;
17
+ }
18
+ export interface UsageComponent {
19
+ knownSubtotal: string | null;
20
+ knownAttempts: string;
21
+ missingAttempts: string;
22
+ }
23
+ export interface UsageSummary {
24
+ operations: string;
25
+ attempts: string;
26
+ pendingAttempts: string;
27
+ knownAttempts: string;
28
+ partialAttempts: string;
29
+ unknownAttempts: string;
30
+ inputTokens: UsageComponent;
31
+ outputTokens: UsageComponent;
32
+ totalTokens: UsageComponent;
33
+ costMicroUsd: UsageComponent;
34
+ }
35
+ export interface UsageWindow {
36
+ from: string;
37
+ to: string;
38
+ }
39
+ export declare const PAGE_SIZE = 20;
40
+ export declare function integer(value: unknown): string;
41
+ export declare function catalog(value: unknown, kind: 'models' | 'providers'): CatalogPage;
42
+ export declare function summary(value: unknown, workspaceId: string, productKey: string, window: UsageWindow): UsageSummary;
43
+ export declare function exactInteger(value: string, locale: string): string;
44
+ export declare function exactUsd(value: string, locale: string): string;
45
+ export declare function sevenDays(now?: Date): UsageWindow;
@@ -0,0 +1,159 @@
1
+ import { gql as e } from "@apollo/client/core";
2
+ //#region src/shared/pages/ai/contracts.ts
3
+ var t = e`
4
+ query AiOperationsModels($pagination: PaginationInput!) {
5
+ promptModels(pagination: $pagination) {
6
+ items {
7
+ id
8
+ key
9
+ displayName
10
+ modality
11
+ isActive
12
+ deprecatedAt
13
+ supportsTools
14
+ supportsStreaming
15
+ supportsVision
16
+ }
17
+ total
18
+ hasMore
19
+ }
20
+ }
21
+ `, n = e`
22
+ query AiOperationsProviders($pagination: PaginationInput!) {
23
+ promptProviders(pagination: $pagination) {
24
+ items {
25
+ id
26
+ key
27
+ displayName
28
+ kind
29
+ isActive
30
+ }
31
+ total
32
+ hasMore
33
+ }
34
+ }
35
+ `, r = e`
36
+ query AiOperationsSummary($from: DateTime!, $to: DateTime!, $productKey: String!) {
37
+ promptUsageSummaryV2(from: $from, to: $to, productKey: $productKey) {
38
+ workspaceId
39
+ from
40
+ to
41
+ scope
42
+ productKey
43
+ operationKey
44
+ origin
45
+ currency
46
+ costKind
47
+ operations
48
+ attempts
49
+ pendingAttempts
50
+ knownAttempts
51
+ partialAttempts
52
+ unknownAttempts
53
+ inputTokens {
54
+ knownSubtotal
55
+ knownAttempts
56
+ missingAttempts
57
+ }
58
+ outputTokens {
59
+ knownSubtotal
60
+ knownAttempts
61
+ missingAttempts
62
+ }
63
+ totalTokens {
64
+ knownSubtotal
65
+ knownAttempts
66
+ missingAttempts
67
+ }
68
+ costMicroUsd {
69
+ knownSubtotal
70
+ knownAttempts
71
+ missingAttempts
72
+ }
73
+ }
74
+ }
75
+ `;
76
+ function i(e) {
77
+ if (!e || typeof e != "object" || Array.isArray(e)) throw Error("AI_READ_SHAPE");
78
+ return Object.fromEntries(Object.entries(e));
79
+ }
80
+ function a(e) {
81
+ if (typeof e != "string" || !e.length) throw Error("AI_READ_SHAPE");
82
+ return e;
83
+ }
84
+ function o(e) {
85
+ if (typeof e != "boolean") throw Error("AI_READ_SHAPE");
86
+ return e;
87
+ }
88
+ function s(e) {
89
+ if (typeof e != "string" || e.trim() !== e || e.length > 200 || !/^(0|[1-9][0-9]*)$/.test(e)) throw Error("AI_READ_INTEGER");
90
+ return e;
91
+ }
92
+ function c(e, t) {
93
+ let n = i(i(e)[t === "models" ? "promptModels" : "promptProviders"]);
94
+ if (!Array.isArray(n.items) || n.items.length > 20 || typeof n.total != "number" || !Number.isSafeInteger(n.total) || n.total < 0) throw Error("AI_READ_SHAPE");
95
+ let r = n.items.map((e) => {
96
+ let n = i(e), r = t === "models" && n.deprecatedAt !== null;
97
+ return r && a(n.deprecatedAt), {
98
+ id: a(n.id),
99
+ key: a(n.key),
100
+ displayName: a(n.displayName),
101
+ isActive: o(n.isActive),
102
+ detail: a(t === "models" ? n.modality : n.kind),
103
+ deprecated: r
104
+ };
105
+ });
106
+ if (new Set(r.map((e) => e.id)).size !== r.length) throw Error("AI_READ_SHAPE");
107
+ let s = o(n.hasMore);
108
+ if (r.length > n.total || s && r.length === 0) throw Error("AI_READ_SHAPE");
109
+ return {
110
+ items: r,
111
+ total: n.total,
112
+ hasMore: s
113
+ };
114
+ }
115
+ function l(e, t, n, r) {
116
+ let o = i(i(e).promptUsageSummaryV2);
117
+ if (o.workspaceId !== t || o.productKey !== n || o.operationKey !== null || o.scope !== "RECORDED_V2_ATTEMPTS" || o.origin !== "CALLER_REPORTED" || o.currency !== "USD" || o.costKind !== "ESTIMATE" || Date.parse(a(o.from)) !== Date.parse(r.from) || Date.parse(a(o.to)) !== Date.parse(r.to)) throw Error("AI_READ_SCOPE");
118
+ let c = s(o.attempts), l = s(o.knownAttempts), u = s(o.partialAttempts), d = s(o.unknownAttempts), f = s(o.pendingAttempts), p = s(o.operations);
119
+ if (BigInt(l) + BigInt(u) + BigInt(d) !== BigInt(c) || BigInt(f) > BigInt(d) || BigInt(p) > BigInt(c)) throw Error("AI_READ_COUNTS");
120
+ let m = (e) => {
121
+ let t = i(e), n = s(t.knownAttempts), r = s(t.missingAttempts), a = t.knownSubtotal === null ? null : s(t.knownSubtotal);
122
+ if (BigInt(n) + BigInt(r) !== BigInt(c) || n === "0" != (a === null)) throw Error("AI_READ_COUNTS");
123
+ return {
124
+ knownSubtotal: a,
125
+ knownAttempts: n,
126
+ missingAttempts: r
127
+ };
128
+ };
129
+ return {
130
+ operations: p,
131
+ attempts: c,
132
+ pendingAttempts: f,
133
+ knownAttempts: l,
134
+ partialAttempts: u,
135
+ unknownAttempts: d,
136
+ inputTokens: m(o.inputTokens),
137
+ outputTokens: m(o.outputTokens),
138
+ totalTokens: m(o.totalTokens),
139
+ costMicroUsd: m(o.costMicroUsd)
140
+ };
141
+ }
142
+ function u(e, t) {
143
+ return new Intl.NumberFormat(t).format(BigInt(s(e)));
144
+ }
145
+ function d(e, t) {
146
+ let n = s(e).padStart(7, "0"), r = new Intl.NumberFormat(t).formatToParts(1.1).find((e) => e.type === "decimal")?.value ?? ".", i = new Intl.NumberFormat(t, {
147
+ useGrouping: !1,
148
+ minimumIntegerDigits: 6
149
+ }).format(BigInt(n.slice(-6)));
150
+ return `USD ${u(n.slice(0, -6).replace(/^0+(?=.)/, ""), t)}${r}${i}`;
151
+ }
152
+ function f(e = /* @__PURE__ */ new Date()) {
153
+ return {
154
+ from: (/* @__PURE__ */ new Date(e.getTime() - 7 * 864e5)).toISOString(),
155
+ to: e.toISOString()
156
+ };
157
+ }
158
+ //#endregion
159
+ export { t as MODELS, n as PROVIDERS, r as SUMMARY, c as catalog, u as exactInteger, d as exactUsd, f as sevenDays, l as summary };
@@ -0,0 +1 @@
1
+ export declare function useAiTr(): (key: string, fallback: string, params?: Record<string, string | number>) => string;
@@ -0,0 +1,10 @@
1
+ import { interpolate as e } from "../../providers/shell/interpolate.js";
2
+ import { useOptionalI18n as t } from "../../providers/shell/I18nProvider.js";
3
+ import { useCallback as n } from "react";
4
+ //#region src/shared/pages/ai/i18n.ts
5
+ function r() {
6
+ let r = t();
7
+ return n((t, n, i) => r ? r.t(`ai.operations.${t}`, n, i) : e(n, i ?? {}), [r]);
8
+ }
9
+ //#endregion
10
+ export { r as useAiTr };
@@ -0,0 +1,18 @@
1
+ import { ApolloClient, DocumentNode } from '@apollo/client/core';
2
+ export type ReadAccess = 'ready' | 'loading' | 'denied' | 'unavailable';
3
+ export interface ReadScope {
4
+ workspaceId: string;
5
+ actorId: string;
6
+ profileId: string | null;
7
+ /** In-memory identity boundary only; never serialized, logged or persisted. */
8
+ accessToken: string | null;
9
+ workspaceToken: string | null;
10
+ }
11
+ export type ReadState<T> = {
12
+ status: 'ready';
13
+ data: T;
14
+ } | {
15
+ status: 'loading' | 'denied' | 'unavailable' | 'error';
16
+ };
17
+ /** No cache writes/deduplication: a previous identity's result cannot be reused. */
18
+ export declare function useAiRead<T>(client: ApolloClient, scope: ReadScope, access: ReadAccess, query: DocumentNode, variables: Record<string, unknown>, parse: (value: unknown) => T, revision?: number): ReadState<T>;
@@ -0,0 +1,57 @@
1
+ import { useEffect as e, useMemo as t, useState as n } from "react";
2
+ //#region src/shared/pages/ai/useAiRead.ts
3
+ function r(r, i, a, o, s, c, l = 0) {
4
+ let u = t(() => ({
5
+ client: r,
6
+ scope: i,
7
+ access: a,
8
+ query: o,
9
+ variables: s,
10
+ parse: c,
11
+ revision: l
12
+ }), [
13
+ r,
14
+ i,
15
+ a,
16
+ o,
17
+ s,
18
+ c,
19
+ l
20
+ ]), [d, f] = n(null);
21
+ return e(() => {
22
+ if (a !== "ready") return;
23
+ let e = new AbortController();
24
+ return r.query({
25
+ query: o,
26
+ variables: s,
27
+ fetchPolicy: "no-cache",
28
+ errorPolicy: "none",
29
+ context: {
30
+ queryDeduplication: !1,
31
+ fetchOptions: { signal: e.signal }
32
+ }
33
+ }).then((t) => {
34
+ e.signal.aborted || f({
35
+ identity: u,
36
+ state: {
37
+ status: "ready",
38
+ data: c(t.data)
39
+ }
40
+ });
41
+ }).catch(() => {
42
+ e.signal.aborted || f({
43
+ identity: u,
44
+ state: { status: "error" }
45
+ });
46
+ }), () => e.abort();
47
+ }, [
48
+ r,
49
+ a,
50
+ o,
51
+ s,
52
+ c,
53
+ u
54
+ ]), a === "ready" ? d?.identity === u ? d.state : { status: "loading" } : { status: a };
55
+ }
56
+ //#endregion
57
+ export { r as useAiRead };
@@ -0,0 +1,212 @@
1
+ //#region src/shared/utils/mockData.ts
2
+ var e = [
3
+ {
4
+ id: "fluidgrids",
5
+ name: "FluidGrids",
6
+ icon: "FG",
7
+ color: "#3b82f6",
8
+ url: "https://app.fluidgrids.com"
9
+ },
10
+ {
11
+ id: "bigconsole",
12
+ name: "BigConsole",
13
+ icon: "BC",
14
+ color: "#8b5cf6",
15
+ url: "https://app.bigconsole.com"
16
+ },
17
+ {
18
+ id: "workspaces",
19
+ name: "Workspaces",
20
+ icon: "WS",
21
+ color: "#06b6d4",
22
+ url: "https://app.burdenoff.com"
23
+ },
24
+ {
25
+ id: "vibecontrols",
26
+ name: "VibeControls",
27
+ icon: "VC",
28
+ color: "#10b981",
29
+ url: "https://app.vibecontrols.com"
30
+ },
31
+ {
32
+ id: "botlit",
33
+ name: "BotManor",
34
+ icon: "BL",
35
+ color: "#f59e0b",
36
+ url: "https://app.botmanor.com"
37
+ }
38
+ ], t = [
39
+ {
40
+ code: "en",
41
+ name: "English",
42
+ nativeName: "English",
43
+ flag: "🇺🇸"
44
+ },
45
+ {
46
+ code: "es",
47
+ name: "Spanish",
48
+ nativeName: "Español",
49
+ flag: "🇪🇸"
50
+ },
51
+ {
52
+ code: "fr",
53
+ name: "French",
54
+ nativeName: "Français",
55
+ flag: "🇫🇷"
56
+ },
57
+ {
58
+ code: "de",
59
+ name: "German",
60
+ nativeName: "Deutsch",
61
+ flag: "🇩🇪"
62
+ },
63
+ {
64
+ code: "ja",
65
+ name: "Japanese",
66
+ nativeName: "日本語",
67
+ flag: "🇯🇵"
68
+ },
69
+ {
70
+ code: "zh",
71
+ name: "Chinese",
72
+ nativeName: "中文",
73
+ flag: "🇨🇳"
74
+ },
75
+ {
76
+ code: "ta",
77
+ name: "Tamil",
78
+ nativeName: "தமிழ்",
79
+ flag: "🇮🇳"
80
+ },
81
+ {
82
+ code: "hi",
83
+ name: "Hindi",
84
+ nativeName: "हिन्दी",
85
+ flag: "🇮🇳"
86
+ },
87
+ {
88
+ code: "ko",
89
+ name: "Korean",
90
+ nativeName: "한국어",
91
+ flag: "🇰🇷"
92
+ }
93
+ ], n = [
94
+ {
95
+ id: "org-1",
96
+ name: "Acme Corporation",
97
+ slug: "acme-corp",
98
+ tenantId: "tenant-1"
99
+ },
100
+ {
101
+ id: "org-2",
102
+ name: "TechStart Inc.",
103
+ slug: "techstart",
104
+ tenantId: "tenant-2"
105
+ },
106
+ {
107
+ id: "org-3",
108
+ name: "GlobalEdge Ltd.",
109
+ slug: "globaledge",
110
+ tenantId: "tenant-3"
111
+ }
112
+ ], r = [
113
+ {
114
+ id: "ws-1",
115
+ name: "Product Engineering",
116
+ organizationId: "org-1",
117
+ slug: "product-eng"
118
+ },
119
+ {
120
+ id: "ws-2",
121
+ name: "Marketing",
122
+ organizationId: "org-1",
123
+ slug: "marketing"
124
+ },
125
+ {
126
+ id: "ws-3",
127
+ name: "Design Studio",
128
+ organizationId: "org-1",
129
+ slug: "design-studio"
130
+ },
131
+ {
132
+ id: "ws-4",
133
+ name: "R&D Lab",
134
+ organizationId: "org-2",
135
+ slug: "rd-lab"
136
+ },
137
+ {
138
+ id: "ws-5",
139
+ name: "Operations",
140
+ organizationId: "org-2",
141
+ slug: "operations"
142
+ },
143
+ {
144
+ id: "ws-6",
145
+ name: "Client Projects",
146
+ organizationId: "org-3",
147
+ slug: "client-projects"
148
+ }
149
+ ], i = [
150
+ {
151
+ id: "proj-1",
152
+ name: "Platform V2",
153
+ workspaceId: "ws-1",
154
+ slug: "platform-v2"
155
+ },
156
+ {
157
+ id: "proj-2",
158
+ name: "Mobile App",
159
+ workspaceId: "ws-1",
160
+ slug: "mobile-app"
161
+ },
162
+ {
163
+ id: "proj-3",
164
+ name: "API Gateway",
165
+ workspaceId: "ws-1",
166
+ slug: "api-gateway"
167
+ },
168
+ {
169
+ id: "proj-4",
170
+ name: "Q1 Campaign",
171
+ workspaceId: "ws-2",
172
+ slug: "q1-campaign"
173
+ },
174
+ {
175
+ id: "proj-5",
176
+ name: "Brand Refresh",
177
+ workspaceId: "ws-2",
178
+ slug: "brand-refresh"
179
+ },
180
+ {
181
+ id: "proj-6",
182
+ name: "Design System",
183
+ workspaceId: "ws-3",
184
+ slug: "design-system"
185
+ },
186
+ {
187
+ id: "proj-7",
188
+ name: "UX Research",
189
+ workspaceId: "ws-3",
190
+ slug: "ux-research"
191
+ },
192
+ {
193
+ id: "proj-8",
194
+ name: "ML Pipeline",
195
+ workspaceId: "ws-4",
196
+ slug: "ml-pipeline"
197
+ },
198
+ {
199
+ id: "proj-9",
200
+ name: "Infra Automation",
201
+ workspaceId: "ws-5",
202
+ slug: "infra-automation"
203
+ },
204
+ {
205
+ id: "proj-10",
206
+ name: "Client Portal",
207
+ workspaceId: "ws-6",
208
+ slug: "client-portal"
209
+ }
210
+ ];
211
+ //#endregion
212
+ export { t as mockLanguages, n as mockOrganizations, e as mockProducts, i as mockProjects, r as mockWorkspaces };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/fe-libs",
3
- "version": "2026.1017.1",
3
+ "version": "2026.1017.2",
4
4
  "description": "Burdenoff frontend primitives and domain libraries",
5
5
  "type": "module",
6
6
  "bin": {
@@ -34,10 +34,6 @@
34
34
  "types": "./dist/chrome.d.ts",
35
35
  "import": "./dist/chrome.js"
36
36
  },
37
- "./workflow": {
38
- "types": "./dist/workflow.d.ts",
39
- "import": "./dist/workflow.js"
40
- },
41
37
  "./tag": {
42
38
  "types": "./dist/tag.d.ts",
43
39
  "import": "./dist/tag.js"