← back to Designer Wallcoverings
auto-save: 2026-07-31T10:26:53 (3 files) — DW-Agents/vendor-command-center/logo-cropper.js DW-Agents/vendor-command-center/standardization-worker.js DW-Agents/vendor-command-center/website-scorer.js
3ddeb92ca40f5478243ec3cc33dfd820164610d8 · 2026-07-31 10:27:02 -0700 · Steve Abrams
Files touched
M DW-Agents/vendor-command-center/logo-cropper.jsM DW-Agents/vendor-command-center/standardization-worker.jsM DW-Agents/vendor-command-center/website-scorer.js
Diff
commit 3ddeb92ca40f5478243ec3cc33dfd820164610d8
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Jul 31 10:27:02 2026 -0700
auto-save: 2026-07-31T10:26:53 (3 files) — DW-Agents/vendor-command-center/logo-cropper.js DW-Agents/vendor-command-center/standardization-worker.js DW-Agents/vendor-command-center/website-scorer.js
---
DW-Agents/vendor-command-center/logo-cropper.js | 7 ++++++-
DW-Agents/vendor-command-center/standardization-worker.js | 7 ++++++-
DW-Agents/vendor-command-center/website-scorer.js | 8 +++++++-
3 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/DW-Agents/vendor-command-center/logo-cropper.js b/DW-Agents/vendor-command-center/logo-cropper.js
index 2dd63e18..75843977 100644
--- a/DW-Agents/vendor-command-center/logo-cropper.js
+++ b/DW-Agents/vendor-command-center/logo-cropper.js
@@ -8,9 +8,13 @@ const sharp = require('sharp');
const fs = require('fs');
const path = require('path');
+// Key check deferred to call time — a require-time throw crash-loops any host
+// whose env lacks the key (Kamatera VCC 2026-07-31); logo cropping is optional there.
const GEMINI_KEY = process.env.GEMINI_API_KEY || process.env.GEMINI_KEY;
-if (!GEMINI_KEY) throw new Error('GEMINI_KEY not set — route via /secrets (master GEMINI_API_KEY)');
const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-flash:generateContent?key=${GEMINI_KEY}`;
+function requireGeminiKey() {
+ if (!GEMINI_KEY) throw new Error('GEMINI_KEY not set — route via /secrets (master GEMINI_API_KEY)');
+}
/**
* Analyze image for logos at top/bottom using Gemini vision
@@ -40,6 +44,7 @@ topPercentage/bottomPercentage = estimated percentage of image height occupied b
If no logo, set percentage to 0. Max 30% — if the area is larger, it's probably part of the product.`;
try {
+ requireGeminiKey();
const resp = await fetch(GEMINI_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
diff --git a/DW-Agents/vendor-command-center/standardization-worker.js b/DW-Agents/vendor-command-center/standardization-worker.js
index ee0cf838..9b4871b6 100644
--- a/DW-Agents/vendor-command-center/standardization-worker.js
+++ b/DW-Agents/vendor-command-center/standardization-worker.js
@@ -16,9 +16,13 @@ const pool = new Pool({
const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
const SHOPIFY_TOKEN = process.env.SHOPIFY_ORDERS_TOKEN;
+// Key check deferred to call time — a require-time throw crash-loops any host
+// whose env lacks the key (Kamatera VCC 2026-07-31), and this worker is optional there.
const GEMINI_API_KEY = process.env.GEMINI_API_KEY || process.env.GEMINI_KEY;
-if (!GEMINI_API_KEY) throw new Error('GEMINI_API_KEY not set — route via /secrets (master GEMINI_API_KEY)');
const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-flash:generateContent?key=${GEMINI_API_KEY}`;
+function requireGeminiKey() {
+ if (!GEMINI_API_KEY) throw new Error('GEMINI_API_KEY not set — route via /secrets (master GEMINI_API_KEY)');
+}
// --- State ---
let engineState = {
@@ -71,6 +75,7 @@ IMPORTANT:
- For commercial/hospitality products, note fire rating if apparent from material type`;
async function analyzeWithGemini(imageUrl, title, productType) {
+ requireGeminiKey();
let imageBase64 = null;
try {
const imgCtrl = new AbortController();
diff --git a/DW-Agents/vendor-command-center/website-scorer.js b/DW-Agents/vendor-command-center/website-scorer.js
index 19e4ebd0..0c139ce2 100644
--- a/DW-Agents/vendor-command-center/website-scorer.js
+++ b/DW-Agents/vendor-command-center/website-scorer.js
@@ -18,10 +18,15 @@ const https = require('https');
const http = require('http');
const { URL } = require('url');
+// Key check is deferred to call time: a require-time throw crash-loops any host
+// whose env lacks the key (took Kamatera VCC down 2026-07-31) even though the
+// scorer is an optional feature there.
const GEMINI_KEY = process.env.GEMINI_API_KEY || process.env.GEMINI_KEY;
-if (!GEMINI_KEY) throw new Error('GEMINI_KEY not set — route via /secrets (master GEMINI_API_KEY)');
const GEMINI_MODEL = 'gemini-3.5-flash';
const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_KEY}`;
+function requireGeminiKey() {
+ if (!GEMINI_KEY) throw new Error('GEMINI_KEY not set — route via /secrets (master GEMINI_API_KEY)');
+}
// ── HTTP fetch with redirect following ──
@@ -264,6 +269,7 @@ function computeHeuristicScore(signals) {
// ── Gemini AI analysis ──
async function geminiAnalyze(url, signals, htmlExcerpt) {
+ requireGeminiKey();
const prompt = `You are a website quality analyst. Score this vendor website from 1-10 (10 = best).
Website: ${url}
← 1fa0b3ac TK-10046: build-residual-plan --inputs-dir fallback to durab
·
back to Designer Wallcoverings
·
auto-save: 2026-07-31T11:27:21 (1 files) — shopify/scripts/c 517e6645 →