@q-agent/agent 0.1.9 → 0.1.10
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/dist/src/runner.js +25 -2
- package/package.json +1 -1
- package/vendor/explore_session.cjs +12 -2
package/dist/src/runner.js
CHANGED
|
@@ -856,10 +856,33 @@ async function processExplorationJob(cfg, session) {
|
|
|
856
856
|
args.push(storageState);
|
|
857
857
|
const child = (0, child_process_1.spawn)((0, paths_1.nodeBin)(), args, { cwd: nm, env: nodePathEnv(nm) });
|
|
858
858
|
activeChild = child;
|
|
859
|
+
// Capture the driver's stderr so a launch failure (missing browser, bad
|
|
860
|
+
// Playwright resolution, …) is visible instead of a silent "complete".
|
|
861
|
+
let driverStderr = "";
|
|
862
|
+
child.stderr?.on("data", (d) => {
|
|
863
|
+
driverStderr += String(d);
|
|
864
|
+
});
|
|
859
865
|
const driver = makeExploreDriver(child);
|
|
860
866
|
try {
|
|
861
|
-
// Wait for the driver's readiness signal before the first observe.
|
|
862
|
-
|
|
867
|
+
// Wait for the driver's readiness signal before the first observe. If the
|
|
868
|
+
// driver died before signalling ready, finalize with a clear driver-error
|
|
869
|
+
// (carrying its stderr) rather than letting the loop break silently.
|
|
870
|
+
const ready = await driver.ready();
|
|
871
|
+
if (!ready || ready.ok === false) {
|
|
872
|
+
const error = (ready && ready.error) || "driver failed to start";
|
|
873
|
+
const detail = driverStderr.trim();
|
|
874
|
+
await api
|
|
875
|
+
.postExploreFinalize(cfg, session.sessionId, {
|
|
876
|
+
discovered: { routes: [], selectors: [] },
|
|
877
|
+
log: [{ phase: "driver", error, stderr: detail || undefined }],
|
|
878
|
+
stopReason: "driver-error",
|
|
879
|
+
stepsTaken: 0,
|
|
880
|
+
})
|
|
881
|
+
.catch((err) => console.error("postExploreFinalize failed:", err));
|
|
882
|
+
(0, bus_1.emit)("explore-complete", { sessionId: session.sessionId, stopReason: "driver-error", error });
|
|
883
|
+
console.error(`Exploration ${session.sessionId} driver-error: ${error}${detail ? ` — ${detail}` : ""}`);
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
863
886
|
await runExplorationLoop(cfg, session, driver, api, bus_1.emit);
|
|
864
887
|
}
|
|
865
888
|
finally {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@q-agent/agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Q-Agent Local Agent — claims execution jobs from the Q-Agent server and runs Playwright locally, so manual login/MFA happens on the user's own machine and session credentials never leave it.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"bin": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
//
|
|
19
19
|
// Protocol (one JSON object per line, each way):
|
|
20
20
|
// {"cmd":"observe"}
|
|
21
|
-
// -> {"ok":true,"url":..,"path":..,"a11y":<
|
|
21
|
+
// -> {"ok":true,"url":..,"path":..,"a11y":<ariaSnapshot() role+name tree>,
|
|
22
22
|
// "elements":[<distilled interactive DOM>]}
|
|
23
23
|
// {"cmd":"act","action":"goto|click|fill|expectVisible","args":{...}}
|
|
24
24
|
// -> {"ok":bool,"error":str|null,"changed":bool}
|
|
@@ -121,7 +121,11 @@ async function doAct(action, args) {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
async function doObserve() {
|
|
124
|
-
|
|
124
|
+
// Playwright removed page.accessibility; the supported role+name tree is
|
|
125
|
+
// locator.ariaSnapshot() (a compact YAML string, ideal for the model and
|
|
126
|
+
// maps directly to getByRole). Best-effort — never fail observe on it.
|
|
127
|
+
let a11y = '';
|
|
128
|
+
try { a11y = await page.locator('body').ariaSnapshot(); } catch { a11y = ''; }
|
|
125
129
|
const elements = await page.evaluate(DISTILL);
|
|
126
130
|
const url = page.url();
|
|
127
131
|
let path = '';
|
|
@@ -161,6 +165,12 @@ async function handle(line) {
|
|
|
161
165
|
const context = await browser.newContext(contextOpts);
|
|
162
166
|
page = await context.newPage();
|
|
163
167
|
|
|
168
|
+
// Land on the app before the first observe so step 1 sees the real page,
|
|
169
|
+
// not about:blank. Best-effort — the model can still goto elsewhere.
|
|
170
|
+
if (baseURL) {
|
|
171
|
+
try { await page.goto(baseURL, { waitUntil: 'domcontentloaded' }); } catch {}
|
|
172
|
+
}
|
|
173
|
+
|
|
164
174
|
// Serialize commands: one line in -> one response out, in order.
|
|
165
175
|
const rl = readline.createInterface({ input: process.stdin });
|
|
166
176
|
let chain = Promise.resolve();
|