@burdenoff/microfe-vibecontrols 2026.524.6 → 2026.524.7

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.
@@ -22,7 +22,7 @@ function r({ title: r, description: i, actions: a, breadcrumb: o }) {
22
22
  }, r))
23
23
  })
24
24
  }), /* @__PURE__ */ n("div", {
25
- className: "flex items-start justify-between gap-4 sm:items-center",
25
+ className: "flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between",
26
26
  children: [/* @__PURE__ */ n(e.div, {
27
27
  initial: {
28
28
  opacity: 0,
@@ -33,7 +33,7 @@ function r({ title: r, description: i, actions: a, breadcrumb: o }) {
33
33
  y: 0
34
34
  },
35
35
  transition: { duration: .2 },
36
- className: "flex-1 min-w-0",
36
+ className: "min-w-0 lg:flex-1",
37
37
  children: [/* @__PURE__ */ t("h1", {
38
38
  className: "text-2xl sm:text-3xl font-bold text-text-primary break-words",
39
39
  children: r
@@ -1 +1 @@
1
- {"version":3,"file":"PageHeader.js","names":[],"sources":["../../../src/components/shared/PageHeader.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { motion } from 'framer-motion';\n\ninterface PageHeaderProps {\n title: string;\n description?: string;\n actions?: ReactNode;\n breadcrumb?: { label: string; path?: string }[];\n}\n\nexport function PageHeader({ title, description, actions, breadcrumb }: PageHeaderProps) {\n return (\n <div data-tour=\"page-header\" className=\"mb-6\">\n {breadcrumb && breadcrumb.length > 0 && (\n <nav className=\"mb-2\">\n <ol className=\"flex items-center gap-2 text-sm text-text-secondary\">\n {breadcrumb.map((item, index) => (\n <li key={index} className=\"flex items-center gap-2\">\n {index > 0 && <span>/</span>}\n {item.path ? (\n <a href={item.path} className=\"hover:text-text-primary transition-colors\">\n {item.label}\n </a>\n ) : (\n <span className=\"text-text-primary\">{item.label}</span>\n )}\n </li>\n ))}\n </ol>\n </nav>\n )}\n <div className=\"flex items-start justify-between gap-4 sm:items-center\">\n <motion.div\n initial={{ opacity: 0, y: -4 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.2 }}\n className=\"flex-1 min-w-0\"\n >\n <h1 className=\"text-2xl sm:text-3xl font-bold text-text-primary break-words\">{title}</h1>\n {description && (\n <p className=\"mt-1 text-sm sm:text-base text-text-secondary\">{description}</p>\n )}\n </motion.div>\n {actions && (\n <div\n data-tour=\"page-header-actions\"\n className=\"flex flex-shrink-0 flex-wrap items-center justify-end gap-2\"\n >\n {actions}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;AAUA,SAAgB,EAAW,EAAE,UAAO,gBAAa,YAAS,iBAA+B;AACvF,QACE,kBAAC,OAAD;EAAK,aAAU;EAAc,WAAU;YAAvC,CACG,KAAc,EAAW,SAAS,KACjC,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,MAAD;IAAI,WAAU;cACX,EAAW,KAAK,GAAM,MACrB,kBAAC,MAAD;KAAgB,WAAU;eAA1B,CACG,IAAQ,KAAK,kBAAC,QAAD,EAAA,UAAM,KAAQ,CAAA,EAC3B,EAAK,OACJ,kBAAC,KAAD;MAAG,MAAM,EAAK;MAAM,WAAU;gBAC3B,EAAK;MACJ,CAAA,GAEJ,kBAAC,QAAD;MAAM,WAAU;gBAAqB,EAAK;MAAa,CAAA,CAEtD;OATI,EASJ,CACL;IACC,CAAA;GACD,CAAA,EAER,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,EAAO,KAAR;IACE,SAAS;KAAE,SAAS;KAAG,GAAG;KAAI;IAC9B,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,YAAY,EAAE,UAAU,IAAK;IAC7B,WAAU;cAJZ,CAME,kBAAC,MAAD;KAAI,WAAU;eAAgE;KAAW,CAAA,EACxF,KACC,kBAAC,KAAD;KAAG,WAAU;eAAiD;KAAgB,CAAA,CAErE;OACZ,KACC,kBAAC,OAAD;IACE,aAAU;IACV,WAAU;cAET;IACG,CAAA,CAEJ;KACF"}
1
+ {"version":3,"file":"PageHeader.js","names":[],"sources":["../../../src/components/shared/PageHeader.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { motion } from 'framer-motion';\n\ninterface PageHeaderProps {\n title: string;\n description?: string;\n actions?: ReactNode;\n breadcrumb?: { label: string; path?: string }[];\n}\n\nexport function PageHeader({ title, description, actions, breadcrumb }: PageHeaderProps) {\n return (\n <div data-tour=\"page-header\" className=\"mb-6\">\n {breadcrumb && breadcrumb.length > 0 && (\n <nav className=\"mb-2\">\n <ol className=\"flex items-center gap-2 text-sm text-text-secondary\">\n {breadcrumb.map((item, index) => (\n <li key={index} className=\"flex items-center gap-2\">\n {index > 0 && <span>/</span>}\n {item.path ? (\n <a href={item.path} className=\"hover:text-text-primary transition-colors\">\n {item.label}\n </a>\n ) : (\n <span className=\"text-text-primary\">{item.label}</span>\n )}\n </li>\n ))}\n </ol>\n </nav>\n )}\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between\">\n <motion.div\n initial={{ opacity: 0, y: -4 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.2 }}\n className=\"min-w-0 lg:flex-1\"\n >\n <h1 className=\"text-2xl sm:text-3xl font-bold text-text-primary break-words\">{title}</h1>\n {description && (\n <p className=\"mt-1 text-sm sm:text-base text-text-secondary\">{description}</p>\n )}\n </motion.div>\n {actions && (\n <div\n data-tour=\"page-header-actions\"\n className=\"flex flex-shrink-0 flex-wrap items-center justify-end gap-2\"\n >\n {actions}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;AAUA,SAAgB,EAAW,EAAE,UAAO,gBAAa,YAAS,iBAA+B;AACvF,QACE,kBAAC,OAAD;EAAK,aAAU;EAAc,WAAU;YAAvC,CACG,KAAc,EAAW,SAAS,KACjC,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,MAAD;IAAI,WAAU;cACX,EAAW,KAAK,GAAM,MACrB,kBAAC,MAAD;KAAgB,WAAU;eAA1B,CACG,IAAQ,KAAK,kBAAC,QAAD,EAAA,UAAM,KAAQ,CAAA,EAC3B,EAAK,OACJ,kBAAC,KAAD;MAAG,MAAM,EAAK;MAAM,WAAU;gBAC3B,EAAK;MACJ,CAAA,GAEJ,kBAAC,QAAD;MAAM,WAAU;gBAAqB,EAAK;MAAa,CAAA,CAEtD;OATI,EASJ,CACL;IACC,CAAA;GACD,CAAA,EAER,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,EAAO,KAAR;IACE,SAAS;KAAE,SAAS;KAAG,GAAG;KAAI;IAC9B,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,YAAY,EAAE,UAAU,IAAK;IAC7B,WAAU;cAJZ,CAME,kBAAC,MAAD;KAAI,WAAU;eAAgE;KAAW,CAAA,EACxF,KACC,kBAAC,KAAD;KAAG,WAAU;eAAiD;KAAgB,CAAA,CAErE;OACZ,KACC,kBAAC,OAAD;IACE,aAAU;IACV,WAAU;cAET;IACG,CAAA,CAEJ;KACF"}
@@ -172,8 +172,10 @@ function p({ vibeId: a }) {
172
172
  placeholder: "reason",
173
173
  className: "w-28 px-1.5 py-1 text-xs bg-bg-sunken border border-border-default rounded text-text-primary"
174
174
  }), /* @__PURE__ */ c("button", {
175
+ type: "button",
175
176
  onClick: () => b(e.id),
176
177
  title: "Admin revoke",
178
+ "aria-label": "Admin revoke URL",
177
179
  className: "p-1.5 text-status-error-text hover:opacity-80",
178
180
  children: /* @__PURE__ */ c(i, { className: "w-4 h-4" })
179
181
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"VibeLlmContextAdminPanel.js","names":[],"sources":["../../../src/components/vibe/VibeLlmContextAdminPanel.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { Clock, Info, Shield, Trash2 } from 'lucide-react';\n\ninterface AdminTokenRow {\n id: string;\n vibeId: string;\n userId: string;\n label: string | null;\n tokenFingerprint: string;\n includeCredentials: boolean;\n includes: string[];\n status: 'ACTIVE' | 'REVOKED';\n expiresAt: string;\n lastFetchedAt: string | null;\n fetchCount: number;\n createdAt: string;\n revokedAt: string | null;\n revokedReason: string | null;\n}\n\nconst ALL_TOKENS = gql`\n query AllVibeLlmContextTokens($vibeId: ID, $userId: ID) {\n allVibeLlmContextTokens(vibeId: $vibeId, userId: $userId) {\n id\n vibeId\n userId\n label\n tokenFingerprint\n includeCredentials\n includes\n status\n expiresAt\n lastFetchedAt\n fetchCount\n createdAt\n revokedAt\n revokedReason\n }\n }\n`;\n\nconst ADMIN_REVOKE = gql`\n mutation AdminRevokeVibeLlmContextToken($tokenId: ID!, $reason: String) {\n adminRevokeVibeLlmContextToken(tokenId: $tokenId, reason: $reason) {\n id\n status\n revokedAt\n revokedReason\n }\n }\n`;\n\nfunction formatExpiry(expiresAt: string): string {\n const diff = new Date(expiresAt).getTime() - Date.now();\n if (diff < 0) return 'expired';\n const hours = Math.floor(diff / (1000 * 60 * 60));\n const mins = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));\n if (hours > 24) return `${Math.floor(hours / 24)}d`;\n if (hours > 0) return `${hours}h ${mins}m`;\n return `${mins}m`;\n}\n\ninterface VibeLlmContextAdminPanelProps {\n vibeId: string;\n}\n\nexport function VibeLlmContextAdminPanel({ vibeId }: VibeLlmContextAdminPanelProps): ReactElement {\n const { data, loading, refetch } = useQuery<{ allVibeLlmContextTokens: AdminTokenRow[] }>(\n ALL_TOKENS,\n {\n variables: { vibeId },\n fetchPolicy: 'cache-and-network',\n errorPolicy: 'ignore',\n }\n );\n const [adminRevoke] = useMutation<\n { adminRevokeVibeLlmContextToken: AdminTokenRow },\n { tokenId: string; reason?: string | null }\n >(ADMIN_REVOKE, { refetchQueries: ['AllVibeLlmContextTokens'] });\n\n const [reasonDraft, setReasonDraft] = useState<Record<string, string>>({});\n const tokens = data?.allVibeLlmContextTokens ?? [];\n\n const onRevoke = async (tokenId: string) => {\n await adminRevoke({\n variables: {\n tokenId,\n reason: (reasonDraft[tokenId] ?? '').trim() || null,\n },\n });\n setReasonDraft((prev) => {\n const next = { ...prev };\n delete next[tokenId];\n return next;\n });\n await refetch();\n };\n\n return (\n <section className=\"bg-bg-surface border border-status-warning-border rounded-lg p-5 space-y-3\">\n <header className=\"flex items-start gap-3\">\n <Shield className=\"w-5 h-5 text-status-warning-text mt-0.5\" />\n <div>\n <h3 className=\"text-base font-semibold text-text-primary\">\n Admin · all URLs for this vibe\n </h3>\n <p className=\"text-sm text-text-secondary\">\n Visible only to workspace admins. Lists every user's signed URLs for this vibe. Use\n revoke to immediately invalidate any URL — takes effect on the next fetch.\n </p>\n </div>\n </header>\n\n {loading && tokens.length === 0 && (\n <div className=\"text-sm text-text-secondary py-3\">Loading…</div>\n )}\n {tokens.length === 0 && !loading && (\n <div className=\"text-sm text-text-secondary py-3 flex items-center gap-2\">\n <Info className=\"w-4 h-4\" />\n No URLs minted for this vibe by any user.\n </div>\n )}\n {tokens.length > 0 && (\n <div className=\"overflow-x-auto\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-default text-left text-xs text-text-secondary\">\n <th className=\"py-2 pr-3\">User</th>\n <th className=\"py-2 pr-3\">Label</th>\n <th className=\"py-2 pr-3\">Fingerprint</th>\n <th className=\"py-2 pr-3\">Creds</th>\n <th className=\"py-2 pr-3\">Status</th>\n <th className=\"py-2 pr-3\">Expires</th>\n <th className=\"py-2 pr-3\">Fetches</th>\n <th className=\"py-2 pr-3\">Revoke</th>\n </tr>\n </thead>\n <tbody>\n {tokens.map((t) => (\n <tr key={t.id} className=\"border-b border-border-subtle align-top\">\n <td\n className=\"py-2 pr-3 font-mono text-xs text-text-secondary truncate max-w-[120px]\"\n title={t.userId}\n >\n {t.userId}\n </td>\n <td className=\"py-2 pr-3 text-text-primary\">{t.label ?? '—'}</td>\n <td className=\"py-2 pr-3 font-mono text-xs text-text-secondary\">\n {t.tokenFingerprint}\n </td>\n <td className=\"py-2 pr-3\">\n {t.includeCredentials ? (\n <span className=\"text-xs text-status-warning-text\">on</span>\n ) : (\n <span className=\"text-xs text-text-secondary\">off</span>\n )}\n </td>\n <td className=\"py-2 pr-3\">\n <span\n className={`text-xs px-1.5 py-0.5 rounded ${\n t.status === 'ACTIVE'\n ? 'bg-status-success-bg/20 text-status-success-text'\n : 'bg-bg-sunken text-text-secondary'\n }`}\n >\n {t.status}\n </span>\n </td>\n <td className=\"py-2 pr-3 text-xs text-text-secondary\">\n <span className=\"inline-flex items-center gap-1\">\n <Clock className=\"w-3 h-3\" />\n {formatExpiry(t.expiresAt)}\n </span>\n </td>\n <td className=\"py-2 pr-3 text-xs text-text-secondary\">{t.fetchCount}</td>\n <td className=\"py-2 pr-3\">\n {t.status === 'ACTIVE' ? (\n <div className=\"flex items-center gap-1\">\n <input\n type=\"text\"\n value={reasonDraft[t.id] ?? ''}\n onChange={(e) =>\n setReasonDraft((prev) => ({ ...prev, [t.id]: e.target.value }))\n }\n placeholder=\"reason\"\n className=\"w-28 px-1.5 py-1 text-xs bg-bg-sunken border border-border-default rounded text-text-primary\"\n />\n <button\n onClick={() => onRevoke(t.id)}\n title=\"Admin revoke\"\n className=\"p-1.5 text-status-error-text hover:opacity-80\"\n >\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </div>\n ) : (\n <span className=\"text-xs text-text-secondary\" title={t.revokedReason ?? ''}>\n {t.revokedReason ?? '—'}\n </span>\n )}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </section>\n );\n}\n"],"mappings":";;;;;;AAuBA,IAAM,IAAa,CAAG;;;;;;;;;;;;;;;;;;;GAqBhB,IAAe,CAAG;;;;;;;;;;AAWxB,SAAS,EAAa,GAA2B;CAC/C,IAAM,IAAO,IAAI,KAAK,EAAU,CAAC,SAAS,GAAG,KAAK,KAAK;AACvD,KAAI,IAAO,EAAG,QAAO;CACrB,IAAM,IAAQ,KAAK,MAAM,KAAQ,MAAO,KAAK,IAAI,EAC3C,IAAO,KAAK,MAAO,KAAQ,MAAO,KAAK,OAAQ,MAAO,IAAI;AAGhE,QAFI,IAAQ,KAAW,GAAG,KAAK,MAAM,IAAQ,GAAG,CAAC,KAC7C,IAAQ,IAAU,GAAG,EAAM,IAAI,EAAK,KACjC,GAAG,EAAK;;AAOjB,SAAgB,EAAyB,EAAE,aAAuD;CAChG,IAAM,EAAE,SAAM,YAAS,eAAY,EACjC,GACA;EACE,WAAW,EAAE,WAAQ;EACrB,aAAa;EACb,aAAa;EACd,CACF,EACK,CAAC,KAAe,EAGpB,GAAc,EAAE,gBAAgB,CAAC,0BAA0B,EAAE,CAAC,EAE1D,CAAC,GAAa,KAAkB,EAAiC,EAAE,CAAC,EACpE,IAAS,GAAM,2BAA2B,EAAE,EAE5C,IAAW,OAAO,MAAoB;AAY1C,EAXA,MAAM,EAAY,EAChB,WAAW;GACT;GACA,SAAS,EAAY,MAAY,IAAI,MAAM,IAAI;GAChD,EACF,CAAC,EACF,GAAgB,MAAS;GACvB,IAAM,IAAO,EAAE,GAAG,GAAM;AAExB,UADA,OAAO,EAAK,IACL;IACP,EACF,MAAM,GAAS;;AAGjB,QACE,kBAAC,WAAD;EAAS,WAAU;YAAnB;GACE,kBAAC,UAAD;IAAQ,WAAU;cAAlB,CACE,kBAAC,GAAD,EAAQ,WAAU,2CAA4C,CAAA,EAC9D,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eAA4C;KAErD,CAAA,EACL,kBAAC,KAAD;KAAG,WAAU;eAA8B;KAGvC,CAAA,CACA,EAAA,CAAA,CACC;;GAER,KAAW,EAAO,WAAW,KAC5B,kBAAC,OAAD;IAAK,WAAU;cAAmC;IAAc,CAAA;GAEjE,EAAO,WAAW,KAAK,CAAC,KACvB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,4CAExB;;GAEP,EAAO,SAAS,KACf,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,SAAD;KAAO,WAAU;eAAjB,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD;MAAI,WAAU;gBAAd;OACE,kBAAC,MAAD;QAAI,WAAU;kBAAY;QAAS,CAAA;OACnC,kBAAC,MAAD;QAAI,WAAU;kBAAY;QAAU,CAAA;OACpC,kBAAC,MAAD;QAAI,WAAU;kBAAY;QAAgB,CAAA;OAC1C,kBAAC,MAAD;QAAI,WAAU;kBAAY;QAAU,CAAA;OACpC,kBAAC,MAAD;QAAI,WAAU;kBAAY;QAAW,CAAA;OACrC,kBAAC,MAAD;QAAI,WAAU;kBAAY;QAAY,CAAA;OACtC,kBAAC,MAAD;QAAI,WAAU;kBAAY;QAAY,CAAA;OACtC,kBAAC,MAAD;QAAI,WAAU;kBAAY;QAAW,CAAA;OAClC;SACC,CAAA,EACR,kBAAC,SAAD,EAAA,UACG,EAAO,KAAK,MACX,kBAAC,MAAD;MAAe,WAAU;gBAAzB;OACE,kBAAC,MAAD;QACE,WAAU;QACV,OAAO,EAAE;kBAER,EAAE;QACA,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAA+B,EAAE,SAAS;QAAS,CAAA;OACjE,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAE;QACA,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAE,qBACD,kBAAC,QAAD;SAAM,WAAU;mBAAmC;SAAS,CAAA,GAE5D,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAU,CAAA;QAEvD,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBACZ,kBAAC,QAAD;SACE,WAAW,iCACT,EAAE,WAAW,WACT,qDACA;mBAGL,EAAE;SACE,CAAA;QACJ,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBACZ,kBAAC,QAAD;SAAM,WAAU;mBAAhB,CACE,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA,EAC5B,EAAa,EAAE,UAAU,CACrB;;QACJ,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAAyC,EAAE;QAAgB,CAAA;OACzE,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAE,WAAW,WACZ,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,SAAD;UACE,MAAK;UACL,OAAO,EAAY,EAAE,OAAO;UAC5B,WAAW,MACT,GAAgB,OAAU;WAAE,GAAG;YAAO,EAAE,KAAK,EAAE,OAAO;WAAO,EAAE;UAEjE,aAAY;UACZ,WAAU;UACV,CAAA,EACF,kBAAC,UAAD;UACE,eAAe,EAAS,EAAE,GAAG;UAC7B,OAAM;UACN,WAAU;oBAEV,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;UACvB,CAAA,CACL;aAEN,kBAAC,QAAD;SAAM,WAAU;SAA8B,OAAO,EAAE,iBAAiB;mBACrE,EAAE,iBAAiB;SACf,CAAA;QAEN,CAAA;OACF;QA9DI,EAAE,GA8DN,CACL,EACI,CAAA,CACF;;IACJ,CAAA;GAEA"}
1
+ {"version":3,"file":"VibeLlmContextAdminPanel.js","names":[],"sources":["../../../src/components/vibe/VibeLlmContextAdminPanel.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { Clock, Info, Shield, Trash2 } from 'lucide-react';\n\ninterface AdminTokenRow {\n id: string;\n vibeId: string;\n userId: string;\n label: string | null;\n tokenFingerprint: string;\n includeCredentials: boolean;\n includes: string[];\n status: 'ACTIVE' | 'REVOKED';\n expiresAt: string;\n lastFetchedAt: string | null;\n fetchCount: number;\n createdAt: string;\n revokedAt: string | null;\n revokedReason: string | null;\n}\n\nconst ALL_TOKENS = gql`\n query AllVibeLlmContextTokens($vibeId: ID, $userId: ID) {\n allVibeLlmContextTokens(vibeId: $vibeId, userId: $userId) {\n id\n vibeId\n userId\n label\n tokenFingerprint\n includeCredentials\n includes\n status\n expiresAt\n lastFetchedAt\n fetchCount\n createdAt\n revokedAt\n revokedReason\n }\n }\n`;\n\nconst ADMIN_REVOKE = gql`\n mutation AdminRevokeVibeLlmContextToken($tokenId: ID!, $reason: String) {\n adminRevokeVibeLlmContextToken(tokenId: $tokenId, reason: $reason) {\n id\n status\n revokedAt\n revokedReason\n }\n }\n`;\n\nfunction formatExpiry(expiresAt: string): string {\n const diff = new Date(expiresAt).getTime() - Date.now();\n if (diff < 0) return 'expired';\n const hours = Math.floor(diff / (1000 * 60 * 60));\n const mins = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));\n if (hours > 24) return `${Math.floor(hours / 24)}d`;\n if (hours > 0) return `${hours}h ${mins}m`;\n return `${mins}m`;\n}\n\ninterface VibeLlmContextAdminPanelProps {\n vibeId: string;\n}\n\nexport function VibeLlmContextAdminPanel({ vibeId }: VibeLlmContextAdminPanelProps): ReactElement {\n const { data, loading, refetch } = useQuery<{ allVibeLlmContextTokens: AdminTokenRow[] }>(\n ALL_TOKENS,\n {\n variables: { vibeId },\n fetchPolicy: 'cache-and-network',\n errorPolicy: 'ignore',\n }\n );\n const [adminRevoke] = useMutation<\n { adminRevokeVibeLlmContextToken: AdminTokenRow },\n { tokenId: string; reason?: string | null }\n >(ADMIN_REVOKE, { refetchQueries: ['AllVibeLlmContextTokens'] });\n\n const [reasonDraft, setReasonDraft] = useState<Record<string, string>>({});\n const tokens = data?.allVibeLlmContextTokens ?? [];\n\n const onRevoke = async (tokenId: string) => {\n await adminRevoke({\n variables: {\n tokenId,\n reason: (reasonDraft[tokenId] ?? '').trim() || null,\n },\n });\n setReasonDraft((prev) => {\n const next = { ...prev };\n delete next[tokenId];\n return next;\n });\n await refetch();\n };\n\n return (\n <section className=\"bg-bg-surface border border-status-warning-border rounded-lg p-5 space-y-3\">\n <header className=\"flex items-start gap-3\">\n <Shield className=\"w-5 h-5 text-status-warning-text mt-0.5\" />\n <div>\n <h3 className=\"text-base font-semibold text-text-primary\">\n Admin · all URLs for this vibe\n </h3>\n <p className=\"text-sm text-text-secondary\">\n Visible only to workspace admins. Lists every user's signed URLs for this vibe. Use\n revoke to immediately invalidate any URL — takes effect on the next fetch.\n </p>\n </div>\n </header>\n\n {loading && tokens.length === 0 && (\n <div className=\"text-sm text-text-secondary py-3\">Loading…</div>\n )}\n {tokens.length === 0 && !loading && (\n <div className=\"text-sm text-text-secondary py-3 flex items-center gap-2\">\n <Info className=\"w-4 h-4\" />\n No URLs minted for this vibe by any user.\n </div>\n )}\n {tokens.length > 0 && (\n <div className=\"overflow-x-auto\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-default text-left text-xs text-text-secondary\">\n <th className=\"py-2 pr-3\">User</th>\n <th className=\"py-2 pr-3\">Label</th>\n <th className=\"py-2 pr-3\">Fingerprint</th>\n <th className=\"py-2 pr-3\">Creds</th>\n <th className=\"py-2 pr-3\">Status</th>\n <th className=\"py-2 pr-3\">Expires</th>\n <th className=\"py-2 pr-3\">Fetches</th>\n <th className=\"py-2 pr-3\">Revoke</th>\n </tr>\n </thead>\n <tbody>\n {tokens.map((t) => (\n <tr key={t.id} className=\"border-b border-border-subtle align-top\">\n <td\n className=\"py-2 pr-3 font-mono text-xs text-text-secondary truncate max-w-[120px]\"\n title={t.userId}\n >\n {t.userId}\n </td>\n <td className=\"py-2 pr-3 text-text-primary\">{t.label ?? '—'}</td>\n <td className=\"py-2 pr-3 font-mono text-xs text-text-secondary\">\n {t.tokenFingerprint}\n </td>\n <td className=\"py-2 pr-3\">\n {t.includeCredentials ? (\n <span className=\"text-xs text-status-warning-text\">on</span>\n ) : (\n <span className=\"text-xs text-text-secondary\">off</span>\n )}\n </td>\n <td className=\"py-2 pr-3\">\n <span\n className={`text-xs px-1.5 py-0.5 rounded ${\n t.status === 'ACTIVE'\n ? 'bg-status-success-bg/20 text-status-success-text'\n : 'bg-bg-sunken text-text-secondary'\n }`}\n >\n {t.status}\n </span>\n </td>\n <td className=\"py-2 pr-3 text-xs text-text-secondary\">\n <span className=\"inline-flex items-center gap-1\">\n <Clock className=\"w-3 h-3\" />\n {formatExpiry(t.expiresAt)}\n </span>\n </td>\n <td className=\"py-2 pr-3 text-xs text-text-secondary\">{t.fetchCount}</td>\n <td className=\"py-2 pr-3\">\n {t.status === 'ACTIVE' ? (\n <div className=\"flex items-center gap-1\">\n <input\n type=\"text\"\n value={reasonDraft[t.id] ?? ''}\n onChange={(e) =>\n setReasonDraft((prev) => ({ ...prev, [t.id]: e.target.value }))\n }\n placeholder=\"reason\"\n className=\"w-28 px-1.5 py-1 text-xs bg-bg-sunken border border-border-default rounded text-text-primary\"\n />\n <button\n type=\"button\"\n onClick={() => onRevoke(t.id)}\n title=\"Admin revoke\"\n aria-label=\"Admin revoke URL\"\n className=\"p-1.5 text-status-error-text hover:opacity-80\"\n >\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </div>\n ) : (\n <span className=\"text-xs text-text-secondary\" title={t.revokedReason ?? ''}>\n {t.revokedReason ?? '—'}\n </span>\n )}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </section>\n );\n}\n"],"mappings":"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"}
@@ -1,13 +1,13 @@
1
1
  import { VIBE_PERMISSIONS as e } from "../../constants/permissions.js";
2
2
  import { VibeLlmContextAdminPanel as t } from "./VibeLlmContextAdminPanel.js";
3
- import { useMemo as n, useState as r } from "react";
4
- import { Bot as i, Check as a, Clock as o, Copy as s, EyeOff as ee, Info as c, Lock as l, RefreshCw as te, RotateCw as ne, Trash2 as u } from "lucide-react";
5
- import { gql as d } from "@apollo/client";
6
- import { useMutation as f, useQuery as p } from "@apollo/client/react";
7
- import { usePermissions as m } from "@burdenoff/fe-libs/shared/providers/shell";
8
- import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
3
+ import { Fragment as n, useEffect as r, useState as i } from "react";
4
+ import { AlertTriangle as a, Bot as o, Check as s, Clock as c, Copy as ee, EyeOff as te, Info as l, Lock as u, RefreshCw as ne, RotateCw as re, Trash2 as d } from "lucide-react";
5
+ import { gql as f } from "@apollo/client";
6
+ import { useMutation as p, useQuery as m } from "@apollo/client/react";
7
+ import { usePermissions as h } from "@burdenoff/fe-libs/shared/providers/shell";
8
+ import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
9
9
  //#region src/components/vibe/VibeLlmContextTabPanel.tsx
10
- var v = [
10
+ var y = [
11
11
  "core",
12
12
  "agents",
13
13
  "sessions",
@@ -17,7 +17,7 @@ var v = [
17
17
  "config",
18
18
  "security",
19
19
  "plugins"
20
- ], y = d`
20
+ ], ie = f`
21
21
  query MyVibeLlmContextSettings($vibeId: ID!) {
22
22
  myVibeLlmContextSettings(vibeId: $vibeId) {
23
23
  vibeId
@@ -33,7 +33,7 @@ var v = [
33
33
  updatedAt
34
34
  }
35
35
  }
36
- `, b = d`
36
+ `, b = f`
37
37
  query MyVibeLlmContextTokens($vibeId: ID!) {
38
38
  myVibeLlmContextTokens(vibeId: $vibeId) {
39
39
  id
@@ -52,7 +52,7 @@ var v = [
52
52
  revokedReason
53
53
  }
54
54
  }
55
- `, re = d`
55
+ `, x = f`
56
56
  mutation SetMyVibeLlmContextSettings($vibeId: ID!, $input: VibeLlmContextSettingsInput!) {
57
57
  setMyVibeLlmContextSettings(vibeId: $vibeId, input: $input) {
58
58
  vibeId
@@ -68,7 +68,7 @@ var v = [
68
68
  updatedAt
69
69
  }
70
70
  }
71
- `, x = d`
71
+ `, ae = f`
72
72
  mutation GenerateVibeLlmContextUrl($vibeId: ID!, $input: VibeLlmContextMintInput) {
73
73
  generateVibeLlmContextUrl(vibeId: $vibeId, input: $input) {
74
74
  tokenId
@@ -82,7 +82,7 @@ var v = [
82
82
  tokenFingerprint
83
83
  }
84
84
  }
85
- `, S = d`
85
+ `, oe = f`
86
86
  mutation RevokeVibeLlmContextToken($tokenId: ID!) {
87
87
  revokeVibeLlmContextToken(tokenId: $tokenId) {
88
88
  id
@@ -90,7 +90,7 @@ var v = [
90
90
  revokedAt
91
91
  }
92
92
  }
93
- `, C = d`
93
+ `, S = f`
94
94
  mutation RotateVibeLlmContextUrl($tokenId: ID!, $input: VibeLlmContextMintInput) {
95
95
  rotateVibeLlmContextUrl(tokenId: $tokenId, input: $input) {
96
96
  tokenId
@@ -104,11 +104,11 @@ var v = [
104
104
  tokenFingerprint
105
105
  }
106
106
  }
107
- `, w = d`
107
+ `, C = f`
108
108
  mutation RevokeAllMyVibeLlmContextTokens($vibeId: ID!) {
109
109
  revokeAllMyVibeLlmContextTokens(vibeId: $vibeId)
110
110
  }
111
- `, T = d`
111
+ `, w = f`
112
112
  query MyVibeLlmContextTokenAudits($tokenId: ID!, $limit: Int) {
113
113
  myVibeLlmContextTokenAudits(tokenId: $tokenId, limit: $limit) {
114
114
  id
@@ -121,7 +121,7 @@ var v = [
121
121
  status
122
122
  }
123
123
  }
124
- `, E = [
124
+ `, T = [
125
125
  {
126
126
  label: "1 hour",
127
127
  hours: 1
@@ -139,7 +139,7 @@ var v = [
139
139
  hours: 168
140
140
  }
141
141
  ];
142
- async function D(e) {
142
+ async function se(e) {
143
143
  try {
144
144
  await navigator.clipboard.writeText(e);
145
145
  } catch {
@@ -147,396 +147,420 @@ async function D(e) {
147
147
  t.value = e, t.style.position = "fixed", t.style.opacity = "0", document.body.appendChild(t), t.select(), document.execCommand("copy"), document.body.removeChild(t);
148
148
  }
149
149
  }
150
- function O(e) {
150
+ function E(e) {
151
151
  let t = new Date(e).getTime() - Date.now();
152
152
  if (t < 0) return "expired";
153
153
  let n = Math.floor(t / (1e3 * 60 * 60)), r = Math.floor(t % (1e3 * 60 * 60) / (1e3 * 60));
154
154
  return n > 24 ? `${Math.floor(n / 24)}d` : n > 0 ? `${n}h ${r}m` : `${r}m`;
155
155
  }
156
- function k({ vibeId: d, attachedAgents: T = [] }) {
157
- let { hasPermission: k } = m(), ae = k(e.VIBE_MANAGE), oe = p(y, {
158
- variables: { vibeId: d },
156
+ function D({ vibeId: f, attachedAgents: w = [] }) {
157
+ let { hasPermission: D } = h(), le = D(e.VIBE_MANAGE), ue = m(ie, {
158
+ variables: { vibeId: f },
159
159
  fetchPolicy: "cache-and-network"
160
- }), A = p(b, {
161
- variables: { vibeId: d },
160
+ }), O = m(b, {
161
+ variables: { vibeId: f },
162
162
  fetchPolicy: "cache-and-network"
163
- }), [se, j] = f(re, { refetchQueries: ["MyVibeLlmContextSettings"] }), [M, N] = f(x, { refetchQueries: ["MyVibeLlmContextTokens"] }), [P] = f(S, { refetchQueries: ["MyVibeLlmContextTokens"] }), [F] = f(C, { refetchQueries: ["MyVibeLlmContextTokens"] }), [I] = f(w, { refetchQueries: ["MyVibeLlmContextTokens"] }), L = oe.data?.myVibeLlmContextSettings, R = A.data?.myVibeLlmContextTokens ?? [], [z, B] = r(1), [V, H] = r(!1), [U, W] = r(new Set(v)), [G, K] = r(""), [q, J] = r(""), [Y, ce] = r(""), [X, Z] = r(null), [le, Q] = r(!1), [$, ue] = r(null);
164
- n(() => {
165
- L && (B(Math.max(1, Math.round((L.ttlSeconds ?? 3600) / 3600))), H(L.includeCredentials), W(new Set(L.includes ?? v)), K(L.customContextText ?? ""), J(L.defaultAgentIdOverride ?? ""));
166
- }, [L]);
167
- let de = (e) => {
168
- W((t) => {
163
+ }), [de, k] = p(x, { refetchQueries: ["MyVibeLlmContextSettings"] }), [fe, A] = p(ae, { refetchQueries: ["MyVibeLlmContextTokens"] }), [j] = p(oe, { refetchQueries: ["MyVibeLlmContextTokens"] }), [M] = p(S, { refetchQueries: ["MyVibeLlmContextTokens"] }), [N] = p(C, { refetchQueries: ["MyVibeLlmContextTokens"] }), P = ue.data?.myVibeLlmContextSettings, F = O.data?.myVibeLlmContextTokens ?? [], [I, L] = i(1), [R, z] = i(!1), [B, V] = i(new Set(y)), [H, U] = i(""), [W, G] = i(""), [K, q] = i(""), [J, Y] = i(null), [pe, X] = i(!1), [Z, Q] = i(!1), [$, me] = i(null);
164
+ r(() => {
165
+ P && (L(Math.max(1, Math.round((P.ttlSeconds ?? 3600) / 3600))), z(P.includeCredentials), V(new Set(P.includes ?? y)), U(P.customContextText ?? ""), G(P.defaultAgentIdOverride ?? ""));
166
+ }, [P]);
167
+ let he = (e) => {
168
+ V((t) => {
169
169
  let n = new Set(t);
170
170
  return n.has(e) ? n.delete(e) : n.add(e), n;
171
171
  });
172
172
  };
173
- return /* @__PURE__ */ _("div", {
173
+ return /* @__PURE__ */ v("div", {
174
174
  className: "space-y-6 max-w-5xl",
175
175
  children: [
176
- /* @__PURE__ */ g("div", {
176
+ /* @__PURE__ */ _("div", {
177
177
  className: "rounded-lg border border-status-warning-border bg-status-warning-bg/30 p-4",
178
- children: /* @__PURE__ */ _("div", {
178
+ children: /* @__PURE__ */ v("div", {
179
179
  className: "flex items-start gap-3",
180
- children: [/* @__PURE__ */ g(l, { className: "w-5 h-5 text-status-warning-text mt-0.5" }), /* @__PURE__ */ _("div", {
180
+ children: [/* @__PURE__ */ _(u, { className: "w-5 h-5 text-status-warning-text mt-0.5" }), /* @__PURE__ */ v("div", {
181
181
  className: "text-sm text-text-primary",
182
- children: [/* @__PURE__ */ g("p", {
182
+ children: [/* @__PURE__ */ _("p", {
183
183
  className: "font-medium mb-1",
184
184
  children: "LLM Context — share this vibe with any LLM via a signed URL"
185
- }), /* @__PURE__ */ g("p", {
185
+ }), /* @__PURE__ */ _("p", {
186
186
  className: "text-text-secondary",
187
187
  children: "Anyone with the URL can read the snapshot until it expires. When \"Include credentials\" is on, the snapshot exposes agent tunnel URLs + API keys. Default is redacted. Rotate or revoke any URL from the list below at any time."
188
188
  })]
189
189
  })]
190
190
  })
191
191
  }),
192
- /* @__PURE__ */ _("section", {
192
+ /* @__PURE__ */ v("section", {
193
193
  className: "bg-bg-surface border border-border-default rounded-lg p-5 space-y-4",
194
194
  children: [
195
- /* @__PURE__ */ _("header", {
195
+ /* @__PURE__ */ v("header", {
196
196
  className: "flex items-center justify-between",
197
- children: [/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("h3", {
197
+ children: [/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("h3", {
198
198
  className: "text-base font-semibold text-text-primary",
199
199
  children: "Saved settings"
200
- }), /* @__PURE__ */ g("p", {
200
+ }), /* @__PURE__ */ _("p", {
201
201
  className: "text-sm text-text-secondary",
202
202
  children: "Defaults used when you generate a URL. Snapshotted into each minted token, so future edits don't change already-minted URLs."
203
- })] }), /* @__PURE__ */ g("button", {
203
+ })] }), /* @__PURE__ */ v("button", {
204
+ type: "button",
204
205
  onClick: async () => {
205
- await se({ variables: {
206
- vibeId: d,
206
+ await de({ variables: {
207
+ vibeId: f,
207
208
  input: {
208
- ttlSeconds: Math.max(60, Math.min(10080 * 60, z * 60 * 60)),
209
- includeCredentials: V,
210
- includes: Array.from(U),
211
- customContextText: G,
212
- defaultAgentIdOverride: q || null
209
+ ttlSeconds: Math.max(60, Math.min(10080 * 60, I * 60 * 60)),
210
+ includeCredentials: R,
211
+ includes: Array.from(B),
212
+ customContextText: H,
213
+ defaultAgentIdOverride: W || null
213
214
  }
214
- } });
215
+ } }), Q(!0), setTimeout(() => Q(!1), 2e3);
215
216
  },
216
- disabled: j.loading,
217
- className: "px-3 py-1.5 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover disabled:opacity-50",
218
- children: j.loading ? "Saving…" : "Save settings"
217
+ disabled: k.loading,
218
+ className: "inline-flex items-center gap-1.5 px-3 py-1.5 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover disabled:opacity-50",
219
+ children: [Z && !k.loading && /* @__PURE__ */ _(s, { className: "w-4 h-4" }), k.loading ? "Saving…" : Z ? "Saved" : "Save settings"]
219
220
  })]
220
221
  }),
221
- /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
222
+ /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
222
223
  className: "block text-sm font-medium text-text-primary mb-2",
223
224
  children: "URL expiry"
224
- }), /* @__PURE__ */ _("div", {
225
+ }), /* @__PURE__ */ v("div", {
225
226
  className: "flex flex-wrap items-center gap-2",
226
227
  children: [
227
- E.map((e) => /* @__PURE__ */ g("button", {
228
- onClick: () => B(e.hours),
229
- className: `px-3 py-1.5 text-sm rounded-md border ${z === e.hours ? "bg-action-primary-bg text-action-primary-text border-action-primary-bg" : "bg-bg-sunken text-text-primary border-border-default"}`,
228
+ T.map((e) => /* @__PURE__ */ _("button", {
229
+ type: "button",
230
+ onClick: () => L(e.hours),
231
+ className: `px-3 py-1.5 text-sm rounded-md border ${I === e.hours ? "bg-action-primary-bg text-action-primary-text border-action-primary-bg" : "bg-bg-sunken text-text-primary border-border-default"}`,
230
232
  children: e.label
231
233
  }, e.hours)),
232
- /* @__PURE__ */ g("span", {
234
+ /* @__PURE__ */ _("span", {
233
235
  className: "text-sm text-text-secondary mx-1",
234
236
  children: "or custom hours:"
235
237
  }),
236
- /* @__PURE__ */ g("input", {
238
+ /* @__PURE__ */ _("input", {
237
239
  type: "number",
238
240
  min: 1,
239
241
  max: 168,
240
- value: z,
241
- onChange: (e) => B(Math.max(1, Math.min(168, Number(e.target.value) || 1))),
242
+ value: I,
243
+ onChange: (e) => L(Math.max(1, Math.min(168, Number(e.target.value) || 1))),
242
244
  className: "w-24 px-2 py-1.5 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary"
243
245
  })
244
246
  ]
245
247
  })] }),
246
- /* @__PURE__ */ g("div", { children: /* @__PURE__ */ _("label", {
248
+ /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ v("label", {
247
249
  className: "flex items-center gap-2 text-sm text-text-primary",
248
250
  children: [
249
- /* @__PURE__ */ g("input", {
251
+ /* @__PURE__ */ _("input", {
250
252
  type: "checkbox",
251
- checked: V,
252
- onChange: (e) => H(e.target.checked),
253
+ checked: R,
254
+ onChange: (e) => z(e.target.checked),
253
255
  className: "w-4 h-4"
254
256
  }),
255
- /* @__PURE__ */ g("span", { children: "Include credentials (tunnel URLs + agent API keys)" }),
256
- !V && /* @__PURE__ */ g(ee, { className: "w-4 h-4 text-text-secondary" })
257
+ /* @__PURE__ */ _("span", { children: "Include credentials (tunnel URLs + agent API keys)" }),
258
+ R ? /* @__PURE__ */ _(a, {
259
+ className: "w-4 h-4 text-status-warning-text",
260
+ "aria-label": "Credentials will be exposed in the snapshot"
261
+ }) : /* @__PURE__ */ _(te, {
262
+ className: "w-4 h-4 text-text-secondary",
263
+ "aria-label": "Credentials redacted"
264
+ })
257
265
  ]
258
- }) }),
259
- /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
266
+ }), R && /* @__PURE__ */ v("p", {
267
+ className: "mt-1.5 text-xs text-status-warning-text flex items-start gap-1.5",
268
+ children: [/* @__PURE__ */ _(a, { className: "w-3.5 h-3.5 mt-0.5 flex-shrink-0" }), /* @__PURE__ */ _("span", { children: "Anyone with a URL minted while this is on can read live agent tunnel URLs and API keys. Only enable for trusted recipients." })]
269
+ })] }),
270
+ /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
260
271
  className: "block text-sm font-medium text-text-primary mb-2",
261
272
  children: "Sections to include"
262
- }), /* @__PURE__ */ g("div", {
273
+ }), /* @__PURE__ */ _("div", {
263
274
  className: "flex flex-wrap gap-2",
264
- children: v.map((e) => /* @__PURE__ */ g("button", {
265
- onClick: () => de(e),
266
- className: `px-2.5 py-1 text-xs rounded-full border ${U.has(e) ? "bg-action-primary-bg/10 text-action-primary-bg border-action-primary-bg" : "bg-bg-sunken text-text-secondary border-border-default"}`,
275
+ children: y.map((e) => /* @__PURE__ */ _("button", {
276
+ type: "button",
277
+ onClick: () => he(e),
278
+ className: `px-2.5 py-1 text-xs rounded-full border ${B.has(e) ? "bg-action-primary-bg/10 text-action-primary-bg border-action-primary-bg" : "bg-bg-sunken text-text-secondary border-border-default"}`,
267
279
  children: e
268
280
  }, e))
269
281
  })] }),
270
- T.length > 0 && /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
282
+ w.length > 0 && /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
271
283
  className: "block text-sm font-medium text-text-primary mb-2",
272
284
  children: "Default agent for context fetch"
273
- }), /* @__PURE__ */ _("select", {
274
- value: q,
275
- onChange: (e) => J(e.target.value),
285
+ }), /* @__PURE__ */ v("select", {
286
+ value: W,
287
+ onChange: (e) => G(e.target.value),
276
288
  className: "w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary",
277
- children: [/* @__PURE__ */ g("option", {
289
+ children: [/* @__PURE__ */ _("option", {
278
290
  value: "",
279
291
  children: "(use my per-vibe default from settings)"
280
- }), T.map((e) => /* @__PURE__ */ g("option", {
292
+ }), w.map((e) => /* @__PURE__ */ _("option", {
281
293
  value: e.id,
282
294
  children: e.name
283
295
  }, e.id))]
284
296
  })] }),
285
- /* @__PURE__ */ _("div", { children: [
286
- /* @__PURE__ */ g("label", {
297
+ /* @__PURE__ */ v("div", { children: [
298
+ /* @__PURE__ */ _("label", {
287
299
  className: "block text-sm font-medium text-text-primary mb-2",
288
300
  children: "Custom context text"
289
301
  }),
290
- /* @__PURE__ */ g("textarea", {
291
- value: G,
292
- onChange: (e) => K(e.target.value.slice(0, 8192)),
302
+ /* @__PURE__ */ _("textarea", {
303
+ value: H,
304
+ onChange: (e) => U(e.target.value.slice(0, 8192)),
293
305
  rows: 5,
294
306
  placeholder: "Free-form notes embedded in every snapshot you mint AFTER saving (existing tokens keep their original copy).",
295
307
  className: "w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder"
296
308
  }),
297
- /* @__PURE__ */ _("p", {
309
+ /* @__PURE__ */ v("p", {
298
310
  className: "text-xs text-text-secondary mt-1",
299
- children: [G.length, " / 8192 chars"]
311
+ children: [H.length, " / 8192 chars"]
300
312
  })
301
313
  ] })
302
314
  ]
303
315
  }),
304
- /* @__PURE__ */ _("section", {
316
+ /* @__PURE__ */ v("section", {
305
317
  className: "bg-bg-surface border border-border-default rounded-lg p-5 space-y-4",
306
318
  children: [
307
- /* @__PURE__ */ _("header", { children: [/* @__PURE__ */ g("h3", {
319
+ /* @__PURE__ */ v("header", { children: [/* @__PURE__ */ _("h3", {
308
320
  className: "text-base font-semibold text-text-primary",
309
321
  children: "Generate a new URL"
310
- }), /* @__PURE__ */ g("p", {
322
+ }), /* @__PURE__ */ _("p", {
311
323
  className: "text-sm text-text-secondary",
312
324
  children: "Mints a fresh signed URL using your current settings. The full token is only shown once — copy it before navigating away. Use Rotate below if you lose it."
313
325
  })] }),
314
- /* @__PURE__ */ _("div", {
326
+ /* @__PURE__ */ v("div", {
315
327
  className: "flex flex-wrap items-end gap-2",
316
- children: [/* @__PURE__ */ _("div", {
328
+ children: [/* @__PURE__ */ v("div", {
317
329
  className: "flex-1 min-w-[200px]",
318
- children: [/* @__PURE__ */ g("label", {
330
+ children: [/* @__PURE__ */ _("label", {
319
331
  className: "block text-sm font-medium text-text-primary mb-1",
320
332
  children: "Label (optional)"
321
- }), /* @__PURE__ */ g("input", {
333
+ }), /* @__PURE__ */ _("input", {
322
334
  type: "text",
323
- value: Y,
324
- onChange: (e) => ce(e.target.value.slice(0, 120)),
335
+ value: K,
336
+ onChange: (e) => q(e.target.value.slice(0, 120)),
325
337
  placeholder: "e.g. Claude desktop",
326
338
  className: "w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder"
327
339
  })]
328
- }), /* @__PURE__ */ g("button", {
340
+ }), /* @__PURE__ */ _("button", {
341
+ type: "button",
329
342
  onClick: async () => {
330
- let e = await M({ variables: {
331
- vibeId: d,
343
+ let e = await fe({ variables: {
344
+ vibeId: f,
332
345
  input: {
333
- label: Y || null,
334
- ttlSeconds: Math.max(60, Math.min(10080 * 60, z * 60 * 60)),
335
- includeCredentials: V,
336
- includes: Array.from(U)
346
+ label: K || null,
347
+ ttlSeconds: Math.max(60, Math.min(10080 * 60, I * 60 * 60)),
348
+ includeCredentials: R,
349
+ includes: Array.from(B)
337
350
  }
338
351
  } });
339
- e.data && (Z(e.data.generateVibeLlmContextUrl), Q(!1));
352
+ e.data && (Y(e.data.generateVibeLlmContextUrl), X(!1), q(""));
340
353
  },
341
- disabled: N.loading,
354
+ disabled: A.loading,
342
355
  className: "px-4 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover disabled:opacity-50",
343
- children: N.loading ? "Generating…" : "Generate URL"
356
+ children: A.loading ? "Generating…" : "Generate URL"
344
357
  })]
345
358
  }),
346
- X && /* @__PURE__ */ _("div", {
359
+ J && /* @__PURE__ */ v("div", {
347
360
  className: "rounded-md border border-status-success-border bg-status-success-bg/20 p-3",
348
- children: [/* @__PURE__ */ _("div", {
361
+ children: [/* @__PURE__ */ v("div", {
349
362
  className: "flex items-center gap-2 text-sm mb-2",
350
363
  children: [
351
- /* @__PURE__ */ g(a, { className: "w-4 h-4 text-status-success-text" }),
352
- /* @__PURE__ */ g("span", {
364
+ /* @__PURE__ */ _(s, { className: "w-4 h-4 text-status-success-text" }),
365
+ /* @__PURE__ */ _("span", {
353
366
  className: "font-medium text-text-primary",
354
367
  children: "URL generated"
355
368
  }),
356
- /* @__PURE__ */ _("span", {
369
+ /* @__PURE__ */ v("span", {
357
370
  className: "text-xs text-text-secondary",
358
- children: ["expires in ", O(X.expiresAt)]
371
+ children: ["expires in ", E(J.expiresAt)]
359
372
  })
360
373
  ]
361
- }), /* @__PURE__ */ _("div", {
374
+ }), /* @__PURE__ */ v("div", {
362
375
  className: "flex items-center gap-2",
363
- children: [/* @__PURE__ */ g("input", {
376
+ children: [/* @__PURE__ */ _("input", {
364
377
  readOnly: !0,
365
- value: X.url,
378
+ value: J.url,
366
379
  className: "flex-1 px-2 py-1.5 text-xs bg-bg-sunken border border-border-default rounded font-mono text-text-primary",
367
380
  "aria-label": "Generated LLM context URL"
368
- }), /* @__PURE__ */ g("button", {
381
+ }), /* @__PURE__ */ _("button", {
382
+ type: "button",
369
383
  onClick: async () => {
370
- X && (await D(X.url), Q(!0), setTimeout(() => Q(!1), 2e3));
384
+ J && (await se(J.url), X(!0), setTimeout(() => X(!1), 2e3));
371
385
  },
372
386
  className: "px-2 py-1.5 text-xs bg-bg-sunken border border-border-default rounded text-text-primary",
373
387
  "aria-label": "Copy URL",
374
- children: le ? /* @__PURE__ */ g(a, { className: "w-4 h-4 text-status-success-text" }) : /* @__PURE__ */ g(s, { className: "w-4 h-4" })
388
+ children: pe ? /* @__PURE__ */ _(s, { className: "w-4 h-4 text-status-success-text" }) : /* @__PURE__ */ _(ee, { className: "w-4 h-4" })
375
389
  })]
376
390
  })]
377
391
  })
378
392
  ]
379
393
  }),
380
- /* @__PURE__ */ _("section", {
394
+ /* @__PURE__ */ v("section", {
381
395
  className: "bg-bg-surface border border-border-default rounded-lg p-5 space-y-3",
382
396
  children: [
383
- /* @__PURE__ */ _("header", {
397
+ /* @__PURE__ */ v("header", {
384
398
  className: "flex items-center justify-between",
385
- children: [/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("h3", {
399
+ children: [/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("h3", {
386
400
  className: "text-base font-semibold text-text-primary",
387
401
  children: "Your active URLs"
388
- }), /* @__PURE__ */ g("p", {
402
+ }), /* @__PURE__ */ _("p", {
389
403
  className: "text-sm text-text-secondary",
390
404
  children: "Tokens you minted for this vibe. Revoke and rotate work immediately; revoked tokens fail with 403 even if the JWT hasn't expired."
391
- })] }), /* @__PURE__ */ _("button", {
392
- onClick: () => I({ variables: { vibeId: d } }),
393
- className: "flex items-center gap-1 px-3 py-1.5 text-sm bg-status-error-bg/10 text-status-error-text border border-status-error-border rounded-md hover:bg-status-error-bg/20",
394
- children: [/* @__PURE__ */ g(u, { className: "w-4 h-4" }), "Revoke all"]
405
+ })] }), /* @__PURE__ */ v("button", {
406
+ type: "button",
407
+ onClick: async () => {
408
+ typeof window < "u" && !window.confirm("Revoke ALL active URLs for this vibe? Every minted URL stops working immediately and cannot be un-revoked (use Rotate to issue a fresh one).") || await N({ variables: { vibeId: f } });
409
+ },
410
+ disabled: F.every((e) => e.status !== "ACTIVE"),
411
+ className: "flex items-center gap-1 px-3 py-1.5 text-sm bg-status-error-bg/10 text-status-error-text border border-status-error-border rounded-md hover:bg-status-error-bg/20 disabled:opacity-40 disabled:cursor-not-allowed",
412
+ children: [/* @__PURE__ */ _(d, { className: "w-4 h-4" }), "Revoke all"]
395
413
  })]
396
414
  }),
397
- A.loading && R.length === 0 && /* @__PURE__ */ _("div", {
415
+ O.loading && F.length === 0 && /* @__PURE__ */ v("div", {
398
416
  className: "text-sm text-text-secondary py-4 flex items-center gap-2",
399
- children: [/* @__PURE__ */ g(te, { className: "w-4 h-4 animate-spin" }), "Loading tokens…"]
417
+ children: [/* @__PURE__ */ _(ne, { className: "w-4 h-4 animate-spin" }), "Loading tokens…"]
400
418
  }),
401
- R.length === 0 && !A.loading && /* @__PURE__ */ _("div", {
419
+ F.length === 0 && !O.loading && /* @__PURE__ */ v("div", {
402
420
  className: "text-sm text-text-secondary py-4 flex items-center gap-2",
403
- children: [/* @__PURE__ */ g(c, { className: "w-4 h-4" }), "No URLs minted yet for this vibe."]
421
+ children: [/* @__PURE__ */ _(l, { className: "w-4 h-4" }), "No URLs minted yet for this vibe."]
404
422
  }),
405
- R.length > 0 && /* @__PURE__ */ g("div", {
423
+ F.length > 0 && /* @__PURE__ */ _("div", {
406
424
  className: "overflow-x-auto",
407
- children: /* @__PURE__ */ _("table", {
425
+ children: /* @__PURE__ */ v("table", {
408
426
  className: "w-full text-sm",
409
- children: [/* @__PURE__ */ g("thead", { children: /* @__PURE__ */ _("tr", {
427
+ children: [/* @__PURE__ */ _("thead", { children: /* @__PURE__ */ v("tr", {
410
428
  className: "border-b border-border-default text-left text-xs text-text-secondary",
411
429
  children: [
412
- /* @__PURE__ */ g("th", {
430
+ /* @__PURE__ */ _("th", {
413
431
  className: "py-2 pr-3",
414
432
  children: "Label"
415
433
  }),
416
- /* @__PURE__ */ g("th", {
434
+ /* @__PURE__ */ _("th", {
417
435
  className: "py-2 pr-3",
418
436
  children: "Fingerprint"
419
437
  }),
420
- /* @__PURE__ */ g("th", {
438
+ /* @__PURE__ */ _("th", {
421
439
  className: "py-2 pr-3",
422
440
  children: "Sections"
423
441
  }),
424
- /* @__PURE__ */ g("th", {
442
+ /* @__PURE__ */ _("th", {
425
443
  className: "py-2 pr-3",
426
444
  children: "Creds"
427
445
  }),
428
- /* @__PURE__ */ g("th", {
446
+ /* @__PURE__ */ _("th", {
429
447
  className: "py-2 pr-3",
430
448
  children: "Status"
431
449
  }),
432
- /* @__PURE__ */ g("th", {
450
+ /* @__PURE__ */ _("th", {
433
451
  className: "py-2 pr-3",
434
452
  children: "Expires"
435
453
  }),
436
- /* @__PURE__ */ g("th", {
454
+ /* @__PURE__ */ _("th", {
437
455
  className: "py-2 pr-3",
438
456
  children: "Fetches"
439
457
  }),
440
- /* @__PURE__ */ g("th", {
458
+ /* @__PURE__ */ _("th", {
441
459
  className: "py-2 pr-3",
442
460
  children: "Actions"
443
461
  })
444
462
  ]
445
- }) }), /* @__PURE__ */ g("tbody", { children: R.map((e) => /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ _("tr", {
463
+ }) }), /* @__PURE__ */ _("tbody", { children: F.map((e) => /* @__PURE__ */ v(n, { children: [/* @__PURE__ */ v("tr", {
446
464
  className: "border-b border-border-subtle align-top",
447
465
  children: [
448
- /* @__PURE__ */ g("td", {
466
+ /* @__PURE__ */ _("td", {
449
467
  className: "py-2 pr-3 text-text-primary",
450
468
  children: e.label ?? "—"
451
469
  }),
452
- /* @__PURE__ */ g("td", {
470
+ /* @__PURE__ */ _("td", {
453
471
  className: "py-2 pr-3 font-mono text-xs text-text-secondary",
454
472
  children: e.tokenFingerprint
455
473
  }),
456
- /* @__PURE__ */ g("td", {
474
+ /* @__PURE__ */ _("td", {
457
475
  className: "py-2 pr-3 text-text-secondary",
458
- children: /* @__PURE__ */ g("span", {
476
+ children: /* @__PURE__ */ _("span", {
459
477
  className: "text-xs",
460
478
  children: e.includes.join(", ")
461
479
  })
462
480
  }),
463
- /* @__PURE__ */ g("td", {
481
+ /* @__PURE__ */ _("td", {
464
482
  className: "py-2 pr-3",
465
- children: e.includeCredentials ? /* @__PURE__ */ g("span", {
483
+ children: e.includeCredentials ? /* @__PURE__ */ _("span", {
466
484
  className: "text-xs text-status-warning-text",
467
485
  children: "on"
468
- }) : /* @__PURE__ */ g("span", {
486
+ }) : /* @__PURE__ */ _("span", {
469
487
  className: "text-xs text-text-secondary",
470
488
  children: "off"
471
489
  })
472
490
  }),
473
- /* @__PURE__ */ g("td", {
491
+ /* @__PURE__ */ _("td", {
474
492
  className: "py-2 pr-3",
475
- children: /* @__PURE__ */ g("span", {
493
+ children: /* @__PURE__ */ _("span", {
476
494
  className: `text-xs px-1.5 py-0.5 rounded ${e.status === "ACTIVE" ? "bg-status-success-bg/20 text-status-success-text" : "bg-bg-sunken text-text-secondary"}`,
477
495
  children: e.status
478
496
  })
479
497
  }),
480
- /* @__PURE__ */ g("td", {
498
+ /* @__PURE__ */ _("td", {
481
499
  className: "py-2 pr-3 text-xs text-text-secondary",
482
- children: /* @__PURE__ */ _("span", {
500
+ children: /* @__PURE__ */ v("span", {
483
501
  className: "inline-flex items-center gap-1",
484
- children: [/* @__PURE__ */ g(o, { className: "w-3 h-3" }), O(e.expiresAt)]
502
+ children: [/* @__PURE__ */ _(c, { className: "w-3 h-3" }), E(e.expiresAt)]
485
503
  })
486
504
  }),
487
- /* @__PURE__ */ g("td", {
505
+ /* @__PURE__ */ _("td", {
488
506
  className: "py-2 pr-3 text-xs text-text-secondary",
489
507
  children: e.fetchCount
490
508
  }),
491
- /* @__PURE__ */ g("td", {
509
+ /* @__PURE__ */ _("td", {
492
510
  className: "py-2 pr-3",
493
- children: /* @__PURE__ */ _("div", {
511
+ children: /* @__PURE__ */ v("div", {
494
512
  className: "flex gap-1",
495
- children: [/* @__PURE__ */ g("button", {
496
- onClick: () => ue($ === e.id ? null : e.id),
513
+ children: [/* @__PURE__ */ _("button", {
514
+ type: "button",
515
+ onClick: () => me($ === e.id ? null : e.id),
497
516
  title: "Show fetch history",
517
+ "aria-label": "Show fetch history",
498
518
  className: "p-1.5 text-text-secondary hover:text-text-primary",
499
- children: /* @__PURE__ */ g(c, { className: "w-4 h-4" })
500
- }), e.status === "ACTIVE" && /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g("button", {
519
+ children: /* @__PURE__ */ _(l, { className: "w-4 h-4" })
520
+ }), e.status === "ACTIVE" && /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _("button", {
521
+ type: "button",
501
522
  onClick: async () => {
502
- let t = await F({ variables: { tokenId: e.id } });
503
- t.data && (Z(t.data.rotateVibeLlmContextUrl), Q(!1));
523
+ let t = await M({ variables: { tokenId: e.id } });
524
+ t.data && (Y(t.data.rotateVibeLlmContextUrl), X(!1));
504
525
  },
505
526
  title: "Rotate (revoke + mint a new one with same settings)",
527
+ "aria-label": "Rotate URL",
506
528
  className: "p-1.5 text-text-secondary hover:text-text-primary",
507
- children: /* @__PURE__ */ g(ne, { className: "w-4 h-4" })
508
- }), /* @__PURE__ */ g("button", {
509
- onClick: () => P({ variables: { tokenId: e.id } }),
529
+ children: /* @__PURE__ */ _(re, { className: "w-4 h-4" })
530
+ }), /* @__PURE__ */ _("button", {
531
+ type: "button",
532
+ onClick: () => j({ variables: { tokenId: e.id } }),
510
533
  title: "Revoke",
534
+ "aria-label": "Revoke URL",
511
535
  className: "p-1.5 text-status-error-text hover:opacity-80",
512
- children: /* @__PURE__ */ g(u, { className: "w-4 h-4" })
536
+ children: /* @__PURE__ */ _(d, { className: "w-4 h-4" })
513
537
  })] })]
514
538
  })
515
539
  })
516
540
  ]
517
- }, e.id), $ === e.id && /* @__PURE__ */ g("tr", { children: /* @__PURE__ */ g("td", {
541
+ }), $ === e.id && /* @__PURE__ */ _("tr", { children: /* @__PURE__ */ _("td", {
518
542
  colSpan: 8,
519
543
  className: "py-2 pr-3 bg-bg-sunken/40",
520
- children: /* @__PURE__ */ g(ie, { tokenId: e.id })
521
- }) }, `${e.id}-audits`)] })) })]
544
+ children: /* @__PURE__ */ _(ce, { tokenId: e.id })
545
+ }) })] }, e.id)) })]
522
546
  })
523
547
  })
524
548
  ]
525
549
  }),
526
- ae && /* @__PURE__ */ g(t, { vibeId: d }),
527
- /* @__PURE__ */ _("p", {
550
+ le && /* @__PURE__ */ _(t, { vibeId: f }),
551
+ /* @__PURE__ */ v("p", {
528
552
  className: "text-xs text-text-secondary flex items-center gap-1",
529
553
  children: [
530
- /* @__PURE__ */ g(i, { className: "w-3 h-3" }),
554
+ /* @__PURE__ */ _(o, { className: "w-3 h-3" }),
531
555
  "Tip: pipe the URL to any LLM with",
532
556
  " ",
533
- /* @__PURE__ */ g("code", {
557
+ /* @__PURE__ */ _("code", {
534
558
  className: "bg-bg-sunken px-1 rounded",
535
559
  children: "curl <url>"
536
560
  }),
537
561
  " or",
538
562
  " ",
539
- /* @__PURE__ */ g("code", {
563
+ /* @__PURE__ */ _("code", {
540
564
  className: "bg-bg-sunken px-1 rounded",
541
565
  children: "curl -H \"Accept: text/markdown\" <url>"
542
566
  }),
@@ -547,76 +571,76 @@ function k({ vibeId: d, attachedAgents: T = [] }) {
547
571
  ]
548
572
  });
549
573
  }
550
- function ie({ tokenId: e }) {
551
- let { data: t, loading: n } = p(T, {
574
+ function ce({ tokenId: e }) {
575
+ let { data: t, loading: n } = m(w, {
552
576
  variables: {
553
577
  tokenId: e,
554
578
  limit: 100
555
579
  },
556
580
  fetchPolicy: "cache-and-network"
557
581
  }), r = t?.myVibeLlmContextTokenAudits ?? [];
558
- return /* @__PURE__ */ g("div", {
582
+ return /* @__PURE__ */ _("div", {
559
583
  className: "text-xs",
560
- children: n && r.length === 0 ? /* @__PURE__ */ g("span", {
584
+ children: n && r.length === 0 ? /* @__PURE__ */ _("span", {
561
585
  className: "text-text-secondary",
562
586
  children: "Loading audit log…"
563
- }) : r.length === 0 ? /* @__PURE__ */ g("span", {
587
+ }) : r.length === 0 ? /* @__PURE__ */ _("span", {
564
588
  className: "text-text-secondary",
565
589
  children: "No fetches yet."
566
- }) : /* @__PURE__ */ _("table", {
590
+ }) : /* @__PURE__ */ v("table", {
567
591
  className: "w-full",
568
- children: [/* @__PURE__ */ g("thead", { children: /* @__PURE__ */ _("tr", {
592
+ children: [/* @__PURE__ */ _("thead", { children: /* @__PURE__ */ v("tr", {
569
593
  className: "text-text-secondary",
570
594
  children: [
571
- /* @__PURE__ */ g("th", {
595
+ /* @__PURE__ */ _("th", {
572
596
  className: "text-left py-1 pr-2",
573
597
  children: "When"
574
598
  }),
575
- /* @__PURE__ */ g("th", {
599
+ /* @__PURE__ */ _("th", {
576
600
  className: "text-left py-1 pr-2",
577
601
  children: "IP"
578
602
  }),
579
- /* @__PURE__ */ g("th", {
603
+ /* @__PURE__ */ _("th", {
580
604
  className: "text-left py-1 pr-2",
581
605
  children: "Format"
582
606
  }),
583
- /* @__PURE__ */ g("th", {
607
+ /* @__PURE__ */ _("th", {
584
608
  className: "text-left py-1 pr-2",
585
609
  children: "Bytes"
586
610
  }),
587
- /* @__PURE__ */ g("th", {
611
+ /* @__PURE__ */ _("th", {
588
612
  className: "text-left py-1 pr-2",
589
613
  children: "Status"
590
614
  }),
591
- /* @__PURE__ */ g("th", {
615
+ /* @__PURE__ */ _("th", {
592
616
  className: "text-left py-1 pr-2",
593
617
  children: "UA"
594
618
  })
595
619
  ]
596
- }) }), /* @__PURE__ */ g("tbody", { children: r.map((e) => /* @__PURE__ */ _("tr", {
620
+ }) }), /* @__PURE__ */ _("tbody", { children: r.map((e) => /* @__PURE__ */ v("tr", {
597
621
  className: "text-text-primary border-t border-border-subtle",
598
622
  children: [
599
- /* @__PURE__ */ g("td", {
623
+ /* @__PURE__ */ _("td", {
600
624
  className: "py-1 pr-2",
601
625
  children: new Date(e.fetchedAt).toLocaleString()
602
626
  }),
603
- /* @__PURE__ */ g("td", {
627
+ /* @__PURE__ */ _("td", {
604
628
  className: "py-1 pr-2 font-mono",
605
629
  children: e.remoteIp ?? "—"
606
630
  }),
607
- /* @__PURE__ */ g("td", {
631
+ /* @__PURE__ */ _("td", {
608
632
  className: "py-1 pr-2",
609
633
  children: e.format
610
634
  }),
611
- /* @__PURE__ */ g("td", {
635
+ /* @__PURE__ */ _("td", {
612
636
  className: "py-1 pr-2",
613
637
  children: e.bytes
614
638
  }),
615
- /* @__PURE__ */ g("td", {
639
+ /* @__PURE__ */ _("td", {
616
640
  className: "py-1 pr-2",
617
641
  children: e.status
618
642
  }),
619
- /* @__PURE__ */ g("td", {
643
+ /* @__PURE__ */ _("td", {
620
644
  className: "py-1 pr-2 truncate max-w-[260px]",
621
645
  title: e.userAgent ?? "",
622
646
  children: e.userAgent ?? "—"
@@ -627,6 +651,6 @@ function ie({ tokenId: e }) {
627
651
  });
628
652
  }
629
653
  //#endregion
630
- export { k as VibeLlmContextTabPanel };
654
+ export { D as VibeLlmContextTabPanel };
631
655
 
632
656
  //# sourceMappingURL=VibeLlmContextTabPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VibeLlmContextTabPanel.js","names":[],"sources":["../../../src/components/vibe/VibeLlmContextTabPanel.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport { useMemo, useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n Bot,\n Check,\n Clock,\n Copy,\n EyeOff,\n Info,\n Lock,\n RefreshCw,\n RotateCw,\n Trash2,\n} from 'lucide-react';\n\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\n\nimport { VIBE_PERMISSIONS } from '@/constants/permissions';\n\nimport { VibeLlmContextAdminPanel } from './VibeLlmContextAdminPanel';\n\nconst ALL_INCLUDES = [\n 'core',\n 'agents',\n 'sessions',\n 'notes',\n 'catalogs',\n 'docs',\n 'config',\n 'security',\n 'plugins',\n] as const;\n\ntype IncludeKey = (typeof ALL_INCLUDES)[number];\n\ninterface VibeLlmContextSettings {\n vibeId: string;\n ttlSeconds: number;\n includeCredentials: boolean;\n includes: string[];\n customContextText: string | null;\n defaultAgentIdOverride: string | null;\n sessionsLimit: number;\n notesLimit: number;\n docsPagesLimit: number;\n securityRunsLimit: number;\n updatedAt: string;\n}\n\ninterface VibeLlmContextTokenRow {\n id: string;\n vibeId: string;\n userId: string;\n label: string | null;\n tokenFingerprint: string;\n includeCredentials: boolean;\n includes: string[];\n status: 'ACTIVE' | 'REVOKED';\n expiresAt: string;\n lastFetchedAt: string | null;\n fetchCount: number;\n createdAt: string;\n revokedAt: string | null;\n revokedReason: string | null;\n}\n\ninterface MintResult {\n tokenId: string;\n url: string;\n token: string;\n expiresAt: string;\n ttlSeconds: number;\n includes: string[];\n includeCredentials: boolean;\n label: string | null;\n tokenFingerprint: string;\n}\n\ninterface AuditRow {\n id: string;\n fetchedAt: string;\n remoteIp: string | null;\n userAgent: string | null;\n format: string;\n bytes: number;\n durationMs: number;\n status: number;\n}\n\nconst GET_SETTINGS = gql`\n query MyVibeLlmContextSettings($vibeId: ID!) {\n myVibeLlmContextSettings(vibeId: $vibeId) {\n vibeId\n ttlSeconds\n includeCredentials\n includes\n customContextText\n defaultAgentIdOverride\n sessionsLimit\n notesLimit\n docsPagesLimit\n securityRunsLimit\n updatedAt\n }\n }\n`;\n\nconst GET_TOKENS = gql`\n query MyVibeLlmContextTokens($vibeId: ID!) {\n myVibeLlmContextTokens(vibeId: $vibeId) {\n id\n vibeId\n userId\n label\n tokenFingerprint\n includeCredentials\n includes\n status\n expiresAt\n lastFetchedAt\n fetchCount\n createdAt\n revokedAt\n revokedReason\n }\n }\n`;\n\nconst SET_SETTINGS = gql`\n mutation SetMyVibeLlmContextSettings($vibeId: ID!, $input: VibeLlmContextSettingsInput!) {\n setMyVibeLlmContextSettings(vibeId: $vibeId, input: $input) {\n vibeId\n ttlSeconds\n includeCredentials\n includes\n customContextText\n defaultAgentIdOverride\n sessionsLimit\n notesLimit\n docsPagesLimit\n securityRunsLimit\n updatedAt\n }\n }\n`;\n\nconst GENERATE_URL = gql`\n mutation GenerateVibeLlmContextUrl($vibeId: ID!, $input: VibeLlmContextMintInput) {\n generateVibeLlmContextUrl(vibeId: $vibeId, input: $input) {\n tokenId\n url\n token\n expiresAt\n ttlSeconds\n includes\n includeCredentials\n label\n tokenFingerprint\n }\n }\n`;\n\nconst REVOKE_TOKEN = gql`\n mutation RevokeVibeLlmContextToken($tokenId: ID!) {\n revokeVibeLlmContextToken(tokenId: $tokenId) {\n id\n status\n revokedAt\n }\n }\n`;\n\nconst ROTATE_TOKEN = gql`\n mutation RotateVibeLlmContextUrl($tokenId: ID!, $input: VibeLlmContextMintInput) {\n rotateVibeLlmContextUrl(tokenId: $tokenId, input: $input) {\n tokenId\n url\n token\n expiresAt\n ttlSeconds\n includes\n includeCredentials\n label\n tokenFingerprint\n }\n }\n`;\n\nconst REVOKE_ALL = gql`\n mutation RevokeAllMyVibeLlmContextTokens($vibeId: ID!) {\n revokeAllMyVibeLlmContextTokens(vibeId: $vibeId)\n }\n`;\n\nconst GET_AUDITS = gql`\n query MyVibeLlmContextTokenAudits($tokenId: ID!, $limit: Int) {\n myVibeLlmContextTokenAudits(tokenId: $tokenId, limit: $limit) {\n id\n fetchedAt\n remoteIp\n userAgent\n format\n bytes\n durationMs\n status\n }\n }\n`;\n\nconst TTL_PRESETS: Array<{ label: string; hours: number }> = [\n { label: '1 hour', hours: 1 },\n { label: '6 hours', hours: 6 },\n { label: '24 hours', hours: 24 },\n { label: '7 days', hours: 24 * 7 },\n];\n\nasync function copyToClipboard(text: string): Promise<void> {\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n const ta = document.createElement('textarea');\n ta.value = text;\n ta.style.position = 'fixed';\n ta.style.opacity = '0';\n document.body.appendChild(ta);\n ta.select();\n document.execCommand('copy');\n document.body.removeChild(ta);\n }\n}\n\nfunction formatExpiry(expiresAt: string): string {\n const diff = new Date(expiresAt).getTime() - Date.now();\n if (diff < 0) return 'expired';\n const hours = Math.floor(diff / (1000 * 60 * 60));\n const mins = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));\n if (hours > 24) return `${Math.floor(hours / 24)}d`;\n if (hours > 0) return `${hours}h ${mins}m`;\n return `${mins}m`;\n}\n\ninterface AttachedAgent {\n id: string;\n name: string;\n}\n\ninterface VibeLlmContextTabPanelProps {\n vibeId: string;\n attachedAgents?: AttachedAgent[];\n}\n\nexport function VibeLlmContextTabPanel({\n vibeId,\n attachedAgents = [],\n}: VibeLlmContextTabPanelProps): ReactElement {\n const { hasPermission } = usePermissions();\n const isAdmin = hasPermission(VIBE_PERMISSIONS.VIBE_MANAGE);\n const settingsQuery = useQuery<{ myVibeLlmContextSettings: VibeLlmContextSettings }>(\n GET_SETTINGS,\n {\n variables: { vibeId },\n fetchPolicy: 'cache-and-network',\n }\n );\n const tokensQuery = useQuery<{ myVibeLlmContextTokens: VibeLlmContextTokenRow[] }>(GET_TOKENS, {\n variables: { vibeId },\n fetchPolicy: 'cache-and-network',\n });\n const [saveSettings, saveSettingsState] = useMutation<\n { setMyVibeLlmContextSettings: VibeLlmContextSettings },\n {\n vibeId: string;\n input: {\n ttlSeconds?: number;\n includeCredentials?: boolean;\n includes?: string[];\n customContextText?: string | null;\n defaultAgentIdOverride?: string | null;\n sessionsLimit?: number;\n notesLimit?: number;\n docsPagesLimit?: number;\n securityRunsLimit?: number;\n };\n }\n >(SET_SETTINGS, { refetchQueries: ['MyVibeLlmContextSettings'] });\n const [generateUrl, generateUrlState] = useMutation<\n { generateVibeLlmContextUrl: MintResult },\n {\n vibeId: string;\n input?: {\n label?: string | null;\n ttlSeconds?: number | null;\n includeCredentials?: boolean | null;\n includes?: string[] | null;\n } | null;\n }\n >(GENERATE_URL, { refetchQueries: ['MyVibeLlmContextTokens'] });\n const [revokeToken] = useMutation<\n { revokeVibeLlmContextToken: VibeLlmContextTokenRow },\n { tokenId: string }\n >(REVOKE_TOKEN, { refetchQueries: ['MyVibeLlmContextTokens'] });\n const [rotateToken] = useMutation<{ rotateVibeLlmContextUrl: MintResult }, { tokenId: string }>(\n ROTATE_TOKEN,\n { refetchQueries: ['MyVibeLlmContextTokens'] }\n );\n const [revokeAll] = useMutation<{ revokeAllMyVibeLlmContextTokens: number }, { vibeId: string }>(\n REVOKE_ALL,\n { refetchQueries: ['MyVibeLlmContextTokens'] }\n );\n\n const settings = settingsQuery.data?.myVibeLlmContextSettings;\n const tokens = tokensQuery.data?.myVibeLlmContextTokens ?? [];\n\n // Local editable copy of settings\n const [ttlHours, setTtlHours] = useState<number>(1);\n const [includeCreds, setIncludeCreds] = useState<boolean>(false);\n const [includesState, setIncludesState] = useState<Set<IncludeKey>>(new Set(ALL_INCLUDES));\n const [customText, setCustomText] = useState<string>('');\n const [defaultAgentOverride, setDefaultAgentOverride] = useState<string>('');\n const [label, setLabel] = useState<string>('');\n const [lastMint, setLastMint] = useState<MintResult | null>(null);\n const [copied, setCopied] = useState<boolean>(false);\n const [auditPanelTokenId, setAuditPanelTokenId] = useState<string | null>(null);\n\n // Hydrate local form when server settings arrive\n useMemo(() => {\n if (!settings) return;\n setTtlHours(Math.max(1, Math.round((settings.ttlSeconds ?? 3600) / 3600)));\n setIncludeCreds(settings.includeCredentials);\n setIncludesState(new Set((settings.includes as IncludeKey[]) ?? ALL_INCLUDES));\n setCustomText(settings.customContextText ?? '');\n setDefaultAgentOverride(settings.defaultAgentIdOverride ?? '');\n }, [settings]);\n\n const onToggleInclude = (key: IncludeKey) => {\n setIncludesState((prev) => {\n const next = new Set(prev);\n if (next.has(key)) next.delete(key);\n else next.add(key);\n return next;\n });\n };\n\n const onSaveSettings = async () => {\n await saveSettings({\n variables: {\n vibeId,\n input: {\n ttlSeconds: Math.max(60, Math.min(7 * 24 * 60 * 60, ttlHours * 60 * 60)),\n includeCredentials: includeCreds,\n includes: Array.from(includesState),\n customContextText: customText,\n defaultAgentIdOverride: defaultAgentOverride || null,\n },\n },\n });\n };\n\n const onGenerate = async () => {\n const res = await generateUrl({\n variables: {\n vibeId,\n input: {\n label: label || null,\n ttlSeconds: Math.max(60, Math.min(7 * 24 * 60 * 60, ttlHours * 60 * 60)),\n includeCredentials: includeCreds,\n includes: Array.from(includesState),\n },\n },\n });\n if (res.data) {\n setLastMint(res.data.generateVibeLlmContextUrl);\n setCopied(false);\n }\n };\n\n const onCopyResultUrl = async () => {\n if (!lastMint) return;\n await copyToClipboard(lastMint.url);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n };\n\n return (\n <div className=\"space-y-6 max-w-5xl\">\n {/* Header */}\n <div className=\"rounded-lg border border-status-warning-border bg-status-warning-bg/30 p-4\">\n <div className=\"flex items-start gap-3\">\n <Lock className=\"w-5 h-5 text-status-warning-text mt-0.5\" />\n <div className=\"text-sm text-text-primary\">\n <p className=\"font-medium mb-1\">\n LLM Context — share this vibe with any LLM via a signed URL\n </p>\n <p className=\"text-text-secondary\">\n Anyone with the URL can read the snapshot until it expires. When \"Include credentials\"\n is on, the snapshot exposes agent tunnel URLs + API keys. Default is redacted. Rotate\n or revoke any URL from the list below at any time.\n </p>\n </div>\n </div>\n </div>\n\n {/* Settings panel */}\n <section className=\"bg-bg-surface border border-border-default rounded-lg p-5 space-y-4\">\n <header className=\"flex items-center justify-between\">\n <div>\n <h3 className=\"text-base font-semibold text-text-primary\">Saved settings</h3>\n <p className=\"text-sm text-text-secondary\">\n Defaults used when you generate a URL. Snapshotted into each minted token, so future\n edits don't change already-minted URLs.\n </p>\n </div>\n <button\n onClick={onSaveSettings}\n disabled={saveSettingsState.loading}\n className=\"px-3 py-1.5 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover disabled:opacity-50\"\n >\n {saveSettingsState.loading ? 'Saving…' : 'Save settings'}\n </button>\n </header>\n\n {/* TTL */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">URL expiry</label>\n <div className=\"flex flex-wrap items-center gap-2\">\n {TTL_PRESETS.map((p) => (\n <button\n key={p.hours}\n onClick={() => setTtlHours(p.hours)}\n className={`px-3 py-1.5 text-sm rounded-md border ${\n ttlHours === p.hours\n ? 'bg-action-primary-bg text-action-primary-text border-action-primary-bg'\n : 'bg-bg-sunken text-text-primary border-border-default'\n }`}\n >\n {p.label}\n </button>\n ))}\n <span className=\"text-sm text-text-secondary mx-1\">or custom hours:</span>\n <input\n type=\"number\"\n min={1}\n max={168}\n value={ttlHours}\n onChange={(e) => setTtlHours(Math.max(1, Math.min(168, Number(e.target.value) || 1)))}\n className=\"w-24 px-2 py-1.5 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary\"\n />\n </div>\n </div>\n\n {/* Credentials toggle */}\n <div>\n <label className=\"flex items-center gap-2 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={includeCreds}\n onChange={(e) => setIncludeCreds(e.target.checked)}\n className=\"w-4 h-4\"\n />\n <span>Include credentials (tunnel URLs + agent API keys)</span>\n {!includeCreds && <EyeOff className=\"w-4 h-4 text-text-secondary\" />}\n </label>\n </div>\n\n {/* Includes chips */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n Sections to include\n </label>\n <div className=\"flex flex-wrap gap-2\">\n {ALL_INCLUDES.map((key) => (\n <button\n key={key}\n onClick={() => onToggleInclude(key)}\n className={`px-2.5 py-1 text-xs rounded-full border ${\n includesState.has(key)\n ? 'bg-action-primary-bg/10 text-action-primary-bg border-action-primary-bg'\n : 'bg-bg-sunken text-text-secondary border-border-default'\n }`}\n >\n {key}\n </button>\n ))}\n </div>\n </div>\n\n {/* Default agent override */}\n {attachedAgents.length > 0 && (\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n Default agent for context fetch\n </label>\n <select\n value={defaultAgentOverride}\n onChange={(e) => setDefaultAgentOverride(e.target.value)}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary\"\n >\n <option value=\"\">(use my per-vibe default from settings)</option>\n {attachedAgents.map((a) => (\n <option key={a.id} value={a.id}>\n {a.name}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Custom context */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n Custom context text\n </label>\n <textarea\n value={customText}\n onChange={(e) => setCustomText(e.target.value.slice(0, 8192))}\n rows={5}\n placeholder=\"Free-form notes embedded in every snapshot you mint AFTER saving (existing tokens keep their original copy).\"\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n <p className=\"text-xs text-text-secondary mt-1\">{customText.length} / 8192 chars</p>\n </div>\n </section>\n\n {/* Generate panel */}\n <section className=\"bg-bg-surface border border-border-default rounded-lg p-5 space-y-4\">\n <header>\n <h3 className=\"text-base font-semibold text-text-primary\">Generate a new URL</h3>\n <p className=\"text-sm text-text-secondary\">\n Mints a fresh signed URL using your current settings. The full token is only shown once\n — copy it before navigating away. Use Rotate below if you lose it.\n </p>\n </header>\n <div className=\"flex flex-wrap items-end gap-2\">\n <div className=\"flex-1 min-w-[200px]\">\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n Label (optional)\n </label>\n <input\n type=\"text\"\n value={label}\n onChange={(e) => setLabel(e.target.value.slice(0, 120))}\n placeholder=\"e.g. Claude desktop\"\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n </div>\n <button\n onClick={onGenerate}\n disabled={generateUrlState.loading}\n className=\"px-4 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover disabled:opacity-50\"\n >\n {generateUrlState.loading ? 'Generating…' : 'Generate URL'}\n </button>\n </div>\n\n {lastMint && (\n <div className=\"rounded-md border border-status-success-border bg-status-success-bg/20 p-3\">\n <div className=\"flex items-center gap-2 text-sm mb-2\">\n <Check className=\"w-4 h-4 text-status-success-text\" />\n <span className=\"font-medium text-text-primary\">URL generated</span>\n <span className=\"text-xs text-text-secondary\">\n expires in {formatExpiry(lastMint.expiresAt)}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <input\n readOnly\n value={lastMint.url}\n className=\"flex-1 px-2 py-1.5 text-xs bg-bg-sunken border border-border-default rounded font-mono text-text-primary\"\n aria-label=\"Generated LLM context URL\"\n />\n <button\n onClick={onCopyResultUrl}\n className=\"px-2 py-1.5 text-xs bg-bg-sunken border border-border-default rounded text-text-primary\"\n aria-label=\"Copy URL\"\n >\n {copied ? (\n <Check className=\"w-4 h-4 text-status-success-text\" />\n ) : (\n <Copy className=\"w-4 h-4\" />\n )}\n </button>\n </div>\n </div>\n )}\n </section>\n\n {/* Active URLs list */}\n <section className=\"bg-bg-surface border border-border-default rounded-lg p-5 space-y-3\">\n <header className=\"flex items-center justify-between\">\n <div>\n <h3 className=\"text-base font-semibold text-text-primary\">Your active URLs</h3>\n <p className=\"text-sm text-text-secondary\">\n Tokens you minted for this vibe. Revoke and rotate work immediately; revoked tokens\n fail with 403 even if the JWT hasn't expired.\n </p>\n </div>\n <button\n onClick={() => revokeAll({ variables: { vibeId } })}\n className=\"flex items-center gap-1 px-3 py-1.5 text-sm bg-status-error-bg/10 text-status-error-text border border-status-error-border rounded-md hover:bg-status-error-bg/20\"\n >\n <Trash2 className=\"w-4 h-4\" />\n Revoke all\n </button>\n </header>\n\n {tokensQuery.loading && tokens.length === 0 && (\n <div className=\"text-sm text-text-secondary py-4 flex items-center gap-2\">\n <RefreshCw className=\"w-4 h-4 animate-spin\" />\n Loading tokens…\n </div>\n )}\n {tokens.length === 0 && !tokensQuery.loading && (\n <div className=\"text-sm text-text-secondary py-4 flex items-center gap-2\">\n <Info className=\"w-4 h-4\" />\n No URLs minted yet for this vibe.\n </div>\n )}\n {tokens.length > 0 && (\n <div className=\"overflow-x-auto\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-default text-left text-xs text-text-secondary\">\n <th className=\"py-2 pr-3\">Label</th>\n <th className=\"py-2 pr-3\">Fingerprint</th>\n <th className=\"py-2 pr-3\">Sections</th>\n <th className=\"py-2 pr-3\">Creds</th>\n <th className=\"py-2 pr-3\">Status</th>\n <th className=\"py-2 pr-3\">Expires</th>\n <th className=\"py-2 pr-3\">Fetches</th>\n <th className=\"py-2 pr-3\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {tokens.map((t) => (\n <>\n <tr key={t.id} className=\"border-b border-border-subtle align-top\">\n <td className=\"py-2 pr-3 text-text-primary\">{t.label ?? '—'}</td>\n <td className=\"py-2 pr-3 font-mono text-xs text-text-secondary\">\n {t.tokenFingerprint}\n </td>\n <td className=\"py-2 pr-3 text-text-secondary\">\n <span className=\"text-xs\">{t.includes.join(', ')}</span>\n </td>\n <td className=\"py-2 pr-3\">\n {t.includeCredentials ? (\n <span className=\"text-xs text-status-warning-text\">on</span>\n ) : (\n <span className=\"text-xs text-text-secondary\">off</span>\n )}\n </td>\n <td className=\"py-2 pr-3\">\n <span\n className={`text-xs px-1.5 py-0.5 rounded ${\n t.status === 'ACTIVE'\n ? 'bg-status-success-bg/20 text-status-success-text'\n : 'bg-bg-sunken text-text-secondary'\n }`}\n >\n {t.status}\n </span>\n </td>\n <td className=\"py-2 pr-3 text-xs text-text-secondary\">\n <span className=\"inline-flex items-center gap-1\">\n <Clock className=\"w-3 h-3\" />\n {formatExpiry(t.expiresAt)}\n </span>\n </td>\n <td className=\"py-2 pr-3 text-xs text-text-secondary\">{t.fetchCount}</td>\n <td className=\"py-2 pr-3\">\n <div className=\"flex gap-1\">\n <button\n onClick={() =>\n setAuditPanelTokenId(auditPanelTokenId === t.id ? null : t.id)\n }\n title=\"Show fetch history\"\n className=\"p-1.5 text-text-secondary hover:text-text-primary\"\n >\n <Info className=\"w-4 h-4\" />\n </button>\n {t.status === 'ACTIVE' && (\n <>\n <button\n onClick={async () => {\n const res = await rotateToken({ variables: { tokenId: t.id } });\n if (res.data) {\n setLastMint(res.data.rotateVibeLlmContextUrl);\n setCopied(false);\n }\n }}\n title=\"Rotate (revoke + mint a new one with same settings)\"\n className=\"p-1.5 text-text-secondary hover:text-text-primary\"\n >\n <RotateCw className=\"w-4 h-4\" />\n </button>\n <button\n onClick={() => revokeToken({ variables: { tokenId: t.id } })}\n title=\"Revoke\"\n className=\"p-1.5 text-status-error-text hover:opacity-80\"\n >\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </>\n )}\n </div>\n </td>\n </tr>\n {auditPanelTokenId === t.id && (\n <tr key={`${t.id}-audits`}>\n <td colSpan={8} className=\"py-2 pr-3 bg-bg-sunken/40\">\n <AuditListInline tokenId={t.id} />\n </td>\n </tr>\n )}\n </>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </section>\n\n {/* Admin sub-panel — gated by vibe:manage permission */}\n {isAdmin && <VibeLlmContextAdminPanel vibeId={vibeId} />}\n\n {/* Help footer */}\n <p className=\"text-xs text-text-secondary flex items-center gap-1\">\n <Bot className=\"w-3 h-3\" />\n Tip: pipe the URL to any LLM with{' '}\n <code className=\"bg-bg-sunken px-1 rounded\">curl &lt;url&gt;</code> or{' '}\n <code className=\"bg-bg-sunken px-1 rounded\">{`curl -H \"Accept: text/markdown\" <url>`}</code>{' '}\n for a markdown snapshot.\n </p>\n </div>\n );\n}\n\nfunction AuditListInline({ tokenId }: { tokenId: string }): ReactElement {\n const { data, loading } = useQuery<{ myVibeLlmContextTokenAudits: AuditRow[] }>(GET_AUDITS, {\n variables: { tokenId, limit: 100 },\n fetchPolicy: 'cache-and-network',\n });\n const rows = data?.myVibeLlmContextTokenAudits ?? [];\n return (\n <div className=\"text-xs\">\n {loading && rows.length === 0 ? (\n <span className=\"text-text-secondary\">Loading audit log…</span>\n ) : rows.length === 0 ? (\n <span className=\"text-text-secondary\">No fetches yet.</span>\n ) : (\n <table className=\"w-full\">\n <thead>\n <tr className=\"text-text-secondary\">\n <th className=\"text-left py-1 pr-2\">When</th>\n <th className=\"text-left py-1 pr-2\">IP</th>\n <th className=\"text-left py-1 pr-2\">Format</th>\n <th className=\"text-left py-1 pr-2\">Bytes</th>\n <th className=\"text-left py-1 pr-2\">Status</th>\n <th className=\"text-left py-1 pr-2\">UA</th>\n </tr>\n </thead>\n <tbody>\n {rows.map((r) => (\n <tr key={r.id} className=\"text-text-primary border-t border-border-subtle\">\n <td className=\"py-1 pr-2\">{new Date(r.fetchedAt).toLocaleString()}</td>\n <td className=\"py-1 pr-2 font-mono\">{r.remoteIp ?? '—'}</td>\n <td className=\"py-1 pr-2\">{r.format}</td>\n <td className=\"py-1 pr-2\">{r.bytes}</td>\n <td className=\"py-1 pr-2\">{r.status}</td>\n <td className=\"py-1 pr-2 truncate max-w-[260px]\" title={r.userAgent ?? ''}>\n {r.userAgent ?? '—'}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"VibeLlmContextTabPanel.js","names":[],"sources":["../../../src/components/vibe/VibeLlmContextTabPanel.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport { Fragment, useEffect, useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n AlertTriangle,\n Bot,\n Check,\n Clock,\n Copy,\n EyeOff,\n Info,\n Lock,\n RefreshCw,\n RotateCw,\n Trash2,\n} from 'lucide-react';\n\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\n\nimport { VIBE_PERMISSIONS } from '@/constants/permissions';\n\nimport { VibeLlmContextAdminPanel } from './VibeLlmContextAdminPanel';\n\nconst ALL_INCLUDES = [\n 'core',\n 'agents',\n 'sessions',\n 'notes',\n 'catalogs',\n 'docs',\n 'config',\n 'security',\n 'plugins',\n] as const;\n\ntype IncludeKey = (typeof ALL_INCLUDES)[number];\n\ninterface VibeLlmContextSettings {\n vibeId: string;\n ttlSeconds: number;\n includeCredentials: boolean;\n includes: string[];\n customContextText: string | null;\n defaultAgentIdOverride: string | null;\n sessionsLimit: number;\n notesLimit: number;\n docsPagesLimit: number;\n securityRunsLimit: number;\n updatedAt: string;\n}\n\ninterface VibeLlmContextTokenRow {\n id: string;\n vibeId: string;\n userId: string;\n label: string | null;\n tokenFingerprint: string;\n includeCredentials: boolean;\n includes: string[];\n status: 'ACTIVE' | 'REVOKED';\n expiresAt: string;\n lastFetchedAt: string | null;\n fetchCount: number;\n createdAt: string;\n revokedAt: string | null;\n revokedReason: string | null;\n}\n\ninterface MintResult {\n tokenId: string;\n url: string;\n token: string;\n expiresAt: string;\n ttlSeconds: number;\n includes: string[];\n includeCredentials: boolean;\n label: string | null;\n tokenFingerprint: string;\n}\n\ninterface AuditRow {\n id: string;\n fetchedAt: string;\n remoteIp: string | null;\n userAgent: string | null;\n format: string;\n bytes: number;\n durationMs: number;\n status: number;\n}\n\nconst GET_SETTINGS = gql`\n query MyVibeLlmContextSettings($vibeId: ID!) {\n myVibeLlmContextSettings(vibeId: $vibeId) {\n vibeId\n ttlSeconds\n includeCredentials\n includes\n customContextText\n defaultAgentIdOverride\n sessionsLimit\n notesLimit\n docsPagesLimit\n securityRunsLimit\n updatedAt\n }\n }\n`;\n\nconst GET_TOKENS = gql`\n query MyVibeLlmContextTokens($vibeId: ID!) {\n myVibeLlmContextTokens(vibeId: $vibeId) {\n id\n vibeId\n userId\n label\n tokenFingerprint\n includeCredentials\n includes\n status\n expiresAt\n lastFetchedAt\n fetchCount\n createdAt\n revokedAt\n revokedReason\n }\n }\n`;\n\nconst SET_SETTINGS = gql`\n mutation SetMyVibeLlmContextSettings($vibeId: ID!, $input: VibeLlmContextSettingsInput!) {\n setMyVibeLlmContextSettings(vibeId: $vibeId, input: $input) {\n vibeId\n ttlSeconds\n includeCredentials\n includes\n customContextText\n defaultAgentIdOverride\n sessionsLimit\n notesLimit\n docsPagesLimit\n securityRunsLimit\n updatedAt\n }\n }\n`;\n\nconst GENERATE_URL = gql`\n mutation GenerateVibeLlmContextUrl($vibeId: ID!, $input: VibeLlmContextMintInput) {\n generateVibeLlmContextUrl(vibeId: $vibeId, input: $input) {\n tokenId\n url\n token\n expiresAt\n ttlSeconds\n includes\n includeCredentials\n label\n tokenFingerprint\n }\n }\n`;\n\nconst REVOKE_TOKEN = gql`\n mutation RevokeVibeLlmContextToken($tokenId: ID!) {\n revokeVibeLlmContextToken(tokenId: $tokenId) {\n id\n status\n revokedAt\n }\n }\n`;\n\nconst ROTATE_TOKEN = gql`\n mutation RotateVibeLlmContextUrl($tokenId: ID!, $input: VibeLlmContextMintInput) {\n rotateVibeLlmContextUrl(tokenId: $tokenId, input: $input) {\n tokenId\n url\n token\n expiresAt\n ttlSeconds\n includes\n includeCredentials\n label\n tokenFingerprint\n }\n }\n`;\n\nconst REVOKE_ALL = gql`\n mutation RevokeAllMyVibeLlmContextTokens($vibeId: ID!) {\n revokeAllMyVibeLlmContextTokens(vibeId: $vibeId)\n }\n`;\n\nconst GET_AUDITS = gql`\n query MyVibeLlmContextTokenAudits($tokenId: ID!, $limit: Int) {\n myVibeLlmContextTokenAudits(tokenId: $tokenId, limit: $limit) {\n id\n fetchedAt\n remoteIp\n userAgent\n format\n bytes\n durationMs\n status\n }\n }\n`;\n\nconst TTL_PRESETS: Array<{ label: string; hours: number }> = [\n { label: '1 hour', hours: 1 },\n { label: '6 hours', hours: 6 },\n { label: '24 hours', hours: 24 },\n { label: '7 days', hours: 24 * 7 },\n];\n\nasync function copyToClipboard(text: string): Promise<void> {\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n const ta = document.createElement('textarea');\n ta.value = text;\n ta.style.position = 'fixed';\n ta.style.opacity = '0';\n document.body.appendChild(ta);\n ta.select();\n document.execCommand('copy');\n document.body.removeChild(ta);\n }\n}\n\nfunction formatExpiry(expiresAt: string): string {\n const diff = new Date(expiresAt).getTime() - Date.now();\n if (diff < 0) return 'expired';\n const hours = Math.floor(diff / (1000 * 60 * 60));\n const mins = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));\n if (hours > 24) return `${Math.floor(hours / 24)}d`;\n if (hours > 0) return `${hours}h ${mins}m`;\n return `${mins}m`;\n}\n\ninterface AttachedAgent {\n id: string;\n name: string;\n}\n\ninterface VibeLlmContextTabPanelProps {\n vibeId: string;\n attachedAgents?: AttachedAgent[];\n}\n\nexport function VibeLlmContextTabPanel({\n vibeId,\n attachedAgents = [],\n}: VibeLlmContextTabPanelProps): ReactElement {\n const { hasPermission } = usePermissions();\n const isAdmin = hasPermission(VIBE_PERMISSIONS.VIBE_MANAGE);\n const settingsQuery = useQuery<{ myVibeLlmContextSettings: VibeLlmContextSettings }>(\n GET_SETTINGS,\n {\n variables: { vibeId },\n fetchPolicy: 'cache-and-network',\n }\n );\n const tokensQuery = useQuery<{ myVibeLlmContextTokens: VibeLlmContextTokenRow[] }>(GET_TOKENS, {\n variables: { vibeId },\n fetchPolicy: 'cache-and-network',\n });\n const [saveSettings, saveSettingsState] = useMutation<\n { setMyVibeLlmContextSettings: VibeLlmContextSettings },\n {\n vibeId: string;\n input: {\n ttlSeconds?: number;\n includeCredentials?: boolean;\n includes?: string[];\n customContextText?: string | null;\n defaultAgentIdOverride?: string | null;\n sessionsLimit?: number;\n notesLimit?: number;\n docsPagesLimit?: number;\n securityRunsLimit?: number;\n };\n }\n >(SET_SETTINGS, { refetchQueries: ['MyVibeLlmContextSettings'] });\n const [generateUrl, generateUrlState] = useMutation<\n { generateVibeLlmContextUrl: MintResult },\n {\n vibeId: string;\n input?: {\n label?: string | null;\n ttlSeconds?: number | null;\n includeCredentials?: boolean | null;\n includes?: string[] | null;\n } | null;\n }\n >(GENERATE_URL, { refetchQueries: ['MyVibeLlmContextTokens'] });\n const [revokeToken] = useMutation<\n { revokeVibeLlmContextToken: VibeLlmContextTokenRow },\n { tokenId: string }\n >(REVOKE_TOKEN, { refetchQueries: ['MyVibeLlmContextTokens'] });\n const [rotateToken] = useMutation<{ rotateVibeLlmContextUrl: MintResult }, { tokenId: string }>(\n ROTATE_TOKEN,\n { refetchQueries: ['MyVibeLlmContextTokens'] }\n );\n const [revokeAll] = useMutation<{ revokeAllMyVibeLlmContextTokens: number }, { vibeId: string }>(\n REVOKE_ALL,\n { refetchQueries: ['MyVibeLlmContextTokens'] }\n );\n\n const settings = settingsQuery.data?.myVibeLlmContextSettings;\n const tokens = tokensQuery.data?.myVibeLlmContextTokens ?? [];\n\n // Local editable copy of settings\n const [ttlHours, setTtlHours] = useState<number>(1);\n const [includeCreds, setIncludeCreds] = useState<boolean>(false);\n const [includesState, setIncludesState] = useState<Set<IncludeKey>>(new Set(ALL_INCLUDES));\n const [customText, setCustomText] = useState<string>('');\n const [defaultAgentOverride, setDefaultAgentOverride] = useState<string>('');\n const [label, setLabel] = useState<string>('');\n const [lastMint, setLastMint] = useState<MintResult | null>(null);\n const [copied, setCopied] = useState<boolean>(false);\n const [justSaved, setJustSaved] = useState<boolean>(false);\n const [auditPanelTokenId, setAuditPanelTokenId] = useState<string | null>(null);\n\n // Hydrate local form when server settings arrive. This is a side effect\n // (it writes component state), so it belongs in useEffect — not useMemo.\n useEffect(() => {\n if (!settings) return;\n setTtlHours(Math.max(1, Math.round((settings.ttlSeconds ?? 3600) / 3600)));\n setIncludeCreds(settings.includeCredentials);\n setIncludesState(new Set((settings.includes as IncludeKey[]) ?? ALL_INCLUDES));\n setCustomText(settings.customContextText ?? '');\n setDefaultAgentOverride(settings.defaultAgentIdOverride ?? '');\n }, [settings]);\n\n const onToggleInclude = (key: IncludeKey) => {\n setIncludesState((prev) => {\n const next = new Set(prev);\n if (next.has(key)) next.delete(key);\n else next.add(key);\n return next;\n });\n };\n\n const onSaveSettings = async () => {\n await saveSettings({\n variables: {\n vibeId,\n input: {\n ttlSeconds: Math.max(60, Math.min(7 * 24 * 60 * 60, ttlHours * 60 * 60)),\n includeCredentials: includeCreds,\n includes: Array.from(includesState),\n customContextText: customText,\n defaultAgentIdOverride: defaultAgentOverride || null,\n },\n },\n });\n setJustSaved(true);\n setTimeout(() => setJustSaved(false), 2000);\n };\n\n const onGenerate = async () => {\n const res = await generateUrl({\n variables: {\n vibeId,\n input: {\n label: label || null,\n ttlSeconds: Math.max(60, Math.min(7 * 24 * 60 * 60, ttlHours * 60 * 60)),\n includeCredentials: includeCreds,\n includes: Array.from(includesState),\n },\n },\n });\n if (res.data) {\n setLastMint(res.data.generateVibeLlmContextUrl);\n setCopied(false);\n setLabel('');\n }\n };\n\n const onRevokeAll = async () => {\n if (\n typeof window !== 'undefined' &&\n !window.confirm(\n 'Revoke ALL active URLs for this vibe? Every minted URL stops working immediately and cannot be un-revoked (use Rotate to issue a fresh one).'\n )\n ) {\n return;\n }\n await revokeAll({ variables: { vibeId } });\n };\n\n const onCopyResultUrl = async () => {\n if (!lastMint) return;\n await copyToClipboard(lastMint.url);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n };\n\n return (\n <div className=\"space-y-6 max-w-5xl\">\n {/* Header */}\n <div className=\"rounded-lg border border-status-warning-border bg-status-warning-bg/30 p-4\">\n <div className=\"flex items-start gap-3\">\n <Lock className=\"w-5 h-5 text-status-warning-text mt-0.5\" />\n <div className=\"text-sm text-text-primary\">\n <p className=\"font-medium mb-1\">\n LLM Context — share this vibe with any LLM via a signed URL\n </p>\n <p className=\"text-text-secondary\">\n Anyone with the URL can read the snapshot until it expires. When \"Include credentials\"\n is on, the snapshot exposes agent tunnel URLs + API keys. Default is redacted. Rotate\n or revoke any URL from the list below at any time.\n </p>\n </div>\n </div>\n </div>\n\n {/* Settings panel */}\n <section className=\"bg-bg-surface border border-border-default rounded-lg p-5 space-y-4\">\n <header className=\"flex items-center justify-between\">\n <div>\n <h3 className=\"text-base font-semibold text-text-primary\">Saved settings</h3>\n <p className=\"text-sm text-text-secondary\">\n Defaults used when you generate a URL. Snapshotted into each minted token, so future\n edits don't change already-minted URLs.\n </p>\n </div>\n <button\n type=\"button\"\n onClick={onSaveSettings}\n disabled={saveSettingsState.loading}\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover disabled:opacity-50\"\n >\n {justSaved && !saveSettingsState.loading && <Check className=\"w-4 h-4\" />}\n {saveSettingsState.loading ? 'Saving…' : justSaved ? 'Saved' : 'Save settings'}\n </button>\n </header>\n\n {/* TTL */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">URL expiry</label>\n <div className=\"flex flex-wrap items-center gap-2\">\n {TTL_PRESETS.map((p) => (\n <button\n key={p.hours}\n type=\"button\"\n onClick={() => setTtlHours(p.hours)}\n className={`px-3 py-1.5 text-sm rounded-md border ${\n ttlHours === p.hours\n ? 'bg-action-primary-bg text-action-primary-text border-action-primary-bg'\n : 'bg-bg-sunken text-text-primary border-border-default'\n }`}\n >\n {p.label}\n </button>\n ))}\n <span className=\"text-sm text-text-secondary mx-1\">or custom hours:</span>\n <input\n type=\"number\"\n min={1}\n max={168}\n value={ttlHours}\n onChange={(e) => setTtlHours(Math.max(1, Math.min(168, Number(e.target.value) || 1)))}\n className=\"w-24 px-2 py-1.5 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary\"\n />\n </div>\n </div>\n\n {/* Credentials toggle */}\n <div>\n <label className=\"flex items-center gap-2 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={includeCreds}\n onChange={(e) => setIncludeCreds(e.target.checked)}\n className=\"w-4 h-4\"\n />\n <span>Include credentials (tunnel URLs + agent API keys)</span>\n {includeCreds ? (\n <AlertTriangle\n className=\"w-4 h-4 text-status-warning-text\"\n aria-label=\"Credentials will be exposed in the snapshot\"\n />\n ) : (\n <EyeOff className=\"w-4 h-4 text-text-secondary\" aria-label=\"Credentials redacted\" />\n )}\n </label>\n {includeCreds && (\n <p className=\"mt-1.5 text-xs text-status-warning-text flex items-start gap-1.5\">\n <AlertTriangle className=\"w-3.5 h-3.5 mt-0.5 flex-shrink-0\" />\n <span>\n Anyone with a URL minted while this is on can read live agent tunnel URLs and API\n keys. Only enable for trusted recipients.\n </span>\n </p>\n )}\n </div>\n\n {/* Includes chips */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n Sections to include\n </label>\n <div className=\"flex flex-wrap gap-2\">\n {ALL_INCLUDES.map((key) => (\n <button\n key={key}\n type=\"button\"\n onClick={() => onToggleInclude(key)}\n className={`px-2.5 py-1 text-xs rounded-full border ${\n includesState.has(key)\n ? 'bg-action-primary-bg/10 text-action-primary-bg border-action-primary-bg'\n : 'bg-bg-sunken text-text-secondary border-border-default'\n }`}\n >\n {key}\n </button>\n ))}\n </div>\n </div>\n\n {/* Default agent override */}\n {attachedAgents.length > 0 && (\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n Default agent for context fetch\n </label>\n <select\n value={defaultAgentOverride}\n onChange={(e) => setDefaultAgentOverride(e.target.value)}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary\"\n >\n <option value=\"\">(use my per-vibe default from settings)</option>\n {attachedAgents.map((a) => (\n <option key={a.id} value={a.id}>\n {a.name}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Custom context */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n Custom context text\n </label>\n <textarea\n value={customText}\n onChange={(e) => setCustomText(e.target.value.slice(0, 8192))}\n rows={5}\n placeholder=\"Free-form notes embedded in every snapshot you mint AFTER saving (existing tokens keep their original copy).\"\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n <p className=\"text-xs text-text-secondary mt-1\">{customText.length} / 8192 chars</p>\n </div>\n </section>\n\n {/* Generate panel */}\n <section className=\"bg-bg-surface border border-border-default rounded-lg p-5 space-y-4\">\n <header>\n <h3 className=\"text-base font-semibold text-text-primary\">Generate a new URL</h3>\n <p className=\"text-sm text-text-secondary\">\n Mints a fresh signed URL using your current settings. The full token is only shown once\n — copy it before navigating away. Use Rotate below if you lose it.\n </p>\n </header>\n <div className=\"flex flex-wrap items-end gap-2\">\n <div className=\"flex-1 min-w-[200px]\">\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n Label (optional)\n </label>\n <input\n type=\"text\"\n value={label}\n onChange={(e) => setLabel(e.target.value.slice(0, 120))}\n placeholder=\"e.g. Claude desktop\"\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n </div>\n <button\n type=\"button\"\n onClick={onGenerate}\n disabled={generateUrlState.loading}\n className=\"px-4 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover disabled:opacity-50\"\n >\n {generateUrlState.loading ? 'Generating…' : 'Generate URL'}\n </button>\n </div>\n\n {lastMint && (\n <div className=\"rounded-md border border-status-success-border bg-status-success-bg/20 p-3\">\n <div className=\"flex items-center gap-2 text-sm mb-2\">\n <Check className=\"w-4 h-4 text-status-success-text\" />\n <span className=\"font-medium text-text-primary\">URL generated</span>\n <span className=\"text-xs text-text-secondary\">\n expires in {formatExpiry(lastMint.expiresAt)}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <input\n readOnly\n value={lastMint.url}\n className=\"flex-1 px-2 py-1.5 text-xs bg-bg-sunken border border-border-default rounded font-mono text-text-primary\"\n aria-label=\"Generated LLM context URL\"\n />\n <button\n type=\"button\"\n onClick={onCopyResultUrl}\n className=\"px-2 py-1.5 text-xs bg-bg-sunken border border-border-default rounded text-text-primary\"\n aria-label=\"Copy URL\"\n >\n {copied ? (\n <Check className=\"w-4 h-4 text-status-success-text\" />\n ) : (\n <Copy className=\"w-4 h-4\" />\n )}\n </button>\n </div>\n </div>\n )}\n </section>\n\n {/* Active URLs list */}\n <section className=\"bg-bg-surface border border-border-default rounded-lg p-5 space-y-3\">\n <header className=\"flex items-center justify-between\">\n <div>\n <h3 className=\"text-base font-semibold text-text-primary\">Your active URLs</h3>\n <p className=\"text-sm text-text-secondary\">\n Tokens you minted for this vibe. Revoke and rotate work immediately; revoked tokens\n fail with 403 even if the JWT hasn't expired.\n </p>\n </div>\n <button\n type=\"button\"\n onClick={onRevokeAll}\n disabled={tokens.every((t) => t.status !== 'ACTIVE')}\n className=\"flex items-center gap-1 px-3 py-1.5 text-sm bg-status-error-bg/10 text-status-error-text border border-status-error-border rounded-md hover:bg-status-error-bg/20 disabled:opacity-40 disabled:cursor-not-allowed\"\n >\n <Trash2 className=\"w-4 h-4\" />\n Revoke all\n </button>\n </header>\n\n {tokensQuery.loading && tokens.length === 0 && (\n <div className=\"text-sm text-text-secondary py-4 flex items-center gap-2\">\n <RefreshCw className=\"w-4 h-4 animate-spin\" />\n Loading tokens…\n </div>\n )}\n {tokens.length === 0 && !tokensQuery.loading && (\n <div className=\"text-sm text-text-secondary py-4 flex items-center gap-2\">\n <Info className=\"w-4 h-4\" />\n No URLs minted yet for this vibe.\n </div>\n )}\n {tokens.length > 0 && (\n <div className=\"overflow-x-auto\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-default text-left text-xs text-text-secondary\">\n <th className=\"py-2 pr-3\">Label</th>\n <th className=\"py-2 pr-3\">Fingerprint</th>\n <th className=\"py-2 pr-3\">Sections</th>\n <th className=\"py-2 pr-3\">Creds</th>\n <th className=\"py-2 pr-3\">Status</th>\n <th className=\"py-2 pr-3\">Expires</th>\n <th className=\"py-2 pr-3\">Fetches</th>\n <th className=\"py-2 pr-3\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {tokens.map((t) => (\n <Fragment key={t.id}>\n <tr className=\"border-b border-border-subtle align-top\">\n <td className=\"py-2 pr-3 text-text-primary\">{t.label ?? '—'}</td>\n <td className=\"py-2 pr-3 font-mono text-xs text-text-secondary\">\n {t.tokenFingerprint}\n </td>\n <td className=\"py-2 pr-3 text-text-secondary\">\n <span className=\"text-xs\">{t.includes.join(', ')}</span>\n </td>\n <td className=\"py-2 pr-3\">\n {t.includeCredentials ? (\n <span className=\"text-xs text-status-warning-text\">on</span>\n ) : (\n <span className=\"text-xs text-text-secondary\">off</span>\n )}\n </td>\n <td className=\"py-2 pr-3\">\n <span\n className={`text-xs px-1.5 py-0.5 rounded ${\n t.status === 'ACTIVE'\n ? 'bg-status-success-bg/20 text-status-success-text'\n : 'bg-bg-sunken text-text-secondary'\n }`}\n >\n {t.status}\n </span>\n </td>\n <td className=\"py-2 pr-3 text-xs text-text-secondary\">\n <span className=\"inline-flex items-center gap-1\">\n <Clock className=\"w-3 h-3\" />\n {formatExpiry(t.expiresAt)}\n </span>\n </td>\n <td className=\"py-2 pr-3 text-xs text-text-secondary\">{t.fetchCount}</td>\n <td className=\"py-2 pr-3\">\n <div className=\"flex gap-1\">\n <button\n type=\"button\"\n onClick={() =>\n setAuditPanelTokenId(auditPanelTokenId === t.id ? null : t.id)\n }\n title=\"Show fetch history\"\n aria-label=\"Show fetch history\"\n className=\"p-1.5 text-text-secondary hover:text-text-primary\"\n >\n <Info className=\"w-4 h-4\" />\n </button>\n {t.status === 'ACTIVE' && (\n <>\n <button\n type=\"button\"\n onClick={async () => {\n const res = await rotateToken({ variables: { tokenId: t.id } });\n if (res.data) {\n setLastMint(res.data.rotateVibeLlmContextUrl);\n setCopied(false);\n }\n }}\n title=\"Rotate (revoke + mint a new one with same settings)\"\n aria-label=\"Rotate URL\"\n className=\"p-1.5 text-text-secondary hover:text-text-primary\"\n >\n <RotateCw className=\"w-4 h-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => revokeToken({ variables: { tokenId: t.id } })}\n title=\"Revoke\"\n aria-label=\"Revoke URL\"\n className=\"p-1.5 text-status-error-text hover:opacity-80\"\n >\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </>\n )}\n </div>\n </td>\n </tr>\n {auditPanelTokenId === t.id && (\n <tr>\n <td colSpan={8} className=\"py-2 pr-3 bg-bg-sunken/40\">\n <AuditListInline tokenId={t.id} />\n </td>\n </tr>\n )}\n </Fragment>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </section>\n\n {/* Admin sub-panel — gated by vibe:manage permission */}\n {isAdmin && <VibeLlmContextAdminPanel vibeId={vibeId} />}\n\n {/* Help footer */}\n <p className=\"text-xs text-text-secondary flex items-center gap-1\">\n <Bot className=\"w-3 h-3\" />\n Tip: pipe the URL to any LLM with{' '}\n <code className=\"bg-bg-sunken px-1 rounded\">curl &lt;url&gt;</code> or{' '}\n <code className=\"bg-bg-sunken px-1 rounded\">{`curl -H \"Accept: text/markdown\" <url>`}</code>{' '}\n for a markdown snapshot.\n </p>\n </div>\n );\n}\n\nfunction AuditListInline({ tokenId }: { tokenId: string }): ReactElement {\n const { data, loading } = useQuery<{ myVibeLlmContextTokenAudits: AuditRow[] }>(GET_AUDITS, {\n variables: { tokenId, limit: 100 },\n fetchPolicy: 'cache-and-network',\n });\n const rows = data?.myVibeLlmContextTokenAudits ?? [];\n return (\n <div className=\"text-xs\">\n {loading && rows.length === 0 ? (\n <span className=\"text-text-secondary\">Loading audit log…</span>\n ) : rows.length === 0 ? (\n <span className=\"text-text-secondary\">No fetches yet.</span>\n ) : (\n <table className=\"w-full\">\n <thead>\n <tr className=\"text-text-secondary\">\n <th className=\"text-left py-1 pr-2\">When</th>\n <th className=\"text-left py-1 pr-2\">IP</th>\n <th className=\"text-left py-1 pr-2\">Format</th>\n <th className=\"text-left py-1 pr-2\">Bytes</th>\n <th className=\"text-left py-1 pr-2\">Status</th>\n <th className=\"text-left py-1 pr-2\">UA</th>\n </tr>\n </thead>\n <tbody>\n {rows.map((r) => (\n <tr key={r.id} className=\"text-text-primary border-t border-border-subtle\">\n <td className=\"py-1 pr-2\">{new Date(r.fetchedAt).toLocaleString()}</td>\n <td className=\"py-1 pr-2 font-mono\">{r.remoteIp ?? '—'}</td>\n <td className=\"py-1 pr-2\">{r.format}</td>\n <td className=\"py-1 pr-2\">{r.bytes}</td>\n <td className=\"py-1 pr-2\">{r.status}</td>\n <td className=\"py-1 pr-2 truncate max-w-[260px]\" title={r.userAgent ?? ''}>\n {r.userAgent ?? '—'}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-vibecontrols",
3
- "version": "2026.524.6",
3
+ "version": "2026.524.7",
4
4
  "description": "VibeControls microfrontend for Burdenoff products",
5
5
  "type": "module",
6
6
  "files": [