seo-intel 1.1.4 → 1.1.5
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/Setup SEO Intel.command +12 -24
- package/package.json +1 -1
- package/reports/generate-html.js +56 -2
- package/server.js +9 -0
- package/setup/openclaw-bridge.js +29 -3
- package/setup/wizard.html +2 -0
package/Setup SEO Intel.command
CHANGED
|
@@ -1,27 +1,15 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
cd "$(dirname "$0")"
|
|
3
|
-
clear
|
|
2
|
+
cd "$(dirname "$0")"
|
|
4
3
|
echo ""
|
|
5
|
-
echo "
|
|
6
|
-
echo " Opening in your browser..."
|
|
4
|
+
echo " SEO Intel — Setup Wizard"
|
|
5
|
+
echo " Opening setup in your browser..."
|
|
7
6
|
echo ""
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
open "http://localhost:3000/setup" 2>/dev/null || xdg-open "http://localhost:3000/setup" 2>/dev/null
|
|
18
|
-
|
|
19
|
-
echo " Setup wizard is open at http://localhost:3000/setup"
|
|
20
|
-
echo " Keep this window open while using the wizard."
|
|
21
|
-
echo ""
|
|
22
|
-
read -n 1 -s -r -p " Press any key to stop the server and exit..."
|
|
23
|
-
|
|
24
|
-
# Clean up
|
|
25
|
-
if [ -n "$SERVER_PID" ]; then
|
|
26
|
-
kill $SERVER_PID 2>/dev/null
|
|
27
|
-
fi
|
|
7
|
+
node cli.js serve &
|
|
8
|
+
SERVER_PID=$!
|
|
9
|
+
# Wait for server to be ready
|
|
10
|
+
for i in {1..10}; do
|
|
11
|
+
sleep 1
|
|
12
|
+
if curl -s http://localhost:3000/ > /dev/null 2>&1; then break; fi
|
|
13
|
+
done
|
|
14
|
+
open "http://localhost:3000/setup"
|
|
15
|
+
wait $SERVER_PID
|
package/package.json
CHANGED
package/reports/generate-html.js
CHANGED
|
@@ -2188,6 +2188,53 @@ function buildHtmlTemplate(data, opts = {}) {
|
|
|
2188
2188
|
if (scopeIdx > -1 && parts[scopeIdx + 1]) extra.scope = parts[scopeIdx + 1];
|
|
2189
2189
|
runCommand(cmd, proj, extra);
|
|
2190
2190
|
});
|
|
2191
|
+
|
|
2192
|
+
// Autorun: if URL has ?autorun=setup-classic, fire seo-intel setup --classic via SSE
|
|
2193
|
+
(function() {
|
|
2194
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
2195
|
+
if (urlParams.get('autorun') === 'setup-classic') {
|
|
2196
|
+
// Remove the param so it doesn't re-trigger on refresh
|
|
2197
|
+
window.history.replaceState({}, '', window.location.pathname);
|
|
2198
|
+
// Wait a tick for the panel to be ready, then stream the command
|
|
2199
|
+
setTimeout(function() {
|
|
2200
|
+
if (!isServed) {
|
|
2201
|
+
appendLine('Not connected to server. Cannot run setup --classic automatically.', 'error');
|
|
2202
|
+
return;
|
|
2203
|
+
}
|
|
2204
|
+
running = true;
|
|
2205
|
+
status.textContent = 'running...';
|
|
2206
|
+
status.style.color = 'var(--color-warning)';
|
|
2207
|
+
appendLine('$ seo-intel setup --classic', 'cmd');
|
|
2208
|
+
const params = new URLSearchParams({ command: 'setup', classic: 'true' });
|
|
2209
|
+
eventSource = new EventSource('/api/terminal?' + params.toString());
|
|
2210
|
+
eventSource.onmessage = function(e) {
|
|
2211
|
+
try {
|
|
2212
|
+
const msg = JSON.parse(e.data);
|
|
2213
|
+
if (msg.type === 'stdout') appendLine(msg.data, 'stdout');
|
|
2214
|
+
else if (msg.type === 'stderr') appendLine(msg.data, 'stderr');
|
|
2215
|
+
else if (msg.type === 'error') { appendLine('Error: ' + msg.data, 'error'); }
|
|
2216
|
+
else if (msg.type === 'exit') {
|
|
2217
|
+
const code = msg.data?.code ?? msg.data;
|
|
2218
|
+
appendLine(code === 0 ? 'Done.' : 'Exited with code ' + code, code === 0 ? 'exit-ok' : 'exit-err');
|
|
2219
|
+
running = false;
|
|
2220
|
+
status.textContent = code === 0 ? 'done' : 'failed';
|
|
2221
|
+
status.style.color = code === 0 ? 'var(--color-success)' : 'var(--color-danger)';
|
|
2222
|
+
eventSource.close();
|
|
2223
|
+
eventSource = null;
|
|
2224
|
+
}
|
|
2225
|
+
} catch (_) {}
|
|
2226
|
+
};
|
|
2227
|
+
eventSource.onerror = function() {
|
|
2228
|
+
if (running) { appendLine('Connection lost.', 'error'); }
|
|
2229
|
+
running = false;
|
|
2230
|
+
status.textContent = 'disconnected';
|
|
2231
|
+
status.style.color = 'var(--color-danger)';
|
|
2232
|
+
eventSource?.close();
|
|
2233
|
+
eventSource = null;
|
|
2234
|
+
};
|
|
2235
|
+
}, 300);
|
|
2236
|
+
}
|
|
2237
|
+
})();
|
|
2191
2238
|
})();
|
|
2192
2239
|
</script>
|
|
2193
2240
|
|
|
@@ -3499,7 +3546,6 @@ function buildHtmlTemplate(data, opts = {}) {
|
|
|
3499
3546
|
};
|
|
3500
3547
|
|
|
3501
3548
|
window.stopJob = function() {
|
|
3502
|
-
if (!confirm('Stop the running job?')) return;
|
|
3503
3549
|
fetch('/api/stop', { method: 'POST' })
|
|
3504
3550
|
.then(function(r) { return r.json(); })
|
|
3505
3551
|
.then(function(data) {
|
|
@@ -3582,6 +3628,11 @@ function buildHtmlTemplate(data, opts = {}) {
|
|
|
3582
3628
|
dot.className = 'es-dot';
|
|
3583
3629
|
label.style.color = 'var(--color-success)';
|
|
3584
3630
|
label.textContent = 'Completed (' + (data.extracted || 0) + ' extracted' + (data.failed ? ', ' + data.failed + ' failed' : '') + ')';
|
|
3631
|
+
} else if (data.status === 'stopped') {
|
|
3632
|
+
panel.classList.remove('is-running', 'is-crashed');
|
|
3633
|
+
dot.className = 'es-dot';
|
|
3634
|
+
label.style.color = 'var(--accent-gold)';
|
|
3635
|
+
label.textContent = 'Stopped' + (data.extracted ? ' (' + data.extracted + ' extracted)' : '');
|
|
3585
3636
|
} else if (data.status === 'crashed') {
|
|
3586
3637
|
panel.classList.remove('is-running');
|
|
3587
3638
|
panel.classList.add('is-crashed');
|
|
@@ -4691,7 +4742,6 @@ function buildMultiHtmlTemplate(allProjectData) {
|
|
|
4691
4742
|
};
|
|
4692
4743
|
|
|
4693
4744
|
window.stopJob = function() {
|
|
4694
|
-
if (!confirm('Stop the running job?')) return;
|
|
4695
4745
|
fetch('/api/stop', { method: 'POST' })
|
|
4696
4746
|
.then(function(r) { return r.json(); })
|
|
4697
4747
|
.then(function(data) {
|
|
@@ -4750,6 +4800,10 @@ function buildMultiHtmlTemplate(allProjectData) {
|
|
|
4750
4800
|
panel.classList.remove('is-running', 'is-crashed');
|
|
4751
4801
|
dot.className = 'es-dot'; label.style.color = 'var(--color-success)';
|
|
4752
4802
|
label.textContent = 'Completed (' + (data.extracted || 0) + ' extracted)';
|
|
4803
|
+
} else if (data.status === 'stopped') {
|
|
4804
|
+
panel.classList.remove('is-running', 'is-crashed');
|
|
4805
|
+
dot.className = 'es-dot'; label.style.color = 'var(--accent-gold)';
|
|
4806
|
+
label.textContent = 'Stopped' + (data.extracted ? ' (' + data.extracted + ' extracted)' : '');
|
|
4753
4807
|
} else if (data.status === 'crashed') {
|
|
4754
4808
|
panel.classList.remove('is-running'); panel.classList.add('is-crashed');
|
|
4755
4809
|
dot.className = 'es-dot crashed'; label.style.color = 'var(--color-danger)';
|
package/server.js
CHANGED
|
@@ -354,6 +354,15 @@ async function handleRequest(req, res) {
|
|
|
354
354
|
if (e.code !== 'ESRCH') throw e;
|
|
355
355
|
// Already dead
|
|
356
356
|
}
|
|
357
|
+
// Update progress file to reflect stopped state
|
|
358
|
+
try {
|
|
359
|
+
writeFileSync(PROGRESS_FILE, JSON.stringify({
|
|
360
|
+
...progress,
|
|
361
|
+
status: 'stopped',
|
|
362
|
+
stopped_at: Date.now(),
|
|
363
|
+
updated_at: Date.now(),
|
|
364
|
+
}, null, 2));
|
|
365
|
+
} catch { /* best-effort */ }
|
|
357
366
|
json(res, 200, { stopped: true, pid: progress.pid, command: progress.command });
|
|
358
367
|
} catch (e) {
|
|
359
368
|
json(res, 500, { error: e.message });
|
package/setup/openclaw-bridge.js
CHANGED
|
@@ -66,13 +66,39 @@ async function askAgent(messages, opts = {}) {
|
|
|
66
66
|
*/
|
|
67
67
|
export async function isGatewayReady() {
|
|
68
68
|
try {
|
|
69
|
+
// Try to read token from env or openclaw config file
|
|
70
|
+
let token = process.env.OPENCLAW_TOKEN;
|
|
71
|
+
if (!token) {
|
|
72
|
+
try {
|
|
73
|
+
const configPath = join(process.env.HOME || '~', '.openclaw', 'openclaw.json');
|
|
74
|
+
const { readFileSync } = await import('fs');
|
|
75
|
+
const raw = readFileSync(configPath, 'utf8');
|
|
76
|
+
// Gateway auth token is a 48-char hex string in the gateway.auth block
|
|
77
|
+
const matches = [...raw.matchAll(/"token":\s*"([a-f0-9]{40,})"/g)];
|
|
78
|
+
if (matches.length > 0) token = matches[matches.length - 1][1];
|
|
79
|
+
} catch {}
|
|
80
|
+
}
|
|
81
|
+
if (!token) return false;
|
|
82
|
+
|
|
83
|
+
// Verify gateway is reachable via a lightweight chat completions ping
|
|
69
84
|
const controller = new AbortController();
|
|
70
|
-
const timeout = setTimeout(() => controller.abort(),
|
|
71
|
-
const res = await fetch(`${OPENCLAW_API}/v1/
|
|
85
|
+
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
86
|
+
const res = await fetch(`${OPENCLAW_API}/v1/chat/completions`, {
|
|
87
|
+
method: 'POST',
|
|
72
88
|
signal: controller.signal,
|
|
89
|
+
headers: {
|
|
90
|
+
'Authorization': `Bearer ${token}`,
|
|
91
|
+
'Content-Type': 'application/json',
|
|
92
|
+
},
|
|
93
|
+
body: JSON.stringify({
|
|
94
|
+
model: 'anthropic/claude-haiku-4-5',
|
|
95
|
+
messages: [{ role: 'user', content: 'ping' }],
|
|
96
|
+
max_tokens: 1,
|
|
97
|
+
}),
|
|
73
98
|
});
|
|
74
99
|
clearTimeout(timeout);
|
|
75
|
-
|
|
100
|
+
const ct = res.headers.get('content-type') || '';
|
|
101
|
+
return res.ok && ct.includes('application/json');
|
|
76
102
|
} catch {
|
|
77
103
|
return false;
|
|
78
104
|
}
|
package/setup/wizard.html
CHANGED
|
@@ -54,6 +54,7 @@ body {
|
|
|
54
54
|
max-width: var(--max-width);
|
|
55
55
|
margin: 0 auto 24px;
|
|
56
56
|
text-align: center;
|
|
57
|
+
position: relative;
|
|
57
58
|
}
|
|
58
59
|
.wizard-header h1 {
|
|
59
60
|
font-family: var(--font-display);
|
|
@@ -1172,6 +1173,7 @@ input::placeholder {
|
|
|
1172
1173
|
<div class="wizard-header">
|
|
1173
1174
|
<h1>SEO Intel</h1>
|
|
1174
1175
|
<div class="subtitle">Setup Wizard</div>
|
|
1176
|
+
<a href="http://localhost:3000/?autorun=setup-classic" title="Run setup in Terminal instead" style="position:absolute;top:14px;right:18px;font-size:0.68rem;color:var(--color-muted,#888);text-decoration:none;opacity:0.7;transition:opacity 0.15s;" onmouseover="this.style.opacity='1'" onmouseout="this.style.opacity='0.7'"><i class="fa-solid fa-terminal"></i> Terminal setup</a>
|
|
1175
1177
|
</div>
|
|
1176
1178
|
|
|
1177
1179
|
<!-- ═══════════════════════════════════════════════════════════════════════
|