halo-agent 2.2.3 → 2.2.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/browser.js +34 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/ui.js +21 -1
package/browser.js
CHANGED
|
@@ -135,7 +135,7 @@ async function connectToChrome(retries = 10, opts = {}) {
|
|
|
135
135
|
ctx = fresh.contexts()[0] || await fresh.newContext();
|
|
136
136
|
conn.context = ctx;
|
|
137
137
|
}
|
|
138
|
-
|
|
138
|
+
let page = await ctx.newPage();
|
|
139
139
|
if (url) {
|
|
140
140
|
try {
|
|
141
141
|
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });
|
|
@@ -153,6 +153,39 @@ async function connectToChrome(retries = 10, opts = {}) {
|
|
|
153
153
|
await page.waitForTimeout(8000);
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
|
+
|
|
157
|
+
// VERIFY-AFTER-GOTO. connectOverCDP against the user's REAL Chrome
|
|
158
|
+
// has a tab-handle race: ctx.newPage() may hand back a different
|
|
159
|
+
// tab than the one that actually navigated (e.g. Chrome already
|
|
160
|
+
// had a restored New Tab open). Symptom: the agent then scans
|
|
161
|
+
// about:blank / chrome://newtab forever while the target URL is
|
|
162
|
+
// loaded in a sibling tab. Self-correct: if our handle isn't on
|
|
163
|
+
// the target host, find the tab that IS and adopt it.
|
|
164
|
+
try {
|
|
165
|
+
const here = page.url();
|
|
166
|
+
const targetHost = new URL(url).hostname;
|
|
167
|
+
const onTarget = (u) => { try { return new URL(u).hostname === targetHost; } catch { return false; } };
|
|
168
|
+
if (!onTarget(here)) {
|
|
169
|
+
// Look across all pages in this context for the one that navigated.
|
|
170
|
+
const pages = ctx.pages();
|
|
171
|
+
const match = pages.find((p) => onTarget(p.url()));
|
|
172
|
+
if (match && match !== page) {
|
|
173
|
+
console.warn(`[halo-agent] newPage handle was on "${here.slice(0, 40)}" but target loaded in another tab — adopting it.`);
|
|
174
|
+
// Close the stray blank tab we opened so it doesn't litter.
|
|
175
|
+
if (/^about:blank$|^chrome:\/\/newtab/i.test(here)) {
|
|
176
|
+
try { await page.close(); } catch {}
|
|
177
|
+
}
|
|
178
|
+
page = match;
|
|
179
|
+
await page.bringToFront().catch(() => {});
|
|
180
|
+
} else if (/^about:blank$|^chrome:\/\/newtab/i.test(here)) {
|
|
181
|
+
// Our tab is genuinely blank and nothing else navigated —
|
|
182
|
+
// the goto silently no-op'd. Retry the navigation on THIS tab.
|
|
183
|
+
console.warn('[halo-agent] Tab still blank after goto — retrying navigation on this handle...');
|
|
184
|
+
await page.goto(url, { waitUntil: 'commit', timeout: 30000 }).catch(() => {});
|
|
185
|
+
await page.waitForTimeout(4000);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
} catch { /* best-effort self-correction; fall through */ }
|
|
156
189
|
}
|
|
157
190
|
return page;
|
|
158
191
|
},
|
package/index.js
CHANGED
|
@@ -479,7 +479,7 @@ async function runStart() {
|
|
|
479
479
|
|
|
480
480
|
let version = '';
|
|
481
481
|
try { version = require('./package.json').version; } catch {}
|
|
482
|
-
ui.
|
|
482
|
+
ui.bigBanner(version); // hero frame — the one you'd screenshot
|
|
483
483
|
|
|
484
484
|
// The agent runs its own isolated Chrome instance (separate --user-data-dir
|
|
485
485
|
// at ~/.halo-agent/chrome-profile) so it never collides with the user's
|
package/package.json
CHANGED
package/ui.js
CHANGED
|
@@ -73,6 +73,26 @@ function banner(version) {
|
|
|
73
73
|
console.log('');
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
// Big block-letter wordmark for the hero moment (`start`) — the frame you'd
|
|
77
|
+
// screenshot for a LinkedIn post. Five-row ASCII HALO in ember, tagline +
|
|
78
|
+
// version underneath. Falls back to the compact boxed banner when color is
|
|
79
|
+
// off (logs/CI) so the auto-start service log doesn't get a wall of blocks.
|
|
80
|
+
const HALO_ART = [
|
|
81
|
+
'██ ██ █████ ██ ██████ ',
|
|
82
|
+
'██ ██ ██ ██ ██ ██ ██ ',
|
|
83
|
+
'███████ ███████ ██ ██ ██ ',
|
|
84
|
+
'██ ██ ██ ██ ██ ██ ██ ',
|
|
85
|
+
'██ ██ ██ ██ ███████ ██████ ',
|
|
86
|
+
];
|
|
87
|
+
function bigBanner(version) {
|
|
88
|
+
if (!useColor) { banner(version); return; }
|
|
89
|
+
const ver = version ? gray('· agent v' + version) : gray('· agent');
|
|
90
|
+
console.log('');
|
|
91
|
+
for (const row of HALO_ART) console.log(' ' + ember(row));
|
|
92
|
+
console.log(' ' + gray('auto-apply, in your own Chrome') + ' ' + ver);
|
|
93
|
+
console.log('');
|
|
94
|
+
}
|
|
95
|
+
|
|
76
96
|
// Affordance helper: the obvious next command, rendered consistently so the
|
|
77
97
|
// user always knows what to type next. Shown after pair/init/etc.
|
|
78
98
|
function nextStep(cmd, note) {
|
|
@@ -123,5 +143,5 @@ function spinner(message) {
|
|
|
123
143
|
module.exports = {
|
|
124
144
|
bold, dim, red, green, yellow, blue, magenta, cyan, gray, ember,
|
|
125
145
|
sym, success, fail, info, warn, muted, step,
|
|
126
|
-
banner, spinner, nextStep, hint, commandTable, visLen,
|
|
146
|
+
banner, bigBanner, spinner, nextStep, hint, commandTable, visLen,
|
|
127
147
|
};
|