@burdenoff/microfe-vibecontrols 2026.528.4 → 2026.528.6

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.
@@ -26,81 +26,82 @@ import { useCallback as c, useEffect as Ce, useMemo as l, useRef as u, useState
26
26
  import { useI18n as we } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
27
27
  import { useUpgradePrompt as Te } from "@burdenoff/fe-libs/shared/hooks";
28
28
  import { Archive as Ee, Grid as De, List as Oe, Play as ke, Plus as Ae, RefreshCw as je, Zap as Me } from "lucide-react";
29
- import { usePermissions as Ne } from "@burdenoff/fe-libs/shared/providers/shell";
30
- import { AnimatePresence as Pe } from "framer-motion";
31
- import { Fragment as Fe, jsx as f, jsxs as p } from "react/jsx-runtime";
32
- import { MotionItem as Ie, MotionList as m, MotionPage as Le } from "@burdenoff/fe-libs/shared/motion";
33
- import { AccessDenied as Re, PermissionButton as ze, PermissionGate as Be } from "@burdenoff/fe-libs/shared/components";
29
+ import { useSearchParams as Ne } from "react-router-dom";
30
+ import { usePermissions as Pe } from "@burdenoff/fe-libs/shared/providers/shell";
31
+ import { AnimatePresence as Fe } from "framer-motion";
32
+ import { Fragment as Ie, jsx as f, jsxs as p } from "react/jsx-runtime";
33
+ import { MotionItem as Le, MotionList as m, MotionPage as Re } from "@burdenoff/fe-libs/shared/motion";
34
+ import { AccessDenied as ze, PermissionButton as Be, PermissionGate as Ve } from "@burdenoff/fe-libs/shared/components";
34
35
  //#region src/pages/VibesPage.tsx
35
36
  function h() {
36
- let { onVibeActivate: h } = re(), g = ie(), { hasPermission: _, isLoading: v, permissions: y } = Ne(), { t: b } = we(), { isFree: Ve, approachingLimits: He } = Te({ resource: "vibes" }), x = He[0], S = c((e, t, n) => {
37
- let r = b(e, n), i = r === e ? t : r;
37
+ let { onVibeActivate: h } = re(), g = ie(), { hasPermission: _, isLoading: v, permissions: He } = Pe(), { t: Ue } = we(), { isFree: We, approachingLimits: Ge } = Te({ resource: "vibes" }), y = Ge[0], b = c((e, t, n) => {
38
+ let r = Ue(e, n), i = r === e ? t : r;
38
39
  return n ? Object.entries(n).reduce((e, [t, n]) => e.replace(`{{${t}}}`, String(n)), i) : i;
39
- }, [b]), Ue = [
40
+ }, [Ue]), Ke = [
40
41
  {
41
42
  value: "all",
42
- label: S("vibesPage.statusAll", "All Statuses")
43
+ label: b("vibesPage.statusAll", "All Statuses")
43
44
  },
44
45
  {
45
46
  value: "ACTIVE",
46
- label: S("vibesPage.statusActive", "Active")
47
+ label: b("vibesPage.statusActive", "Active")
47
48
  },
48
49
  {
49
50
  value: "INACTIVE",
50
- label: S("vibesPage.statusInactive", "Inactive")
51
+ label: b("vibesPage.statusInactive", "Inactive")
51
52
  },
52
53
  {
53
54
  value: "ARCHIVED",
54
- label: S("vibesPage.statusArchived", "Archived")
55
+ label: b("vibesPage.statusArchived", "Archived")
55
56
  },
56
57
  {
57
58
  value: "ERROR",
58
- label: S("vibesPage.statusError", "Error")
59
+ label: b("vibesPage.statusError", "Error")
59
60
  }
60
61
  ];
61
- S("vibesPage.typeAll", "All Types"), S("vibesPage.typeProject", "Project"), S("vibesPage.typeRepository", "Repository"), S("vibesPage.typeWorkspace", "Workspace"), S("vibesPage.typeMonorepo", "Monorepo"), S("vibesPage.typePackage", "Package"), S("vibesPage.typeCustom", "Custom");
62
- let C = _(s.VIBE_LIST), We = _(s.VIBE_UPDATE), w = v || !C, [T, Ge] = d(""), [E, Ke] = d("all"), [D, qe] = d("all"), [O, Je] = d("all"), [k, Ye] = d("grid"), [Xe, A] = d(!1), [Ze, j] = d(null), [M, Qe] = d(!1), [N, P] = d(null), [$e, F] = d(!1), [I, L] = d({}), [et, R] = d(null), [z, B] = d(/* @__PURE__ */ new Set()), [tt, V] = d(null), H = u(null);
62
+ b("vibesPage.typeAll", "All Types"), b("vibesPage.typeProject", "Project"), b("vibesPage.typeRepository", "Repository"), b("vibesPage.typeWorkspace", "Workspace"), b("vibesPage.typeMonorepo", "Monorepo"), b("vibesPage.typePackage", "Package"), b("vibesPage.typeCustom", "Custom");
63
+ let qe = _(s.VIBE_LIST), Je = _(s.VIBE_UPDATE), x = v || !qe, [S, Ye] = d(""), [C, Xe] = d("all"), [w, Ze] = d("all"), [T, Qe] = d("all"), [E, D] = d("grid"), [$e, O] = d(!1), [et, k] = d(null), [A, tt] = d(!1), [nt, j] = d(null), [rt, M] = d(!1), [N, P] = d({}), [it, F] = d(null), [I, L] = d(/* @__PURE__ */ new Set()), [at, R] = d(null), z = u(null);
63
64
  Ce(() => () => {
64
- H.current && clearTimeout(H.current);
65
+ z.current && clearTimeout(z.current);
65
66
  }, []);
66
- let nt = c(() => {
67
- R(null), H.current &&= (clearTimeout(H.current), null);
68
- }, []), rt = u(null), it = u(null), at = u(null), ot = u(null), [st] = o(), [ct] = a(), { setDraftTagIds: lt, flushTags: ut } = de("VIBECONTROLS_VIBE"), [dt] = ne(), [ft] = i(), { data: pt, loading: U, error: mt, refetch: W } = te({
67
+ let ot = c(() => {
68
+ F(null), z.current &&= (clearTimeout(z.current), null);
69
+ }, []), st = u(null), ct = u(null), lt = u(null), ut = u(null), [dt] = o(), [ft] = a(), { setDraftTagIds: pt, flushTags: mt } = de("VIBECONTROLS_VIBE"), [ht] = ne(), [gt] = i(), { data: _t, loading: B, error: vt, refetch: V } = te({
69
70
  variables: l(() => ({ filter: {
70
- status: E === "all" ? void 0 : E,
71
- type: D === "all" ? void 0 : D,
72
- attachedAgentIds: O === "all" ? void 0 : [O]
71
+ status: C === "all" ? void 0 : C,
72
+ type: w === "all" ? void 0 : w,
73
+ attachedAgentIds: T === "all" ? void 0 : [T]
73
74
  } }), [
74
- E,
75
- D,
76
- O
75
+ C,
76
+ w,
77
+ T
77
78
  ]),
78
- fetchPolicy: E === "all" && D === "all" && O === "all" ? "cache-first" : "cache-and-network",
79
+ fetchPolicy: C === "all" && w === "all" && T === "all" ? "cache-first" : "cache-and-network",
79
80
  nextFetchPolicy: "cache-first",
80
- skip: w,
81
+ skip: x,
81
82
  notifyOnNetworkStatusChange: !0
82
- }), { agents: ht } = oe(), [gt, { data: _t }] = ee({ fetchPolicy: "cache-first" }), vt = u(!1), G = c(() => {
83
- vt.current || w || (vt.current = !0, gt({ variables: { pagination: { limit: 100 } } }));
84
- }, [gt, w]), yt = l(() => {
85
- let e = _t?.vibecontrolsAgents ?? null, t = e ? e.map((e) => ({
83
+ }), { agents: yt } = oe(), [bt, { data: xt }] = ee({ fetchPolicy: "cache-first" }), St = u(!1), H = c(() => {
84
+ St.current || x || (St.current = !0, bt({ variables: { pagination: { limit: 100 } } }));
85
+ }, [bt, x]), Ct = l(() => {
86
+ let e = xt?.vibecontrolsAgents ?? null, t = e ? e.map((e) => ({
86
87
  id: e.id,
87
88
  name: e.name
88
- })) : ht.map((e) => ({
89
+ })) : yt.map((e) => ({
89
90
  id: e.id,
90
91
  name: e.name
91
92
  }));
92
93
  return [{
93
94
  value: "all",
94
- label: S("vibesPage.allAgents", "All Agents")
95
+ label: b("vibesPage.allAgents", "All Agents")
95
96
  }, ...t.map((e) => ({
96
97
  value: e.id,
97
98
  label: e.name
98
99
  }))];
99
100
  }, [
100
- _t?.vibecontrolsAgents,
101
- ht,
102
- S
103
- ]), K = l(() => (pt?.vibes?.items ?? []).map((e) => ({
101
+ xt?.vibecontrolsAgents,
102
+ yt,
103
+ b
104
+ ]), U = l(() => (_t?.vibes?.items ?? []).map((e) => ({
104
105
  id: e.id,
105
106
  workspaceId: e.workspaceId,
106
107
  name: e.name,
@@ -123,17 +124,17 @@ function h() {
123
124
  isActive: e.isActive,
124
125
  ownerUserId: e.ownerUserId ?? null
125
126
  }))
126
- })), [pt?.vibes?.items]), q = l(() => K.filter((e) => {
127
- if (T) {
128
- let t = T.toLowerCase();
127
+ })), [_t?.vibes?.items]), W = l(() => U.filter((e) => {
128
+ if (S) {
129
+ let t = S.toLowerCase();
129
130
  if (!(e.name.toLowerCase().includes(t) || e.description?.toLowerCase().includes(t) || e.path?.toLowerCase().includes(t) || e.tags?.some((e) => e.toLowerCase().includes(t)))) return !1;
130
131
  }
131
132
  return !0;
132
- }), [K, T]), bt = l(() => K.filter((e) => z.has(e.id)), [K, z]), J = bt.filter((e) => e.status !== "ACTIVE"), Y = bt.filter((e) => e.status !== "ARCHIVED"), X = q.length > 0 && q.every((e) => z.has(e.id)), xt = q.some((e) => z.has(e.id)) && !X, St = (e) => {
133
+ }), [U, S]), wt = l(() => U.filter((e) => I.has(e.id)), [U, I]), G = wt.filter((e) => e.status !== "ACTIVE"), K = wt.filter((e) => e.status !== "ARCHIVED"), q = W.length > 0 && W.every((e) => I.has(e.id)), Tt = W.some((e) => I.has(e.id)) && !q, Et = (e) => {
133
134
  g(`/vibes/${e.id}`);
134
- }, Ct = async (e) => {
135
+ }, Dt = async (e) => {
135
136
  try {
136
- (await dt({ variables: {
137
+ (await ht({ variables: {
137
138
  id: e.id,
138
139
  status: "ACTIVE"
139
140
  } })).data?.updateVibeStatus && h?.({
@@ -145,55 +146,67 @@ function h() {
145
146
  } catch (e) {
146
147
  console.error("Failed to activate vibe:", e);
147
148
  }
148
- }, wt = async (e) => {
149
+ }, Ot = async (e) => {
149
150
  try {
150
- await ft({ variables: { id: e.id } });
151
+ await gt({ variables: { id: e.id } });
151
152
  } catch (e) {
152
153
  console.error("Failed to archive vibe:", e);
153
154
  }
154
- }, Tt = ae((e) => e.preferredIdeCommand), Et = ae((e) => e.vibeIdeOverrides), Dt = (e) => {
155
+ }, kt = ae((e) => e.preferredIdeCommand), At = ae((e) => e.vibeIdeOverrides), jt = (e) => {
155
156
  if (!e.path) {
156
- R(S("vibesPage.openEditorPathMissing", "No path available to open in editor")), H.current = setTimeout(() => {
157
- R(null), H.current = null;
157
+ F(b("vibesPage.openEditorPathMissing", "No path available to open in editor")), z.current = setTimeout(() => {
158
+ F(null), z.current = null;
158
159
  }, 3e3);
159
160
  return;
160
161
  }
161
- let t = be(e.id, Tt, Et), n = ye(t), r = n ? ve(n, e.path) : `vscode://file/${e.path}`;
162
- r ? window.location.href = r : (R(S("vibesPage.openEditorNoProtocol", `${n?.label ?? t} has no URL handler — open this Vibe and use the editor menu.`)), H.current = setTimeout(() => {
163
- R(null), H.current = null;
162
+ let t = be(e.id, kt, At), n = ye(t), r = n ? ve(n, e.path) : `vscode://file/${e.path}`;
163
+ r ? window.location.href = r : (F(b("vibesPage.openEditorNoProtocol", `${n?.label ?? t} has no URL handler — open this Vibe and use the editor menu.`)), z.current = setTimeout(() => {
164
+ F(null), z.current = null;
164
165
  }, 4e3));
165
- }, Ot = () => {
166
- j(null), A(!0), G();
167
- }, kt = (e, t) => {
168
- B((n) => {
166
+ }, J = c(() => {
167
+ k(null), O(!0), H();
168
+ }, [H]), [Y, Mt] = Ne();
169
+ Ce(() => {
170
+ if (Y.get("create") === "true") {
171
+ J();
172
+ let e = new URLSearchParams(Y);
173
+ e.delete("create"), Mt(e, { replace: !0 });
174
+ }
175
+ }, [
176
+ Y,
177
+ Mt,
178
+ J
179
+ ]);
180
+ let Nt = (e, t) => {
181
+ L((n) => {
169
182
  let r = new Set(n);
170
183
  return t ? r.add(e.id) : r.delete(e.id), r;
171
184
  });
172
- }, At = (e) => {
173
- B((t) => {
185
+ }, Pt = (e) => {
186
+ L((t) => {
174
187
  let n = new Set(t);
175
- return q.forEach((t) => {
188
+ return W.forEach((t) => {
176
189
  e ? n.add(t.id) : n.delete(t.id);
177
190
  }), n;
178
191
  });
179
- }, Z = () => B(/* @__PURE__ */ new Set()), jt = async () => {
180
- if (J.length === 0) return;
181
- let e = await Promise.allSettled(J.map((e) => dt({ variables: {
192
+ }, X = () => L(/* @__PURE__ */ new Set()), Ft = async () => {
193
+ if (G.length === 0) return;
194
+ let e = await Promise.allSettled(G.map((e) => ht({ variables: {
182
195
  id: e.id,
183
196
  status: "ACTIVE"
184
197
  } }))), t = e.filter((e) => e.status === "fulfilled").length, n = e.length - t;
185
- P(`Activated ${t} vibe${t === 1 ? "" : "s"}${n > 0 ? ` • ${n} failed` : ""}`), setTimeout(() => P(null), 4e3), Z(), V(null), await W();
186
- }, Mt = async () => {
187
- if (Y.length === 0) return;
188
- let e = await Promise.allSettled(Y.map((e) => ft({ variables: { id: e.id } }))), t = e.filter((e) => e.status === "fulfilled").length, n = e.length - t;
189
- P(`Archived ${t} vibe${t === 1 ? "" : "s"}${n > 0 ? ` • ${n} failed` : ""}`), setTimeout(() => P(null), 4e3), Z(), V(null), await W();
190
- }, Nt = async () => {
191
- let e = rt.current?.value?.trim(), t = it.current?.value?.trim(), i = at.current?.value, a = ot.current?.value, o = {};
192
- if (e || (o.name = S("vibesPage.nameRequired", "Name is required")), t || (o.path = S("vibesPage.pathRequired", "Path is required")), o.name || o.path) {
193
- L(o), j(S("vibesPage.fillRequired", "Please fill in all required fields"));
198
+ j(`Activated ${t} vibe${t === 1 ? "" : "s"}${n > 0 ? ` • ${n} failed` : ""}`), setTimeout(() => j(null), 4e3), X(), R(null), await V();
199
+ }, It = async () => {
200
+ if (K.length === 0) return;
201
+ let e = await Promise.allSettled(K.map((e) => gt({ variables: { id: e.id } }))), t = e.filter((e) => e.status === "fulfilled").length, n = e.length - t;
202
+ j(`Archived ${t} vibe${t === 1 ? "" : "s"}${n > 0 ? ` • ${n} failed` : ""}`), setTimeout(() => j(null), 4e3), X(), R(null), await V();
203
+ }, Lt = async () => {
204
+ let e = st.current?.value?.trim(), t = ct.current?.value?.trim(), i = lt.current?.value, a = ut.current?.value, o = {};
205
+ if (e || (o.name = b("vibesPage.nameRequired", "Name is required")), t || (o.path = b("vibesPage.pathRequired", "Path is required")), o.name || o.path) {
206
+ P(o), k(b("vibesPage.fillRequired", "Please fill in all required fields"));
194
207
  return;
195
208
  }
196
- L({});
209
+ P({});
197
210
  let ee = [
198
211
  "PROJECT",
199
212
  "REPOSITORY",
@@ -202,85 +215,85 @@ function h() {
202
215
  "PACKAGE",
203
216
  "CUSTOM"
204
217
  ].includes(a) ? a : "PROJECT";
205
- Qe(!0), j(null);
218
+ tt(!0), k(null);
206
219
  try {
207
- let n = await st({ variables: { input: {
220
+ let n = await dt({ variables: { input: {
208
221
  name: e,
209
222
  path: t,
210
223
  type: ee
211
224
  } } });
212
- if (!n.data?.createVibe?.id) throw Error(S("vibesPage.failedCreate", "Failed to create vibe"));
225
+ if (!n.data?.createVibe?.id) throw Error(b("vibesPage.failedCreate", "Failed to create vibe"));
213
226
  let r = n.data.createVibe.id;
214
227
  if (i) try {
215
- await ct({ variables: { input: {
228
+ await ft({ variables: { input: {
216
229
  vibeId: r,
217
230
  agentId: i
218
231
  } } });
219
232
  } catch {}
220
- A(!1), P(S("vibesPage.createdSuccess", "Vibe created successfully")), await ut(r), await W(), setTimeout(() => P(null), 3e3);
233
+ O(!1), j(b("vibesPage.createdSuccess", "Vibe created successfully")), await mt(r), await V(), setTimeout(() => j(null), 3e3);
221
234
  } catch (e) {
222
235
  if (n(e)) {
223
- A(!1), j(null), L({}), r(), F(!0);
236
+ O(!1), k(null), P({}), r(), M(!0);
224
237
  return;
225
238
  }
226
- j(e instanceof Error ? e.message : S("vibesPage.failedCreate", "Failed to create vibe"));
239
+ k(e instanceof Error ? e.message : b("vibesPage.failedCreate", "Failed to create vibe"));
227
240
  } finally {
228
- Qe(!1);
241
+ tt(!1);
229
242
  }
230
- }, Pt = {
231
- total: K.length,
232
- active: K.filter((e) => e.status === "ACTIVE").length,
233
- inactive: K.filter((e) => e.status === "INACTIVE").length
234
- }, Q = v, $ = !v && !!y && (y.permissionStrings?.length ?? 0) > 0 && !C, Ft = !Q && !$ && U && K.length === 0, It = !Q && !$ && !!mt && K.length === 0, Lt = !Q && !$ && !It;
235
- return /* @__PURE__ */ p(Le, {
243
+ }, Rt = {
244
+ total: U.length,
245
+ active: U.filter((e) => e.status === "ACTIVE").length,
246
+ inactive: U.filter((e) => e.status === "INACTIVE").length
247
+ }, Z = v, Q = !v && !!He && (He.permissionStrings?.length ?? 0) > 0 && !qe, zt = !Z && !Q && B && U.length === 0, $ = !Z && !Q && !!vt && U.length === 0, Bt = !Z && !Q && !$;
248
+ return /* @__PURE__ */ p(Re, {
236
249
  className: "space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen",
237
250
  children: [
238
- Q && /* @__PURE__ */ f(ce, { message: S("vibesPage.loadingPermissions", "Loading permissions...") }),
239
- $ && /* @__PURE__ */ f(Re, {
240
- title: S("vibesPage.accessDeniedTitle", "Access Denied"),
241
- description: S("vibesPage.accessDeniedDescription", "You don't have permission to view vibes. Contact your workspace administrator for access.")
251
+ Z && /* @__PURE__ */ f(ce, { message: b("vibesPage.loadingPermissions", "Loading permissions...") }),
252
+ Q && /* @__PURE__ */ f(ze, {
253
+ title: b("vibesPage.accessDeniedTitle", "Access Denied"),
254
+ description: b("vibesPage.accessDeniedDescription", "You don't have permission to view vibes. Contact your workspace administrator for access.")
242
255
  }),
243
- It && /* @__PURE__ */ f(le, {
244
- title: S("vibesPage.failedLoad", "Failed to load vibes"),
245
- message: mt?.message ?? "",
246
- onRetry: () => W()
256
+ $ && /* @__PURE__ */ f(le, {
257
+ title: b("vibesPage.failedLoad", "Failed to load vibes"),
258
+ message: vt?.message ?? "",
259
+ onRetry: () => V()
247
260
  }),
248
- Lt && /* @__PURE__ */ p(Fe, { children: [
261
+ Bt && /* @__PURE__ */ p(Ie, { children: [
249
262
  /* @__PURE__ */ f(se, {
250
- title: S("vibesPage.title", "Vibes"),
251
- description: S("vibesPage.descriptionActive", "{{active}} of {{total}} vibes active", {
252
- active: Pt.active,
253
- total: Pt.total
263
+ title: b("vibesPage.title", "Vibes"),
264
+ description: b("vibesPage.descriptionActive", "{{active}} of {{total}} vibes active", {
265
+ active: Rt.active,
266
+ total: Rt.total
254
267
  }),
255
268
  actions: /* @__PURE__ */ p("div", {
256
269
  className: "flex items-center gap-2",
257
270
  children: [
258
- Ve && x && typeof x.limit == "number" && /* @__PURE__ */ f("a", {
271
+ We && y && typeof y.limit == "number" && /* @__PURE__ */ f("a", {
259
272
  href: "/billing/plans",
260
- className: `inline-flex items-center gap-1 px-2 py-1 text-xs font-medium rounded-md border ${x.current >= x.limit ? "border-status-error-border bg-status-error-bg-subtle text-status-error-text" : "border-status-warning-border bg-status-warning-bg-subtle text-status-warning-text"}`,
261
- title: S("vibesPage.upgradeChipTooltip", "Free plan limit — upgrade for more vibes"),
262
- children: S("vibesPage.usageChip", "{{current}} of {{limit}} vibes used", {
263
- current: x.current,
264
- limit: x.limit
273
+ className: `inline-flex items-center gap-1 px-2 py-1 text-xs font-medium rounded-md border ${y.current >= y.limit ? "border-status-error-border bg-status-error-bg-subtle text-status-error-text" : "border-status-warning-border bg-status-warning-bg-subtle text-status-warning-text"}`,
274
+ title: b("vibesPage.upgradeChipTooltip", "Free plan limit — upgrade for more vibes"),
275
+ children: b("vibesPage.usageChip", "{{current}} of {{limit}} vibes used", {
276
+ current: y.current,
277
+ limit: y.limit
265
278
  })
266
279
  }),
267
280
  /* @__PURE__ */ f("button", {
268
281
  type: "button",
269
- onClick: () => W(),
270
- disabled: U,
282
+ onClick: () => V(),
283
+ disabled: B,
271
284
  className: "flex items-center gap-2 px-3 py-2 text-text-secondary hover:bg-bg-sunken rounded-md transition-colors disabled:opacity-50",
272
- title: S("vibesPage.refreshTitle", "Refresh vibes"),
273
- children: /* @__PURE__ */ f(je, { className: `size-4 ${U ? "animate-spin" : ""}` })
285
+ title: b("vibesPage.refreshTitle", "Refresh vibes"),
286
+ children: /* @__PURE__ */ f(je, { className: `size-4 ${B ? "animate-spin" : ""}` })
274
287
  }),
275
- /* @__PURE__ */ f(ze, {
288
+ /* @__PURE__ */ f(Be, {
276
289
  permission: s.VIBE_CREATE,
277
290
  deniedBehavior: "disable",
278
- deniedTooltip: S("vibesPage.deniedCreateTooltip", "You don't have permission to create vibes"),
291
+ deniedTooltip: b("vibesPage.deniedCreateTooltip", "You don't have permission to create vibes"),
279
292
  children: /* @__PURE__ */ p("button", {
280
293
  type: "button",
281
- onClick: Ot,
294
+ onClick: J,
282
295
  className: "flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
283
- children: [/* @__PURE__ */ f(Ae, { className: "size-4" }), S("vibesPage.addVibe", "Add Vibe")]
296
+ children: [/* @__PURE__ */ f(Ae, { className: "size-4" }), b("vibesPage.addVibe", "Add Vibe")]
284
297
  })
285
298
  })
286
299
  ]
@@ -291,56 +304,56 @@ function h() {
291
304
  children: [/* @__PURE__ */ p("div", {
292
305
  className: "flex items-center gap-2",
293
306
  children: [/* @__PURE__ */ f(pe, {
294
- value: T,
295
- onChange: Ge,
296
- placeholder: S("vibesPage.searchPlaceholder", "Search vibes..."),
307
+ value: S,
308
+ onChange: Ye,
309
+ placeholder: b("vibesPage.searchPlaceholder", "Search vibes..."),
297
310
  className: "flex-1 sm:w-64 sm:flex-none"
298
311
  }), /* @__PURE__ */ p("div", {
299
312
  className: "flex items-center gap-1 bg-bg-sunken rounded-md p-1 flex-shrink-0",
300
313
  children: [/* @__PURE__ */ f("button", {
301
314
  type: "button",
302
- onClick: () => Ye("grid"),
303
- className: `p-1.5 sm:p-2 rounded ${k === "grid" ? "bg-bg-surface shadow-sm" : "hover:bg-bg-surface/50"}`,
304
- title: S("vibesPage.gridViewTitle", "Grid view"),
315
+ onClick: () => D("grid"),
316
+ className: `p-1.5 sm:p-2 rounded ${E === "grid" ? "bg-bg-surface shadow-sm" : "hover:bg-bg-surface/50"}`,
317
+ title: b("vibesPage.gridViewTitle", "Grid view"),
305
318
  children: /* @__PURE__ */ f(De, { className: "size-4 text-text-secondary" })
306
319
  }), /* @__PURE__ */ f("button", {
307
320
  type: "button",
308
- onClick: () => Ye("list"),
309
- className: `p-1.5 sm:p-2 rounded ${k === "list" ? "bg-bg-surface shadow-sm" : "hover:bg-bg-surface/50"}`,
310
- title: S("vibesPage.listViewTitle", "List view"),
321
+ onClick: () => D("list"),
322
+ className: `p-1.5 sm:p-2 rounded ${E === "list" ? "bg-bg-surface shadow-sm" : "hover:bg-bg-surface/50"}`,
323
+ title: b("vibesPage.listViewTitle", "List view"),
311
324
  children: /* @__PURE__ */ f(Oe, { className: "size-4 text-text-secondary" })
312
325
  })]
313
326
  })]
314
327
  }), /* @__PURE__ */ p("div", {
315
328
  className: "flex items-center gap-2 sm:gap-3 flex-wrap",
316
329
  children: [/* @__PURE__ */ f(me, {
317
- label: S("vibesPage.filterStatus", "Status"),
318
- value: E,
319
- options: Ue,
320
- onChange: Ke
330
+ label: b("vibesPage.filterStatus", "Status"),
331
+ value: C,
332
+ options: Ke,
333
+ onChange: Xe
321
334
  }), /* @__PURE__ */ f("div", {
322
- onMouseDown: G,
323
- onFocus: G,
335
+ onMouseDown: H,
336
+ onFocus: H,
324
337
  children: /* @__PURE__ */ f(me, {
325
- label: S("vibesPage.filterAgent", "Agent"),
326
- value: O,
327
- options: yt,
328
- onChange: Je
338
+ label: b("vibesPage.filterAgent", "Agent"),
339
+ value: T,
340
+ options: Ct,
341
+ onChange: Qe
329
342
  })
330
343
  })]
331
344
  })]
332
345
  }),
333
- T || E !== "all" || D !== "all" || O !== "all" ? /* @__PURE__ */ p("p", {
346
+ S || C !== "all" || w !== "all" || T !== "all" ? /* @__PURE__ */ p("p", {
334
347
  className: "text-sm text-text-secondary",
335
- children: [S("vibesPage.showingResults", "Showing {{filtered}} of {{total}} vibes", {
336
- filtered: q.length,
337
- total: K.length
338
- }), U && /* @__PURE__ */ f("span", {
348
+ children: [b("vibesPage.showingResults", "Showing {{filtered}} of {{total}} vibes", {
349
+ filtered: W.length,
350
+ total: U.length
351
+ }), B && /* @__PURE__ */ f("span", {
339
352
  className: "ml-2 text-text-muted",
340
- children: S("vibesPage.refreshing", "(refreshing...)")
353
+ children: b("vibesPage.refreshing", "(refreshing...)")
341
354
  })]
342
355
  }) : null,
343
- q.length > 0 && /* @__PURE__ */ f("div", {
356
+ W.length > 0 && /* @__PURE__ */ f("div", {
344
357
  className: "rounded-lg border border-border-default bg-bg-surface p-4",
345
358
  children: /* @__PURE__ */ p("div", {
346
359
  className: "flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between",
@@ -349,17 +362,17 @@ function h() {
349
362
  children: [/* @__PURE__ */ p("div", {
350
363
  className: "flex items-center gap-2",
351
364
  children: [/* @__PURE__ */ f(ge, {
352
- checked: X,
353
- indeterminate: xt,
354
- onChange: At,
365
+ checked: q,
366
+ indeterminate: Tt,
367
+ onChange: Pt,
355
368
  ariaLabel: "Select all visible vibes"
356
369
  }), /* @__PURE__ */ f("span", {
357
370
  className: "text-sm font-medium text-text-primary",
358
371
  children: "Select all visible"
359
372
  })]
360
- }), z.size > 0 && /* @__PURE__ */ f("button", {
373
+ }), I.size > 0 && /* @__PURE__ */ f("button", {
361
374
  type: "button",
362
- onClick: Z,
375
+ onClick: X,
363
376
  className: "text-sm text-text-secondary hover:text-text-primary",
364
377
  children: "Clear selection"
365
378
  })]
@@ -368,12 +381,12 @@ function h() {
368
381
  children: [
369
382
  /* @__PURE__ */ p("span", {
370
383
  className: "rounded-full bg-bg-sunken px-3 py-1 text-sm font-medium text-text-secondary",
371
- children: [z.size, " selected"]
384
+ children: [I.size, " selected"]
372
385
  }),
373
386
  /* @__PURE__ */ f("button", {
374
387
  type: "button",
375
- onClick: () => V("activate"),
376
- disabled: J.length === 0,
388
+ onClick: () => R("activate"),
389
+ disabled: G.length === 0,
377
390
  title: "Mark selected vibes as ACTIVE so they appear in the default vibe list and can run sessions/tunnels via their attached agent(s).",
378
391
  className: "rounded-md border border-status-success-border px-3 py-2 text-sm font-medium text-status-success-text hover:bg-status-success-bg disabled:cursor-not-allowed disabled:opacity-50",
379
392
  children: /* @__PURE__ */ p("span", {
@@ -381,21 +394,21 @@ function h() {
381
394
  children: [
382
395
  /* @__PURE__ */ f(ke, { className: "size-4" }),
383
396
  "Activate Selected",
384
- J.length > 0 ? ` (${J.length})` : ""
397
+ G.length > 0 ? ` (${G.length})` : ""
385
398
  ]
386
399
  })
387
400
  }),
388
401
  /* @__PURE__ */ f("button", {
389
402
  type: "button",
390
- onClick: () => V("archive"),
391
- disabled: Y.length === 0,
403
+ onClick: () => R("archive"),
404
+ disabled: K.length === 0,
392
405
  className: "rounded-md border border-status-warning-border px-3 py-2 text-sm font-medium text-status-warning-text hover:bg-status-warning-bg disabled:cursor-not-allowed disabled:opacity-50",
393
406
  children: /* @__PURE__ */ p("span", {
394
407
  className: "inline-flex items-center gap-2",
395
408
  children: [
396
409
  /* @__PURE__ */ f(Ee, { className: "size-4" }),
397
410
  "Archive Selected",
398
- Y.length > 0 ? ` (${Y.length})` : ""
411
+ K.length > 0 ? ` (${K.length})` : ""
399
412
  ]
400
413
  })
401
414
  })
@@ -403,186 +416,186 @@ function h() {
403
416
  })]
404
417
  })
405
418
  }),
406
- Ft ? /* @__PURE__ */ f(_e, {
419
+ zt ? /* @__PURE__ */ f(_e, {
407
420
  variant: "cards",
408
421
  count: 6
409
- }) : q.length > 0 ? /* @__PURE__ */ f(Pe, {
422
+ }) : W.length > 0 ? /* @__PURE__ */ f(Fe, {
410
423
  mode: "wait",
411
- children: k === "grid" ? /* @__PURE__ */ f(m, {
424
+ children: E === "grid" ? /* @__PURE__ */ f(m, {
412
425
  stagger: .04,
413
426
  className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4",
414
- children: q.map((e) => /* @__PURE__ */ f(Ie, { children: /* @__PURE__ */ f(xe, {
427
+ children: W.map((e) => /* @__PURE__ */ f(Le, { children: /* @__PURE__ */ f(xe, {
415
428
  vibe: e,
416
- onOpen: St,
417
- onActivate: We ? Ct : void 0,
418
- onArchive: We ? wt : void 0,
419
- onOpenInEditor: Dt,
420
- selected: z.has(e.id),
421
- onToggleSelect: (t) => kt(e, t)
429
+ onOpen: Et,
430
+ onActivate: Je ? Dt : void 0,
431
+ onArchive: Je ? Ot : void 0,
432
+ onOpenInEditor: jt,
433
+ selected: I.has(e.id),
434
+ onToggleSelect: (t) => Nt(e, t)
422
435
  }) }, e.id))
423
436
  }, "grid") : /* @__PURE__ */ f(m, { children: /* @__PURE__ */ f(Se, {
424
- vibes: q,
425
- onOpen: St,
426
- onActivate: Ct,
427
- onArchive: wt,
428
- onOpenInEditor: Dt,
429
- selectedVibeIds: z,
430
- onToggleSelect: kt,
431
- onToggleAllVisible: At,
432
- allVisibleSelected: X,
433
- partiallySelected: xt
437
+ vibes: W,
438
+ onOpen: Et,
439
+ onActivate: Dt,
440
+ onArchive: Ot,
441
+ onOpenInEditor: jt,
442
+ selectedVibeIds: I,
443
+ onToggleSelect: Nt,
444
+ onToggleAllVisible: Pt,
445
+ allVisibleSelected: q,
446
+ partiallySelected: Tt
434
447
  }) }, "list")
435
448
  }) : /* @__PURE__ */ f(fe, {
436
449
  icon: /* @__PURE__ */ f(Me, { className: "size-8 text-text-secondary" }),
437
- title: T || E !== "all" || D !== "all" || O !== "all" ? S("vibesPage.emptyNoVibesFound", "No vibes found") : S("vibesPage.emptyNoVibesConfigured", "No vibes configured"),
438
- description: T || E !== "all" || D !== "all" || O !== "all" ? S("vibesPage.emptyAdjustSearch", "Try adjusting your search or filters") : S("vibesPage.emptyNoVibesDescription", "Add your first vibe to start managing your development projects"),
439
- action: !T && E === "all" && D === "all" && O === "all" ? /* @__PURE__ */ p("div", {
450
+ title: S || C !== "all" || w !== "all" || T !== "all" ? b("vibesPage.emptyNoVibesFound", "No vibes found") : b("vibesPage.emptyNoVibesConfigured", "No vibes configured"),
451
+ description: S || C !== "all" || w !== "all" || T !== "all" ? b("vibesPage.emptyAdjustSearch", "Try adjusting your search or filters") : b("vibesPage.emptyNoVibesDescription", "Add your first vibe to start managing your development projects"),
452
+ action: !S && C === "all" && w === "all" && T === "all" ? /* @__PURE__ */ p("div", {
440
453
  className: "flex items-center gap-2",
441
- children: [/* @__PURE__ */ f(Be, {
454
+ children: [/* @__PURE__ */ f(Ve, {
442
455
  permission: s.VIBE_CREATE,
443
456
  children: /* @__PURE__ */ p("button", {
444
457
  type: "button",
445
- onClick: Ot,
458
+ onClick: J,
446
459
  className: "flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors",
447
- children: [/* @__PURE__ */ f(Ae, { className: "size-4" }), S("vibesPage.addVibe", "Add Vibe")]
460
+ children: [/* @__PURE__ */ f(Ae, { className: "size-4" }), b("vibesPage.addVibe", "Add Vibe")]
448
461
  })
449
462
  }), /* @__PURE__ */ f(he, { prompt: "What is a Vibe in VibeControls and how do I create one?" })]
450
463
  }) : void 0
451
464
  }),
452
- N && /* @__PURE__ */ f("div", {
465
+ nt && /* @__PURE__ */ f("div", {
453
466
  className: "fixed bottom-4 right-4 z-50 px-4 py-3 bg-status-success-bg text-status-success-text rounded-md shadow-lg text-sm",
454
- children: N
467
+ children: nt
455
468
  }),
456
469
  /* @__PURE__ */ f(e, {
457
- isOpen: tt === "activate",
458
- onClose: () => V(null),
459
- onConfirm: jt,
470
+ isOpen: at === "activate",
471
+ onClose: () => R(null),
472
+ onConfirm: Ft,
460
473
  title: "Activate selected vibes",
461
- message: `Activate ${J.length} selected vibe${J.length === 1 ? "" : "s"}?`,
474
+ message: `Activate ${G.length} selected vibe${G.length === 1 ? "" : "s"}?`,
462
475
  confirmLabel: "Activate",
463
476
  variant: "default"
464
477
  }),
465
478
  /* @__PURE__ */ f(e, {
466
- isOpen: tt === "archive",
467
- onClose: () => V(null),
468
- onConfirm: Mt,
479
+ isOpen: at === "archive",
480
+ onClose: () => R(null),
481
+ onConfirm: It,
469
482
  title: "Archive selected vibes",
470
- message: `Archive ${Y.length} selected vibe${Y.length === 1 ? "" : "s"}? Archived vibes will be hidden from active workflows.`,
483
+ message: `Archive ${K.length} selected vibe${K.length === 1 ? "" : "s"}? Archived vibes will be hidden from active workflows.`,
471
484
  confirmLabel: "Archive",
472
485
  variant: "warning"
473
486
  }),
474
- et && /* @__PURE__ */ p("div", {
487
+ it && /* @__PURE__ */ p("div", {
475
488
  role: "alert",
476
489
  className: "fixed bottom-4 right-4 z-50 px-4 py-3 bg-status-error-bg text-status-error-text rounded-md shadow-lg text-sm",
477
- children: [et, /* @__PURE__ */ f("button", {
490
+ children: [it, /* @__PURE__ */ f("button", {
478
491
  type: "button",
479
- onClick: nt,
492
+ onClick: ot,
480
493
  className: "ml-3 text-xs underline opacity-80 hover:opacity-100",
481
- children: S("vibesPage.dismiss", "Dismiss")
494
+ children: b("vibesPage.dismiss", "Dismiss")
482
495
  })]
483
496
  }),
484
- Xe && /* @__PURE__ */ f("div", {
497
+ $e && /* @__PURE__ */ f("div", {
485
498
  className: "fixed inset-0 bg-bg-overlay flex items-center justify-center z-50 p-4",
486
499
  children: /* @__PURE__ */ p("div", {
487
500
  className: "bg-bg-surface rounded-lg p-6 w-full max-w-lg",
488
501
  children: [
489
502
  /* @__PURE__ */ f("h2", {
490
503
  className: "text-lg font-semibold text-text-primary mb-4",
491
- children: S("vibesPage.addNewVibe", "Add New Vibe")
504
+ children: b("vibesPage.addNewVibe", "Add New Vibe")
492
505
  }),
493
506
  /* @__PURE__ */ p("div", {
494
507
  className: "space-y-4",
495
508
  children: [
496
- Ze && /* @__PURE__ */ f("div", {
509
+ et && /* @__PURE__ */ f("div", {
497
510
  className: "p-3 bg-status-error-bg text-status-error-text text-sm rounded-md",
498
- children: Ze
511
+ children: et
499
512
  }),
500
513
  /* @__PURE__ */ p("div", { children: [
501
514
  /* @__PURE__ */ f("label", {
502
515
  className: "block text-sm font-medium text-text-primary mb-1",
503
- children: S("vibesPage.nameLabel", "Name *")
516
+ children: b("vibesPage.nameLabel", "Name *")
504
517
  }),
505
518
  /* @__PURE__ */ f("input", {
506
519
  "aria-label": "control",
507
- ref: rt,
520
+ ref: st,
508
521
  type: "text",
509
- placeholder: S("vibesPage.namePlaceholder", "My Project"),
510
- onChange: () => I.name && L((e) => ({
522
+ placeholder: b("vibesPage.namePlaceholder", "My Project"),
523
+ onChange: () => N.name && P((e) => ({
511
524
  ...e,
512
525
  name: void 0
513
526
  })),
514
- className: `w-full px-3 py-2 bg-bg-sunken border rounded-md text-text-primary placeholder:text-text-placeholder ${I.name ? "border-status-error-border" : "border-border-default"}`
527
+ className: `w-full px-3 py-2 bg-bg-sunken border rounded-md text-text-primary placeholder:text-text-placeholder ${N.name ? "border-status-error-border" : "border-border-default"}`
515
528
  }),
516
- I.name && /* @__PURE__ */ f("p", {
529
+ N.name && /* @__PURE__ */ f("p", {
517
530
  className: "mt-1 text-xs text-status-error-text",
518
- children: I.name
531
+ children: N.name
519
532
  })
520
533
  ] }),
521
534
  /* @__PURE__ */ p("div", { children: [
522
535
  /* @__PURE__ */ f("label", {
523
536
  className: "block text-sm font-medium text-text-primary mb-1",
524
- children: S("vibesPage.pathLabel", "Path *")
537
+ children: b("vibesPage.pathLabel", "Path *")
525
538
  }),
526
539
  /* @__PURE__ */ f("input", {
527
540
  "aria-label": "control",
528
- ref: it,
541
+ ref: ct,
529
542
  type: "text",
530
- placeholder: S("vibesPage.pathPlaceholder", "/path/to/project"),
531
- onChange: () => I.path && L((e) => ({
543
+ placeholder: b("vibesPage.pathPlaceholder", "/path/to/project"),
544
+ onChange: () => N.path && P((e) => ({
532
545
  ...e,
533
546
  path: void 0
534
547
  })),
535
- className: `w-full px-3 py-2 bg-bg-sunken border rounded-md text-text-primary placeholder:text-text-placeholder ${I.path ? "border-status-error-border" : "border-border-default"}`
548
+ className: `w-full px-3 py-2 bg-bg-sunken border rounded-md text-text-primary placeholder:text-text-placeholder ${N.path ? "border-status-error-border" : "border-border-default"}`
536
549
  }),
537
- I.path && /* @__PURE__ */ f("p", {
550
+ N.path && /* @__PURE__ */ f("p", {
538
551
  className: "mt-1 text-xs text-status-error-text",
539
- children: I.path
552
+ children: N.path
540
553
  })
541
554
  ] }),
542
555
  /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
543
556
  className: "block text-sm font-medium text-text-primary mb-1",
544
- children: S("vibesPage.agentLabel", "Agent")
557
+ children: b("vibesPage.agentLabel", "Agent")
545
558
  }), /* @__PURE__ */ p("select", {
546
- ref: at,
559
+ ref: lt,
547
560
  className: "w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary",
548
561
  children: [/* @__PURE__ */ f("option", {
549
562
  value: "",
550
- children: S("vibesPage.selectAgent", "Select an agent")
551
- }), yt.filter((e) => e.value !== "all").map((e) => /* @__PURE__ */ f("option", {
563
+ children: b("vibesPage.selectAgent", "Select an agent")
564
+ }), Ct.filter((e) => e.value !== "all").map((e) => /* @__PURE__ */ f("option", {
552
565
  value: e.value,
553
566
  children: e.label
554
567
  }, e.value))]
555
568
  })] }),
556
569
  /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
557
570
  className: "block text-sm font-medium text-text-primary mb-1",
558
- children: S("vibesPage.typeLabel", "Type")
571
+ children: b("vibesPage.typeLabel", "Type")
559
572
  }), /* @__PURE__ */ p("select", {
560
- ref: ot,
573
+ ref: ut,
561
574
  className: "w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary",
562
575
  children: [
563
576
  /* @__PURE__ */ f("option", {
564
577
  value: "PROJECT",
565
- children: S("vibesPage.typeProject", "Project")
578
+ children: b("vibesPage.typeProject", "Project")
566
579
  }),
567
580
  /* @__PURE__ */ f("option", {
568
581
  value: "REPOSITORY",
569
- children: S("vibesPage.typeRepository", "Repository")
582
+ children: b("vibesPage.typeRepository", "Repository")
570
583
  }),
571
584
  /* @__PURE__ */ f("option", {
572
585
  value: "WORKSPACE",
573
- children: S("vibesPage.typeWorkspace", "Workspace")
586
+ children: b("vibesPage.typeWorkspace", "Workspace")
574
587
  }),
575
588
  /* @__PURE__ */ f("option", {
576
589
  value: "MONOREPO",
577
- children: S("vibesPage.typeMonorepo", "Monorepo")
590
+ children: b("vibesPage.typeMonorepo", "Monorepo")
578
591
  }),
579
592
  /* @__PURE__ */ f("option", {
580
593
  value: "PACKAGE",
581
- children: S("vibesPage.typePackage", "Package")
594
+ children: b("vibesPage.typePackage", "Package")
582
595
  }),
583
596
  /* @__PURE__ */ f("option", {
584
597
  value: "CUSTOM",
585
- children: S("vibesPage.typeCustom", "Custom")
598
+ children: b("vibesPage.typeCustom", "Custom")
586
599
  })
587
600
  ]
588
601
  })] })
@@ -592,36 +605,36 @@ function h() {
592
605
  className: "mt-4 border-t border-border-default pt-4",
593
606
  children: [/* @__PURE__ */ f("h3", {
594
607
  className: "text-sm font-medium text-text-secondary mb-2",
595
- children: S("vibesPage.tags", "Tags")
608
+ children: b("vibesPage.tags", "Tags")
596
609
  }), /* @__PURE__ */ f(ue, {
597
610
  entityType: "VIBECONTROLS_VIBE",
598
- onDraftChange: lt
611
+ onDraftChange: pt
599
612
  })]
600
613
  }),
601
614
  /* @__PURE__ */ p("div", {
602
615
  className: "flex flex-col sm:flex-row justify-end gap-3 mt-6",
603
616
  children: [/* @__PURE__ */ f("button", {
604
617
  type: "button",
605
- onClick: () => A(!1),
606
- disabled: M,
618
+ onClick: () => O(!1),
619
+ disabled: A,
607
620
  className: "px-4 py-2 text-text-primary hover:bg-bg-sunken rounded-md transition-colors disabled:opacity-50",
608
- children: S("vibesPage.cancel", "Cancel")
621
+ children: b("vibesPage.cancel", "Cancel")
609
622
  }), /* @__PURE__ */ f("button", {
610
623
  type: "button",
611
- onClick: Nt,
612
- disabled: M,
624
+ onClick: Lt,
625
+ disabled: A,
613
626
  className: "px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50",
614
- children: M ? S("vibesPage.creating", "Creating...") : S("vibesPage.createVibe", "Create Vibe")
627
+ children: A ? b("vibesPage.creating", "Creating...") : b("vibesPage.createVibe", "Create Vibe")
615
628
  })]
616
629
  })
617
630
  ]
618
631
  })
619
632
  }),
620
633
  /* @__PURE__ */ f(t, {
621
- isOpen: $e,
622
- onClose: () => F(!1),
634
+ isOpen: rt,
635
+ onClose: () => M(!1),
623
636
  onConfirm: () => {
624
- F(!1), g("/billing");
637
+ M(!1), g("/billing");
625
638
  },
626
639
  title: "Vibe Quota Reached",
627
640
  message: "You've used all available vibe creation quota on your current plan. Upgrade your plan to create more vibes."