From d91eef7a4ba0f2695aa3e2d1449f59055f1d93c8 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Mon, 29 Jun 2026 11:53:46 -0400 Subject: [PATCH] =?UTF-8?q?feat(gpu):=20GPU=20agent=20admin=20card=20?= =?UTF-8?q?=E2=80=94=20token,=20queue,=20backfill=20(#114)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FC-side control surface the operator asked for: Settings → Tagging → "GPU agent". Generate/reveal/copy/rotate the agent bearer token (with the FC URL to point the agent at), see the live job-queue depth (pending/in-flight/done/ errored, polled), and a "Queue character embedding (CCIP)" button that triggers the library backfill. Plain-HTTP-safe copy (copyText resolves on success, throws on fail). Closes the "how do I get the token in the UI" gap. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Ttrj5P7upUTueSfoJcxEqa --- .../src/components/settings/GpuAgentCard.vue | 166 ++++++++++++++++++ .../components/settings/MaintenancePanel.vue | 2 + frontend/src/stores/gpu.js | 33 ++++ 3 files changed, 201 insertions(+) create mode 100644 frontend/src/components/settings/GpuAgentCard.vue create mode 100644 frontend/src/stores/gpu.js diff --git a/frontend/src/components/settings/GpuAgentCard.vue b/frontend/src/components/settings/GpuAgentCard.vue new file mode 100644 index 0000000..d4a3d96 --- /dev/null +++ b/frontend/src/components/settings/GpuAgentCard.vue @@ -0,0 +1,166 @@ + + + + + diff --git a/frontend/src/components/settings/MaintenancePanel.vue b/frontend/src/components/settings/MaintenancePanel.vue index 44dafe6..77a8035 100644 --- a/frontend/src/components/settings/MaintenancePanel.vue +++ b/frontend/src/components/settings/MaintenancePanel.vue @@ -27,6 +27,7 @@
+ @@ -54,6 +55,7 @@ import MissingFileRepairCard from './MissingFileRepairCard.vue' import DbMaintenanceCard from './DbMaintenanceCard.vue' import MLThresholdSliders from './MLThresholdSliders.vue' import HeadsCard from './HeadsCard.vue' +import GpuAgentCard from './GpuAgentCard.vue' import AllowlistTable from './AllowlistTable.vue' import AliasTable from './AliasTable.vue' import TagEvalCard from './TagEvalCard.vue' diff --git a/frontend/src/stores/gpu.js b/frontend/src/stores/gpu.js new file mode 100644 index 0000000..6c677c0 --- /dev/null +++ b/frontend/src/stores/gpu.js @@ -0,0 +1,33 @@ +import { defineStore } from 'pinia' + +import { useApi } from '../composables/useApi.js' + +// GPU agent control surface (#114): the FC-side admin for the desktop agent — +// the bearer token it authenticates with, the job-queue depth, and the backfill +// trigger. The agent itself talks to /api/gpu/jobs/* over HTTP; nothing here +// touches Redis/Postgres directly. +export const useGpuStore = defineStore('gpu', () => { + const api = useApi() + + // { token: , configured: bool } + async function token() { + return await api.get('/api/gpu/token') + } + + // Generate a fresh token (invalidates the old one). Returns { token }. + async function rotateToken() { + return await api.post('/api/gpu/token/rotate') + } + + // { pending, leased, done, error } + async function status() { + return await api.get('/api/gpu/status') + } + + // Enqueue a job per image lacking one for `task` (the agent drains it). + async function backfill(task = 'ccip') { + return await api.post('/api/gpu/backfill', { body: { task } }) + } + + return { token, rotateToken, status, backfill } +})