Skip to content

Commit 4048b9a

Browse files
v1.4.1: Hash Vault Browser — keybinding + sidebar tab
Three ways to open the browser now: - Ctrl+Shift+H keybinding from anywhere in ComfyUI - Left-sidebar "Hash Vault" tab with entry count + Open Browser button - Top menu (Extensions → AKURATE: Hash Vault Browser) — unchanged from v1.4.0 Sidebar registration guarded on app.extensionManager.registerSidebarTab so older frontends fall back cleanly to menu + keybinding only. No backend changes — pure JS polish.
1 parent 04e31f5 commit 4048b9a

3 files changed

Lines changed: 76 additions & 2 deletions

File tree

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ ComfyUI's native caching often breaks with external API nodes (dynamic timestamp
3333
- **Atomic Writes:** Cache files are written to a temp file first, then atomically replaced — preventing corruption from interrupted writes.
3434
- **Concurrent-Safe:** File locking on every cache read/write operation.
3535
- **Sidecar Metadata (v1.3.0):** Every saved entry gets a `{hash_key}.json` sidecar with human-readable `label`, `created_at`, `last_accessed_at`, and payload summary. Image outputs also get a `{hash_key}.thumb.png` 256px preview. Sidecar data is decoupled from the hash, so editing a `label` never invalidates cache. This is what the Hash Vault Browser indexes.
36-
- **Hash Vault Browser (v1.4.0):** A modal gallery over the entire vault. Open from `Extensions → AKURATE → Hash Vault Browser` in the ComfyUI menu. Shows every cached entry as a card with thumbnail, label, relative age, and `.pt` size. Live substring filter on label + hash. Click a card to copy its hash to clipboard. Sorted by last-accessed desc. No load-into-workflow action in v0.1 — that's v1.5+.
36+
- **Hash Vault Browser (v1.4.0+):** A modal gallery over the entire vault. Three ways to open:
37+
1. **Keyboard**: `Ctrl+Shift+H` from anywhere in ComfyUI (added v1.4.1)
38+
2. **Sidebar**: click the `Hash Vault` tab in the left sidebar, then the `Open Browser` button (added v1.4.1)
39+
3. **Menu**: `Extensions → AKURATE: Hash Vault Browser` in the top menu bar
40+
41+
Shows every cached entry as a card with thumbnail, label, relative age, and `.pt` size. Live substring filter on label + hash. Click a card to copy its hash to clipboard. Sorted by last-accessed desc. No load-into-workflow action yet — that's v1.5+.
3742

3843
### Sidecar Label Input
3944

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "comfyui-api-optimizer"
33
description = "API cost tracking, deterministic hash caching, and lazy execution bypass for cloud API workflows"
4-
version = "1.4.0"
4+
version = "1.4.1"
55
license = { file = "LICENSE" }
66

77
[project.urls]

web/hash_vault_browser.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,51 @@ async function openBrowser() {
250250
}
251251
}
252252

253+
function renderSidebarTab(el) {
254+
el.innerHTML = "";
255+
el.style.padding = "16px";
256+
el.style.color = "#ddd";
257+
el.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif";
258+
259+
const title = document.createElement("div");
260+
title.textContent = "Hash Vault";
261+
title.style.fontSize = "14px";
262+
title.style.fontWeight = "600";
263+
title.style.marginBottom = "4px";
264+
265+
const sub = document.createElement("div");
266+
sub.textContent = "Loading…";
267+
sub.style.fontSize = "12px";
268+
sub.style.color = "#888";
269+
sub.style.marginBottom = "14px";
270+
271+
const btn = document.createElement("button");
272+
btn.textContent = "Open Browser";
273+
btn.style.cssText = `
274+
width: 100%; padding: 8px 12px; font-size: 13px;
275+
background: #2a2a2a; color: #eee; border: 1px solid #3a3a3a;
276+
border-radius: 4px; cursor: pointer; font-family: inherit;
277+
`;
278+
btn.addEventListener("mouseenter", () => { btn.style.borderColor = "#4a90e2"; });
279+
btn.addEventListener("mouseleave", () => { btn.style.borderColor = "#3a3a3a"; });
280+
btn.addEventListener("click", openBrowser);
281+
282+
const hint = document.createElement("div");
283+
hint.textContent = "Shortcut: Ctrl+Shift+H";
284+
hint.style.cssText = "font-size: 11px; color: #666; margin-top: 10px; text-align: center;";
285+
286+
el.append(title, sub, btn, hint);
287+
288+
// Populate count asynchronously
289+
fetch(LIST_URL)
290+
.then((r) => (r.ok ? r.json() : Promise.reject(r.status)))
291+
.then((d) => {
292+
const n = d.count ?? (d.entries || []).length;
293+
sub.textContent = `${n} cached ${n === 1 ? "entry" : "entries"}`;
294+
})
295+
.catch(() => { sub.textContent = "Vault list unavailable"; });
296+
}
297+
253298
app.registerExtension({
254299
name: "akurate.HashVaultBrowser",
255300
commands: [
@@ -260,10 +305,34 @@ app.registerExtension({
260305
function: openBrowser,
261306
},
262307
],
308+
keybindings: [
309+
{
310+
combo: { key: "H", ctrl: true, shift: true },
311+
commandId: "akurate.HashVaultBrowser.open",
312+
},
313+
],
263314
menuCommands: [
264315
{
265316
path: ["Extensions"],
266317
commands: ["akurate.HashVaultBrowser.open"],
267318
},
268319
],
320+
setup() {
321+
// Register sidebar tab. Guard in case the frontend is older than
322+
// extensionManager.registerSidebarTab — fall back to menu-only.
323+
try {
324+
if (app.extensionManager?.registerSidebarTab) {
325+
app.extensionManager.registerSidebarTab({
326+
id: "akurate.HashVaultBrowser.tab",
327+
icon: "pi pi-database",
328+
title: "Hash Vault",
329+
tooltip: "AKURATE Hash Vault Browser",
330+
type: "custom",
331+
render: renderSidebarTab,
332+
});
333+
}
334+
} catch (e) {
335+
console.warn("[akurate.HashVaultBrowser] sidebar tab registration failed:", e);
336+
}
337+
},
269338
});

0 commit comments

Comments
 (0)