@burdenoff/microfe-vibecontrols 2026.528.7 → 2026.528.8

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 (33) hide show
  1. package/dist/VibeControlsRoot.js +1 -0
  2. package/dist/VibeControlsRoot.js.map +1 -1
  3. package/dist/components/audit/AuditLogFilters.js +71 -47
  4. package/dist/components/audit/AuditLogFilters.js.map +1 -1
  5. package/dist/components/shared/AgentSetupBanner.js +50 -45
  6. package/dist/components/shared/AgentSetupBanner.js.map +1 -1
  7. package/dist/components/shared/LinkToVibePanel.js +97 -0
  8. package/dist/components/shared/LinkToVibePanel.js.map +1 -0
  9. package/dist/components/shared/index.js +1 -0
  10. package/dist/components/vibe/VibeLinkedEntitiesPanel.js +60 -0
  11. package/dist/components/vibe/VibeLinkedEntitiesPanel.js.map +1 -0
  12. package/dist/components/vibedeck/VibeDeckButtonTile.js +25 -23
  13. package/dist/components/vibedeck/VibeDeckButtonTile.js.map +1 -1
  14. package/dist/components/vibedeck/VibeDeckGrid.js +2 -2
  15. package/dist/components/vibedeck/VibeDeckGrid.js.map +1 -1
  16. package/dist/microfe-vibecontrols.css +1 -1
  17. package/dist/pages/AgentDetailsPage.js +2 -2
  18. package/dist/pages/AgentDetailsPage.js.map +1 -1
  19. package/dist/pages/AnalyticsPage.js +255 -204
  20. package/dist/pages/AnalyticsPage.js.map +1 -1
  21. package/dist/pages/OverviewPage.js +1 -11
  22. package/dist/pages/OverviewPage.js.map +1 -1
  23. package/dist/pages/SessionsPage.js +825 -629
  24. package/dist/pages/SessionsPage.js.map +1 -1
  25. package/dist/pages/VibeAuditPage.js +184 -153
  26. package/dist/pages/VibeAuditPage.js.map +1 -1
  27. package/dist/pages/VibeDeckPage.js +416 -379
  28. package/dist/pages/VibeDeckPage.js.map +1 -1
  29. package/dist/pages/VibeDetailsPage.js +621 -557
  30. package/dist/pages/VibeDetailsPage.js.map +1 -1
  31. package/dist/pages/tunnels/TunnelsTab.js +115 -90
  32. package/dist/pages/tunnels/TunnelsTab.js.map +1 -1
  33. package/package.json +1 -1
@@ -1,239 +1,270 @@
1
- import { useBulkDeleteVibeAuditLogsMutation as e, useDeleteVibeAuditLogMutation as t, useGetVibeAuditLogQuery as n, useVibeAuditDashboardQuery as r } from "../generated/wspace-operations.js";
2
- import { useVibeControls as ee } from "../providers/VibeControlsProvider.js";
3
- import { PageHeader as te } from "../components/shared/PageHeader.js";
1
+ import { useBulkDeleteVibeAuditLogsMutation as e, useDeleteVibeAuditLogMutation as t, useGetVibeAuditLogQuery as n, useListAgentsQuery as r, useListVibesQuery as ee, useVibeAuditDashboardQuery as te } from "../generated/wspace-operations.js";
2
+ import { useVibeControls as ne } from "../providers/VibeControlsProvider.js";
3
+ import { PageHeader as re } from "../components/shared/PageHeader.js";
4
4
  import { LoadingState as i } from "../components/shared/LoadingState.js";
5
- import { ErrorState as ne } from "../components/shared/ErrorState.js";
6
- import { isNative as a, nativeNotify as o } from "../utils/nativeBridge.js";
7
- import { EmptyState as re } from "../components/shared/EmptyState.js";
8
- import { GetHelpButton as ie } from "../components/shared/GetHelpButton.js";
5
+ import { ErrorState as ie } from "../components/shared/ErrorState.js";
6
+ import { isNative as ae, nativeNotify as a } from "../utils/nativeBridge.js";
7
+ import { EmptyState as oe } from "../components/shared/EmptyState.js";
8
+ import { GetHelpButton as se } from "../components/shared/GetHelpButton.js";
9
9
  import "../components/shared/index.js";
10
- import { VIBE_PERMISSIONS as s } from "../constants/permissions.js";
11
- import { AuditLogTable as ae } from "../components/audit/AuditLogTable.js";
12
- import { AuditLogFilters as oe } from "../components/audit/AuditLogFilters.js";
13
- import { AuditLogDetail as se } from "../components/audit/AuditLogDetail.js";
14
- import { AuditLogStats as ce } from "../components/audit/AuditLogStats.js";
15
- import { AuditDeleteDialog as le } from "../components/audit/AuditDeleteDialog.js";
16
- import { AuditExportButton as ue } from "../components/audit/AuditExportButton.js";
10
+ import { VIBE_PERMISSIONS as o } from "../constants/permissions.js";
11
+ import { AuditLogTable as ce } from "../components/audit/AuditLogTable.js";
12
+ import { AuditLogFilters as le } from "../components/audit/AuditLogFilters.js";
13
+ import { AuditLogDetail as ue } from "../components/audit/AuditLogDetail.js";
14
+ import { AuditLogStats as de } from "../components/audit/AuditLogStats.js";
15
+ import { AuditDeleteDialog as fe } from "../components/audit/AuditDeleteDialog.js";
16
+ import { AuditExportButton as pe } from "../components/audit/AuditExportButton.js";
17
17
  import "../components/audit/index.js";
18
- import { useCallback as c, useEffect as l, useRef as de, useState as u } from "react";
19
- import { useI18n as d } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
20
- import { Shield as fe } from "lucide-react";
21
- import { usePermissions as pe } from "@burdenoff/fe-libs/shared/providers/shell";
22
- import { jsx as f, jsxs as p } from "react/jsx-runtime";
23
- import { AccessDenied as me } from "@burdenoff/fe-libs/shared/components";
18
+ import { useCallback as s, useEffect as c, useRef as me, useState as l } from "react";
19
+ import { useI18n as he } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
20
+ import { Shield as u } from "lucide-react";
21
+ import { usePermissions as ge } from "@burdenoff/fe-libs/shared/providers/shell";
22
+ import { jsx as d, jsxs as f } from "react/jsx-runtime";
23
+ import { AccessDenied as _e } from "@burdenoff/fe-libs/shared/components";
24
24
  //#region src/pages/VibeAuditPage.tsx
