@rubytech/taskmaster 1.0.43 → 1.0.45
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/routes/screencast.js +22 -2
- package/dist/browser/screencast.js +9 -1
- package/dist/build-info.json +3 -3
- package/dist/cli/provision-seed.js +4 -1
- package/dist/control-ui/assets/{index-CpAWYZjj.js → index-BKYdwFD8.js} +172 -163
- package/dist/control-ui/assets/index-BKYdwFD8.js.map +1 -0
- package/dist/control-ui/assets/{index-D5w5UtCL.css → index-BjsEHhKc.css} +1 -1
- package/dist/control-ui/index.html +2 -2
- package/dist/gateway/server-methods/browser-screencast.js +25 -5
- package/package.json +1 -1
- package/skills/google-ai/references/browser-setup.md +2 -0
- package/skills/tavily/references/browser-setup.md +1 -0
- package/taskmaster-docs/USER-GUIDE.md +7 -4
- package/templates/customer/agents/admin/BOOTSTRAP.md +55 -17
- package/dist/control-ui/assets/index-CpAWYZjj.js.map +0 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { createSubsystemLogger } from "../../logging/subsystem.js";
|
|
1
2
|
import { startScreencast, stopScreencast } from "../screencast.js";
|
|
2
3
|
import { getProfileContext, jsonError, toStringOrEmpty, toNumber } from "./utils.js";
|
|
3
4
|
import { normalizeCdpWsUrl, appendCdpPath, fetchJson } from "../cdp.js";
|
|
5
|
+
const log = createSubsystemLogger("browser").child("screencast");
|
|
4
6
|
// Active screencast sessions, keyed by a caller-chosen label
|
|
5
7
|
const activeSessions = new Map();
|
|
6
8
|
// Frame listeners registered by the gateway relay
|
|
@@ -23,36 +25,51 @@ export function getActiveScreencastSession(key) {
|
|
|
23
25
|
}
|
|
24
26
|
export function registerBrowserScreencastRoutes(app, ctx) {
|
|
25
27
|
app.post("/screencast/start", async (req, res) => {
|
|
28
|
+
log.info("POST /screencast/start");
|
|
26
29
|
const profileCtx = getProfileContext(req, ctx);
|
|
27
|
-
if ("error" in profileCtx)
|
|
30
|
+
if ("error" in profileCtx) {
|
|
31
|
+
log.error(`profile context error: ${profileCtx.error}`);
|
|
28
32
|
return jsonError(res, profileCtx.status, profileCtx.error);
|
|
33
|
+
}
|
|
29
34
|
const body = (req.body ?? {});
|
|
30
35
|
const label = toStringOrEmpty(body.label) || "default";
|
|
31
36
|
const targetId = toStringOrEmpty(body.targetId) || undefined;
|
|
32
37
|
const quality = toNumber(body.quality) ?? 60;
|
|
33
38
|
const maxWidth = toNumber(body.maxWidth) ?? 1280;
|
|
34
39
|
const maxHeight = toNumber(body.maxHeight) ?? 720;
|
|
40
|
+
log.info(`profile=${profileCtx.profile.name} label=${label} quality=${quality}`);
|
|
35
41
|
// Stop existing session with same label
|
|
36
42
|
const existing = activeSessions.get(label);
|
|
37
43
|
if (existing?.active) {
|
|
44
|
+
log.info(`stopping existing session label=${label}`);
|
|
38
45
|
stopScreencast(existing);
|
|
39
46
|
}
|
|
40
47
|
try {
|
|
48
|
+
log.info("ensuring browser available");
|
|
41
49
|
await profileCtx.ensureBrowserAvailable();
|
|
50
|
+
log.info("ensuring tab available");
|
|
42
51
|
const tab = await profileCtx.ensureTabAvailable(targetId);
|
|
52
|
+
log.info(`tab resolved: targetId=${tab.targetId} wsUrl=${tab.wsUrl ? "yes" : "no"}`);
|
|
43
53
|
// Resolve WebSocket URL
|
|
44
54
|
let wsUrl = tab.wsUrl;
|
|
45
55
|
if (!wsUrl) {
|
|
56
|
+
log.info("tab has no wsUrl, trying /json/version endpoint");
|
|
46
57
|
// For remote profiles, try version endpoint
|
|
47
58
|
const version = await fetchJson(appendCdpPath(profileCtx.profile.cdpUrl, "/json/version"), 1500);
|
|
48
59
|
const rawWsUrl = String(version?.webSocketDebuggerUrl ?? "").trim();
|
|
49
60
|
if (rawWsUrl) {
|
|
50
61
|
wsUrl = normalizeCdpWsUrl(rawWsUrl, profileCtx.profile.cdpUrl);
|
|
62
|
+
log.info(`resolved wsUrl from /json/version: ${wsUrl}`);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
log.warn("no webSocketDebuggerUrl in /json/version response");
|
|
51
66
|
}
|
|
52
67
|
}
|
|
53
68
|
if (!wsUrl) {
|
|
69
|
+
log.error("could not resolve WebSocket URL for screencast");
|
|
54
70
|
return jsonError(res, 500, "Could not resolve WebSocket URL for screencast");
|
|
55
71
|
}
|
|
72
|
+
log.info(`starting CDP screencast on ${wsUrl}`);
|
|
56
73
|
const session = await startScreencast({
|
|
57
74
|
wsUrl,
|
|
58
75
|
quality,
|
|
@@ -68,14 +85,17 @@ export function registerBrowserScreencastRoutes(app, ctx) {
|
|
|
68
85
|
}
|
|
69
86
|
}
|
|
70
87
|
},
|
|
71
|
-
onClose: () => {
|
|
88
|
+
onClose: (reason) => {
|
|
89
|
+
log.info(`screencast session closed: label=${label} reason=${reason}`);
|
|
72
90
|
activeSessions.delete(label);
|
|
73
91
|
},
|
|
74
92
|
});
|
|
75
93
|
activeSessions.set(label, session);
|
|
94
|
+
log.info(`screencast started: sessionId=${session.id} label=${label}`);
|
|
76
95
|
res.json({ ok: true, sessionId: session.id, label });
|
|
77
96
|
}
|
|
78
97
|
catch (err) {
|
|
98
|
+
log.error(`screencast start failed: ${err}`);
|
|
79
99
|
jsonError(res, 500, String(err));
|
|
80
100
|
}
|
|
81
101
|
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import WebSocket from "ws";
|
|
2
|
+
import { createSubsystemLogger } from "../logging/subsystem.js";
|
|
2
3
|
import { getHeadersWithAuth } from "./cdp.helpers.js";
|
|
3
4
|
import { rawDataToString } from "../infra/ws.js";
|
|
5
|
+
const log = createSubsystemLogger("browser").child("screencast-cdp");
|
|
4
6
|
let sessionCounter = 0;
|
|
5
7
|
/**
|
|
6
8
|
* Start a persistent CDP screencast session.
|
|
@@ -14,6 +16,7 @@ export async function startScreencast(opts) {
|
|
|
14
16
|
const quality = Math.max(0, Math.min(100, opts.quality ?? 60));
|
|
15
17
|
const maxWidth = opts.maxWidth ?? 1280;
|
|
16
18
|
const maxHeight = opts.maxHeight ?? 720;
|
|
19
|
+
log.info(`connecting to CDP: ${opts.wsUrl}`);
|
|
17
20
|
const headers = getHeadersWithAuth(opts.wsUrl);
|
|
18
21
|
const ws = new WebSocket(opts.wsUrl, {
|
|
19
22
|
handshakeTimeout: 5000,
|
|
@@ -87,7 +90,8 @@ export async function startScreencast(opts) {
|
|
|
87
90
|
// ignore parse errors
|
|
88
91
|
}
|
|
89
92
|
});
|
|
90
|
-
ws.on("close", () => {
|
|
93
|
+
ws.on("close", (code, reason) => {
|
|
94
|
+
log.info(`CDP socket closed: code=${code} reason=${reason?.toString() ?? ""}`);
|
|
91
95
|
session.active = false;
|
|
92
96
|
for (const [, p] of pending) {
|
|
93
97
|
p.reject(new Error("CDP socket closed"));
|
|
@@ -96,6 +100,7 @@ export async function startScreencast(opts) {
|
|
|
96
100
|
opts.onClose?.("WebSocket closed");
|
|
97
101
|
});
|
|
98
102
|
ws.on("error", (err) => {
|
|
103
|
+
log.error(`CDP socket error: ${err.message}`);
|
|
99
104
|
opts.onClose?.(`WebSocket error: ${err.message}`);
|
|
100
105
|
});
|
|
101
106
|
// Wait for connection
|
|
@@ -103,8 +108,10 @@ export async function startScreencast(opts) {
|
|
|
103
108
|
ws.once("open", () => resolve());
|
|
104
109
|
ws.once("error", (err) => reject(err));
|
|
105
110
|
});
|
|
111
|
+
log.info("CDP socket connected, enabling Page domain");
|
|
106
112
|
// Enable Page domain and start screencast
|
|
107
113
|
await send("Page.enable");
|
|
114
|
+
log.info(`starting Page.startScreencast format=${format} quality=${quality}`);
|
|
108
115
|
await send("Page.startScreencast", {
|
|
109
116
|
format,
|
|
110
117
|
quality,
|
|
@@ -112,6 +119,7 @@ export async function startScreencast(opts) {
|
|
|
112
119
|
maxHeight,
|
|
113
120
|
});
|
|
114
121
|
session.active = true;
|
|
122
|
+
log.info(`screencast active: ${id}`);
|
|
115
123
|
return session;
|
|
116
124
|
}
|
|
117
125
|
/**
|
package/dist/build-info.json
CHANGED
|
@@ -118,6 +118,9 @@ export function buildDefaultAgentList(workspaceRoot) {
|
|
|
118
118
|
},
|
|
119
119
|
tools: {
|
|
120
120
|
allow: [
|
|
121
|
+
"read",
|
|
122
|
+
"write",
|
|
123
|
+
"edit",
|
|
121
124
|
"message",
|
|
122
125
|
"memory_search",
|
|
123
126
|
"memory_get",
|
|
@@ -143,7 +146,7 @@ export function buildDefaultAgentList(workspaceRoot) {
|
|
|
143
146
|
"browser",
|
|
144
147
|
"skill_read",
|
|
145
148
|
],
|
|
146
|
-
deny: ["exec", "process", "group:
|
|
149
|
+
deny: ["exec", "process", "group:runtime", "canvas"],
|
|
147
150
|
},
|
|
148
151
|
};
|
|
149
152
|
return [publicAgent, adminAgent];
|