sf-builder-agent 0.7.0 → 0.7.2
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/browser.d.ts +6 -0
- package/dist/browser.js +35 -3
- package/dist/browser.js.map +1 -1
- package/dist/heartbeat.d.ts +2 -1
- package/dist/heartbeat.js +3 -3
- package/dist/heartbeat.js.map +1 -1
- package/dist/index.js +55 -2
- package/dist/index.js.map +1 -1
- package/dist/pairing.d.ts +1 -0
- package/dist/pairing.js +3 -2
- package/dist/pairing.js.map +1 -1
- package/dist/reporter.d.ts +2 -1
- package/dist/reporter.js +3 -2
- package/dist/reporter.js.map +1 -1
- package/dist/sse-client.d.ts +2 -1
- package/dist/sse-client.js +3 -4
- package/dist/sse-client.js.map +1 -1
- package/package.json +1 -1
- package/src/browser.ts +39 -3
- package/src/heartbeat.ts +3 -4
- package/src/index.ts +103 -35
- package/src/pairing.ts +3 -2
- package/src/reporter.ts +4 -3
- package/src/sse-client.ts +3 -4
package/dist/browser.d.ts
CHANGED
|
@@ -9,11 +9,17 @@ export declare function launchBrowser(): Promise<{
|
|
|
9
9
|
browser: Browser;
|
|
10
10
|
page: Page;
|
|
11
11
|
}>;
|
|
12
|
+
/**
|
|
13
|
+
* Check if the current page URL indicates a login/SSO redirect.
|
|
14
|
+
* Skips the check if the original target was itself a login page.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isLoginPage(currentUrl: string, originalTarget: string): boolean;
|
|
12
17
|
export interface CommandResult {
|
|
13
18
|
success: boolean;
|
|
14
19
|
result?: unknown;
|
|
15
20
|
error?: string;
|
|
16
21
|
screenshot?: string;
|
|
17
22
|
shutdown?: boolean;
|
|
23
|
+
waitingForLogin?: boolean;
|
|
18
24
|
}
|
|
19
25
|
export declare function executeCommand(page: Page, commandType: string, payload: Record<string, unknown>): Promise<CommandResult>;
|
package/dist/browser.js
CHANGED
|
@@ -85,14 +85,35 @@ async function findByText(page, selector, text) {
|
|
|
85
85
|
}, selector, text);
|
|
86
86
|
return handle;
|
|
87
87
|
}
|
|
88
|
+
// ─── Login Detection ─────────────────────────────────────────────────
|
|
89
|
+
const LOGIN_PATTERNS = [
|
|
90
|
+
"/identity/",
|
|
91
|
+
"login.microsoftonline.com",
|
|
92
|
+
"login.salesforce.com",
|
|
93
|
+
"/secur/frontdoor.jsp",
|
|
94
|
+
"/setup/secur/RemoteAccessAuthorizationPage",
|
|
95
|
+
];
|
|
96
|
+
/**
|
|
97
|
+
* Check if the current page URL indicates a login/SSO redirect.
|
|
98
|
+
* Skips the check if the original target was itself a login page.
|
|
99
|
+
*/
|
|
100
|
+
export function isLoginPage(currentUrl, originalTarget) {
|
|
101
|
+
if (LOGIN_PATTERNS.some((p) => originalTarget.includes(p)))
|
|
102
|
+
return false;
|
|
103
|
+
return LOGIN_PATTERNS.some((p) => currentUrl.includes(p));
|
|
104
|
+
}
|
|
88
105
|
export async function executeCommand(page, commandType, payload) {
|
|
89
106
|
try {
|
|
90
107
|
switch (commandType) {
|
|
91
108
|
// ── navigate ──
|
|
92
109
|
case "navigate": {
|
|
93
|
-
const
|
|
94
|
-
await page.goto(
|
|
95
|
-
|
|
110
|
+
const targetUrl = payload.url;
|
|
111
|
+
await page.goto(targetUrl, { waitUntil: "networkidle2", timeout: 30_000 });
|
|
112
|
+
const landedUrl = page.url();
|
|
113
|
+
if (isLoginPage(landedUrl, targetUrl)) {
|
|
114
|
+
return { success: false, waitingForLogin: true, result: { targetUrl, loginUrl: landedUrl } };
|
|
115
|
+
}
|
|
116
|
+
return { success: true, result: { url: targetUrl } };
|
|
96
117
|
}
|
|
97
118
|
// ── click ──
|
|
98
119
|
case "click": {
|
|
@@ -240,6 +261,17 @@ export async function executeCommand(page, commandType, payload) {
|
|
|
240
261
|
case "ping": {
|
|
241
262
|
return { success: true };
|
|
242
263
|
}
|
|
264
|
+
// ── restart ──
|
|
265
|
+
case "restart": {
|
|
266
|
+
// Close all pages and open a fresh one
|
|
267
|
+
const browser = page.browser();
|
|
268
|
+
const allPages = await browser.pages();
|
|
269
|
+
for (const p of allPages) {
|
|
270
|
+
await p.close().catch(() => { });
|
|
271
|
+
}
|
|
272
|
+
const newPage = await browser.newPage();
|
|
273
|
+
return { success: true, result: { restarted: true, newPage: true } };
|
|
274
|
+
}
|
|
243
275
|
// ── shutdown ──
|
|
244
276
|
case "shutdown": {
|
|
245
277
|
return { success: true, shutdown: true };
|
package/dist/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
|
package/dist/heartbeat.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Heartbeat — periodically pings the server so it knows we're alive.
|
|
3
|
+
* Uses /api/agent/heartbeat (flat route, not behind Easy Auth).
|
|
3
4
|
*/
|
|
4
|
-
export declare function startHeartbeat(baseUrl: string,
|
|
5
|
+
export declare function startHeartbeat(baseUrl: string, _sessionId: string, token: string, intervalMs?: number): {
|
|
5
6
|
stop: () => void;
|
|
6
7
|
};
|
package/dist/heartbeat.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Heartbeat — periodically pings the server so it knows we're alive.
|
|
3
|
+
* Uses /api/agent/heartbeat (flat route, not behind Easy Auth).
|
|
3
4
|
*/
|
|
4
|
-
export function startHeartbeat(baseUrl,
|
|
5
|
+
export function startHeartbeat(baseUrl, _sessionId, token, intervalMs = 10_000) {
|
|
5
6
|
let timer = null;
|
|
6
7
|
const tick = async () => {
|
|
7
8
|
try {
|
|
8
|
-
const res = await fetch(`${baseUrl}/api/
|
|
9
|
+
const res = await fetch(`${baseUrl}/api/agent/heartbeat`, {
|
|
9
10
|
method: "POST",
|
|
10
11
|
headers: { Authorization: `Bearer ${token}` },
|
|
11
12
|
});
|
|
@@ -21,7 +22,6 @@ export function startHeartbeat(baseUrl, sessionId, token, intervalMs = 10_000) {
|
|
|
21
22
|
}
|
|
22
23
|
};
|
|
23
24
|
timer = setInterval(tick, intervalMs);
|
|
24
|
-
// Send an initial heartbeat immediately
|
|
25
25
|
tick();
|
|
26
26
|
return {
|
|
27
27
|
stop() {
|
package/dist/heartbeat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../src/heartbeat.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../src/heartbeat.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,cAAc,CAC5B,OAAe,EACf,UAAkB,EAClB,KAAa,EACb,UAAU,GAAG,MAAM;IAEnB,IAAI,KAAK,GAA0C,IAAI,CAAC;IAExD,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;QACtB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,GAAG,OAAO,sBAAsB,EAChC;gBACE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;aAC9C,CACF,CAAC;YACF,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;YAC7C,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,8BAA8B,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CACX,yBAAyB,EACzB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACzC,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACtC,IAAI,EAAE,CAAC;IAEP,OAAO;QACL,IAAI;YACF,IAAI,KAAK,EAAE,CAAC;gBACV,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { createInterface } from "node:readline/promises";
|
|
|
9
9
|
import { stdin, stdout } from "node:process";
|
|
10
10
|
import { pair } from "./pairing.js";
|
|
11
11
|
import { connectSSE } from "./sse-client.js";
|
|
12
|
-
import { launchBrowser, executeCommand } from "./browser.js";
|
|
12
|
+
import { launchBrowser, executeCommand, isLoginPage } from "./browser.js";
|
|
13
13
|
import { reportResult } from "./reporter.js";
|
|
14
14
|
import { startHeartbeat } from "./heartbeat.js";
|
|
15
15
|
// ─── Arg Parsing ─────────────────────────────────────────────────────
|
|
@@ -96,11 +96,30 @@ async function main() {
|
|
|
96
96
|
console.error("\u274C Browser launch failed:", err instanceof Error ? err.message : err);
|
|
97
97
|
process.exit(1);
|
|
98
98
|
}
|
|
99
|
+
// ── Login Wait Helper ──
|
|
100
|
+
const LOGIN_POLL_INTERVAL = 2_000;
|
|
101
|
+
const LOGIN_TIMEOUT = 5 * 60 * 1_000; // 5 minutes
|
|
102
|
+
async function waitForLogin(currentPage, targetUrl) {
|
|
103
|
+
const start = Date.now();
|
|
104
|
+
while (Date.now() - start < LOGIN_TIMEOUT) {
|
|
105
|
+
await new Promise((r) => setTimeout(r, LOGIN_POLL_INTERVAL));
|
|
106
|
+
const url = currentPage.url();
|
|
107
|
+
if (!isLoginPage(url, targetUrl)) {
|
|
108
|
+
return { loggedIn: true, waitedMs: Date.now() - start };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return { loggedIn: false, waitedMs: Date.now() - start };
|
|
112
|
+
}
|
|
99
113
|
// ── Step 3: Start Heartbeat ──
|
|
100
114
|
const heartbeat = startHeartbeat(baseUrl, sessionId, token);
|
|
101
115
|
// ── Step 4: Connect to command stream ──
|
|
102
116
|
console.log("\uD83D\uDCE1 Connecting to command stream...");
|
|
103
|
-
|
|
117
|
+
// Serial command queue — ensures only one command runs at a time.
|
|
118
|
+
// SSE delivers all queued commands at once, but Puppeteer can only
|
|
119
|
+
// interact with one page action at a time. Without this, commands
|
|
120
|
+
// overlap and cause page flickering / race conditions.
|
|
121
|
+
let commandQueue = Promise.resolve();
|
|
122
|
+
async function handleCommand(command) {
|
|
104
123
|
const label = command.stepKey
|
|
105
124
|
? `${command.commandType} (step: ${command.stepKey})`
|
|
106
125
|
: command.commandType;
|
|
@@ -109,6 +128,34 @@ async function main() {
|
|
|
109
128
|
: "";
|
|
110
129
|
console.log(`\u26A1 Executing: ${label}${payloadHint}`);
|
|
111
130
|
const result = await executeCommand(page, command.commandType, command.payload);
|
|
131
|
+
// ── Handle login detection ──
|
|
132
|
+
if (result.waitingForLogin) {
|
|
133
|
+
console.log("\uD83D\uDD10 Login page detected — waiting for user to authenticate...");
|
|
134
|
+
// Report waiting_for_login immediately so the web UI can show the banner
|
|
135
|
+
await reportResult(baseUrl, sessionId, token, command.id, "waiting_for_login", result.result);
|
|
136
|
+
// Poll until login completes or timeout
|
|
137
|
+
const loginResult = await waitForLogin(page, command.payload.url);
|
|
138
|
+
if (loginResult.loggedIn) {
|
|
139
|
+
console.log(`\u2705 Login complete (waited ${Math.round(loginResult.waitedMs / 1000)}s)`);
|
|
140
|
+
await reportResult(baseUrl, sessionId, token, command.id, "success", {
|
|
141
|
+
loginDetected: true,
|
|
142
|
+
waitedMs: loginResult.waitedMs,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
console.error("\u274C Login timed out after 5 minutes");
|
|
147
|
+
await reportResult(baseUrl, sessionId, token, command.id, "error", {
|
|
148
|
+
error: "Login timed out — user did not complete authentication within 5 minutes",
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
// ── Handle restart — update page reference ──
|
|
154
|
+
if (command.commandType === "restart" && result.success) {
|
|
155
|
+
const pages = await browser.pages();
|
|
156
|
+
page = pages[pages.length - 1];
|
|
157
|
+
console.log("\u2705 Browser restarted — new page ready");
|
|
158
|
+
}
|
|
112
159
|
if (result.success) {
|
|
113
160
|
console.log(`\u2705 Command complete: ${command.commandType}`);
|
|
114
161
|
}
|
|
@@ -129,6 +176,12 @@ async function main() {
|
|
|
129
176
|
console.log("\uD83D\uDC4B Shutting down (server requested)...");
|
|
130
177
|
shutdown();
|
|
131
178
|
}
|
|
179
|
+
}
|
|
180
|
+
const sse = connectSSE(baseUrl, sessionId, token, (command) => {
|
|
181
|
+
// Queue commands serially — each waits for the previous to complete
|
|
182
|
+
commandQueue = commandQueue.then(() => handleCommand(command)).catch((err) => {
|
|
183
|
+
console.error(`\u274C Unhandled command error: ${err instanceof Error ? err.message : err}`);
|
|
184
|
+
});
|
|
132
185
|
}, (err) => {
|
|
133
186
|
console.error(`\u274C SSE error: ${err.message}`);
|
|
134
187
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGhD,wEAAwE;AAExE,SAAS,SAAS,CAAC,IAAc;IAK/B,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACxB,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;YAChB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,EAAE,CAAC;YACtC,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;YACnB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,EAAE,CAAC;YAClC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;YACf,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IACD,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,oCAAoC;KACtD,CAAC;AACJ,CAAC;AAED,wEAAwE;AAExE,KAAK,UAAU,MAAM,CAAC,QAAgB;IACpC,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC3C,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED,wEAAwE;AAExE,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAErC,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACrB,IAAI,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC;IAEzB,0CAA0C;IAC1C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,SAAS,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAC/C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;YAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IACD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACvC,IAAI,KAAa,CAAC;IAClB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;QACxD,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC;QACzB,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,wBAAwB,EACxB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACzC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,+BAA+B;IAC/B,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACjD,IAAI,OAAgB,CAAC;IACrB,IAAI,IAAU,CAAC;IACf,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,aAAa,EAAE,CAAC;QACvC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;QAC3B,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,+BAA+B,EAC/B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACzC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,0BAA0B;IAC1B,MAAM,mBAAmB,GAAG,KAAK,CAAC;IAClC,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,YAAY;IAElD,KAAK,UAAU,YAAY,CAAC,WAAiB,EAAE,SAAiB;QAC9D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,aAAa,EAAE,CAAC;YAC1C,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC,CAAC;YAC7D,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;YAC9B,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,CAAC;gBACjC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;YAC1D,CAAC;QACH,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;IAC3D,CAAC;IAED,gCAAgC;IAChC,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IAE5D,0CAA0C;IAC1C,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAE5D,kEAAkE;IAClE,mEAAmE;IACnE,kEAAkE;IAClE,uDAAuD;IACvD,IAAI,YAAY,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAEpD,KAAK,UAAU,aAAa,CAAC,OAAsG;QACjI,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO;YAC3B,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,WAAW,OAAO,CAAC,OAAO,GAAG;YACrD,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;QAExB,MAAM,WAAW,GACf,OAAO,CAAC,WAAW,KAAK,UAAU;YAChC,CAAC,CAAC,WAAW,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;YAClC,CAAC,CAAC,EAAE,CAAC;QAET,OAAO,CAAC,GAAG,CAAC,qBAAqB,KAAK,GAAG,WAAW,EAAE,CAAC,CAAC;QAExD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAEhF,+BAA+B;QAC/B,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAC;YAEtF,yEAAyE;YACzE,MAAM,YAAY,CAChB,OAAO,EACP,SAAU,EACV,KAAK,EACL,OAAO,CAAC,EAAE,EACV,mBAAmB,EACnB,MAAM,CAAC,MAA6C,CACrD,CAAC;YAEF,wCAAwC;YACxC,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,GAAa,CAAC,CAAC;YAE5E,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC1F,MAAM,YAAY,CAAC,OAAO,EAAE,SAAU,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE;oBACpE,aAAa,EAAE,IAAI;oBACnB,QAAQ,EAAE,WAAW,CAAC,QAAQ;iBAC/B,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;gBACxD,MAAM,YAAY,CAAC,OAAO,EAAE,SAAU,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE;oBAClE,KAAK,EAAE,yEAAyE;iBACjF,CAAC,CAAC;YACL,CAAC;YACD,OAAO;QACT,CAAC;QAED,+CAA+C;QAC/C,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACxD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACpC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;QAC3D,CAAC;QAED,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,4BAA4B,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QACjE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CACX,0BAA0B,OAAO,CAAC,WAAW,WAAW,MAAM,CAAC,KAAK,EAAE,CACvE,CAAC;QACJ,CAAC;QAED,wBAAwB;QACxB,MAAM,aAAa,GAA4B,EAAE,CAAC;QAClD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;YAAE,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QACtE,IAAI,MAAM,CAAC,UAAU;YAAE,aAAa,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACpE,IAAI,MAAM,CAAC,KAAK;YAAE,aAAa,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAErD,MAAM,YAAY,CAChB,OAAO,EACP,SAAU,EACV,KAAK,EACL,OAAO,CAAC,EAAE,EACV,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EACpC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAClE,CAAC;QAEF,0BAA0B;QAC1B,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;YAChE,QAAQ,EAAE,CAAC;QACb,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,UAAU,CACpB,OAAO,EACP,SAAS,EACT,KAAK,EACL,CAAC,OAAO,EAAE,EAAE;QACV,oEAAoE;QACpE,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YAC3E,OAAO,CAAC,KAAK,CAAC,mCAAmC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QAC/F,CAAC,CAAC,CAAC;IACL,CAAC,EACD,CAAC,GAAG,EAAE,EAAE;QACN,OAAO,CAAC,KAAK,CAAC,qBAAqB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACpD,CAAC,CACF,CAAC;IAEF,0BAA0B;IAC1B,IAAI,YAAY,GAAG,KAAK,CAAC;IAEzB,SAAS,QAAQ;QACf,IAAI,YAAY;YAAE,OAAO;QACzB,YAAY,GAAG,IAAI,CAAC;QAEpB,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAE7C,GAAG,CAAC,KAAK,EAAE,CAAC;QACZ,SAAS,CAAC,IAAI,EAAE,CAAC;QAEjB,OAAO;aACJ,KAAK,EAAE;aACP,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;aACf,OAAO,CAAC,GAAG,EAAE;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEhC,aAAa;IACb,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;AACzB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/pairing.d.ts
CHANGED
package/dist/pairing.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pairing — exchange a one-time code for a persistent auth token.
|
|
3
|
+
* Uses /api/agent/pair (flat route, not behind Easy Auth).
|
|
3
4
|
*/
|
|
4
5
|
export async function pair(baseUrl, sessionId, code) {
|
|
5
|
-
const url = `${baseUrl}/api/
|
|
6
|
+
const url = `${baseUrl}/api/agent/pair`;
|
|
6
7
|
const res = await fetch(url, {
|
|
7
8
|
method: "POST",
|
|
8
9
|
headers: { "Content-Type": "application/json" },
|
|
9
|
-
body: JSON.stringify({ code }),
|
|
10
|
+
body: JSON.stringify({ sessionId, code }),
|
|
10
11
|
});
|
|
11
12
|
if (!res.ok) {
|
|
12
13
|
const body = await res.text().catch(() => "");
|
package/dist/pairing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pairing.js","sourceRoot":"","sources":["../src/pairing.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pairing.js","sourceRoot":"","sources":["../src/pairing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,OAAe,EACf,SAAiB,EACjB,IAAY;IAEZ,MAAM,GAAG,GAAG,GAAG,OAAO,iBAAiB,CAAC;IAExC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;KAC1C,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,mBAAmB,GAAG,CAAC,MAAM,MAAM,IAAI,IAAI,GAAG,CAAC,UAAU,EAAE,CAC5D,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA2C,CAAC;IAE1E,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,SAAS,EAAE,CAAC;AACvE,CAAC"}
|
package/dist/reporter.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Reporter — POST command results back to the web app.
|
|
3
|
+
* Uses /api/agent/result (flat route, not behind Easy Auth).
|
|
3
4
|
*/
|
|
4
|
-
export declare function reportResult(baseUrl: string,
|
|
5
|
+
export declare function reportResult(baseUrl: string, _sessionId: string, token: string, commandId: string, status: "success" | "error" | "waiting_for_login", result?: Record<string, unknown>): Promise<void>;
|
package/dist/reporter.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Reporter — POST command results back to the web app.
|
|
3
|
+
* Uses /api/agent/result (flat route, not behind Easy Auth).
|
|
3
4
|
*/
|
|
4
|
-
export async function reportResult(baseUrl,
|
|
5
|
-
const url = `${baseUrl}/api/
|
|
5
|
+
export async function reportResult(baseUrl, _sessionId, token, commandId, status, result) {
|
|
6
|
+
const url = `${baseUrl}/api/agent/result`;
|
|
6
7
|
try {
|
|
7
8
|
const res = await fetch(url, {
|
|
8
9
|
method: "POST",
|
package/dist/reporter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAe,EACf,UAAkB,EAClB,KAAa,EACb,SAAiB,EACjB,MAAiD,EACjD,MAAgC;IAEhC,MAAM,GAAG,GAAG,GAAG,OAAO,mBAAmB,CAAC;IAE1C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,KAAK,EAAE;gBAChC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;SACpD,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,OAAO,CAAC,KAAK,CAAC,yBAAyB,GAAG,CAAC,MAAM,MAAM,IAAI,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,sBAAsB,EACtB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACzC,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/sse-client.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SSE client — listens for browser-automation commands from the server.
|
|
3
|
+
* Uses /api/agent/commands (flat route, not behind Easy Auth).
|
|
3
4
|
*/
|
|
4
5
|
interface IncomingCommand {
|
|
5
6
|
id: string;
|
|
@@ -7,7 +8,7 @@ interface IncomingCommand {
|
|
|
7
8
|
stepKey: string | null;
|
|
8
9
|
payload: Record<string, unknown>;
|
|
9
10
|
}
|
|
10
|
-
export declare function connectSSE(baseUrl: string,
|
|
11
|
+
export declare function connectSSE(baseUrl: string, _sessionId: string, token: string, onCommand: (command: IncomingCommand) => void, onError: (error: Error) => void): {
|
|
11
12
|
close: () => void;
|
|
12
13
|
};
|
|
13
14
|
export {};
|
package/dist/sse-client.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SSE client — listens for browser-automation commands from the server.
|
|
3
|
+
* Uses /api/agent/commands (flat route, not behind Easy Auth).
|
|
3
4
|
*/
|
|
4
5
|
import { EventSource } from "eventsource";
|
|
5
|
-
export function connectSSE(baseUrl,
|
|
6
|
-
const url = `${baseUrl}/api/
|
|
6
|
+
export function connectSSE(baseUrl, _sessionId, token, onCommand, onError) {
|
|
7
|
+
const url = `${baseUrl}/api/agent/commands?token=${encodeURIComponent(token)}`;
|
|
7
8
|
let es = null;
|
|
8
9
|
let closed = false;
|
|
9
10
|
let retryDelay = 1_000;
|
|
@@ -16,7 +17,6 @@ export function connectSSE(baseUrl, sessionId, token, onCommand, onError) {
|
|
|
16
17
|
try {
|
|
17
18
|
const data = JSON.parse(evt.data);
|
|
18
19
|
onCommand(data);
|
|
19
|
-
// Reset backoff on successful message
|
|
20
20
|
retryDelay = 1_000;
|
|
21
21
|
}
|
|
22
22
|
catch (err) {
|
|
@@ -38,7 +38,6 @@ export function connectSSE(baseUrl, sessionId, token, onCommand, onError) {
|
|
|
38
38
|
: "SSE connection error";
|
|
39
39
|
console.error(`\u274C SSE error: ${message} — reconnecting in ${retryDelay / 1_000}s`);
|
|
40
40
|
onError(new Error(message));
|
|
41
|
-
// Close the broken connection and schedule reconnect
|
|
42
41
|
es?.close();
|
|
43
42
|
es = null;
|
|
44
43
|
setTimeout(() => {
|
package/dist/sse-client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse-client.js","sourceRoot":"","sources":["../src/sse-client.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sse-client.js","sourceRoot":"","sources":["../src/sse-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAS1C,MAAM,UAAU,UAAU,CACxB,OAAe,EACf,UAAkB,EAClB,KAAa,EACb,SAA6C,EAC7C,OAA+B;IAE/B,MAAM,GAAG,GAAG,GAAG,OAAO,6BAA6B,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;IAE/E,IAAI,EAAE,GAAuB,IAAI,CAAC;IAClC,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,MAAM,SAAS,GAAG,MAAM,CAAC;IAEzB,SAAS,OAAO;QACd,IAAI,MAAM;YAAE,OAAO;QAEnB,EAAE,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC;QAE1B,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,GAAiB,EAAE,EAAE;YACnD,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAoB,CAAC;gBACrD,SAAS,CAAC,IAAI,CAAC,CAAC;gBAChB,UAAU,GAAG,KAAK,CAAC;YACrB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CACX,iCAAiC,EACjC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACzC,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;YAC/B,6BAA6B;QAC/B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;YAC/B,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;YAClD,UAAU,GAAG,KAAK,CAAC;QACrB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,OAAO,GAAG,CAAC,GAAU,EAAE,EAAE;YAC1B,IAAI,MAAM;gBAAE,OAAO;YAEnB,MAAM,OAAO,GACX,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,SAAS,IAAI,GAAG;gBAChD,CAAC,CAAE,GAAsC,CAAC,OAAO;gBACjD,CAAC,CAAC,sBAAsB,CAAC;YAE7B,OAAO,CAAC,KAAK,CAAC,qBAAqB,OAAO,uBAAuB,UAAU,GAAG,KAAK,GAAG,CAAC,CAAC;YACxF,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAE5B,EAAE,EAAE,KAAK,EAAE,CAAC;YACZ,EAAE,GAAG,IAAI,CAAC;YAEV,UAAU,CAAC,GAAG,EAAE;gBACd,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;gBACjD,OAAO,EAAE,CAAC;YACZ,CAAC,EAAE,UAAU,CAAC,CAAC;QACjB,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,CAAC;IAEV,OAAO;QACL,KAAK;YACH,MAAM,GAAG,IAAI,CAAC;YACd,EAAE,EAAE,KAAK,EAAE,CAAC;YACZ,EAAE,GAAG,IAAI,CAAC;QACZ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
package/src/browser.ts
CHANGED
|
@@ -125,6 +125,25 @@ async function findByText(
|
|
|
125
125
|
return handle as ElementHandle<Element>;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
// ─── Login Detection ─────────────────────────────────────────────────
|
|
129
|
+
|
|
130
|
+
const LOGIN_PATTERNS = [
|
|
131
|
+
"/identity/",
|
|
132
|
+
"login.microsoftonline.com",
|
|
133
|
+
"login.salesforce.com",
|
|
134
|
+
"/secur/frontdoor.jsp",
|
|
135
|
+
"/setup/secur/RemoteAccessAuthorizationPage",
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Check if the current page URL indicates a login/SSO redirect.
|
|
140
|
+
* Skips the check if the original target was itself a login page.
|
|
141
|
+
*/
|
|
142
|
+
export function isLoginPage(currentUrl: string, originalTarget: string): boolean {
|
|
143
|
+
if (LOGIN_PATTERNS.some((p) => originalTarget.includes(p))) return false;
|
|
144
|
+
return LOGIN_PATTERNS.some((p) => currentUrl.includes(p));
|
|
145
|
+
}
|
|
146
|
+
|
|
128
147
|
// ─── Command Executor ────────────────────────────────────────────────
|
|
129
148
|
|
|
130
149
|
export interface CommandResult {
|
|
@@ -133,6 +152,7 @@ export interface CommandResult {
|
|
|
133
152
|
error?: string;
|
|
134
153
|
screenshot?: string;
|
|
135
154
|
shutdown?: boolean;
|
|
155
|
+
waitingForLogin?: boolean;
|
|
136
156
|
}
|
|
137
157
|
|
|
138
158
|
export async function executeCommand(
|
|
@@ -144,9 +164,13 @@ export async function executeCommand(
|
|
|
144
164
|
switch (commandType) {
|
|
145
165
|
// ── navigate ──
|
|
146
166
|
case "navigate": {
|
|
147
|
-
const
|
|
148
|
-
await page.goto(
|
|
149
|
-
|
|
167
|
+
const targetUrl = payload.url as string;
|
|
168
|
+
await page.goto(targetUrl, { waitUntil: "networkidle2", timeout: 30_000 });
|
|
169
|
+
const landedUrl = page.url();
|
|
170
|
+
if (isLoginPage(landedUrl, targetUrl)) {
|
|
171
|
+
return { success: false, waitingForLogin: true, result: { targetUrl, loginUrl: landedUrl } };
|
|
172
|
+
}
|
|
173
|
+
return { success: true, result: { url: targetUrl } };
|
|
150
174
|
}
|
|
151
175
|
|
|
152
176
|
// ── click ──
|
|
@@ -321,6 +345,18 @@ export async function executeCommand(
|
|
|
321
345
|
return { success: true };
|
|
322
346
|
}
|
|
323
347
|
|
|
348
|
+
// ── restart ──
|
|
349
|
+
case "restart": {
|
|
350
|
+
// Close all pages and open a fresh one
|
|
351
|
+
const browser = page.browser();
|
|
352
|
+
const allPages = await browser.pages();
|
|
353
|
+
for (const p of allPages) {
|
|
354
|
+
await p.close().catch(() => {});
|
|
355
|
+
}
|
|
356
|
+
const newPage = await browser.newPage();
|
|
357
|
+
return { success: true, result: { restarted: true, newPage: true } };
|
|
358
|
+
}
|
|
359
|
+
|
|
324
360
|
// ── shutdown ──
|
|
325
361
|
case "shutdown": {
|
|
326
362
|
return { success: true, shutdown: true };
|
package/src/heartbeat.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Heartbeat — periodically pings the server so it knows we're alive.
|
|
3
|
+
* Uses /api/agent/heartbeat (flat route, not behind Easy Auth).
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
export function startHeartbeat(
|
|
6
7
|
baseUrl: string,
|
|
7
|
-
|
|
8
|
+
_sessionId: string,
|
|
8
9
|
token: string,
|
|
9
10
|
intervalMs = 10_000
|
|
10
11
|
): { stop: () => void } {
|
|
@@ -13,7 +14,7 @@ export function startHeartbeat(
|
|
|
13
14
|
const tick = async () => {
|
|
14
15
|
try {
|
|
15
16
|
const res = await fetch(
|
|
16
|
-
`${baseUrl}/api/
|
|
17
|
+
`${baseUrl}/api/agent/heartbeat`,
|
|
17
18
|
{
|
|
18
19
|
method: "POST",
|
|
19
20
|
headers: { Authorization: `Bearer ${token}` },
|
|
@@ -33,8 +34,6 @@ export function startHeartbeat(
|
|
|
33
34
|
};
|
|
34
35
|
|
|
35
36
|
timer = setInterval(tick, intervalMs);
|
|
36
|
-
|
|
37
|
-
// Send an initial heartbeat immediately
|
|
38
37
|
tick();
|
|
39
38
|
|
|
40
39
|
return {
|
package/src/index.ts
CHANGED
|
@@ -11,10 +11,10 @@ import { createInterface } from "node:readline/promises";
|
|
|
11
11
|
import { stdin, stdout } from "node:process";
|
|
12
12
|
import { pair } from "./pairing.js";
|
|
13
13
|
import { connectSSE } from "./sse-client.js";
|
|
14
|
-
import { launchBrowser, executeCommand } from "./browser.js";
|
|
14
|
+
import { launchBrowser, executeCommand, isLoginPage } from "./browser.js";
|
|
15
15
|
import { reportResult } from "./reporter.js";
|
|
16
16
|
import { startHeartbeat } from "./heartbeat.js";
|
|
17
|
-
import type { Browser } from "puppeteer";
|
|
17
|
+
import type { Browser, Page } from "puppeteer";
|
|
18
18
|
|
|
19
19
|
// ─── Arg Parsing ─────────────────────────────────────────────────────
|
|
20
20
|
|
|
@@ -101,7 +101,7 @@ async function main() {
|
|
|
101
101
|
// ── Step 2: Launch Browser ──
|
|
102
102
|
console.log("\uD83C\uDF10 Launching browser...");
|
|
103
103
|
let browser: Browser;
|
|
104
|
-
let page:
|
|
104
|
+
let page: Page;
|
|
105
105
|
try {
|
|
106
106
|
const launched = await launchBrowser();
|
|
107
107
|
browser = launched.browser;
|
|
@@ -115,58 +115,126 @@ async function main() {
|
|
|
115
115
|
process.exit(1);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
// ── Login Wait Helper ──
|
|
119
|
+
const LOGIN_POLL_INTERVAL = 2_000;
|
|
120
|
+
const LOGIN_TIMEOUT = 5 * 60 * 1_000; // 5 minutes
|
|
121
|
+
|
|
122
|
+
async function waitForLogin(currentPage: Page, targetUrl: string): Promise<{ loggedIn: boolean; waitedMs: number }> {
|
|
123
|
+
const start = Date.now();
|
|
124
|
+
while (Date.now() - start < LOGIN_TIMEOUT) {
|
|
125
|
+
await new Promise((r) => setTimeout(r, LOGIN_POLL_INTERVAL));
|
|
126
|
+
const url = currentPage.url();
|
|
127
|
+
if (!isLoginPage(url, targetUrl)) {
|
|
128
|
+
return { loggedIn: true, waitedMs: Date.now() - start };
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return { loggedIn: false, waitedMs: Date.now() - start };
|
|
132
|
+
}
|
|
133
|
+
|
|
118
134
|
// ── Step 3: Start Heartbeat ──
|
|
119
135
|
const heartbeat = startHeartbeat(baseUrl, sessionId, token);
|
|
120
136
|
|
|
121
137
|
// ── Step 4: Connect to command stream ──
|
|
122
138
|
console.log("\uD83D\uDCE1 Connecting to command stream...");
|
|
123
139
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const label = command.stepKey
|
|
130
|
-
? `${command.commandType} (step: ${command.stepKey})`
|
|
131
|
-
: command.commandType;
|
|
140
|
+
// Serial command queue — ensures only one command runs at a time.
|
|
141
|
+
// SSE delivers all queued commands at once, but Puppeteer can only
|
|
142
|
+
// interact with one page action at a time. Without this, commands
|
|
143
|
+
// overlap and cause page flickering / race conditions.
|
|
144
|
+
let commandQueue: Promise<void> = Promise.resolve();
|
|
132
145
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
146
|
+
async function handleCommand(command: { id: string; commandType: string; stepKey: string | null; payload: Record<string, unknown> }) {
|
|
147
|
+
const label = command.stepKey
|
|
148
|
+
? `${command.commandType} (step: ${command.stepKey})`
|
|
149
|
+
: command.commandType;
|
|
137
150
|
|
|
138
|
-
|
|
151
|
+
const payloadHint =
|
|
152
|
+
command.commandType === "navigate"
|
|
153
|
+
? ` \u2192 ${command.payload.url}`
|
|
154
|
+
: "";
|
|
139
155
|
|
|
140
|
-
|
|
156
|
+
console.log(`\u26A1 Executing: ${label}${payloadHint}`);
|
|
141
157
|
|
|
142
|
-
|
|
143
|
-
console.log(`\u2705 Command complete: ${command.commandType}`);
|
|
144
|
-
} else {
|
|
145
|
-
console.error(
|
|
146
|
-
`\u274C Command failed: ${command.commandType} \u2014 ${result.error}`
|
|
147
|
-
);
|
|
148
|
-
}
|
|
158
|
+
const result = await executeCommand(page, command.commandType, command.payload);
|
|
149
159
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (result.screenshot) resultPayload.screenshot = result.screenshot;
|
|
154
|
-
if (result.error) resultPayload.error = result.error;
|
|
160
|
+
// ── Handle login detection ──
|
|
161
|
+
if (result.waitingForLogin) {
|
|
162
|
+
console.log("\uD83D\uDD10 Login page detected — waiting for user to authenticate...");
|
|
155
163
|
|
|
164
|
+
// Report waiting_for_login immediately so the web UI can show the banner
|
|
156
165
|
await reportResult(
|
|
157
166
|
baseUrl,
|
|
158
167
|
sessionId!,
|
|
159
168
|
token,
|
|
160
169
|
command.id,
|
|
161
|
-
|
|
162
|
-
|
|
170
|
+
"waiting_for_login",
|
|
171
|
+
result.result as Record<string, unknown> | undefined
|
|
163
172
|
);
|
|
164
173
|
|
|
165
|
-
//
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
174
|
+
// Poll until login completes or timeout
|
|
175
|
+
const loginResult = await waitForLogin(page, command.payload.url as string);
|
|
176
|
+
|
|
177
|
+
if (loginResult.loggedIn) {
|
|
178
|
+
console.log(`\u2705 Login complete (waited ${Math.round(loginResult.waitedMs / 1000)}s)`);
|
|
179
|
+
await reportResult(baseUrl, sessionId!, token, command.id, "success", {
|
|
180
|
+
loginDetected: true,
|
|
181
|
+
waitedMs: loginResult.waitedMs,
|
|
182
|
+
});
|
|
183
|
+
} else {
|
|
184
|
+
console.error("\u274C Login timed out after 5 minutes");
|
|
185
|
+
await reportResult(baseUrl, sessionId!, token, command.id, "error", {
|
|
186
|
+
error: "Login timed out — user did not complete authentication within 5 minutes",
|
|
187
|
+
});
|
|
169
188
|
}
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ── Handle restart — update page reference ──
|
|
193
|
+
if (command.commandType === "restart" && result.success) {
|
|
194
|
+
const pages = await browser.pages();
|
|
195
|
+
page = pages[pages.length - 1];
|
|
196
|
+
console.log("\u2705 Browser restarted — new page ready");
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (result.success) {
|
|
200
|
+
console.log(`\u2705 Command complete: ${command.commandType}`);
|
|
201
|
+
} else {
|
|
202
|
+
console.error(
|
|
203
|
+
`\u274C Command failed: ${command.commandType} \u2014 ${result.error}`
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Report back to server
|
|
208
|
+
const resultPayload: Record<string, unknown> = {};
|
|
209
|
+
if (result.result !== undefined) resultPayload.result = result.result;
|
|
210
|
+
if (result.screenshot) resultPayload.screenshot = result.screenshot;
|
|
211
|
+
if (result.error) resultPayload.error = result.error;
|
|
212
|
+
|
|
213
|
+
await reportResult(
|
|
214
|
+
baseUrl,
|
|
215
|
+
sessionId!,
|
|
216
|
+
token,
|
|
217
|
+
command.id,
|
|
218
|
+
result.success ? "success" : "error",
|
|
219
|
+
Object.keys(resultPayload).length > 0 ? resultPayload : undefined
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
// Handle shutdown command
|
|
223
|
+
if (result.shutdown) {
|
|
224
|
+
console.log("\uD83D\uDC4B Shutting down (server requested)...");
|
|
225
|
+
shutdown();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const sse = connectSSE(
|
|
230
|
+
baseUrl,
|
|
231
|
+
sessionId,
|
|
232
|
+
token,
|
|
233
|
+
(command) => {
|
|
234
|
+
// Queue commands serially — each waits for the previous to complete
|
|
235
|
+
commandQueue = commandQueue.then(() => handleCommand(command)).catch((err) => {
|
|
236
|
+
console.error(`\u274C Unhandled command error: ${err instanceof Error ? err.message : err}`);
|
|
237
|
+
});
|
|
170
238
|
},
|
|
171
239
|
(err) => {
|
|
172
240
|
console.error(`\u274C SSE error: ${err.message}`);
|
package/src/pairing.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pairing — exchange a one-time code for a persistent auth token.
|
|
3
|
+
* Uses /api/agent/pair (flat route, not behind Easy Auth).
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
export async function pair(
|
|
@@ -7,12 +8,12 @@ export async function pair(
|
|
|
7
8
|
sessionId: string,
|
|
8
9
|
code: string
|
|
9
10
|
): Promise<{ token: string; sessionId: string }> {
|
|
10
|
-
const url = `${baseUrl}/api/
|
|
11
|
+
const url = `${baseUrl}/api/agent/pair`;
|
|
11
12
|
|
|
12
13
|
const res = await fetch(url, {
|
|
13
14
|
method: "POST",
|
|
14
15
|
headers: { "Content-Type": "application/json" },
|
|
15
|
-
body: JSON.stringify({ code }),
|
|
16
|
+
body: JSON.stringify({ sessionId, code }),
|
|
16
17
|
});
|
|
17
18
|
|
|
18
19
|
if (!res.ok) {
|
package/src/reporter.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Reporter — POST command results back to the web app.
|
|
3
|
+
* Uses /api/agent/result (flat route, not behind Easy Auth).
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
export async function reportResult(
|
|
6
7
|
baseUrl: string,
|
|
7
|
-
|
|
8
|
+
_sessionId: string,
|
|
8
9
|
token: string,
|
|
9
10
|
commandId: string,
|
|
10
|
-
status: "success" | "error",
|
|
11
|
+
status: "success" | "error" | "waiting_for_login",
|
|
11
12
|
result?: Record<string, unknown>
|
|
12
13
|
): Promise<void> {
|
|
13
|
-
const url = `${baseUrl}/api/
|
|
14
|
+
const url = `${baseUrl}/api/agent/result`;
|
|
14
15
|
|
|
15
16
|
try {
|
|
16
17
|
const res = await fetch(url, {
|
package/src/sse-client.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SSE client — listens for browser-automation commands from the server.
|
|
3
|
+
* Uses /api/agent/commands (flat route, not behind Easy Auth).
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
import { EventSource } from "eventsource";
|
|
@@ -13,12 +14,12 @@ interface IncomingCommand {
|
|
|
13
14
|
|
|
14
15
|
export function connectSSE(
|
|
15
16
|
baseUrl: string,
|
|
16
|
-
|
|
17
|
+
_sessionId: string,
|
|
17
18
|
token: string,
|
|
18
19
|
onCommand: (command: IncomingCommand) => void,
|
|
19
20
|
onError: (error: Error) => void
|
|
20
21
|
): { close: () => void } {
|
|
21
|
-
const url = `${baseUrl}/api/
|
|
22
|
+
const url = `${baseUrl}/api/agent/commands?token=${encodeURIComponent(token)}`;
|
|
22
23
|
|
|
23
24
|
let es: EventSource | null = null;
|
|
24
25
|
let closed = false;
|
|
@@ -34,7 +35,6 @@ export function connectSSE(
|
|
|
34
35
|
try {
|
|
35
36
|
const data = JSON.parse(evt.data) as IncomingCommand;
|
|
36
37
|
onCommand(data);
|
|
37
|
-
// Reset backoff on successful message
|
|
38
38
|
retryDelay = 1_000;
|
|
39
39
|
} catch (err) {
|
|
40
40
|
console.error(
|
|
@@ -64,7 +64,6 @@ export function connectSSE(
|
|
|
64
64
|
console.error(`\u274C SSE error: ${message} — reconnecting in ${retryDelay / 1_000}s`);
|
|
65
65
|
onError(new Error(message));
|
|
66
66
|
|
|
67
|
-
// Close the broken connection and schedule reconnect
|
|
68
67
|
es?.close();
|
|
69
68
|
es = null;
|
|
70
69
|
|