25
- var m = 50;
26
- function h() {
27
- ee();
28
- let { t: h } = d(), { hasPermission: g, isLoading: _, permissions: v } = pe(), [y, he] = u(""), [b, ge] = u(""), [x, _e] = u("all"), [S, ve] = u("all"), [C, ye] = u("all"), [w, be] = u(!1), [T, E] = u(0), [D, O] = u(null), [k, A] = u(/* @__PURE__ */ new Set()), [j, M] = u([]), [N, P] = u(null), [F, I] = u(null), L = de(null), R = c((e, t) => {
29
- let n = h(e);
25
+ var p = 50;
26
+ function m() {
27
+ ne();
28
+ let { t: m } = he(), { hasPermission: h, isLoading: g, permissions: _ } = ge(), [v, ve] = l(""), [y, ye] = l(""), [b, be] = l("all"), [x, xe] = l("all"), [S, Se] = l("all"), [C, w] = l("all"), [T, E] = l("all"), [D, Ce] = l(!1), [O, k] = l(0), [A, j] = l(null), [M, N] = l(/* @__PURE__ */ new Set()), [P, F] = l([]), [we, I] = l(null), [Te, L] = l(null), R = me(null), z = s((e, t) => {
29
+ let n = m(e);
30
30
  return n === e ? t : n;
31
- }, [h]), z = g(s.AUDIT_LIST), B = g(s.AUDIT_DELETE), xe = g(s.AUDIT_EXPORT), Se = _ || !z, V = {};
32
- b && (V.search = b), x && x !== "all" && (V.action = x), S && S !== "all" && (V.resourceType = S), C && C !== "all" && (V.status = C), w && (V.hasCommand = !0);
33
- let { data: H, loading: U, error: W, refetch: G } = r({
31
+ }, [m]), B = h(o.AUDIT_LIST), V = h(o.AUDIT_DELETE), Ee = h(o.AUDIT_EXPORT), H = g || !B, U = {};
32
+ y && (U.search = y), b && b !== "all" && (U.action = b), x && x !== "all" && (U.resourceType = x), S && S !== "all" && (U.status = S), D && (U.hasCommand = !0), C && C !== "all" ? (U.resourceId = C, U.resourceType ||= "AGENT") : T && T !== "all" && (U.resourceId = T, U.resourceType ||= "VIBE");
33
+ let { data: W, loading: G, error: K, refetch: q } = te({
34
34
  variables: {
35
- filter: V,
36
- pagination: { limit: Math.min(Math.max((T + 1) * m, m), 100) }
35
+ filter: U,
36
+ pagination: { limit: Math.min(Math.max((O + 1) * p, p), 100) }
37
37
  },
38
- skip: Se,
38
+ skip: H,
39
39
  fetchPolicy: "cache-and-network",
40
40
  notifyOnNetworkStatusChange: !0
41
- }), { data: K } = n({
42
- variables: { id: D },
43
- skip: !D
44
- }), [Ce, { loading: q }] = t(), [we] = e();
45
- l(() => {
41
+ }), { data: De } = r({
42
+ variables: { pagination: { limit: 200 } },
43
+ fetchPolicy: "cache-first",
44
+ skip: H
45
+ }), Oe = (De?.vibecontrolsAgents ?? []).map((e) => ({
46
+ id: e.id,
47
+ name: e.name
48
+ })), { data: ke } = ee({
49
+ variables: { pagination: { limit: 200 } },
50
+ fetchPolicy: "cache-first",
51
+ skip: H
52
+ }), Ae = (ke?.vibes?.items ?? []).map((e) => ({
53
+ id: e.id,
54
+ name: e.name
55
+ })), je = W?.vibeAuditLogStats?.retentionPolicy?.retentionDays ?? 90, J = W?.vibeAuditLogStats?.retentionPolicy?.nextCleanup ?? null, { data: Y } = n({
56
+ variables: { id: A },
57
+ skip: !A
58
+ }), [Me, { loading: Ne }] = t(), [Pe] = e();
59
+ c(() => {
46
60
  let e = window.setTimeout(() => {
47
- ge(y), E(0);
61
+ ye(v), k(0);
48
62
  }, 300);
49
63
  return () => window.clearTimeout(e);
50
- }, [y]), l(() => () => {
51
- L.current && clearTimeout(L.current);
64
+ }, [v]), c(() => () => {
65
+ R.current && clearTimeout(R.current);
52
66
  }, []);
53
- let J = c(() => {
54
- P(null), L.current &&= (clearTimeout(L.current), null);
55
- }, []), Y = c(() => {
56
- I(null);
57
- }, []), X = (H?.vibeAuditLogs.items ?? []).slice(T * m, (T + 1) * m), Z = H?.vibeAuditLogs.total ?? 0, Q = X.map((e) => e.id), $ = Q.length > 0 && Q.every((e) => k.has(e)), Te = Q.some((e) => k.has(e)) && !$, Ee = async (e) => {
58
- if (j.length !== 0) {
59
- J(), Y();
67
+ let X = s(() => {
68
+ I(null), R.current &&= (clearTimeout(R.current), null);
69
+ }, []), Z = s(() => {
70
+ L(null);
71
+ }, []), Q = (W?.vibeAuditLogs.items ?? []).slice(O * p, (O + 1) * p), Fe = W?.vibeAuditLogs.total ?? 0, $ = Q.map((e) => e.id), Ie = $.length > 0 && $.every((e) => M.has(e)), Le = $.some((e) => M.has(e)) && !Ie, Re = async (e) => {
72
+ if (P.length !== 0) {
73
+ X(), Z();
60
74
  try {
61
- if (j.length === 1) await Ce({ variables: {
62
- id: j[0],
75
+ if (P.length === 1) await Me({ variables: {
76
+ id: P[0],
63
77
  input: { reason: e }
64
- } }), I("Deleted 1 audit log");
78
+ } }), L("Deleted 1 audit log");
65
79
  else {
66
- let t = await we({ variables: {
67
- ids: j,
80
+ let t = await Pe({ variables: {
81
+ ids: P,
68
82
  input: { reason: e }
69
83
  } }), n = t.data?.bulkDeleteVibeAuditLogs.deletedCount ?? 0, r = t.data?.bulkDeleteVibeAuditLogs.failedCount ?? 0;
70
- I(`Deleted ${n} audit logs${r > 0 ? ` • ${r} failed` : ""}`);
84
+ L(`Deleted ${n} audit logs${r > 0 ? ` • ${r} failed` : ""}`);
71
85
  }
72
- M([]), A((e) => {
86
+ F([]), N((e) => {
73
87
  let t = new Set(e);
74
- return j.forEach((e) => t.delete(e)), t;
75
- }), D && j.includes(D) && O(null), await G(), a() && o("success");
88
+ return P.forEach((e) => t.delete(e)), t;
89
+ }), A && P.includes(A) && j(null), await q(), ae() && a("success");
76
90
  } catch (e) {
77
- console.error("Failed to delete audit log:", e), P(R("audit.deleteFailed", "Failed to delete audit log. Please try again.")), a() && o("error"), L.current = setTimeout(() => {
78
- P(null), L.current = null;
91
+ console.error("Failed to delete audit log:", e), I(z("audit.deleteFailed", "Failed to delete audit log. Please try again.")), ae() && a("error"), R.current = setTimeout(() => {
92
+ I(null), R.current = null;
79
93
  }, 3e4);
80
94
  }
81
95
  }
82
- }, De = c((e) => {
83
- B && (J(), Y(), M([e]));
96
+ }, ze = s((e) => {
97
+ V && (X(), Z(), F([e]));
84
98
  }, [
85
- B,
86
- J,
87
- Y
88
- ]), Oe = c((e, t) => {
89
- A((n) => {
99
+ V,
100
+ X,
101
+ Z
102
+ ]), Be = s((e, t) => {
103
+ N((n) => {
90
104
  let r = new Set(n);
91
105
  return t ? r.add(e) : r.delete(e), r;
92
106
  });
93
- }, []), ke = c((e) => {
94
- A((t) => {
107
+ }, []), Ve = s((e) => {
108
+ N((t) => {
95
109
  let n = new Set(t);
96
- return Q.forEach((t) => {
110
+ return $.forEach((t) => {
97
111
  e ? n.add(t) : n.delete(t);
98
112
  }), n;
99
113
  });
100
- }, [Q]), Ae = c(() => {
101
- !B || k.size === 0 || (J(), Y(), M(Array.from(k)));
114
+ }, [$]), He = s(() => {
115
+ !V || M.size === 0 || (X(), Z(), F(Array.from(M)));
102
116
  }, [
103
- B,
104
- J,
105
- Y,
106
- k
117
+ V,
118
+ X,
119
+ Z,
120
+ M
107
121
  ]);
108
- return _ ? /* @__PURE__ */ f("div", {
122
+ return g ? /* @__PURE__ */ d("div", {
109
123
  className: "mx-auto max-w-[1400px] p-4 sm:p-6",
110
- children: /* @__PURE__ */ f(i, { message: R("audit.loadingPermissions", "Loading permissions...") })
111
- }) : v && v.permissionStrings?.length > 0 && !z ? /* @__PURE__ */ f(me, {
112
- title: R("common.accessDeniedTitle", "Access Denied"),
113
- description: R("common.accessDeniedDescription", "You don't have permission to access this resource.")
114
- }) : /* @__PURE__ */ p("div", {
124
+ children: /* @__PURE__ */ d(i, { message: z("audit.loadingPermissions", "Loading permissions...") })
125
+ }) : _ && _.permissionStrings?.length > 0 && !B ? /* @__PURE__ */ d(_e, {
126
+ title: z("common.accessDeniedTitle", "Access Denied"),
127
+ description: z("common.accessDeniedDescription", "You don't have permission to access this resource.")
128
+ }) : /* @__PURE__ */ f("div", {
115
129
  className: "mx-auto max-w-[1400px] p-4 sm:p-6",
116
130
  children: [
117
- /* @__PURE__ */ f(te, {
118
- title: R("nav.vibeAudit", "Audit"),
119
- description: R("audit.description", "Comprehensive audit trail of all VibeControls operations"),
120
- actions: xe ? /* @__PURE__ */ f(ue, { filter: V }) : void 0
131
+ /* @__PURE__ */ d(re, {
132
+ title: z("nav.vibeAudit", "Audit"),
133
+ description: z("audit.description", "Comprehensive audit trail of all VibeControls operations"),
134
+ actions: Ee ? /* @__PURE__ */ d(pe, { filter: U }) : void 0
121
135
  }),
122
- /* @__PURE__ */ f(ce, {
123
- stats: H?.vibeAuditLogStats,
124
- loading: U && !H
136
+ /* @__PURE__ */ f("div", {
137
+ className: "mb-4 flex items-start gap-2 rounded-md border border-status-info-border bg-status-info-bg/10 px-3 py-2 text-xs text-status-info-text",
138
+ children: [/* @__PURE__ */ d(u, {
139
+ size: 14,
140
+ className: "mt-0.5 flex-shrink-0"
141
+ }), /* @__PURE__ */ f("span", { children: [z("audit.retentionBanner", `Audit logs are kept for ${je} days. Older entries are automatically purged.`), J ? ` ${z("audit.retentionNextCleanup", `Next cleanup: ${new Date(J).toLocaleString()}.`)}` : ""] })]
125
142
  }),
126
- /* @__PURE__ */ f(oe, {
127
- searchQuery: y,
128
- onSearchChange: he,
129
- actionFilter: x,
143
+ /* @__PURE__ */ d(de, {
144
+ stats: W?.vibeAuditLogStats,
145
+ loading: G && !W
146
+ }),
147
+ /* @__PURE__ */ d(le, {
148
+ searchQuery: v,
149
+ onSearchChange: ve,
150
+ actionFilter: b,
130
151
  onActionChange: (e) => {
131
- _e(e), E(0);
152
+ be(e), k(0);
132
153
  },
133
- resourceTypeFilter: S,
154
+ resourceTypeFilter: x,
134
155
  onResourceTypeChange: (e) => {
135
- ve(e), E(0);
156
+ xe(e), k(0);
136
157
  },
137
- statusFilter: C,
158
+ statusFilter: S,
138
159
  onStatusChange: (e) => {
139
- ye(e), E(0);
160
+ Se(e), k(0);
140
161
  },
141
- hasCommandFilter: w,
162
+ hasCommandFilter: D,
142
163
  onHasCommandChange: (e) => {
143
- be(e), E(0);
144
- }
164
+ Ce(e), k(0);
165
+ },
166
+ agentFilter: C,
167
+ onAgentChange: (e) => {
168
+ w(e), e !== "all" && E("all"), k(0);
169
+ },
170
+ agents: Oe,
171
+ vibeFilter: T,
172
+ onVibeChange: (e) => {
173
+ E(e), e !== "all" && w("all"), k(0);
174
+ },
175
+ vibes: Ae
145
176
  }),
146
- X.length > 0 ? /* @__PURE__ */ f("div", {
177
+ Q.length > 0 ? /* @__PURE__ */ d("div", {
147
178
  className: "rounded-lg border border-border-primary bg-bg-surface p-4",
148
- children: /* @__PURE__ */ p("div", {
179
+ children: /* @__PURE__ */ f("div", {
149
180
  className: "flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between",
150
- children: [/* @__PURE__ */ p("div", {
181
+ children: [/* @__PURE__ */ f("div", {
151
182
  className: "flex flex-wrap items-center gap-3",
152
- children: [/* @__PURE__ */ p("span", {
183
+ children: [/* @__PURE__ */ f("span", {
153
184
  className: "text-sm font-medium text-text-primary",
154
- children: [k.size, " selected"]
155
- }), k.size > 0 ? /* @__PURE__ */ f("button", {
185
+ children: [M.size, " selected"]
186
+ }), M.size > 0 ? /* @__PURE__ */ d("button", {
156
187
  type: "button",
157
- onClick: () => A(/* @__PURE__ */ new Set()),
188
+ onClick: () => N(/* @__PURE__ */ new Set()),
158
189
  className: "text-sm text-text-secondary transition-colors hover:text-text-primary",
159
190
  children: "Clear selection"
160
191
  }) : null]
161
- }), /* @__PURE__ */ f("div", {
192
+ }), /* @__PURE__ */ d("div", {
162
193
  className: "flex flex-wrap items-center gap-2",
163
- children: /* @__PURE__ */ p("button", {
194
+ children: /* @__PURE__ */ f("button", {
164
195
  type: "button",
165
- onClick: Ae,
166
- disabled: !B || k.size === 0,
196
+ onClick: He,
197
+ disabled: !V || M.size === 0,
167
198
  className: "rounded-md border border-status-error-border px-3 py-2 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg disabled:cursor-not-allowed disabled:opacity-50",
168
- children: ["Delete Selected", k.size > 0 ? ` (${k.size})` : ""]
199
+ children: ["Delete Selected", M.size > 0 ? ` (${M.size})` : ""]
169
200
  })
170
201
  })]
171
202
  })
172
203
  }) : null,
173
- U && !H ? /* @__PURE__ */ f(i, { message: R("audit.loadingLogs", "Loading audit logs...") }) : W ? /* @__PURE__ */ f(ne, {
174
- message: W.message,
175
- onRetry: () => G()
176
- }) : Z === 0 ? /* @__PURE__ */ f(re, {
177
- icon: /* @__PURE__ */ f(fe, {
204
+ G && !W ? /* @__PURE__ */ d(i, { message: z("audit.loadingLogs", "Loading audit logs...") }) : K ? /* @__PURE__ */ d(ie, {
205
+ message: K.message,
206
+ onRetry: () => q()
207
+ }) : Fe === 0 ? /* @__PURE__ */ d(oe, {
208
+ icon: /* @__PURE__ */ d(u, {
178
209
  size: 48,
179
210
  className: "text-text-secondary"
180
211
  }),
181
- title: R("audit.noLogs", "No audit logs"),
182
- description: R("audit.emptyDescription", "Audit logs will appear here as operations are performed in VibeControls."),
183
- action: /* @__PURE__ */ f(ie, { prompt: "What is the Audit Log in VibeControls and how do I use it?" })
184
- }) : /* @__PURE__ */ f(ae, {
185
- items: X,
186
- total: Z,
187
- hasMore: H?.vibeAuditLogs.hasMore ?? !1,
188
- page: T,
189
- pageSize: m,
190
- onPageChange: E,
191
- onSelectLog: O,
192
- onDeleteLog: De,
193
- selectedLogId: D,
194
- selectedLogIds: k,
195
- allVisibleSelected: $,
196
- partiallySelected: Te,
197
- onToggleLogSelection: Oe,
198
- onToggleAllVisible: ke
212
+ title: z("audit.noLogs", "No audit logs"),
213
+ description: z("audit.emptyDescription", "Audit logs will appear here as operations are performed in VibeControls."),
214
+ action: /* @__PURE__ */ d(se, { prompt: "What is the Audit Log in VibeControls and how do I use it?" })
215
+ }) : /* @__PURE__ */ d(ce, {
216
+ items: Q,
217
+ total: Fe,
218
+ hasMore: W?.vibeAuditLogs.hasMore ?? !1,
219
+ page: O,
220
+ pageSize: p,
221
+ onPageChange: k,
222
+ onSelectLog: j,
223
+ onDeleteLog: ze,
224
+ selectedLogId: A,
225
+ selectedLogIds: M,
226
+ allVisibleSelected: Ie,
227
+ partiallySelected: Le,
228
+ onToggleLogSelection: Be,
229
+ onToggleAllVisible: Ve
199
230
  }),
200
- D && K?.vibeAuditLog ? /* @__PURE__ */ f(se, {
201
- log: K.vibeAuditLog,
202
- onClose: () => O(null)
231
+ A && Y?.vibeAuditLog ? /* @__PURE__ */ d(ue, {
232
+ log: Y.vibeAuditLog,
233
+ onClose: () => j(null)
203
234
  }) : null,
204
- N ? /* @__PURE__ */ p("div", {
235
+ we ? /* @__PURE__ */ f("div", {
205
236
  role: "alert",
206
237
  className: "fixed bottom-4 right-4 z-50 rounded-md bg-status-error-bg px-4 py-3 text-sm text-status-error-text shadow-lg",
207
- children: [N, /* @__PURE__ */ f("button", {
238
+ children: [we, /* @__PURE__ */ d("button", {
208
239
  type: "button",
209
- onClick: J,
240
+ onClick: X,
210
241
  className: "ml-3 text-xs underline opacity-80 hover:opacity-100",
211
- children: R("common.dismiss", "Dismiss")
242
+ children: z("common.dismiss", "Dismiss")
212
243
  })]
213
244
  }) : null,
214
- F ? /* @__PURE__ */ p("div", {
245
+ Te ? /* @__PURE__ */ f("div", {
215
246
  role: "status",
216
247
  className: "fixed bottom-4 right-4 z-50 rounded-md bg-status-success-bg px-4 py-3 text-sm text-status-success-text shadow-lg",
217
- children: [F, /* @__PURE__ */ f("button", {
248
+ children: [Te, /* @__PURE__ */ d("button", {
218
249
  type: "button",
219
- onClick: Y,
250
+ onClick: Z,
220
251
  className: "ml-3 text-xs underline opacity-80 hover:opacity-100",
221
- children: R("common.dismiss", "Dismiss")
252
+ children: z("common.dismiss", "Dismiss")
222
253
  })]
223
254
  }) : null,
224
- /* @__PURE__ */ f(le, {
225
- isOpen: j.length > 0,
226
- onClose: () => M([]),
227
- onConfirm: Ee,
228
- loading: q,
229
- title: j.length > 1 ? "Delete Audit Logs" : "Delete Audit Log",
230
- description: j.length > 1 ? `This will permanently delete ${j.length} audit logs and record the reason in the audit trail.` : "This action will be recorded in the audit trail.",
231
- confirmLabel: j.length > 1 ? "Delete Logs" : "Delete"
255
+ /* @__PURE__ */ d(fe, {
256
+ isOpen: P.length > 0,
257
+ onClose: () => F([]),
258
+ onConfirm: Re,
259
+ loading: Ne,
260
+ title: P.length > 1 ? "Delete Audit Logs" : "Delete Audit Log",
261
+ description: P.length > 1 ? `This will permanently delete ${P.length} audit logs and record the reason in the audit trail.` : "This action will be recorded in the audit trail.",
262
+ confirmLabel: P.length > 1 ? "Delete Logs" : "Delete"
232
263
  })
233
264
  ]
234
265
  });
235
266
  }
236
267
  //#endregion
237
- export { h as VibeAuditPage };
268
+ export { m as VibeAuditPage };
238
269
 
239
270
  //# sourceMappingURL=VibeAuditPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VibeAuditPage.js","names":[],"sources":["../../src/pages/VibeAuditPage.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport { Shield } from 'lucide-react';\nimport { AccessDenied } from '@burdenoff/fe-libs/shared/components';\nimport { isNative, nativeNotify } from '../utils/nativeBridge';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n AuditDeleteDialog,\n AuditExportButton,\n AuditLogDetail,\n AuditLogFilters,\n AuditLogStats,\n AuditLogTable,\n} from '@/components/audit';\nimport {\n EmptyState,\n ErrorState,\n GetHelpButton,\n LoadingState,\n PageHeader,\n} from '@/components/shared';\nimport { VIBE_PERMISSIONS } from '@/constants/permissions';\nimport {\n useBulkDeleteVibeAuditLogsMutation,\n useDeleteVibeAuditLogMutation,\n useGetVibeAuditLogQuery,\n useVibeAuditDashboardQuery,\n} from '@/generated/wspace-operations';\nimport type {\n VibeAuditAction,\n VibeAuditLogFilterInput,\n VibeAuditResourceType,\n VibeAuditStatus,\n} from '@/generated/wspace-types';\nimport { useVibeControls } from '@/providers/VibeControlsProvider';\n\nconst PAGE_SIZE = 50;\n\nexport function VibeAuditPage() {\n useVibeControls();\n\n const { t } = useI18n();\n const { hasPermission, isLoading: permissionsLoading, permissions } = usePermissions();\n\n const [searchQuery, setSearchQuery] = useState('');\n const [debouncedSearchQuery, setDebouncedSearchQuery] = useState('');\n const [actionFilter, setActionFilter] = useState<string | null>('all');\n const [resourceTypeFilter, setResourceTypeFilter] = useState<string | null>('all');\n const [statusFilter, setStatusFilter] = useState<string | null>('all');\n const [hasCommandFilter, setHasCommandFilter] = useState(false);\n const [page, setPage] = useState(0);\n const [selectedLogId, setSelectedLogId] = useState<string | null>(null);\n const [selectedLogIds, setSelectedLogIds] = useState<Set<string>>(new Set());\n const [deleteTargetIds, setDeleteTargetIds] = useState<string[]>([]);\n const [deleteError, setDeleteError] = useState<string | null>(null);\n const [deleteSuccess, setDeleteSuccess] = useState<string | null>(null);\n\n const deleteErrorTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n\n const canListAudit = hasPermission(VIBE_PERMISSIONS.AUDIT_LIST);\n const canDeleteAudit = hasPermission(VIBE_PERMISSIONS.AUDIT_DELETE);\n const canExportAudit = hasPermission(VIBE_PERMISSIONS.AUDIT_EXPORT);\n const shouldSkipQueries = permissionsLoading || !canListAudit;\n\n const filter: VibeAuditLogFilterInput = {};\n if (debouncedSearchQuery) filter.search = debouncedSearchQuery;\n if (actionFilter && actionFilter !== 'all') filter.action = actionFilter as VibeAuditAction;\n if (resourceTypeFilter && resourceTypeFilter !== 'all')\n filter.resourceType = resourceTypeFilter as VibeAuditResourceType;\n if (statusFilter && statusFilter !== 'all') filter.status = statusFilter as VibeAuditStatus;\n if (hasCommandFilter) filter.hasCommand = true;\n\n const { data, loading, error, refetch } = useVibeAuditDashboardQuery({\n variables: {\n filter,\n pagination: { limit: Math.min(Math.max((page + 1) * PAGE_SIZE, PAGE_SIZE), 100) },\n },\n skip: shouldSkipQueries,\n fetchPolicy: 'cache-and-network',\n notifyOnNetworkStatusChange: true,\n });\n\n const { data: detailData } = useGetVibeAuditLogQuery({\n variables: { id: selectedLogId! },\n skip: !selectedLogId,\n });\n\n const [deleteAuditLog, { loading: deleteLoading }] = useDeleteVibeAuditLogMutation();\n const [bulkDeleteAuditLogs] = useBulkDeleteVibeAuditLogsMutation();\n\n useEffect(() => {\n const timeoutId = window.setTimeout(() => {\n setDebouncedSearchQuery(searchQuery);\n setPage(0);\n }, 300);\n\n return () => window.clearTimeout(timeoutId);\n }, [searchQuery]);\n\n useEffect(() => {\n return () => {\n if (deleteErrorTimer.current) {\n clearTimeout(deleteErrorTimer.current);\n }\n };\n }, []);\n\n const clearDeleteError = useCallback(() => {\n setDeleteError(null);\n if (deleteErrorTimer.current) {\n clearTimeout(deleteErrorTimer.current);\n deleteErrorTimer.current = null;\n }\n }, []);\n\n const clearDeleteSuccess = useCallback(() => {\n setDeleteSuccess(null);\n }, []);\n\n const allItems = data?.vibeAuditLogs.items ?? [];\n const items = allItems.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE);\n const totalAuditItems = data?.vibeAuditLogs.total ?? 0;\n const visibleLogIds = items.map((item: (typeof items)[number]) => item.id);\n const allVisibleSelected =\n visibleLogIds.length > 0 && visibleLogIds.every((id: string) => selectedLogIds.has(id));\n const partiallySelected =\n visibleLogIds.some((id: string) => selectedLogIds.has(id)) && !allVisibleSelected;\n\n const handleDelete = async (reason: string) => {\n if (deleteTargetIds.length === 0) return;\n\n clearDeleteError();\n clearDeleteSuccess();\n\n try {\n if (deleteTargetIds.length === 1) {\n await deleteAuditLog({ variables: { id: deleteTargetIds[0], input: { reason } } });\n setDeleteSuccess('Deleted 1 audit log');\n } else {\n const result = await bulkDeleteAuditLogs({\n variables: { ids: deleteTargetIds, input: { reason } },\n });\n const deletedCount = result.data?.bulkDeleteVibeAuditLogs.deletedCount ?? 0;\n const failedCount = result.data?.bulkDeleteVibeAuditLogs.failedCount ?? 0;\n setDeleteSuccess(\n `Deleted ${deletedCount} audit logs${failedCount > 0 ? ` • ${failedCount} failed` : ''}`\n );\n }\n\n setDeleteTargetIds([]);\n setSelectedLogIds((previous) => {\n const next = new Set(previous);\n deleteTargetIds.forEach((id) => next.delete(id));\n return next;\n });\n if (selectedLogId && deleteTargetIds.includes(selectedLogId)) {\n setSelectedLogId(null);\n }\n await refetch();\n if (isNative()) void nativeNotify('success');\n } catch (deleteAuditError) {\n console.error('Failed to delete audit log:', deleteAuditError);\n setDeleteError(tr('audit.deleteFailed', 'Failed to delete audit log. Please try again.'));\n if (isNative()) void nativeNotify('error');\n deleteErrorTimer.current = setTimeout(() => {\n setDeleteError(null);\n deleteErrorTimer.current = null;\n }, 30000);\n }\n };\n\n const handleOpenDelete = useCallback(\n (id: string) => {\n if (!canDeleteAudit) return;\n clearDeleteError();\n clearDeleteSuccess();\n setDeleteTargetIds([id]);\n },\n [canDeleteAudit, clearDeleteError, clearDeleteSuccess]\n );\n\n const handleToggleLogSelection = useCallback((id: string, checked: boolean) => {\n setSelectedLogIds((previous) => {\n const next = new Set(previous);\n if (checked) {\n next.add(id);\n } else {\n next.delete(id);\n }\n return next;\n });\n }, []);\n\n const handleToggleAllVisible = useCallback(\n (checked: boolean) => {\n setSelectedLogIds((previous) => {\n const next = new Set(previous);\n visibleLogIds.forEach((id: string) => {\n if (checked) {\n next.add(id);\n } else {\n next.delete(id);\n }\n });\n return next;\n });\n },\n [visibleLogIds]\n );\n\n const handleOpenBulkDelete = useCallback(() => {\n if (!canDeleteAudit || selectedLogIds.size === 0) return;\n clearDeleteError();\n clearDeleteSuccess();\n setDeleteTargetIds(Array.from(selectedLogIds));\n }, [canDeleteAudit, clearDeleteError, clearDeleteSuccess, selectedLogIds]);\n\n if (permissionsLoading) {\n return (\n <div className=\"mx-auto max-w-[1400px] p-4 sm:p-6\">\n <LoadingState message={tr('audit.loadingPermissions', 'Loading permissions...')} />\n </div>\n );\n }\n\n if (permissions && permissions.permissionStrings?.length > 0 && !canListAudit) {\n return (\n <AccessDenied\n title={tr('common.accessDeniedTitle', 'Access Denied')}\n description={tr(\n 'common.accessDeniedDescription',\n \"You don't have permission to access this resource.\"\n )}\n />\n );\n }\n\n return (\n <div className=\"mx-auto max-w-[1400px] p-4 sm:p-6\">\n <PageHeader\n title={tr('nav.vibeAudit', 'Audit')}\n description={tr(\n 'audit.description',\n 'Comprehensive audit trail of all VibeControls operations'\n )}\n actions={canExportAudit ? <AuditExportButton filter={filter} /> : undefined}\n />\n\n <AuditLogStats stats={data?.vibeAuditLogStats} loading={loading && !data} />\n\n <AuditLogFilters\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n actionFilter={actionFilter}\n onActionChange={(value) => {\n setActionFilter(value);\n setPage(0);\n }}\n resourceTypeFilter={resourceTypeFilter}\n onResourceTypeChange={(value) => {\n setResourceTypeFilter(value);\n setPage(0);\n }}\n statusFilter={statusFilter}\n onStatusChange={(value) => {\n setStatusFilter(value);\n setPage(0);\n }}\n hasCommandFilter={hasCommandFilter}\n onHasCommandChange={(value) => {\n setHasCommandFilter(value);\n setPage(0);\n }}\n />\n\n {items.length > 0 ? (\n <div className=\"rounded-lg border border-border-primary bg-bg-surface p-4\">\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"text-sm font-medium text-text-primary\">\n {selectedLogIds.size} selected\n </span>\n {selectedLogIds.size > 0 ? (\n <button\n type=\"button\"\n onClick={() => setSelectedLogIds(new Set())}\n className=\"text-sm text-text-secondary transition-colors hover:text-text-primary\"\n >\n Clear selection\n </button>\n ) : null}\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleOpenBulkDelete}\n disabled={!canDeleteAudit || selectedLogIds.size === 0}\n className=\"rounded-md border border-status-error-border px-3 py-2 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg disabled:cursor-not-allowed disabled:opacity-50\"\n >\n Delete Selected{selectedLogIds.size > 0 ? ` (${selectedLogIds.size})` : ''}\n </button>\n </div>\n </div>\n </div>\n ) : null}\n\n {loading && !data ? (\n <LoadingState message={tr('audit.loadingLogs', 'Loading audit logs...')} />\n ) : error ? (\n <ErrorState message={error.message} onRetry={() => refetch()} />\n ) : totalAuditItems === 0 ? (\n <EmptyState\n icon={<Shield size={48} className=\"text-text-secondary\" />}\n title={tr('audit.noLogs', 'No audit logs')}\n description={tr(\n 'audit.emptyDescription',\n 'Audit logs will appear here as operations are performed in VibeControls.'\n )}\n action={\n <GetHelpButton prompt=\"What is the Audit Log in VibeControls and how do I use it?\" />\n }\n />\n ) : (\n <AuditLogTable\n items={items}\n total={totalAuditItems}\n hasMore={data?.vibeAuditLogs.hasMore ?? false}\n page={page}\n pageSize={PAGE_SIZE}\n onPageChange={setPage}\n onSelectLog={setSelectedLogId}\n onDeleteLog={handleOpenDelete}\n selectedLogId={selectedLogId}\n selectedLogIds={selectedLogIds}\n allVisibleSelected={allVisibleSelected}\n partiallySelected={partiallySelected}\n onToggleLogSelection={handleToggleLogSelection}\n onToggleAllVisible={handleToggleAllVisible}\n />\n )}\n\n {selectedLogId && detailData?.vibeAuditLog ? (\n <AuditLogDetail log={detailData.vibeAuditLog} onClose={() => setSelectedLogId(null)} />\n ) : null}\n\n {deleteError ? (\n <div\n role=\"alert\"\n className=\"fixed bottom-4 right-4 z-50 rounded-md bg-status-error-bg px-4 py-3 text-sm text-status-error-text shadow-lg\"\n >\n {deleteError}\n <button\n type=\"button\"\n onClick={clearDeleteError}\n className=\"ml-3 text-xs underline opacity-80 hover:opacity-100\"\n >\n {tr('common.dismiss', 'Dismiss')}\n </button>\n </div>\n ) : null}\n\n {deleteSuccess ? (\n <div\n role=\"status\"\n className=\"fixed bottom-4 right-4 z-50 rounded-md bg-status-success-bg px-4 py-3 text-sm text-status-success-text shadow-lg\"\n >\n {deleteSuccess}\n <button\n type=\"button\"\n onClick={clearDeleteSuccess}\n className=\"ml-3 text-xs underline opacity-80 hover:opacity-100\"\n >\n {tr('common.dismiss', 'Dismiss')}\n </button>\n </div>\n ) : null}\n\n <AuditDeleteDialog\n isOpen={deleteTargetIds.length > 0}\n onClose={() => setDeleteTargetIds([])}\n onConfirm={handleDelete}\n loading={deleteLoading}\n title={deleteTargetIds.length > 1 ? 'Delete Audit Logs' : 'Delete Audit Log'}\n description={\n deleteTargetIds.length > 1\n ? `This will permanently delete ${deleteTargetIds.length} audit logs and record the reason in the audit trail.`\n : 'This action will be recorded in the audit trail.'\n }\n confirmLabel={deleteTargetIds.length > 1 ? 'Delete Logs' : 'Delete'}\n />\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"VibeAuditPage.js","names":[],"sources":["../../src/pages/VibeAuditPage.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport { Shield } from 'lucide-react';\nimport { AccessDenied } from '@burdenoff/fe-libs/shared/components';\nimport { isNative, nativeNotify } from '../utils/nativeBridge';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n AuditDeleteDialog,\n AuditExportButton,\n AuditLogDetail,\n AuditLogFilters,\n AuditLogStats,\n AuditLogTable,\n} from '@/components/audit';\nimport {\n EmptyState,\n ErrorState,\n GetHelpButton,\n LoadingState,\n PageHeader,\n} from '@/components/shared';\nimport { VIBE_PERMISSIONS } from '@/constants/permissions';\nimport {\n useBulkDeleteVibeAuditLogsMutation,\n useDeleteVibeAuditLogMutation,\n useGetVibeAuditLogQuery,\n useListAgentsQuery,\n useListVibesQuery,\n useVibeAuditDashboardQuery,\n} from '@/generated/wspace-operations';\nimport type {\n VibeAuditAction,\n VibeAuditLogFilterInput,\n VibeAuditResourceType,\n VibeAuditStatus,\n} from '@/generated/wspace-types';\nimport { useVibeControls } from '@/providers/VibeControlsProvider';\n\nconst PAGE_SIZE = 50;\n\nexport function VibeAuditPage() {\n useVibeControls();\n\n const { t } = useI18n();\n const { hasPermission, isLoading: permissionsLoading, permissions } = usePermissions();\n\n const [searchQuery, setSearchQuery] = useState('');\n const [debouncedSearchQuery, setDebouncedSearchQuery] = useState('');\n const [actionFilter, setActionFilter] = useState<string | null>('all');\n const [resourceTypeFilter, setResourceTypeFilter] = useState<string | null>('all');\n const [statusFilter, setStatusFilter] = useState<string | null>('all');\n const [agentFilter, setAgentFilter] = useState<string | null>('all');\n const [vibeFilter, setVibeFilter] = useState<string | null>('all');\n const [hasCommandFilter, setHasCommandFilter] = useState(false);\n const [page, setPage] = useState(0);\n const [selectedLogId, setSelectedLogId] = useState<string | null>(null);\n const [selectedLogIds, setSelectedLogIds] = useState<Set<string>>(new Set());\n const [deleteTargetIds, setDeleteTargetIds] = useState<string[]>([]);\n const [deleteError, setDeleteError] = useState<string | null>(null);\n const [deleteSuccess, setDeleteSuccess] = useState<string | null>(null);\n\n const deleteErrorTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n\n const canListAudit = hasPermission(VIBE_PERMISSIONS.AUDIT_LIST);\n const canDeleteAudit = hasPermission(VIBE_PERMISSIONS.AUDIT_DELETE);\n const canExportAudit = hasPermission(VIBE_PERMISSIONS.AUDIT_EXPORT);\n const shouldSkipQueries = permissionsLoading || !canListAudit;\n\n const filter: VibeAuditLogFilterInput = {};\n if (debouncedSearchQuery) filter.search = debouncedSearchQuery;\n if (actionFilter && actionFilter !== 'all') filter.action = actionFilter as VibeAuditAction;\n if (resourceTypeFilter && resourceTypeFilter !== 'all')\n filter.resourceType = resourceTypeFilter as VibeAuditResourceType;\n if (statusFilter && statusFilter !== 'all') filter.status = statusFilter as VibeAuditStatus;\n if (hasCommandFilter) filter.hasCommand = true;\n // Agent / Vibe filters: backend exposes `resourceId` + `resourceType`.\n // We narrow `resourceType` accordingly so the server returns only audit\n // rows whose target is the chosen agent / vibe. If the user already\n // chose a resourceType that conflicts (e.g. SESSION), the resourceId\n // filter would over-narrow — but that combination is documented as\n // intentional power-user behaviour.\n if (agentFilter && agentFilter !== 'all') {\n filter.resourceId = agentFilter;\n if (!filter.resourceType) filter.resourceType = 'AGENT' as VibeAuditResourceType;\n } else if (vibeFilter && vibeFilter !== 'all') {\n filter.resourceId = vibeFilter;\n if (!filter.resourceType) filter.resourceType = 'VIBE' as VibeAuditResourceType;\n }\n\n const { data, loading, error, refetch } = useVibeAuditDashboardQuery({\n variables: {\n filter,\n pagination: { limit: Math.min(Math.max((page + 1) * PAGE_SIZE, PAGE_SIZE), 100) },\n },\n skip: shouldSkipQueries,\n fetchPolicy: 'cache-and-network',\n notifyOnNetworkStatusChange: true,\n });\n\n const { data: agentsData } = useListAgentsQuery({\n variables: { pagination: { limit: 200 } },\n fetchPolicy: 'cache-first',\n skip: shouldSkipQueries,\n });\n const agentsList = (agentsData?.vibecontrolsAgents ?? []).map(\n (a: { id: string; name: string }) => ({ id: a.id, name: a.name })\n );\n\n const { data: vibesData } = useListVibesQuery({\n variables: { pagination: { limit: 200 } },\n fetchPolicy: 'cache-first',\n skip: shouldSkipQueries,\n });\n const vibesList = (vibesData?.vibes?.items ?? []).map((v: { id: string; name: string }) => ({\n id: v.id,\n name: v.name,\n }));\n\n const retentionDays = data?.vibeAuditLogStats?.retentionPolicy?.retentionDays ?? 90;\n const nextCleanupAt = data?.vibeAuditLogStats?.retentionPolicy?.nextCleanup ?? null;\n\n const { data: detailData } = useGetVibeAuditLogQuery({\n variables: { id: selectedLogId! },\n skip: !selectedLogId,\n });\n\n const [deleteAuditLog, { loading: deleteLoading }] = useDeleteVibeAuditLogMutation();\n const [bulkDeleteAuditLogs] = useBulkDeleteVibeAuditLogsMutation();\n\n useEffect(() => {\n const timeoutId = window.setTimeout(() => {\n setDebouncedSearchQuery(searchQuery);\n setPage(0);\n }, 300);\n\n return () => window.clearTimeout(timeoutId);\n }, [searchQuery]);\n\n useEffect(() => {\n return () => {\n if (deleteErrorTimer.current) {\n clearTimeout(deleteErrorTimer.current);\n }\n };\n }, []);\n\n const clearDeleteError = useCallback(() => {\n setDeleteError(null);\n if (deleteErrorTimer.current) {\n clearTimeout(deleteErrorTimer.current);\n deleteErrorTimer.current = null;\n }\n }, []);\n\n const clearDeleteSuccess = useCallback(() => {\n setDeleteSuccess(null);\n }, []);\n\n const allItems = data?.vibeAuditLogs.items ?? [];\n const items = allItems.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE);\n const totalAuditItems = data?.vibeAuditLogs.total ?? 0;\n const visibleLogIds = items.map((item: (typeof items)[number]) => item.id);\n const allVisibleSelected =\n visibleLogIds.length > 0 && visibleLogIds.every((id: string) => selectedLogIds.has(id));\n const partiallySelected =\n visibleLogIds.some((id: string) => selectedLogIds.has(id)) && !allVisibleSelected;\n\n const handleDelete = async (reason: string) => {\n if (deleteTargetIds.length === 0) return;\n\n clearDeleteError();\n clearDeleteSuccess();\n\n try {\n if (deleteTargetIds.length === 1) {\n await deleteAuditLog({ variables: { id: deleteTargetIds[0], input: { reason } } });\n setDeleteSuccess('Deleted 1 audit log');\n } else {\n const result = await bulkDeleteAuditLogs({\n variables: { ids: deleteTargetIds, input: { reason } },\n });\n const deletedCount = result.data?.bulkDeleteVibeAuditLogs.deletedCount ?? 0;\n const failedCount = result.data?.bulkDeleteVibeAuditLogs.failedCount ?? 0;\n setDeleteSuccess(\n `Deleted ${deletedCount} audit logs${failedCount > 0 ? ` • ${failedCount} failed` : ''}`\n );\n }\n\n setDeleteTargetIds([]);\n setSelectedLogIds((previous) => {\n const next = new Set(previous);\n deleteTargetIds.forEach((id) => next.delete(id));\n return next;\n });\n if (selectedLogId && deleteTargetIds.includes(selectedLogId)) {\n setSelectedLogId(null);\n }\n await refetch();\n if (isNative()) void nativeNotify('success');\n } catch (deleteAuditError) {\n console.error('Failed to delete audit log:', deleteAuditError);\n setDeleteError(tr('audit.deleteFailed', 'Failed to delete audit log. Please try again.'));\n if (isNative()) void nativeNotify('error');\n deleteErrorTimer.current = setTimeout(() => {\n setDeleteError(null);\n deleteErrorTimer.current = null;\n }, 30000);\n }\n };\n\n const handleOpenDelete = useCallback(\n (id: string) => {\n if (!canDeleteAudit) return;\n clearDeleteError();\n clearDeleteSuccess();\n setDeleteTargetIds([id]);\n },\n [canDeleteAudit, clearDeleteError, clearDeleteSuccess]\n );\n\n const handleToggleLogSelection = useCallback((id: string, checked: boolean) => {\n setSelectedLogIds((previous) => {\n const next = new Set(previous);\n if (checked) {\n next.add(id);\n } else {\n next.delete(id);\n }\n return next;\n });\n }, []);\n\n const handleToggleAllVisible = useCallback(\n (checked: boolean) => {\n setSelectedLogIds((previous) => {\n const next = new Set(previous);\n visibleLogIds.forEach((id: string) => {\n if (checked) {\n next.add(id);\n } else {\n next.delete(id);\n }\n });\n return next;\n });\n },\n [visibleLogIds]\n );\n\n const handleOpenBulkDelete = useCallback(() => {\n if (!canDeleteAudit || selectedLogIds.size === 0) return;\n clearDeleteError();\n clearDeleteSuccess();\n setDeleteTargetIds(Array.from(selectedLogIds));\n }, [canDeleteAudit, clearDeleteError, clearDeleteSuccess, selectedLogIds]);\n\n if (permissionsLoading) {\n return (\n <div className=\"mx-auto max-w-[1400px] p-4 sm:p-6\">\n <LoadingState message={tr('audit.loadingPermissions', 'Loading permissions...')} />\n </div>\n );\n }\n\n if (permissions && permissions.permissionStrings?.length > 0 && !canListAudit) {\n return (\n <AccessDenied\n title={tr('common.accessDeniedTitle', 'Access Denied')}\n description={tr(\n 'common.accessDeniedDescription',\n \"You don't have permission to access this resource.\"\n )}\n />\n );\n }\n\n return (\n <div className=\"mx-auto max-w-[1400px] p-4 sm:p-6\">\n <PageHeader\n title={tr('nav.vibeAudit', 'Audit')}\n description={tr(\n 'audit.description',\n 'Comprehensive audit trail of all VibeControls operations'\n )}\n actions={canExportAudit ? <AuditExportButton filter={filter} /> : undefined}\n />\n\n {/* Retention banner — sourced from the backend `retentionPolicy`\n so the displayed window updates if the tier changes. */}\n <div className=\"mb-4 flex items-start gap-2 rounded-md border border-status-info-border bg-status-info-bg/10 px-3 py-2 text-xs text-status-info-text\">\n <Shield size={14} className=\"mt-0.5 flex-shrink-0\" />\n <span>\n {tr(\n 'audit.retentionBanner',\n `Audit logs are kept for ${retentionDays} days. Older entries are automatically purged.`\n )}\n {nextCleanupAt\n ? ` ${tr('audit.retentionNextCleanup', `Next cleanup: ${new Date(nextCleanupAt).toLocaleString()}.`)}`\n : ''}\n </span>\n </div>\n\n <AuditLogStats stats={data?.vibeAuditLogStats} loading={loading && !data} />\n\n <AuditLogFilters\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n actionFilter={actionFilter}\n onActionChange={(value) => {\n setActionFilter(value);\n setPage(0);\n }}\n resourceTypeFilter={resourceTypeFilter}\n onResourceTypeChange={(value) => {\n setResourceTypeFilter(value);\n setPage(0);\n }}\n statusFilter={statusFilter}\n onStatusChange={(value) => {\n setStatusFilter(value);\n setPage(0);\n }}\n hasCommandFilter={hasCommandFilter}\n onHasCommandChange={(value) => {\n setHasCommandFilter(value);\n setPage(0);\n }}\n agentFilter={agentFilter}\n onAgentChange={(value) => {\n setAgentFilter(value);\n // Agent + Vibe are mutually exclusive via resourceId — clearing one when\n // the other is set keeps the resolved filter input coherent.\n if (value !== 'all') setVibeFilter('all');\n setPage(0);\n }}\n agents={agentsList}\n vibeFilter={vibeFilter}\n onVibeChange={(value) => {\n setVibeFilter(value);\n if (value !== 'all') setAgentFilter('all');\n setPage(0);\n }}\n vibes={vibesList}\n />\n\n {items.length > 0 ? (\n <div className=\"rounded-lg border border-border-primary bg-bg-surface p-4\">\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"text-sm font-medium text-text-primary\">\n {selectedLogIds.size} selected\n </span>\n {selectedLogIds.size > 0 ? (\n <button\n type=\"button\"\n onClick={() => setSelectedLogIds(new Set())}\n className=\"text-sm text-text-secondary transition-colors hover:text-text-primary\"\n >\n Clear selection\n </button>\n ) : null}\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleOpenBulkDelete}\n disabled={!canDeleteAudit || selectedLogIds.size === 0}\n className=\"rounded-md border border-status-error-border px-3 py-2 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg disabled:cursor-not-allowed disabled:opacity-50\"\n >\n Delete Selected{selectedLogIds.size > 0 ? ` (${selectedLogIds.size})` : ''}\n </button>\n </div>\n </div>\n </div>\n ) : null}\n\n {loading && !data ? (\n <LoadingState message={tr('audit.loadingLogs', 'Loading audit logs...')} />\n ) : error ? (\n <ErrorState message={error.message} onRetry={() => refetch()} />\n ) : totalAuditItems === 0 ? (\n <EmptyState\n icon={<Shield size={48} className=\"text-text-secondary\" />}\n title={tr('audit.noLogs', 'No audit logs')}\n description={tr(\n 'audit.emptyDescription',\n 'Audit logs will appear here as operations are performed in VibeControls.'\n )}\n action={\n <GetHelpButton prompt=\"What is the Audit Log in VibeControls and how do I use it?\" />\n }\n />\n ) : (\n <AuditLogTable\n items={items}\n total={totalAuditItems}\n hasMore={data?.vibeAuditLogs.hasMore ?? false}\n page={page}\n pageSize={PAGE_SIZE}\n onPageChange={setPage}\n onSelectLog={setSelectedLogId}\n onDeleteLog={handleOpenDelete}\n selectedLogId={selectedLogId}\n selectedLogIds={selectedLogIds}\n allVisibleSelected={allVisibleSelected}\n partiallySelected={partiallySelected}\n onToggleLogSelection={handleToggleLogSelection}\n onToggleAllVisible={handleToggleAllVisible}\n />\n )}\n\n {selectedLogId && detailData?.vibeAuditLog ? (\n <AuditLogDetail log={detailData.vibeAuditLog} onClose={() => setSelectedLogId(null)} />\n ) : null}\n\n {deleteError ? (\n <div\n role=\"alert\"\n className=\"fixed bottom-4 right-4 z-50 rounded-md bg-status-error-bg px-4 py-3 text-sm text-status-error-text shadow-lg\"\n >\n {deleteError}\n <button\n type=\"button\"\n onClick={clearDeleteError}\n className=\"ml-3 text-xs underline opacity-80 hover:opacity-100\"\n >\n {tr('common.dismiss', 'Dismiss')}\n </button>\n </div>\n ) : null}\n\n {deleteSuccess ? (\n <div\n role=\"status\"\n className=\"fixed bottom-4 right-4 z-50 rounded-md bg-status-success-bg px-4 py-3 text-sm text-status-success-text shadow-lg\"\n >\n {deleteSuccess}\n <button\n type=\"button\"\n onClick={clearDeleteSuccess}\n className=\"ml-3 text-xs underline opacity-80 hover:opacity-100\"\n >\n {tr('common.dismiss', 'Dismiss')}\n </button>\n </div>\n ) : null}\n\n <AuditDeleteDialog\n isOpen={deleteTargetIds.length > 0}\n onClose={() => setDeleteTargetIds([])}\n onConfirm={handleDelete}\n loading={deleteLoading}\n title={deleteTargetIds.length > 1 ? 'Delete Audit Logs' : 'Delete Audit Log'}\n description={\n deleteTargetIds.length > 1\n ? `This will permanently delete ${deleteTargetIds.length} audit logs and record the reason in the audit trail.`\n : 'This action will be recorded in the audit trail.'\n }\n confirmLabel={deleteTargetIds.length > 1 ? 'Delete Logs' : 'Delete'}\n />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAsCA,IAAM,IAAY;AAElB,SAAgB,IAAgB;AAC9B,KAAiB;CAEjB,IAAM,EAAE,SAAM,IAAS,EACjB,EAAE,kBAAe,WAAW,GAAoB,mBAAgB,IAAgB,EAEhF,CAAC,GAAa,MAAkB,EAAS,GAAG,EAC5C,CAAC,GAAsB,MAA2B,EAAS,GAAG,EAC9D,CAAC,GAAc,MAAmB,EAAwB,MAAM,EAChE,CAAC,GAAoB,MAAyB,EAAwB,MAAM,EAC5E,CAAC,GAAc,MAAmB,EAAwB,MAAM,EAChE,CAAC,GAAa,KAAkB,EAAwB,MAAM,EAC9D,CAAC,GAAY,KAAiB,EAAwB,MAAM,EAC5D,CAAC,GAAkB,MAAuB,EAAS,GAAM,EACzD,CAAC,GAAM,KAAW,EAAS,EAAE,EAC7B,CAAC,GAAe,KAAoB,EAAwB,KAAK,EACjE,CAAC,GAAgB,KAAqB,kBAAsB,IAAI,KAAK,CAAC,EACtE,CAAC,GAAiB,KAAsB,EAAmB,EAAE,CAAC,EAC9D,CAAC,IAAa,KAAkB,EAAwB,KAAK,EAC7D,CAAC,IAAe,KAAoB,EAAwB,KAAK,EAEjE,IAAmB,GAA6C,KAAK,EAErE,IAAK,GACR,GAAa,MAA6B;EACzC,IAAM,IAAQ,EAAE,EAAI;AACpB,SAAO,MAAU,IAAM,IAAW;IAEpC,CAAC,EAAE,CACJ,EAEK,IAAe,EAAc,EAAiB,WAAW,EACzD,IAAiB,EAAc,EAAiB,aAAa,EAC7D,KAAiB,EAAc,EAAiB,aAAa,EAC7D,IAAoB,KAAsB,CAAC,GAE3C,IAAkC,EAAE;AAa1C,CAZI,MAAsB,EAAO,SAAS,IACtC,KAAgB,MAAiB,UAAO,EAAO,SAAS,IACxD,KAAsB,MAAuB,UAC/C,EAAO,eAAe,IACpB,KAAgB,MAAiB,UAAO,EAAO,SAAS,IACxD,MAAkB,EAAO,aAAa,KAOtC,KAAe,MAAgB,SACjC,EAAO,aAAa,GACpB,AAA0B,EAAO,iBAAe,WACvC,KAAc,MAAe,UACtC,EAAO,aAAa,GACpB,AAA0B,EAAO,iBAAe;CAGlD,IAAM,EAAE,SAAM,YAAS,UAAO,eAAY,GAA2B;EACnE,WAAW;GACT;GACA,YAAY,EAAE,OAAO,KAAK,IAAI,KAAK,KAAK,IAAO,KAAK,GAAW,EAAU,EAAE,IAAI,EAAE;GAClF;EACD,MAAM;EACN,aAAa;EACb,6BAA6B;EAC9B,CAAC,EAEI,EAAE,MAAM,OAAe,EAAmB;EAC9C,WAAW,EAAE,YAAY,EAAE,OAAO,KAAK,EAAE;EACzC,aAAa;EACb,MAAM;EACP,CAAC,EACI,MAAc,IAAY,sBAAsB,EAAE,EAAE,KACvD,OAAqC;EAAE,IAAI,EAAE;EAAI,MAAM,EAAE;EAAM,EACjE,EAEK,EAAE,MAAM,OAAc,GAAkB;EAC5C,WAAW,EAAE,YAAY,EAAE,OAAO,KAAK,EAAE;EACzC,aAAa;EACb,MAAM;EACP,CAAC,EACI,MAAa,IAAW,OAAO,SAAS,EAAE,EAAE,KAAK,OAAqC;EAC1F,IAAI,EAAE;EACN,MAAM,EAAE;EACT,EAAE,EAEG,KAAgB,GAAM,mBAAmB,iBAAiB,iBAAiB,IAC3E,IAAgB,GAAM,mBAAmB,iBAAiB,eAAe,MAEzE,EAAE,MAAM,MAAe,EAAwB;EACnD,WAAW,EAAE,IAAI,GAAgB;EACjC,MAAM,CAAC;EACR,CAAC,EAEI,CAAC,IAAgB,EAAE,SAAS,QAAmB,GAA+B,EAC9E,CAAC,MAAuB,GAAoC;AAWlE,CATA,QAAgB;EACd,IAAM,IAAY,OAAO,iBAAiB;AAExC,GADA,GAAwB,EAAY,EACpC,EAAQ,EAAE;KACT,IAAI;AAEP,eAAa,OAAO,aAAa,EAAU;IAC1C,CAAC,EAAY,CAAC,EAEjB,cACe;AACX,EAAI,EAAiB,WACnB,aAAa,EAAiB,QAAQ;IAGzC,EAAE,CAAC;CAEN,IAAM,IAAmB,QAAkB;AAEzC,EADA,EAAe,KAAK,EACpB,AAEE,EAAiB,aADjB,aAAa,EAAiB,QAAQ,EACX;IAE5B,EAAE,CAAC,EAEA,IAAqB,QAAkB;AAC3C,IAAiB,KAAK;IACrB,EAAE,CAAC,EAGA,KADW,GAAM,cAAc,SAAS,EAAE,EACzB,MAAM,IAAO,IAAY,IAAO,KAAK,EAAU,EAChE,KAAkB,GAAM,cAAc,SAAS,GAC/C,IAAgB,EAAM,KAAK,MAAiC,EAAK,GAAG,EACpE,KACJ,EAAc,SAAS,KAAK,EAAc,OAAO,MAAe,EAAe,IAAI,EAAG,CAAC,EACnF,KACJ,EAAc,MAAM,MAAe,EAAe,IAAI,EAAG,CAAC,IAAI,CAAC,IAE3D,KAAe,OAAO,MAAmB;AACzC,QAAgB,WAAW,GAG/B;GADA,GAAkB,EAClB,GAAoB;AAEpB,OAAI;AACF,QAAI,EAAgB,WAAW,EAE7B,CADA,MAAM,GAAe,EAAE,WAAW;KAAE,IAAI,EAAgB;KAAI,OAAO,EAAE,WAAQ;KAAE,EAAE,CAAC,EAClF,EAAiB,sBAAsB;SAClC;KACL,IAAM,IAAS,MAAM,GAAoB,EACvC,WAAW;MAAE,KAAK;MAAiB,OAAO,EAAE,WAAQ;MAAE,EACvD,CAAC,EACI,IAAe,EAAO,MAAM,wBAAwB,gBAAgB,GACpE,IAAc,EAAO,MAAM,wBAAwB,eAAe;AACxE,OACE,WAAW,EAAa,aAAa,IAAc,IAAI,MAAM,EAAY,WAAW,KACrF;;AAaH,IAVA,EAAmB,EAAE,CAAC,EACtB,GAAmB,MAAa;KAC9B,IAAM,IAAO,IAAI,IAAI,EAAS;AAE9B,YADA,EAAgB,SAAS,MAAO,EAAK,OAAO,EAAG,CAAC,EACzC;MACP,EACE,KAAiB,EAAgB,SAAS,EAAc,IAC1D,EAAiB,KAAK,EAExB,MAAM,GAAS,EACX,IAAU,IAAO,EAAa,UAAU;YACrC,GAAkB;AAIzB,IAHA,QAAQ,MAAM,+BAA+B,EAAiB,EAC9D,EAAe,EAAG,sBAAsB,gDAAgD,CAAC,EACrF,IAAU,IAAO,EAAa,QAAQ,EAC1C,EAAiB,UAAU,iBAAiB;AAE1C,KADA,EAAe,KAAK,EACpB,EAAiB,UAAU;OAC1B,IAAM;;;IAIP,KAAmB,GACtB,MAAe;AACT,QACL,GAAkB,EAClB,GAAoB,EACpB,EAAmB,CAAC,EAAG,CAAC;IAE1B;EAAC;EAAgB;EAAkB;EAAmB,CACvD,EAEK,KAA2B,GAAa,GAAY,MAAqB;AAC7E,KAAmB,MAAa;GAC9B,IAAM,IAAO,IAAI,IAAI,EAAS;AAM9B,UALI,IACF,EAAK,IAAI,EAAG,GAEZ,EAAK,OAAO,EAAG,EAEV;IACP;IACD,EAAE,CAAC,EAEA,KAAyB,GAC5B,MAAqB;AACpB,KAAmB,MAAa;GAC9B,IAAM,IAAO,IAAI,IAAI,EAAS;AAQ9B,UAPA,EAAc,SAAS,MAAe;AACpC,IAAI,IACF,EAAK,IAAI,EAAG,GAEZ,EAAK,OAAO,EAAG;KAEjB,EACK;IACP;IAEJ,CAAC,EAAc,CAChB,EAEK,KAAuB,QAAkB;AACzC,GAAC,KAAkB,EAAe,SAAS,MAC/C,GAAkB,EAClB,GAAoB,EACpB,EAAmB,MAAM,KAAK,EAAe,CAAC;IAC7C;EAAC;EAAgB;EAAkB;EAAoB;EAAe,CAAC;AAsB1E,QApBI,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD,EAAc,SAAS,EAAG,4BAA4B,yBAAyB,EAAI,CAAA;EAC/E,CAAA,GAIN,KAAe,EAAY,mBAAmB,SAAS,KAAK,CAAC,IAE7D,kBAAC,IAAD;EACE,OAAO,EAAG,4BAA4B,gBAAgB;EACtD,aAAa,EACX,kCACA,qDACD;EACD,CAAA,GAKJ,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,IAAD;IACE,OAAO,EAAG,iBAAiB,QAAQ;IACnC,aAAa,EACX,qBACA,2DACD;IACD,SAAS,KAAiB,kBAAC,IAAD,EAA2B,WAAU,CAAA,GAAG,KAAA;IAClE,CAAA;GAIF,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAQ,MAAM;KAAI,WAAU;KAAyB,CAAA,EACrD,kBAAC,QAAD,EAAA,UAAA,CACG,EACC,yBACA,2BAA2B,GAAc,gDAC1C,EACA,IACG,IAAI,EAAG,8BAA8B,iBAAiB,IAAI,KAAK,EAAc,CAAC,gBAAgB,CAAC,GAAG,KAClG,GACC,EAAA,CAAA,CACH;;GAEN,kBAAC,IAAD;IAAe,OAAO,GAAM;IAAmB,SAAS,KAAW,CAAC;IAAQ,CAAA;GAE5E,kBAAC,IAAD;IACe;IACb,gBAAgB;IACF;IACd,iBAAiB,MAAU;AAEzB,KADA,GAAgB,EAAM,EACtB,EAAQ,EAAE;;IAEQ;IACpB,uBAAuB,MAAU;AAE/B,KADA,GAAsB,EAAM,EAC5B,EAAQ,EAAE;;IAEE;IACd,iBAAiB,MAAU;AAEzB,KADA,GAAgB,EAAM,EACtB,EAAQ,EAAE;;IAEM;IAClB,qBAAqB,MAAU;AAE7B,KADA,GAAoB,EAAM,EAC1B,EAAQ,EAAE;;IAEC;IACb,gBAAgB,MAAU;AAKxB,KAJA,EAAe,EAAM,EAGjB,MAAU,SAAO,EAAc,MAAM,EACzC,EAAQ,EAAE;;IAEZ,QAAQ;IACI;IACZ,eAAe,MAAU;AAGvB,KAFA,EAAc,EAAM,EAChB,MAAU,SAAO,EAAe,MAAM,EAC1C,EAAQ,EAAE;;IAEZ,OAAO;IACP,CAAA;GAED,EAAM,SAAS,IACd,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAhB,CACG,EAAe,MAAK,YAChB;UACN,EAAe,OAAO,IACrB,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,kBAAkB,IAAI,KAAK,CAAC;OAC3C,WAAU;iBACX;OAEQ,CAAA,GACP,KACA;SACN,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,UAAD;OACE,MAAK;OACL,SAAS;OACT,UAAU,CAAC,KAAkB,EAAe,SAAS;OACrD,WAAU;iBAJZ,CAKC,mBACiB,EAAe,OAAO,IAAI,KAAK,EAAe,KAAK,KAAK,GACjE;;MACL,CAAA,CACF;;IACF,CAAA,GACJ;GAEH,KAAW,CAAC,IACX,kBAAC,GAAD,EAAc,SAAS,EAAG,qBAAqB,wBAAwB,EAAI,CAAA,GACzE,IACF,kBAAC,IAAD;IAAY,SAAS,EAAM;IAAS,eAAe,GAAS;IAAI,CAAA,GAC9D,OAAoB,IACtB,kBAAC,IAAD;IACE,MAAM,kBAAC,GAAD;KAAQ,MAAM;KAAI,WAAU;KAAwB,CAAA;IAC1D,OAAO,EAAG,gBAAgB,gBAAgB;IAC1C,aAAa,EACX,0BACA,2EACD;IACD,QACE,kBAAC,IAAD,EAAe,QAAO,8DAA+D,CAAA;IAEvF,CAAA,GAEF,kBAAC,IAAD;IACS;IACP,OAAO;IACP,SAAS,GAAM,cAAc,WAAW;IAClC;IACN,UAAU;IACV,cAAc;IACd,aAAa;IACb,aAAa;IACE;IACC;IACI;IACD;IACnB,sBAAsB;IACtB,oBAAoB;IACpB,CAAA;GAGH,KAAiB,GAAY,eAC5B,kBAAC,IAAD;IAAgB,KAAK,EAAW;IAAc,eAAe,EAAiB,KAAK;IAAI,CAAA,GACrF;GAEH,KACC,kBAAC,OAAD;IACE,MAAK;IACL,WAAU;cAFZ,CAIG,IACD,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;eAET,EAAG,kBAAkB,UAAU;KACzB,CAAA,CACL;QACJ;GAEH,KACC,kBAAC,OAAD;IACE,MAAK;IACL,WAAU;cAFZ,CAIG,IACD,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;eAET,EAAG,kBAAkB,UAAU;KACzB,CAAA,CACL;QACJ;GAEJ,kBAAC,IAAD;IACE,QAAQ,EAAgB,SAAS;IACjC,eAAe,EAAmB,EAAE,CAAC;IACrC,WAAW;IACX,SAAS;IACT,OAAO,EAAgB,SAAS,IAAI,sBAAsB;IAC1D,aACE,EAAgB,SAAS,IACrB,gCAAgC,EAAgB,OAAO,yDACvD;IAEN,cAAc,EAAgB,SAAS,IAAI,gBAAgB;IAC3D,CAAA;GACE"}