@burdenoff/microfe-vibecontrols 2026.522.9 → 2026.523.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,196 @@
1
+ import { useState as e } from "react";
2
+ import { Clock as t, Info as n, Shield as r, Trash2 as i } from "lucide-react";
3
+ import { gql as a } from "@apollo/client";
4
+ import { useMutation as o, useQuery as s } from "@apollo/client/react";
5
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
6
+ //#region src/components/vibe/VibeLlmContextAdminPanel.tsx
7
+ var u = a`
8
+ query AllVibeLlmContextTokens($vibeId: ID, $userId: ID) {
9
+ allVibeLlmContextTokens(vibeId: $vibeId, userId: $userId) {
10
+ id
11
+ vibeId
12
+ userId
13
+ label
14
+ tokenFingerprint
15
+ includeCredentials
16
+ includes
17
+ status
18
+ expiresAt
19
+ lastFetchedAt
20
+ fetchCount
21
+ createdAt
22
+ revokedAt
23
+ revokedReason
24
+ }
25
+ }
26
+ `, d = a`
27
+ mutation AdminRevokeVibeLlmContextToken($tokenId: ID!, $reason: String) {
28
+ adminRevokeVibeLlmContextToken(tokenId: $tokenId, reason: $reason) {
29
+ id
30
+ status
31
+ revokedAt
32
+ revokedReason
33
+ }
34
+ }
35
+ `;
36
+ function f(e) {
37
+ let t = new Date(e).getTime() - Date.now();
38
+ if (t < 0) return "expired";
39
+ let n = Math.floor(t / (1e3 * 60 * 60)), r = Math.floor(t % (1e3 * 60 * 60) / (1e3 * 60));
40
+ return n > 24 ? `${Math.floor(n / 24)}d` : n > 0 ? `${n}h ${r}m` : `${r}m`;
41
+ }
42
+ function p({ vibeId: a }) {
43
+ let { data: p, loading: m, refetch: h } = s(u, {
44
+ variables: { vibeId: a },
45
+ fetchPolicy: "cache-and-network",
46
+ errorPolicy: "ignore"
47
+ }), [g] = o(d, { refetchQueries: ["AllVibeLlmContextTokens"] }), [_, v] = e({}), y = p?.allVibeLlmContextTokens ?? [], b = async (e) => {
48
+ await g({ variables: {
49
+ tokenId: e,
50
+ reason: (_[e] ?? "").trim() || null
51
+ } }), v((t) => {
52
+ let n = { ...t };
53
+ return delete n[e], n;
54
+ }), await h();
55
+ };
56
+ return /* @__PURE__ */ l("section", {
57
+ className: "bg-bg-surface border border-status-warning-border rounded-lg p-5 space-y-3",
58
+ children: [
59
+ /* @__PURE__ */ l("header", {
60
+ className: "flex items-start gap-3",
61
+ children: [/* @__PURE__ */ c(r, { className: "w-5 h-5 text-status-warning-text mt-0.5" }), /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("h3", {
62
+ className: "text-base font-semibold text-text-primary",
63
+ children: "Admin · all URLs for this vibe"
64
+ }), /* @__PURE__ */ c("p", {
65
+ className: "text-sm text-text-secondary",
66
+ children: "Visible only to workspace admins. Lists every user's signed URLs for this vibe. Use revoke to immediately invalidate any URL — takes effect on the next fetch."
67
+ })] })]
68
+ }),
69
+ m && y.length === 0 && /* @__PURE__ */ c("div", {
70
+ className: "text-sm text-text-secondary py-3",
71
+ children: "Loading…"
72
+ }),
73
+ y.length === 0 && !m && /* @__PURE__ */ l("div", {
74
+ className: "text-sm text-text-secondary py-3 flex items-center gap-2",
75
+ children: [/* @__PURE__ */ c(n, { className: "w-4 h-4" }), "No URLs minted for this vibe by any user."]
76
+ }),
77
+ y.length > 0 && /* @__PURE__ */ c("div", {
78
+ className: "overflow-x-auto",
79
+ children: /* @__PURE__ */ l("table", {
80
+ className: "w-full text-sm",
81
+ children: [/* @__PURE__ */ c("thead", { children: /* @__PURE__ */ l("tr", {
82
+ className: "border-b border-border-default text-left text-xs text-text-secondary",
83
+ children: [
84
+ /* @__PURE__ */ c("th", {
85
+ className: "py-2 pr-3",
86
+ children: "User"
87
+ }),
88
+ /* @__PURE__ */ c("th", {
89
+ className: "py-2 pr-3",
90
+ children: "Label"
91
+ }),
92
+ /* @__PURE__ */ c("th", {
93
+ className: "py-2 pr-3",
94
+ children: "Fingerprint"
95
+ }),
96
+ /* @__PURE__ */ c("th", {
97
+ className: "py-2 pr-3",
98
+ children: "Creds"
99
+ }),
100
+ /* @__PURE__ */ c("th", {
101
+ className: "py-2 pr-3",
102
+ children: "Status"
103
+ }),
104
+ /* @__PURE__ */ c("th", {
105
+ className: "py-2 pr-3",
106
+ children: "Expires"
107
+ }),
108
+ /* @__PURE__ */ c("th", {
109
+ className: "py-2 pr-3",
110
+ children: "Fetches"
111
+ }),
112
+ /* @__PURE__ */ c("th", {
113
+ className: "py-2 pr-3",
114
+ children: "Revoke"
115
+ })
116
+ ]
117
+ }) }), /* @__PURE__ */ c("tbody", { children: y.map((e) => /* @__PURE__ */ l("tr", {
118
+ className: "border-b border-border-subtle align-top",
119
+ children: [
120
+ /* @__PURE__ */ c("td", {
121
+ className: "py-2 pr-3 font-mono text-xs text-text-secondary truncate max-w-[120px]",
122
+ title: e.userId,
123
+ children: e.userId
124
+ }),
125
+ /* @__PURE__ */ c("td", {
126
+ className: "py-2 pr-3 text-text-primary",
127
+ children: e.label ?? "—"
128
+ }),
129
+ /* @__PURE__ */ c("td", {
130
+ className: "py-2 pr-3 font-mono text-xs text-text-secondary",
131
+ children: e.tokenFingerprint
132
+ }),
133
+ /* @__PURE__ */ c("td", {
134
+ className: "py-2 pr-3",
135
+ children: e.includeCredentials ? /* @__PURE__ */ c("span", {
136
+ className: "text-xs text-status-warning-text",
137
+ children: "on"
138
+ }) : /* @__PURE__ */ c("span", {
139
+ className: "text-xs text-text-secondary",
140
+ children: "off"
141
+ })
142
+ }),
143
+ /* @__PURE__ */ c("td", {
144
+ className: "py-2 pr-3",
145
+ children: /* @__PURE__ */ c("span", {
146
+ 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"}`,
147
+ children: e.status
148
+ })
149
+ }),
150
+ /* @__PURE__ */ c("td", {
151
+ className: "py-2 pr-3 text-xs text-text-secondary",
152
+ children: /* @__PURE__ */ l("span", {
153
+ className: "inline-flex items-center gap-1",
154
+ children: [/* @__PURE__ */ c(t, { className: "w-3 h-3" }), f(e.expiresAt)]
155
+ })
156
+ }),
157
+ /* @__PURE__ */ c("td", {
158
+ className: "py-2 pr-3 text-xs text-text-secondary",
159
+ children: e.fetchCount
160
+ }),
161
+ /* @__PURE__ */ c("td", {
162
+ className: "py-2 pr-3",
163
+ children: e.status === "ACTIVE" ? /* @__PURE__ */ l("div", {
164
+ className: "flex items-center gap-1",
165
+ children: [/* @__PURE__ */ c("input", {
166
+ type: "text",
167
+ value: _[e.id] ?? "",
168
+ onChange: (t) => v((n) => ({
169
+ ...n,
170
+ [e.id]: t.target.value
171
+ })),
172
+ placeholder: "reason",
173
+ className: "w-28 px-1.5 py-1 text-xs bg-bg-sunken border border-border-default rounded text-text-primary"
174
+ }), /* @__PURE__ */ c("button", {
175
+ onClick: () => b(e.id),
176
+ title: "Admin revoke",
177
+ className: "p-1.5 text-status-error-text hover:opacity-80",
178
+ children: /* @__PURE__ */ c(i, { className: "w-4 h-4" })
179
+ })]
180
+ }) : /* @__PURE__ */ c("span", {
181
+ className: "text-xs text-text-secondary",
182
+ title: e.revokedReason ?? "",
183
+ children: e.revokedReason ?? "—"
184
+ })
185
+ })
186
+ ]
187
+ }, e.id)) })]
188
+ })
189
+ })
190
+ ]
191
+ });
192
+ }
193
+ //#endregion
194
+ export { p as VibeLlmContextAdminPanel };
195
+
196
+ //# sourceMappingURL=VibeLlmContextAdminPanel.js.map
@@ -0,0 +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":"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"}