astro-claw 1.0.3 → 1.0.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/package.json +1 -1
- package/slack-setup.js +70 -1
package/package.json
CHANGED
package/slack-setup.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import puppeteer from "puppeteer-core";
|
|
9
|
-
import { readFileSync } from "node:fs";
|
|
9
|
+
import { readFileSync, writeFileSync, unlinkSync } from "node:fs";
|
|
10
10
|
import { resolve, dirname } from "node:path";
|
|
11
11
|
import { fileURLToPath } from "node:url";
|
|
12
12
|
import { execSync } from "node:child_process";
|
|
@@ -14,6 +14,30 @@ import { homedir } from "node:os";
|
|
|
14
14
|
|
|
15
15
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
16
|
const MANIFEST_PATH = resolve(__dirname, "slack-manifest.json");
|
|
17
|
+
const ICON_PATH = resolve(__dirname, "astronaut-icon.png");
|
|
18
|
+
|
|
19
|
+
// Create a tiny base64 icon for the browser banner
|
|
20
|
+
function getIconDataUrl() {
|
|
21
|
+
try {
|
|
22
|
+
const tmpIcon = resolve(__dirname, ".banner-icon-tmp.png");
|
|
23
|
+
// Use sips (macOS) or convert to resize, fall back to full image
|
|
24
|
+
try {
|
|
25
|
+
execSync(`sips -z 48 48 "${ICON_PATH}" --out "${tmpIcon}" 2>/dev/null`, { stdio: "ignore" });
|
|
26
|
+
} catch {
|
|
27
|
+
try {
|
|
28
|
+
execSync(`convert "${ICON_PATH}" -resize 48x48 "${tmpIcon}" 2>/dev/null`, { stdio: "ignore" });
|
|
29
|
+
} catch {
|
|
30
|
+
// Use original (will be larger but still works)
|
|
31
|
+
return `data:image/png;base64,${readFileSync(ICON_PATH).toString("base64")}`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const data = `data:image/png;base64,${readFileSync(tmpIcon).toString("base64")}`;
|
|
35
|
+
try { unlinkSync(tmpIcon); } catch {}
|
|
36
|
+
return data;
|
|
37
|
+
} catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
17
41
|
|
|
18
42
|
// ─── Terminal Colors ────────────────────────────────────────────────
|
|
19
43
|
const bold = (s) => `\x1b[1m${s}\x1b[0m`;
|
|
@@ -117,6 +141,49 @@ export default async function selfDrivingSlackSetup() {
|
|
|
117
141
|
|
|
118
142
|
const page = (await browser.pages())[0] || await browser.newPage();
|
|
119
143
|
|
|
144
|
+
// ── Visual cue: inject banner on every page load ──
|
|
145
|
+
const iconDataUrl = getIconDataUrl();
|
|
146
|
+
const iconEl = iconDataUrl
|
|
147
|
+
? `<img src="${iconDataUrl}" style="width: 22px; height: 22px; border-radius: 5px;" />`
|
|
148
|
+
: `<span style="font-size: 16px;">🤖</span>`;
|
|
149
|
+
const BANNER_CSS = `
|
|
150
|
+
position: fixed; top: 0; left: 0; right: 0; z-index: 2147483647;
|
|
151
|
+
height: 38px; display: flex; align-items: center; justify-content: center; gap: 10px;
|
|
152
|
+
background: linear-gradient(135deg, #6C5CE7, #A855F7);
|
|
153
|
+
color: #fff; font: 600 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
|
|
154
|
+
box-shadow: 0 2px 8px rgba(108, 92, 231, 0.4);
|
|
155
|
+
letter-spacing: 0.3px;
|
|
156
|
+
`;
|
|
157
|
+
const BANNER_HTML = `
|
|
158
|
+
<div id="astro-claw-banner" style="${BANNER_CSS}">
|
|
159
|
+
${iconEl}
|
|
160
|
+
<span>Astro Claw is driving this browser</span>
|
|
161
|
+
<span style="opacity: 0.6; font-weight: 400; font-size: 11px; margin-left: 4px;">— do not close</span>
|
|
162
|
+
</div>
|
|
163
|
+
`;
|
|
164
|
+
const BODY_PADDING = `
|
|
165
|
+
if (!document.body.dataset.astroClaw) {
|
|
166
|
+
document.body.style.paddingTop = (parseFloat(getComputedStyle(document.body).paddingTop) + 36) + 'px';
|
|
167
|
+
document.body.dataset.astroClaw = '1';
|
|
168
|
+
}
|
|
169
|
+
`;
|
|
170
|
+
const injectBanner = async (p) => {
|
|
171
|
+
try {
|
|
172
|
+
await p.evaluate((html, bodyJs) => {
|
|
173
|
+
if (!document.getElementById('astro-claw-banner')) {
|
|
174
|
+
document.body.insertAdjacentHTML('beforeend', html);
|
|
175
|
+
eval(bodyJs);
|
|
176
|
+
}
|
|
177
|
+
}, BANNER_HTML, BODY_PADDING);
|
|
178
|
+
} catch {}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// Inject banner after every navigation and periodically
|
|
182
|
+
page.on('load', () => injectBanner(page));
|
|
183
|
+
page.on('domcontentloaded', () => injectBanner(page));
|
|
184
|
+
page.on('framenavigated', () => setTimeout(() => injectBanner(page), 500));
|
|
185
|
+
const bannerInterval = setInterval(() => injectBanner(page), 2000);
|
|
186
|
+
|
|
120
187
|
// ── Step 1: Sign in to Slack (single tab, no interruptions) ──
|
|
121
188
|
console.log(` → Checking Slack login...`);
|
|
122
189
|
await page.goto("https://api.slack.com/apps", { waitUntil: "networkidle2", timeout: 30000 });
|
|
@@ -509,6 +576,7 @@ export default async function selfDrivingSlackSetup() {
|
|
|
509
576
|
}
|
|
510
577
|
|
|
511
578
|
// ── Clean up ──
|
|
579
|
+
clearInterval(bannerInterval);
|
|
512
580
|
await browser.close();
|
|
513
581
|
|
|
514
582
|
// Return whatever we captured
|
|
@@ -524,6 +592,7 @@ export default async function selfDrivingSlackSetup() {
|
|
|
524
592
|
return result;
|
|
525
593
|
} catch (err) {
|
|
526
594
|
console.log(` ${WARN} Browser automation error: ${err.message}`);
|
|
595
|
+
clearInterval(bannerInterval);
|
|
527
596
|
if (browser) await browser.close().catch(() => {});
|
|
528
597
|
return null;
|
|
529
598
|
}
|