astro-claw 1.0.2 → 1.0.4
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-manifest.json +2 -2
- package/slack-manifest.yml +1 -1
- package/slack-setup.js +70 -38
package/package.json
CHANGED
package/slack-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"display_information": {
|
|
3
|
-
"name": "
|
|
3
|
+
"name": "Astro Claw",
|
|
4
4
|
"description": "AI crew member powered by Claude Code",
|
|
5
5
|
"background_color": "#1a1a2e"
|
|
6
6
|
},
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"messages_tab_read_only_enabled": false
|
|
12
12
|
},
|
|
13
13
|
"bot_user": {
|
|
14
|
-
"display_name": "
|
|
14
|
+
"display_name": "Astro Claw",
|
|
15
15
|
"always_online": true
|
|
16
16
|
}
|
|
17
17
|
},
|
package/slack-manifest.yml
CHANGED
package/slack-setup.js
CHANGED
|
@@ -117,6 +117,45 @@ export default async function selfDrivingSlackSetup() {
|
|
|
117
117
|
|
|
118
118
|
const page = (await browser.pages())[0] || await browser.newPage();
|
|
119
119
|
|
|
120
|
+
// ── Visual cue: inject banner on every page load ──
|
|
121
|
+
const BANNER_CSS = `
|
|
122
|
+
position: fixed; top: 0; left: 0; right: 0; z-index: 2147483647;
|
|
123
|
+
height: 36px; display: flex; align-items: center; justify-content: center; gap: 8px;
|
|
124
|
+
background: linear-gradient(135deg, #6C5CE7, #A855F7);
|
|
125
|
+
color: #fff; font: 600 13px/1 -apple-system, BlinkMacSystemFont, sans-serif;
|
|
126
|
+
box-shadow: 0 2px 8px rgba(108, 92, 231, 0.4);
|
|
127
|
+
letter-spacing: 0.3px;
|
|
128
|
+
`;
|
|
129
|
+
const BANNER_HTML = `
|
|
130
|
+
<div id="astro-claw-banner" style="${BANNER_CSS}">
|
|
131
|
+
<span style="font-size: 16px;">🤖</span>
|
|
132
|
+
<span>Astro Claw is driving this browser</span>
|
|
133
|
+
<span style="opacity: 0.6; font-weight: 400; font-size: 11px; margin-left: 4px;">— do not close</span>
|
|
134
|
+
</div>
|
|
135
|
+
`;
|
|
136
|
+
const BODY_PADDING = `
|
|
137
|
+
if (!document.body.dataset.astroClaw) {
|
|
138
|
+
document.body.style.paddingTop = (parseFloat(getComputedStyle(document.body).paddingTop) + 36) + 'px';
|
|
139
|
+
document.body.dataset.astroClaw = '1';
|
|
140
|
+
}
|
|
141
|
+
`;
|
|
142
|
+
const injectBanner = async (p) => {
|
|
143
|
+
try {
|
|
144
|
+
await p.evaluate((html, bodyJs) => {
|
|
145
|
+
if (!document.getElementById('astro-claw-banner')) {
|
|
146
|
+
document.body.insertAdjacentHTML('beforeend', html);
|
|
147
|
+
eval(bodyJs);
|
|
148
|
+
}
|
|
149
|
+
}, BANNER_HTML, BODY_PADDING);
|
|
150
|
+
} catch {}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// Inject banner after every navigation and periodically
|
|
154
|
+
page.on('load', () => injectBanner(page));
|
|
155
|
+
page.on('domcontentloaded', () => injectBanner(page));
|
|
156
|
+
page.on('framenavigated', () => setTimeout(() => injectBanner(page), 500));
|
|
157
|
+
const bannerInterval = setInterval(() => injectBanner(page), 2000);
|
|
158
|
+
|
|
120
159
|
// ── Step 1: Sign in to Slack (single tab, no interruptions) ──
|
|
121
160
|
console.log(` → Checking Slack login...`);
|
|
122
161
|
await page.goto("https://api.slack.com/apps", { waitUntil: "networkidle2", timeout: 30000 });
|
|
@@ -246,50 +285,41 @@ export default async function selfDrivingSlackSetup() {
|
|
|
246
285
|
}
|
|
247
286
|
}
|
|
248
287
|
|
|
249
|
-
//
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
288
|
+
// Helper: check if we've landed on the app page (creation complete)
|
|
289
|
+
const isOnAppPage = () => /api\.slack\.com\/apps\/[A-Z0-9]+(?:\/|$)/.test(page.url());
|
|
290
|
+
|
|
291
|
+
// Click through the wizard steps — Slack may have 2 or 3 steps
|
|
292
|
+
// After each click, check if the app was already created
|
|
293
|
+
console.log(` → Walking through wizard...`);
|
|
294
|
+
for (let step = 0; step < 3; step++) {
|
|
295
|
+
if (isOnAppPage()) break;
|
|
296
|
+
|
|
297
|
+
// Look for the primary action button (Next or Create)
|
|
298
|
+
const btn = await page.$('button.c-button--primary')
|
|
254
299
|
|| await page.$('button[data-qa="next"]')
|
|
255
300
|
|| await page.$('button[type="submit"]');
|
|
256
|
-
if (nextBtn) {
|
|
257
|
-
await nextBtn.click();
|
|
258
|
-
await new Promise((r) => setTimeout(r, 2000));
|
|
259
|
-
}
|
|
260
|
-
} catch {}
|
|
261
301
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
await new Promise((r) => setTimeout(r, 2000));
|
|
269
|
-
}
|
|
270
|
-
} catch {}
|
|
271
|
-
|
|
272
|
-
// Step 3: Click "Create"
|
|
273
|
-
console.log(` → Creating app...`);
|
|
274
|
-
try {
|
|
275
|
-
// Look for the Create button (usually the primary button on step 3)
|
|
276
|
-
const buttons = await page.$$('button');
|
|
277
|
-
for (const btn of buttons) {
|
|
278
|
-
const text = await page.evaluate((el) => el.textContent?.trim(), btn);
|
|
279
|
-
if (text === "Create" || text === "Create App") {
|
|
280
|
-
await btn.click();
|
|
281
|
-
await new Promise((r) => setTimeout(r, 3000));
|
|
282
|
-
break;
|
|
302
|
+
if (btn) {
|
|
303
|
+
const btnText = await page.evaluate((el) => el.textContent?.trim(), btn);
|
|
304
|
+
if (btnText === "Create" || btnText === "Create App") {
|
|
305
|
+
console.log(` → Creating app...`);
|
|
306
|
+
} else {
|
|
307
|
+
console.log(` → ${btnText || "Next"}...`);
|
|
283
308
|
}
|
|
309
|
+
await btn.click();
|
|
310
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
311
|
+
} else {
|
|
312
|
+
break;
|
|
284
313
|
}
|
|
285
|
-
}
|
|
314
|
+
}
|
|
286
315
|
|
|
287
|
-
//
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
316
|
+
// Wait for redirect to app page
|
|
317
|
+
if (!isOnAppPage()) {
|
|
318
|
+
await page.waitForFunction(
|
|
319
|
+
() => /api\.slack\.com\/apps\/[A-Z0-9]+/.test(window.location.href),
|
|
320
|
+
{ timeout: 30000 }
|
|
321
|
+
).catch(() => {});
|
|
322
|
+
}
|
|
293
323
|
|
|
294
324
|
const appUrl = page.url();
|
|
295
325
|
const appIdMatch = appUrl.match(/apps\/([A-Z0-9]+)/);
|
|
@@ -518,6 +548,7 @@ export default async function selfDrivingSlackSetup() {
|
|
|
518
548
|
}
|
|
519
549
|
|
|
520
550
|
// ── Clean up ──
|
|
551
|
+
clearInterval(bannerInterval);
|
|
521
552
|
await browser.close();
|
|
522
553
|
|
|
523
554
|
// Return whatever we captured
|
|
@@ -533,6 +564,7 @@ export default async function selfDrivingSlackSetup() {
|
|
|
533
564
|
return result;
|
|
534
565
|
} catch (err) {
|
|
535
566
|
console.log(` ${WARN} Browser automation error: ${err.message}`);
|
|
567
|
+
clearInterval(bannerInterval);
|
|
536
568
|
if (browser) await browser.close().catch(() => {});
|
|
537
569
|
return null;
|
|
538
570
|
}
|