seo-intel 1.1.7 → 1.1.9
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.
- package/.env.example +3 -1
- package/CHANGELOG.md +54 -0
- package/LICENSE +4 -5
- package/README.md +3 -3
- package/cli.js +136 -16
- package/crawler/index.js +11 -2
- package/crawler/subdomain-discovery.js +1 -1
- package/lib/gate.js +5 -5
- package/lib/license.js +150 -69
- package/lib/updater.js +19 -18
- package/package.json +3 -2
- package/seo-audit.js +2 -2
- package/server.js +3 -5
- package/setup/wizard.html +352 -32
package/setup/wizard.html
CHANGED
|
@@ -170,6 +170,10 @@ body {
|
|
|
170
170
|
max-width: var(--max-width);
|
|
171
171
|
margin: 0 auto;
|
|
172
172
|
}
|
|
173
|
+
#step2.step-panel {
|
|
174
|
+
max-width: 1100px;
|
|
175
|
+
margin: 0 auto;
|
|
176
|
+
}
|
|
173
177
|
.step-panel {
|
|
174
178
|
display: none;
|
|
175
179
|
animation: fadeIn 0.3s ease;
|
|
@@ -333,7 +337,7 @@ body {
|
|
|
333
337
|
/* ─── Model Cards (Step 2) ───────────────────────────────────────────── */
|
|
334
338
|
.model-columns {
|
|
335
339
|
display: grid;
|
|
336
|
-
grid-template-columns: 1fr 1fr;
|
|
340
|
+
grid-template-columns: 1fr 1fr 1fr;
|
|
337
341
|
gap: 20px;
|
|
338
342
|
}
|
|
339
343
|
.model-section {
|
|
@@ -1234,7 +1238,7 @@ input::placeholder {
|
|
|
1234
1238
|
<button class="btn btn-gold" onclick="saveLicenseKey()" id="activateBtn" style="white-space:nowrap;">Activate →</button>
|
|
1235
1239
|
</div>
|
|
1236
1240
|
<p style="font-size:0.65rem; color:var(--text-muted); margin-top:6px;">
|
|
1237
|
-
Get Solo at <a href="https://ukkometa.fi/seo-intel/" target="_blank" style="color:var(--accent-gold);">ukkometa.fi/seo-intel</a>
|
|
1241
|
+
Get Solo at <a href="https://ukkometa.fi/en/seo-intel/" target="_blank" style="color:var(--accent-gold);">ukkometa.fi/seo-intel</a>
|
|
1238
1242
|
</p>
|
|
1239
1243
|
</div>
|
|
1240
1244
|
<div id="licenseSolo" style="display:none;">
|
|
@@ -1286,39 +1290,133 @@ input::placeholder {
|
|
|
1286
1290
|
|
|
1287
1291
|
<!-- OpenClaw Setup Banner -->
|
|
1288
1292
|
<div id="openclawBanner" class="openclaw-banner" style="display:none;">
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
<
|
|
1293
|
-
|
|
1294
|
-
<path d="M9 12c0-2.8 2.2-5 5-5s5 2.2 5 5c0 1.8-1 3.4-2.4 4.3L18 20H10l1.4-3.7C10 15.4 9 13.8 9 12z" fill="currentColor" opacity="0.8"/>
|
|
1295
|
-
</svg>
|
|
1293
|
+
<!-- Always-shown agentic setup block -->
|
|
1294
|
+
<div id="ocBannerRecommended" style="display:none;">
|
|
1295
|
+
<div class="openclaw-banner-title" style="margin-bottom:8px;">
|
|
1296
|
+
<i class="fa-solid fa-wand-magic-sparkles" style="color:var(--accent-purple); margin-right:6px;"></i>
|
|
1297
|
+
Agentic Setup — let an AI handle this
|
|
1296
1298
|
</div>
|
|
1297
|
-
<div class="openclaw-banner-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1299
|
+
<div class="openclaw-banner-desc" style="margin-bottom:14px;">Pick your agent. Copy the prompt. Paste it in. Done.</div>
|
|
1300
|
+
|
|
1301
|
+
<!-- Runtime tabs -->
|
|
1302
|
+
<div style="display:flex; gap:6px; flex-wrap:wrap; margin-bottom:12px;" id="agentRuntimeTabs">
|
|
1303
|
+
<button class="btn btn-sm agent-runtime-tab active" data-runtime="openclaw" onclick="selectAgentRuntime('openclaw', this)" style="font-size:0.65rem;">
|
|
1304
|
+
<i class="fa-solid fa-wand-magic-sparkles" style="margin-right:4px;"></i>OpenClaw
|
|
1305
|
+
</button>
|
|
1306
|
+
<button class="btn btn-sm agent-runtime-tab" data-runtime="claudecode" onclick="selectAgentRuntime('claudecode', this)" style="font-size:0.65rem;">
|
|
1307
|
+
<i class="fa-solid fa-terminal" style="margin-right:4px;"></i>Claude Code
|
|
1308
|
+
</button>
|
|
1309
|
+
<button class="btn btn-sm agent-runtime-tab" data-runtime="codex" onclick="selectAgentRuntime('codex', this)" style="font-size:0.65rem;">
|
|
1310
|
+
<i class="fa-solid fa-code" style="margin-right:4px;"></i>Codex CLI
|
|
1311
|
+
</button>
|
|
1312
|
+
<button class="btn btn-sm agent-runtime-tab" data-runtime="perplexity" onclick="selectAgentRuntime('perplexity', this)" style="font-size:0.65rem;">
|
|
1313
|
+
<i class="fa-solid fa-magnifying-glass" style="margin-right:4px;"></i>Perplexity
|
|
1314
|
+
</button>
|
|
1315
|
+
</div>
|
|
1316
|
+
|
|
1317
|
+
<!-- Runtime panels -->
|
|
1318
|
+
<div id="agentRuntime-openclaw" class="agent-runtime-panel">
|
|
1319
|
+
<div style="font-size:0.68rem; color:var(--text-muted); margin-bottom:8px;">OpenClaw is running — it can guide setup directly. Run this in your terminal first:</div>
|
|
1320
|
+
<div style="padding:8px 10px; background:rgba(10,10,10,0.5); border:1px solid var(--border-subtle); border-radius:var(--radius); font-family:var(--font-mono); font-size:0.68rem; color:var(--text-secondary); display:flex; align-items:center; gap:8px; margin-bottom:8px;">
|
|
1301
1321
|
<span style="color:var(--text-muted);">$</span>
|
|
1302
1322
|
<span id="clawhubCmd">clawhub install ukkometa/seo-intel</span>
|
|
1303
|
-
<button class="btn btn-sm" style="margin-left:auto; padding:3px 8px; font-size:0.
|
|
1323
|
+
<button class="btn btn-sm" style="margin-left:auto; padding:3px 8px; font-size:0.6rem;" onclick="navigator.clipboard.writeText('clawhub install ukkometa/seo-intel');this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500);">Copy</button>
|
|
1324
|
+
</div>
|
|
1325
|
+
<div style="font-size:0.65rem; color:var(--text-muted); margin-bottom:8px;">Or paste this into your OpenClaw chat:</div>
|
|
1326
|
+
<div style="position:relative; padding:8px 10px; background:rgba(10,10,10,0.5); border:1px solid var(--border-subtle); border-radius:var(--radius); font-family:var(--font-mono); font-size:0.62rem; color:var(--text-secondary); line-height:1.6; margin-bottom:10px;">
|
|
1327
|
+
<div id="oc-prompt">Set up SEO Intel on my machine.
|
|
1328
|
+
Check dependencies, install Ollama if needed, recommend a model based on my VRAM, configure a project with my target site, and run a test crawl.</div>
|
|
1329
|
+
<button class="btn btn-sm" style="position:absolute; top:6px; right:6px; padding:2px 6px; font-size:0.5rem;" onclick="navigator.clipboard.writeText(document.getElementById('oc-prompt').textContent.trim());this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500);">Copy</button>
|
|
1304
1330
|
</div>
|
|
1305
1331
|
<div class="openclaw-banner-actions">
|
|
1306
|
-
<button class="btn btn-gold" onclick="startAgentSetup()"><i class="fa-solid fa-play"></i> Start Setup</button>
|
|
1307
|
-
<button class="btn" onclick="continueManualSetup()"><i class="fa-solid fa-list-check"></i>
|
|
1332
|
+
<button class="btn btn-gold" onclick="startAgentSetup()"><i class="fa-solid fa-play"></i> Start Agent Setup</button>
|
|
1333
|
+
<button class="btn" onclick="continueManualSetup()"><i class="fa-solid fa-list-check"></i> Manual</button>
|
|
1308
1334
|
</div>
|
|
1309
1335
|
</div>
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
<
|
|
1314
|
-
<
|
|
1315
|
-
|
|
1316
|
-
|
|
1336
|
+
|
|
1337
|
+
<div id="agentRuntime-claudecode" class="agent-runtime-panel" style="display:none;">
|
|
1338
|
+
<div style="font-size:0.68rem; color:var(--text-muted); margin-bottom:8px;">Open Claude Code in your terminal (<code style="background:rgba(255,255,255,0.05);padding:1px 4px;border-radius:3px;">claude</code>) and paste this prompt:</div>
|
|
1339
|
+
<div style="position:relative; padding:8px 10px; background:rgba(10,10,10,0.5); border:1px solid var(--border-subtle); border-radius:var(--radius); font-family:var(--font-mono); font-size:0.62rem; color:var(--text-secondary); line-height:1.6; margin-bottom:8px;">
|
|
1340
|
+
<div id="cc-prompt">I'm setting up SEO Intel (npm package: seo-intel).
|
|
1341
|
+
Help me:
|
|
1342
|
+
1. Check Node.js 22.5+ is installed
|
|
1343
|
+
2. Install Ollama if missing (https://ollama.com)
|
|
1344
|
+
3. Pull a Qwen model matching my VRAM (run: system_profiler SPDisplaysDataType | grep VRAM)
|
|
1345
|
+
4. Create a config file at ./config/myproject.json with my target site
|
|
1346
|
+
5. Run: seo-intel crawl myproject
|
|
1347
|
+
6. Fix any errors that come up
|
|
1348
|
+
|
|
1349
|
+
Start by checking what's already installed.</div>
|
|
1350
|
+
<button class="btn btn-sm" style="position:absolute; top:6px; right:6px; padding:2px 6px; font-size:0.5rem;" onclick="navigator.clipboard.writeText(document.getElementById('cc-prompt').textContent.trim());this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500);">Copy</button>
|
|
1351
|
+
</div>
|
|
1352
|
+
<div style="font-size:0.62rem; color:var(--text-muted);">Run Claude Code with: <code style="background:rgba(255,255,255,0.05);padding:1px 4px;border-radius:3px;">claude --permission-mode bypassPermissions</code> for full access</div>
|
|
1317
1353
|
</div>
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1354
|
+
|
|
1355
|
+
<div id="agentRuntime-codex" class="agent-runtime-panel" style="display:none;">
|
|
1356
|
+
<div style="font-size:0.68rem; color:var(--text-muted); margin-bottom:8px;">Open Codex CLI (<code style="background:rgba(255,255,255,0.05);padding:1px 4px;border-radius:3px;">codex</code>) and paste this prompt:</div>
|
|
1357
|
+
<div style="position:relative; padding:8px 10px; background:rgba(10,10,10,0.5); border:1px solid var(--border-subtle); border-radius:var(--radius); font-family:var(--font-mono); font-size:0.62rem; color:var(--text-secondary); line-height:1.6; margin-bottom:8px;">
|
|
1358
|
+
<div id="cx-prompt">Set up the seo-intel npm CLI tool on this machine.
|
|
1359
|
+
Tasks:
|
|
1360
|
+
1. Verify Node.js 22.5+ (install via nvm if needed)
|
|
1361
|
+
2. Install Ollama (https://ollama.com) if not present
|
|
1362
|
+
3. Pull qwen3.5:9b or smaller if VRAM < 6GB
|
|
1363
|
+
4. Create ./config/myproject.json — ask me for my target domain and up to 3 competitor domains
|
|
1364
|
+
5. Add GEMINI_API_KEY or ANTHROPIC_API_KEY to .env if I have one
|
|
1365
|
+
6. Run: seo-intel crawl myproject
|
|
1366
|
+
7. Fix any errors
|
|
1367
|
+
|
|
1368
|
+
Use full disk access. Check what's installed before proceeding.</div>
|
|
1369
|
+
<button class="btn btn-sm" style="position:absolute; top:6px; right:6px; padding:2px 6px; font-size:0.5rem;" onclick="navigator.clipboard.writeText(document.getElementById('cx-prompt').textContent.trim());this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500);">Copy</button>
|
|
1321
1370
|
</div>
|
|
1371
|
+
<div style="font-size:0.62rem; color:var(--text-muted);">Codex config: <code style="background:rgba(255,255,255,0.05);padding:1px 4px;border-radius:3px;">sandbox_mode = "danger-full-access"</code> recommended for install tasks</div>
|
|
1372
|
+
</div>
|
|
1373
|
+
|
|
1374
|
+
<div id="agentRuntime-perplexity" class="agent-runtime-panel" style="display:none;">
|
|
1375
|
+
<div style="font-size:0.68rem; color:var(--text-muted); margin-bottom:8px;">Open Perplexity Computer and paste this prompt:</div>
|
|
1376
|
+
<div style="position:relative; padding:8px 10px; background:rgba(10,10,10,0.5); border:1px solid var(--border-subtle); border-radius:var(--radius); font-family:var(--font-mono); font-size:0.62rem; color:var(--text-secondary); line-height:1.6; margin-bottom:8px;">
|
|
1377
|
+
<div id="pp-prompt">I want to set up a local SEO analysis tool called SEO Intel.
|
|
1378
|
+
It's installed via: npm install -g seo-intel
|
|
1379
|
+
|
|
1380
|
+
Please help me:
|
|
1381
|
+
1. Check that Node.js 22.5+ is installed on my machine
|
|
1382
|
+
2. Install Ollama (ollama.com) if it's not there
|
|
1383
|
+
3. Download a Qwen AI model that fits my machine's RAM
|
|
1384
|
+
4. Create a project config file pointing at my website and competitors
|
|
1385
|
+
5. Run the first crawl and show me the results
|
|
1386
|
+
|
|
1387
|
+
Ask me for my website URL before starting.</div>
|
|
1388
|
+
<button class="btn btn-sm" style="position:absolute; top:6px; right:6px; padding:2px 6px; font-size:0.5rem;" onclick="navigator.clipboard.writeText(document.getElementById('pp-prompt').textContent.trim());this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500);">Copy</button>
|
|
1389
|
+
</div>
|
|
1390
|
+
<div style="font-size:0.62rem; color:var(--text-muted);">Works best with Perplexity Computer's full computer-use mode enabled</div>
|
|
1391
|
+
</div>
|
|
1392
|
+
</div>
|
|
1393
|
+
|
|
1394
|
+
<div id="ocBannerMinimal" style="display:none;">
|
|
1395
|
+
<div class="openclaw-banner-desc" style="color:var(--text-muted); font-size:0.72rem; margin-bottom:10px;">
|
|
1396
|
+
<strong style="color:var(--text-secondary);">Agent setup available.</strong> Pick a runtime below and copy the prompt:
|
|
1397
|
+
</div>
|
|
1398
|
+
<!-- Same runtime tabs, minimal version -->
|
|
1399
|
+
<div style="display:flex; gap:6px; flex-wrap:wrap; margin-bottom:10px;">
|
|
1400
|
+
<button class="btn btn-sm agent-runtime-tab-min active" data-runtime="claudecode" onclick="selectAgentRuntimeMin('claudecode', this)" style="font-size:0.62rem;"><i class="fa-solid fa-terminal" style="margin-right:3px;"></i>Claude Code</button>
|
|
1401
|
+
<button class="btn btn-sm agent-runtime-tab-min" data-runtime="codex" onclick="selectAgentRuntimeMin('codex', this)" style="font-size:0.62rem;"><i class="fa-solid fa-code" style="margin-right:3px;"></i>Codex CLI</button>
|
|
1402
|
+
<button class="btn btn-sm agent-runtime-tab-min" data-runtime="perplexity" onclick="selectAgentRuntimeMin('perplexity', this)" style="font-size:0.62rem;"><i class="fa-solid fa-magnifying-glass" style="margin-right:3px;"></i>Perplexity</button>
|
|
1403
|
+
<button class="btn btn-sm agent-runtime-tab-min" data-runtime="openclaw" onclick="selectAgentRuntimeMin('openclaw', this)" style="font-size:0.62rem;"><i class="fa-solid fa-wand-magic-sparkles" style="margin-right:3px;"></i>OpenClaw</button>
|
|
1404
|
+
</div>
|
|
1405
|
+
<div id="minRuntime-claudecode" class="min-runtime-panel" style="position:relative; padding:7px 9px; background:rgba(10,10,10,0.5); border:1px solid var(--border-subtle); border-radius:var(--radius); font-family:var(--font-mono); font-size:0.6rem; color:var(--text-secondary); line-height:1.5;">
|
|
1406
|
+
<div>Set up seo-intel: check Node 22.5+, install Ollama, pull qwen3.5:9b, create config, run crawl.</div>
|
|
1407
|
+
<button class="btn btn-sm" style="position:absolute; top:4px; right:4px; padding:2px 5px; font-size:0.48rem;" onclick="navigator.clipboard.writeText(this.previousElementSibling.textContent.trim());this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500);">Copy</button>
|
|
1408
|
+
</div>
|
|
1409
|
+
<div id="minRuntime-codex" class="min-runtime-panel" style="display:none; position:relative; padding:7px 9px; background:rgba(10,10,10,0.5); border:1px solid var(--border-subtle); border-radius:var(--radius); font-family:var(--font-mono); font-size:0.6rem; color:var(--text-secondary); line-height:1.5;">
|
|
1410
|
+
<div>Install seo-intel deps (Node 22.5+, Ollama, qwen3.5:9b), create project config, run: seo-intel crawl myproject. Use full disk access.</div>
|
|
1411
|
+
<button class="btn btn-sm" style="position:absolute; top:4px; right:4px; padding:2px 5px; font-size:0.48rem;" onclick="navigator.clipboard.writeText(this.previousElementSibling.textContent.trim());this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500);">Copy</button>
|
|
1412
|
+
</div>
|
|
1413
|
+
<div id="minRuntime-perplexity" class="min-runtime-panel" style="display:none; position:relative; padding:7px 9px; background:rgba(10,10,10,0.5); border:1px solid var(--border-subtle); border-radius:var(--radius); font-family:var(--font-mono); font-size:0.6rem; color:var(--text-secondary); line-height:1.5;">
|
|
1414
|
+
<div>Help me set up SEO Intel local SEO tool: install Node.js 22.5+, Ollama, download a Qwen model, create config for my website. Ask for my URL.</div>
|
|
1415
|
+
<button class="btn btn-sm" style="position:absolute; top:4px; right:4px; padding:2px 5px; font-size:0.48rem;" onclick="navigator.clipboard.writeText(this.previousElementSibling.textContent.trim());this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500);">Copy</button>
|
|
1416
|
+
</div>
|
|
1417
|
+
<div id="minRuntime-openclaw" class="min-runtime-panel" style="display:none; position:relative; padding:7px 9px; background:rgba(10,10,10,0.5); border:1px solid var(--border-subtle); border-radius:var(--radius); font-family:var(--font-mono); font-size:0.6rem; color:var(--text-secondary); line-height:1.5;">
|
|
1418
|
+
<div>clawhub install ukkometa/seo-intel</div>
|
|
1419
|
+
<button class="btn btn-sm" style="position:absolute; top:4px; right:4px; padding:2px 5px; font-size:0.48rem;" onclick="navigator.clipboard.writeText('clawhub install ukkometa/seo-intel');this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500);">Copy</button>
|
|
1322
1420
|
</div>
|
|
1323
1421
|
</div>
|
|
1324
1422
|
</div>
|
|
@@ -1338,10 +1436,15 @@ input::placeholder {
|
|
|
1338
1436
|
</div>
|
|
1339
1437
|
|
|
1340
1438
|
<!-- ─── Step 2: Model Selection ───────────────────────────────────────── -->
|
|
1341
|
-
<div class="step-panel" id="step2">
|
|
1342
|
-
<div style="
|
|
1439
|
+
<div class="step-panel" id="step2" style="max-width:none;">
|
|
1440
|
+
<div style="position:relative;">
|
|
1343
1441
|
<div class="card" style="margin-bottom:0; min-width:0;">
|
|
1344
|
-
<
|
|
1442
|
+
<div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:4px;">
|
|
1443
|
+
<h2 style="margin-bottom:0;"><i class="fa-solid fa-microchip"></i> Model Selection</h2>
|
|
1444
|
+
<button class="btn btn-sm" onclick="document.getElementById('openclawFloating').style.display=''" style="font-size:0.65rem; color:var(--accent-purple); border-color:rgba(124,109,235,0.3); background:rgba(124,109,235,0.06);">
|
|
1445
|
+
<i class="fa-solid fa-wand-magic-sparkles" style="margin-right:4px;"></i>OpenClaw
|
|
1446
|
+
</button>
|
|
1447
|
+
</div>
|
|
1345
1448
|
|
|
1346
1449
|
<!-- Ollama Hosts -->
|
|
1347
1450
|
<div id="ollamaHostsPanel" style="margin-bottom:16px; padding:12px 14px; background:var(--bg-card); border:1px solid var(--border-card); border-radius:var(--radius);">
|
|
@@ -1443,6 +1546,122 @@ input::placeholder {
|
|
|
1443
1546
|
</div>
|
|
1444
1547
|
</div>
|
|
1445
1548
|
</div>
|
|
1549
|
+
<!-- ─── Cloud Analysis column ─────────────────────────────────────── -->
|
|
1550
|
+
<div class="model-section" id="cloudAnalysisSection">
|
|
1551
|
+
<h3><i class="fa-solid fa-cloud"></i> Cloud Analysis</h3>
|
|
1552
|
+
<p class="section-note">Use cloud frontier models for analysis. Add your API key to .env</p>
|
|
1553
|
+
<!-- Cloud model cards -->
|
|
1554
|
+
<div id="cloudAnalysisModels">
|
|
1555
|
+
<!-- Gemini 3.1 Pro -->
|
|
1556
|
+
<div class="model-radio-card cloud-model" data-model="gemini-3.1-pro" data-provider="gemini" data-envvar="GEMINI_API_KEY" onclick="selectCloudAnalysisModel(this)">
|
|
1557
|
+
<div style="display:flex; justify-content:space-between; align-items:flex-start;">
|
|
1558
|
+
<div>
|
|
1559
|
+
<div style="font-weight:600; font-size:0.82rem; color:var(--text-primary);">gemini-3.1-pro</div>
|
|
1560
|
+
<div style="font-size:0.68rem; color:var(--text-muted); margin-top:2px;">Google Gemini</div>
|
|
1561
|
+
</div>
|
|
1562
|
+
<span style="font-size:0.55rem; font-weight:700; letter-spacing:0.06em; padding:2px 6px; border-radius:4px; background:rgba(232,213,163,0.15); color:#e8d5a3;">BEST</span>
|
|
1563
|
+
</div>
|
|
1564
|
+
<div style="font-size:0.65rem; color:var(--text-muted); margin-top:6px;">Highest quality Gemini — best for deep competitive analysis</div>
|
|
1565
|
+
<div class="cloud-privacy-note"><i class="fa-solid fa-key"></i> GEMINI_API_KEY</div>
|
|
1566
|
+
</div>
|
|
1567
|
+
<!-- Claude Sonnet 4.6 -->
|
|
1568
|
+
<div class="model-radio-card cloud-model" data-model="claude-sonnet-4-6" data-provider="anthropic" data-envvar="ANTHROPIC_API_KEY" onclick="selectCloudAnalysisModel(this)">
|
|
1569
|
+
<div style="display:flex; justify-content:space-between; align-items:flex-start;">
|
|
1570
|
+
<div>
|
|
1571
|
+
<div style="font-weight:600; font-size:0.82rem; color:var(--text-primary);">claude-sonnet-4-6</div>
|
|
1572
|
+
<div style="font-size:0.68rem; color:var(--text-muted); margin-top:2px;">Anthropic</div>
|
|
1573
|
+
</div>
|
|
1574
|
+
<span style="font-size:0.55rem; font-weight:700; letter-spacing:0.06em; padding:2px 6px; border-radius:4px; background:rgba(96,165,250,0.15); color:#60a5fa;">FAST</span>
|
|
1575
|
+
</div>
|
|
1576
|
+
<div style="font-size:0.65rem; color:var(--text-muted); margin-top:6px;">Best cost/quality balance — fast and reliable</div>
|
|
1577
|
+
<div class="cloud-privacy-note"><i class="fa-solid fa-key"></i> ANTHROPIC_API_KEY</div>
|
|
1578
|
+
</div>
|
|
1579
|
+
<!-- Claude Opus 4.6 -->
|
|
1580
|
+
<div class="model-radio-card cloud-model" data-model="claude-opus-4-6" data-provider="anthropic" data-envvar="ANTHROPIC_API_KEY" onclick="selectCloudAnalysisModel(this)">
|
|
1581
|
+
<div style="display:flex; justify-content:space-between; align-items:flex-start;">
|
|
1582
|
+
<div>
|
|
1583
|
+
<div style="font-weight:600; font-size:0.82rem; color:var(--text-primary);">claude-opus-4-6</div>
|
|
1584
|
+
<div style="font-size:0.68rem; color:var(--text-muted); margin-top:2px;">Anthropic</div>
|
|
1585
|
+
</div>
|
|
1586
|
+
<span style="font-size:0.55rem; font-weight:700; letter-spacing:0.06em; padding:2px 6px; border-radius:4px; background:rgba(124,109,235,0.15); color:#a78bfa;">DEEP</span>
|
|
1587
|
+
</div>
|
|
1588
|
+
<div style="font-size:0.65rem; color:var(--text-muted); margin-top:6px;">Deepest analysis, highest quality — slower</div>
|
|
1589
|
+
<div class="cloud-privacy-note"><i class="fa-solid fa-key"></i> ANTHROPIC_API_KEY</div>
|
|
1590
|
+
</div>
|
|
1591
|
+
<!-- GPT-5.4 -->
|
|
1592
|
+
<div class="model-radio-card cloud-model" data-model="gpt-5.4" data-provider="openai" data-envvar="OPENAI_API_KEY" onclick="selectCloudAnalysisModel(this)">
|
|
1593
|
+
<div style="display:flex; justify-content:space-between; align-items:flex-start;">
|
|
1594
|
+
<div>
|
|
1595
|
+
<div style="font-weight:600; font-size:0.82rem; color:var(--text-primary);">gpt-5.4</div>
|
|
1596
|
+
<div style="font-size:0.68rem; color:var(--text-muted); margin-top:2px;">OpenAI</div>
|
|
1597
|
+
</div>
|
|
1598
|
+
<span style="font-size:0.55rem; font-weight:700; letter-spacing:0.06em; padding:2px 6px; border-radius:4px; background:rgba(156,163,175,0.15); color:#9ca3af;">SOLID</span>
|
|
1599
|
+
</div>
|
|
1600
|
+
<div style="font-size:0.65rem; color:var(--text-muted); margin-top:6px;">Reliable, broad knowledge — solid all-around</div>
|
|
1601
|
+
<div class="cloud-privacy-note"><i class="fa-solid fa-key"></i> OPENAI_API_KEY</div>
|
|
1602
|
+
</div>
|
|
1603
|
+
<!-- DeepSeek R1 -->
|
|
1604
|
+
<div class="model-radio-card cloud-model" data-model="deepseek-r1" data-provider="deepseek" data-envvar="DEEPSEEK_API_KEY" onclick="selectCloudAnalysisModel(this)">
|
|
1605
|
+
<div style="display:flex; justify-content:space-between; align-items:flex-start;">
|
|
1606
|
+
<div>
|
|
1607
|
+
<div style="font-weight:600; font-size:0.82rem; color:var(--text-primary);">deepseek-r1</div>
|
|
1608
|
+
<div style="font-size:0.68rem; color:var(--text-muted); margin-top:2px;">DeepSeek</div>
|
|
1609
|
+
</div>
|
|
1610
|
+
<span style="font-size:0.55rem; font-weight:700; letter-spacing:0.06em; padding:2px 6px; border-radius:4px; background:rgba(52,211,153,0.15); color:#34d399;">BUDGET</span>
|
|
1611
|
+
</div>
|
|
1612
|
+
<div style="font-size:0.65rem; color:var(--text-muted); margin-top:6px;">Best reasoning model at budget price</div>
|
|
1613
|
+
<div class="cloud-privacy-note"><i class="fa-solid fa-key"></i> DEEPSEEK_API_KEY</div>
|
|
1614
|
+
</div>
|
|
1615
|
+
</div>
|
|
1616
|
+
<!-- API Key input area (shown when a cloud card is selected) -->
|
|
1617
|
+
<div id="cloudKeyArea" style="display:none; margin-top:12px; padding:12px; background:rgba(124,109,235,0.04); border:1px solid rgba(124,109,235,0.18); border-radius:var(--radius);">
|
|
1618
|
+
<label style="font-size:0.7rem; font-weight:600; color:var(--text-secondary); display:block; margin-bottom:6px;"><i class="fa-solid fa-key" style="color:var(--accent-purple); margin-right:5px;"></i> API Key</label>
|
|
1619
|
+
<div style="display:flex; gap:6px; align-items:center; margin-bottom:6px;">
|
|
1620
|
+
<input type="password" id="cloudApiKeyInput" placeholder="" style="flex:1; background:var(--bg-elevated); border:1px solid var(--border-subtle); border-radius:var(--radius); padding:6px 8px; color:var(--text-primary); font-family:var(--font-mono); font-size:0.7rem;">
|
|
1621
|
+
<button class="btn btn-sm" onclick="saveCloudApiKeyFromUI()" style="white-space:nowrap; padding:4px 10px; font-size:0.62rem;"><i class="fa-solid fa-floppy-disk"></i> Save to .env</button>
|
|
1622
|
+
</div>
|
|
1623
|
+
<p id="cloudKeySaveStatus" style="font-size:0.62rem; color:var(--text-muted); min-height:1em;"></p>
|
|
1624
|
+
<p style="font-size:0.6rem; color:var(--text-muted); margin-top:4px;">Or use <strong style="color:var(--accent-purple);">OpenClaw</strong> to skip API key management entirely</p>
|
|
1625
|
+
</div>
|
|
1626
|
+
</div>
|
|
1627
|
+
|
|
1628
|
+
|
|
1629
|
+
<p style="font-size:0.72rem; color:var(--text-muted); line-height:1.6; margin-bottom:12px;">
|
|
1630
|
+
Route analysis through frontier models. OpenClaw manages API keys, OAuth, and model routing automatically.
|
|
1631
|
+
</p>
|
|
1632
|
+
|
|
1633
|
+
<div style="font-size:0.68rem; color:var(--text-secondary); margin-bottom:12px;">
|
|
1634
|
+
<div style="display:flex; align-items:center; gap:6px; margin-bottom:6px;">
|
|
1635
|
+
<i class="fa-solid fa-check" style="color:var(--accent-purple); font-size:0.6rem; width:12px;"></i>
|
|
1636
|
+
Claude Opus 4.6
|
|
1637
|
+
</div>
|
|
1638
|
+
<div style="display:flex; align-items:center; gap:6px; margin-bottom:6px;">
|
|
1639
|
+
<i class="fa-solid fa-check" style="color:var(--accent-purple); font-size:0.6rem; width:12px;"></i>
|
|
1640
|
+
Gemini 3.1 Pro
|
|
1641
|
+
</div>
|
|
1642
|
+
<div style="display:flex; align-items:center; gap:6px; margin-bottom:6px;">
|
|
1643
|
+
<i class="fa-solid fa-check" style="color:var(--accent-purple); font-size:0.6rem; width:12px;"></i>
|
|
1644
|
+
GPT-5.4
|
|
1645
|
+
</div>
|
|
1646
|
+
</div>
|
|
1647
|
+
|
|
1648
|
+
<p style="font-size:0.62rem; color:var(--text-muted); line-height:1.5; margin-bottom:8px;">
|
|
1649
|
+
No .env keys needed. OAuth-based model access means the pipeline test may show "no API key" — this is normal when using OpenClaw.
|
|
1650
|
+
</p>
|
|
1651
|
+
|
|
1652
|
+
<div style="padding:6px 8px; background:rgba(10,10,10,0.5); border:1px solid var(--border-subtle); border-radius:var(--radius); font-family:var(--font-mono); font-size:0.65rem; color:var(--text-secondary); display:flex; align-items:center; gap:6px; margin-bottom:8px;">
|
|
1653
|
+
<span style="color:var(--text-muted);">$</span>
|
|
1654
|
+
<span>clawhub install ukkometa/seo-intel</span>
|
|
1655
|
+
<button class="btn btn-sm" style="margin-left:auto; padding:2px 6px; font-size:0.55rem;" onclick="navigator.clipboard.writeText('clawhub install ukkometa/seo-intel');this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500);">Copy</button>
|
|
1656
|
+
</div>
|
|
1657
|
+
|
|
1658
|
+
<p style="font-size:0.6rem; color:var(--text-muted); margin-bottom:6px;">Or paste into OpenClaw chat:</p>
|
|
1659
|
+
<div style="padding:8px 10px; background:rgba(10,10,10,0.5); border:1px solid var(--border-subtle); border-radius:var(--radius); font-family:var(--font-mono); font-size:0.6rem; color:var(--text-secondary); line-height:1.6; position:relative;">
|
|
1660
|
+
<div style="white-space:pre;">Set up SEO Intel cloud analysis.
|
|
1661
|
+
Use Gemini for extraction, Claude for analysis.
|
|
1662
|
+
Configure API keys and run a test crawl.</div>
|
|
1663
|
+
<button class="btn btn-sm" style="position:absolute; top:6px; right:6px; padding:2px 6px; font-size:0.5rem;" onclick="navigator.clipboard.writeText('Set up SEO Intel cloud analysis.\nUse Gemini for extraction, Claude for analysis.\nConfigure API keys and run a test crawl.');this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500);">Copy</button>
|
|
1664
|
+
</div>
|
|
1446
1665
|
</div>
|
|
1447
1666
|
<!-- Unified upgrade card (free tier only) -->
|
|
1448
1667
|
<div id="unifiedUpgrade" style="display:none; position:relative; margin-top:0; padding:48px 32px; border:1px solid rgba(232,213,163,0.15); border-radius:var(--radius); overflow:hidden; text-align:center;">
|
|
@@ -1475,8 +1694,9 @@ input::placeholder {
|
|
|
1475
1694
|
</div>
|
|
1476
1695
|
</div>
|
|
1477
1696
|
|
|
1478
|
-
<!-- OpenClaw sidebar
|
|
1479
|
-
<div class="card" style="margin-bottom:0; position:
|
|
1697
|
+
<!-- OpenClaw floating sidebar -->
|
|
1698
|
+
<div class="card" id="openclawFloating" style="margin-bottom:0; position:fixed; top:80px; right:20px; width:240px; z-index:50; box-shadow:0 8px 40px rgba(0,0,0,0.5); border-color:rgba(124,109,235,0.3);">
|
|
1699
|
+
<button onclick="document.getElementById('openclawFloating').style.display='none'" style="position:absolute;top:8px;right:8px;background:none;border:none;color:var(--text-muted);cursor:pointer;font-size:0.7rem;"><i class="fa-solid fa-xmark"></i></button>
|
|
1480
1700
|
<div style="display:flex; align-items:center; gap:10px; margin-bottom:12px;">
|
|
1481
1701
|
<svg width="22" height="22" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1482
1702
|
<circle cx="14" cy="14" r="13" stroke="var(--accent-purple)" stroke-width="1.5" opacity="0.6"/>
|
|
@@ -1523,7 +1743,7 @@ Configure API keys and run a test crawl.</div>
|
|
|
1523
1743
|
</div>
|
|
1524
1744
|
</div>
|
|
1525
1745
|
|
|
1526
|
-
</div><!-- close grid -->
|
|
1746
|
+
</div><!-- close step2 outer grid -->
|
|
1527
1747
|
</div>
|
|
1528
1748
|
|
|
1529
1749
|
<!-- ─── Step 3: Project Configuration ─────────────────────────────────── -->
|
|
@@ -2987,6 +3207,22 @@ Configure API keys and run a test crawl.</div>
|
|
|
2987
3207
|
let agentHistory = [];
|
|
2988
3208
|
let agentBusy = false;
|
|
2989
3209
|
|
|
3210
|
+
window.selectAgentRuntime = function(runtime, btn) {
|
|
3211
|
+
document.querySelectorAll('.agent-runtime-tab').forEach(b => b.classList.remove('active'));
|
|
3212
|
+
btn.classList.add('active');
|
|
3213
|
+
document.querySelectorAll('.agent-runtime-panel').forEach(p => p.style.display = 'none');
|
|
3214
|
+
const panel = document.getElementById('agentRuntime-' + runtime);
|
|
3215
|
+
if (panel) panel.style.display = '';
|
|
3216
|
+
};
|
|
3217
|
+
|
|
3218
|
+
window.selectAgentRuntimeMin = function(runtime, btn) {
|
|
3219
|
+
document.querySelectorAll('.agent-runtime-tab-min').forEach(b => b.classList.remove('active'));
|
|
3220
|
+
btn.classList.add('active');
|
|
3221
|
+
document.querySelectorAll('.min-runtime-panel').forEach(p => p.style.display = 'none');
|
|
3222
|
+
const panel = document.getElementById('minRuntime-' + runtime);
|
|
3223
|
+
if (panel) panel.style.display = '';
|
|
3224
|
+
};
|
|
3225
|
+
|
|
2990
3226
|
window.startAgentSetup = function() {
|
|
2991
3227
|
// Hide wizard steps, show agent panel
|
|
2992
3228
|
document.querySelector('.wizard-body').style.display = 'none';
|
|
@@ -3152,6 +3388,90 @@ Configure API keys and run a test crawl.</div>
|
|
|
3152
3388
|
btn.disabled = false;
|
|
3153
3389
|
};
|
|
3154
3390
|
|
|
3391
|
+
// ── Cloud Analysis Column ─────────────────────────────────────────────
|
|
3392
|
+
|
|
3393
|
+
window.selectCloudAnalysisModel = function(card) {
|
|
3394
|
+
const modelId = card.dataset.modelId;
|
|
3395
|
+
const provider = card.dataset.provider;
|
|
3396
|
+
const envVar = card.dataset.envVar;
|
|
3397
|
+
const placeholder = card.dataset.keyPlaceholder || '';
|
|
3398
|
+
|
|
3399
|
+
// Set global state
|
|
3400
|
+
window.selectedAnalysisModel = 'cloud:' + modelId;
|
|
3401
|
+
window.selectedCloudProvider = provider;
|
|
3402
|
+
|
|
3403
|
+
// Deselect all local Ollama analysis model cards
|
|
3404
|
+
document.querySelectorAll('#analysisModels .model-radio-card').forEach(c => c.classList.remove('selected'));
|
|
3405
|
+
|
|
3406
|
+
// Deselect other cloud cards, select this one
|
|
3407
|
+
document.querySelectorAll('#cloudAnalysisModels .model-radio-card').forEach(c => c.classList.remove('selected'));
|
|
3408
|
+
card.classList.add('selected');
|
|
3409
|
+
|
|
3410
|
+
// Hide analysis pull row and old cloud hint
|
|
3411
|
+
const pullRow = document.getElementById('analysisPullRow');
|
|
3412
|
+
const cloudHint = document.getElementById('analysisCloudHint');
|
|
3413
|
+
if (pullRow) pullRow.style.display = 'none';
|
|
3414
|
+
if (cloudHint) cloudHint.style.display = 'none';
|
|
3415
|
+
|
|
3416
|
+
// Show key input area with correct env var placeholder
|
|
3417
|
+
const keyArea = document.getElementById('cloudKeyArea');
|
|
3418
|
+
const keyInput = document.getElementById('cloudApiKeyInput');
|
|
3419
|
+
const saveStatus = document.getElementById('cloudKeySaveStatus');
|
|
3420
|
+
if (keyArea) keyArea.style.display = 'block';
|
|
3421
|
+
if (keyInput) {
|
|
3422
|
+
keyInput.placeholder = placeholder;
|
|
3423
|
+
keyInput.dataset.envVar = envVar;
|
|
3424
|
+
keyInput.dataset.provider = provider;
|
|
3425
|
+
}
|
|
3426
|
+
if (saveStatus) saveStatus.textContent = '';
|
|
3427
|
+
|
|
3428
|
+
// Also update state.selectedAnalysis for consistency with existing code
|
|
3429
|
+
if (typeof state !== 'undefined') state.selectedAnalysis = 'cloud:' + modelId;
|
|
3430
|
+
};
|
|
3431
|
+
|
|
3432
|
+
window.saveCloudApiKeyFromUI = function() {
|
|
3433
|
+
const keyInput = document.getElementById('cloudApiKeyInput');
|
|
3434
|
+
const saveStatus = document.getElementById('cloudKeySaveStatus');
|
|
3435
|
+
if (!keyInput || !saveStatus) return;
|
|
3436
|
+
const envVar = keyInput.dataset.envVar;
|
|
3437
|
+
const provider = keyInput.dataset.provider;
|
|
3438
|
+
const value = keyInput.value.trim();
|
|
3439
|
+
if (!value) { saveStatus.textContent = 'Enter an API key first.'; saveStatus.style.color = 'var(--color-danger)'; return; }
|
|
3440
|
+
saveCloudApiKey(provider, envVar, value);
|
|
3441
|
+
};
|
|
3442
|
+
|
|
3443
|
+
window.saveCloudApiKey = async function(provider, envVar, keyValue) {
|
|
3444
|
+
const saveStatus = document.getElementById('cloudKeySaveStatus');
|
|
3445
|
+
if (saveStatus) { saveStatus.textContent = 'Saving…'; saveStatus.style.color = 'var(--text-muted)'; }
|
|
3446
|
+
try {
|
|
3447
|
+
const res = await fetch('/api/setup/save-env', {
|
|
3448
|
+
method: 'POST',
|
|
3449
|
+
headers: { 'Content-Type': 'application/json' },
|
|
3450
|
+
body: JSON.stringify({ key: envVar, value: keyValue }),
|
|
3451
|
+
});
|
|
3452
|
+
const data = await res.json();
|
|
3453
|
+
if (!res.ok) throw new Error(data.error || 'Save failed');
|
|
3454
|
+
if (saveStatus) { saveStatus.textContent = '✓ Saved to .env'; saveStatus.style.color = 'var(--color-success)'; }
|
|
3455
|
+
} catch (err) {
|
|
3456
|
+
if (saveStatus) { saveStatus.textContent = err.message; saveStatus.style.color = 'var(--color-danger)'; }
|
|
3457
|
+
}
|
|
3458
|
+
};
|
|
3459
|
+
|
|
3460
|
+
// Patch: selecting a local Ollama analysis model should deselect any cloud card
|
|
3461
|
+
const _origSelectAnalysisModel = typeof selectAnalysisModel !== 'undefined' ? selectAnalysisModel : null;
|
|
3462
|
+
// Hook into the cloud deselect when local analysis cards are clicked via delegated event
|
|
3463
|
+
document.addEventListener('click', function(e) {
|
|
3464
|
+
const card = e.target.closest('#analysisModels .model-radio-card');
|
|
3465
|
+
if (card) {
|
|
3466
|
+
// Deselect cloud cards
|
|
3467
|
+
document.querySelectorAll('#cloudAnalysisModels .model-radio-card').forEach(c => c.classList.remove('selected'));
|
|
3468
|
+
const keyArea = document.getElementById('cloudKeyArea');
|
|
3469
|
+
if (keyArea) keyArea.style.display = 'none';
|
|
3470
|
+
window.selectedAnalysisModel = undefined;
|
|
3471
|
+
window.selectedCloudProvider = undefined;
|
|
3472
|
+
}
|
|
3473
|
+
});
|
|
3474
|
+
|
|
3155
3475
|
// ── Init ──────────────────────────────────────────────────────────────
|
|
3156
3476
|
initStep3();
|
|
3157
3477
|
runSystemCheck();
|