trawl-devices-agent 0.1.0
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/LICENSE +21 -0
- package/README.md +61 -0
- package/dist/auth.js +23 -0
- package/dist/auth.js.map +1 -0
- package/dist/codegen.js +41 -0
- package/dist/codegen.js.map +1 -0
- package/dist/control.js +106 -0
- package/dist/control.js.map +1 -0
- package/dist/devices.js +69 -0
- package/dist/devices.js.map +1 -0
- package/dist/guide.js +14 -0
- package/dist/guide.js.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/interpolate.js +20 -0
- package/dist/interpolate.js.map +1 -0
- package/dist/mask.js +19 -0
- package/dist/mask.js.map +1 -0
- package/dist/recorder.js +99 -0
- package/dist/recorder.js.map +1 -0
- package/dist/recorderInject.js +165 -0
- package/dist/recorderInject.js.map +1 -0
- package/dist/retention.js +21 -0
- package/dist/retention.js.map +1 -0
- package/dist/routes.js +140 -0
- package/dist/routes.js.map +1 -0
- package/dist/runner.js +373 -0
- package/dist/runner.js.map +1 -0
- package/dist/sandbox.js +80 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/server.js +100 -0
- package/dist/server.js.map +1 -0
- package/dist/sessions.js +85 -0
- package/dist/sessions.js.map +1 -0
- package/dist/steps.js +27 -0
- package/dist/steps.js.map +1 -0
- package/dist/targets.js +68 -0
- package/dist/targets.js.map +1 -0
- package/dist/traffic.js +116 -0
- package/dist/traffic.js.map +1 -0
- package/dist/transform.js +110 -0
- package/dist/transform.js.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/dist/workspace.js +50 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +50 -0
- package/skills/writing-device-scripts/SKILL.md +59 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-side recorder. Injected via addInitScript, so it runs before page
|
|
3
|
+
* scripts on every navigation. It reports candidate targets; the Node side
|
|
4
|
+
* decides which one survives (see recorder.ts).
|
|
5
|
+
*/
|
|
6
|
+
export const RECORDER_SOURCE = String.raw `
|
|
7
|
+
(() => {
|
|
8
|
+
if (window.__trawlRecorderInstalled) return;
|
|
9
|
+
window.__trawlRecorderInstalled = true;
|
|
10
|
+
|
|
11
|
+
const MARK = 'data-trawl-rec-el';
|
|
12
|
+
const state = { paused: false, mode: 'record', pendingFill: null };
|
|
13
|
+
|
|
14
|
+
const inOverlay = (el) => !!(el && el.closest && el.closest('[data-trawl-overlay]'));
|
|
15
|
+
|
|
16
|
+
const cssPath = (el) => {
|
|
17
|
+
const parts = [];
|
|
18
|
+
let node = el;
|
|
19
|
+
while (node && node.nodeType === 1 && parts.length < 6) {
|
|
20
|
+
let part = node.tagName.toLowerCase();
|
|
21
|
+
if (node.id) { parts.unshift('#' + CSS.escape(node.id)); break; }
|
|
22
|
+
const parent = node.parentElement;
|
|
23
|
+
if (parent) {
|
|
24
|
+
const sameTag = [...parent.children].filter((c) => c.tagName === node.tagName);
|
|
25
|
+
if (sameTag.length > 1) part += ':nth-of-type(' + (sameTag.indexOf(node) + 1) + ')';
|
|
26
|
+
}
|
|
27
|
+
parts.unshift(part);
|
|
28
|
+
node = node.parentElement;
|
|
29
|
+
}
|
|
30
|
+
return parts.join(' > ');
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const implicitRole = (el) => {
|
|
34
|
+
const tag = el.tagName.toLowerCase();
|
|
35
|
+
if (el.getAttribute('role')) return el.getAttribute('role');
|
|
36
|
+
if (tag === 'button') return 'button';
|
|
37
|
+
if (tag === 'a' && el.hasAttribute('href')) return 'link';
|
|
38
|
+
if (tag === 'select') return 'combobox';
|
|
39
|
+
if (tag === 'textarea') return 'textbox';
|
|
40
|
+
if (tag === 'input') {
|
|
41
|
+
const type = (el.getAttribute('type') || 'text').toLowerCase();
|
|
42
|
+
if (type === 'checkbox') return 'checkbox';
|
|
43
|
+
if (type === 'radio') return 'radio';
|
|
44
|
+
if (type === 'submit' || type === 'button') return 'button';
|
|
45
|
+
return 'textbox';
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const accessibleName = (el) => {
|
|
51
|
+
const aria = el.getAttribute('aria-label');
|
|
52
|
+
if (aria) return aria.trim();
|
|
53
|
+
if (el.labels && el.labels[0]) return el.labels[0].textContent.trim();
|
|
54
|
+
const text = (el.textContent || '').trim();
|
|
55
|
+
if (text && text.length <= 60) return text;
|
|
56
|
+
const value = el.getAttribute('value');
|
|
57
|
+
return value ? value.trim() : '';
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const labelText = (el) => (el.labels && el.labels[0] ? el.labels[0].textContent.trim() : '');
|
|
61
|
+
|
|
62
|
+
/** Ordered candidate targets, best first. */
|
|
63
|
+
const candidates = (el) => {
|
|
64
|
+
const out = [];
|
|
65
|
+
const testId = el.getAttribute('data-testid') || el.getAttribute('data-test-id') || el.getAttribute('data-qa');
|
|
66
|
+
if (testId) out.push({ testId: testId });
|
|
67
|
+
const role = implicitRole(el);
|
|
68
|
+
const name = accessibleName(el);
|
|
69
|
+
if (role && name) out.push({ role: role, name: name });
|
|
70
|
+
const label = labelText(el);
|
|
71
|
+
if (label) out.push({ label: label });
|
|
72
|
+
const placeholder = el.getAttribute('placeholder');
|
|
73
|
+
if (placeholder) out.push({ placeholder: placeholder });
|
|
74
|
+
const own = (el.textContent || '').trim();
|
|
75
|
+
if (own && own.length <= 40) out.push({ text: own });
|
|
76
|
+
out.push({ css: cssPath(el) });
|
|
77
|
+
return out;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const emit = (action, el, args) => {
|
|
81
|
+
if (state.paused) return;
|
|
82
|
+
el.setAttribute(MARK, '1');
|
|
83
|
+
return window.__trawlRec({ action: action, candidates: candidates(el), args: args || [] })
|
|
84
|
+
.catch(() => {})
|
|
85
|
+
.then(() => el.removeAttribute(MARK));
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const flushFill = () => {
|
|
89
|
+
const pending = state.pendingFill;
|
|
90
|
+
if (!pending) return;
|
|
91
|
+
state.pendingFill = null;
|
|
92
|
+
emit('fill', pending.el, [pending.value]);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
document.addEventListener('click', (e) => {
|
|
96
|
+
const el = e.target;
|
|
97
|
+
if (!el || inOverlay(el)) return;
|
|
98
|
+
flushFill();
|
|
99
|
+
if (state.mode === 'assert') {
|
|
100
|
+
state.mode = 'record';
|
|
101
|
+
const text = (el.textContent || '').trim();
|
|
102
|
+
emit(text ? 'expectText' : 'expectVisible', el, text ? [text] : []);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const tag = el.tagName ? el.tagName.toLowerCase() : '';
|
|
106
|
+
const type = (el.getAttribute && (el.getAttribute('type') || '')).toLowerCase();
|
|
107
|
+
if (tag === 'input' && (type === 'checkbox' || type === 'radio')) {
|
|
108
|
+
emit(el.checked ? 'check' : 'uncheck', el, []);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
emit('click', el, []);
|
|
112
|
+
}, true);
|
|
113
|
+
|
|
114
|
+
document.addEventListener('input', (e) => {
|
|
115
|
+
const el = e.target;
|
|
116
|
+
if (!el || inOverlay(el)) return;
|
|
117
|
+
if (el.tagName === 'SELECT') { emit('select', el, [el.value]); return; }
|
|
118
|
+
if (state.pendingFill && state.pendingFill.el !== el) flushFill();
|
|
119
|
+
state.pendingFill = { el: el, value: el.value };
|
|
120
|
+
}, true);
|
|
121
|
+
|
|
122
|
+
document.addEventListener('change', (e) => {
|
|
123
|
+
if (state.pendingFill && state.pendingFill.el === e.target) flushFill();
|
|
124
|
+
}, true);
|
|
125
|
+
|
|
126
|
+
document.addEventListener('keydown', (e) => {
|
|
127
|
+
if (inOverlay(e.target)) return;
|
|
128
|
+
if (e.key === 'Enter' || e.key === 'Escape') { flushFill(); emit('press', e.target, [e.key]); }
|
|
129
|
+
}, true);
|
|
130
|
+
|
|
131
|
+
window.addEventListener('beforeunload', flushFill);
|
|
132
|
+
|
|
133
|
+
window.__trawlRecorderControl = (command) => {
|
|
134
|
+
if (command === 'pause') state.paused = true;
|
|
135
|
+
if (command === 'resume') state.paused = false;
|
|
136
|
+
if (command === 'assert') state.mode = 'assert';
|
|
137
|
+
if (command === 'flush') flushFill();
|
|
138
|
+
return { paused: state.paused, mode: state.mode };
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const overlay = document.createElement('div');
|
|
142
|
+
overlay.setAttribute('data-trawl-overlay', '1');
|
|
143
|
+
overlay.style.cssText =
|
|
144
|
+
'position:fixed;z-index:2147483647;right:12px;bottom:12px;display:flex;gap:6px;' +
|
|
145
|
+
'padding:8px;border-radius:8px;background:#111;color:#fff;font:12px system-ui;box-shadow:0 2px 12px rgba(0,0,0,.4)';
|
|
146
|
+
const button = (label, command) => {
|
|
147
|
+
const b = document.createElement('button');
|
|
148
|
+
b.textContent = label;
|
|
149
|
+
b.style.cssText = 'all:unset;cursor:pointer;padding:4px 8px;border-radius:4px;background:#333;color:#fff';
|
|
150
|
+
b.addEventListener('click', () => {
|
|
151
|
+
const next = window.__trawlRecorderControl(command === 'pause' && state.paused ? 'resume' : command);
|
|
152
|
+
if (command === 'pause') b.textContent = next.paused ? '▶' : '⏸';
|
|
153
|
+
}, true);
|
|
154
|
+
return b;
|
|
155
|
+
};
|
|
156
|
+
const install = () => {
|
|
157
|
+
if (!document.body || document.querySelector('[data-trawl-overlay]')) return;
|
|
158
|
+
overlay.append(button('⏸', 'pause'), button('✓ assert', 'assert'));
|
|
159
|
+
document.body.appendChild(overlay);
|
|
160
|
+
};
|
|
161
|
+
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', install);
|
|
162
|
+
else install();
|
|
163
|
+
})();
|
|
164
|
+
`;
|
|
165
|
+
//# sourceMappingURL=recorderInject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recorderInject.js","sourceRoot":"","sources":["../src/recorderInject.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8JxC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { runsDir } from "./workspace.js";
|
|
4
|
+
/** Delete all but the `keep` most recent run folders. Returns what was removed. */
|
|
5
|
+
export async function pruneRuns(root, keep) {
|
|
6
|
+
const dir = runsDir(root);
|
|
7
|
+
let entries;
|
|
8
|
+
try {
|
|
9
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
const dated = await Promise.all(entries
|
|
15
|
+
.filter((e) => e.isDirectory())
|
|
16
|
+
.map(async (e) => ({ name: e.name, mtime: (await fs.stat(path.join(dir, e.name))).mtimeMs })));
|
|
17
|
+
const doomed = dated.sort((a, b) => b.mtime - a.mtime).slice(keep);
|
|
18
|
+
await Promise.all(doomed.map((d) => fs.rm(path.join(dir, d.name), { recursive: true, force: true })));
|
|
19
|
+
return doomed.map((d) => d.name);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=retention.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention.js","sourceRoot":"","sources":["../src/retention.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,IAAY;IACxD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAC7B,OAAO;SACJ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SAC9B,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAChG,CAAC;IACF,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnE,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACtG,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC"}
|
package/dist/routes.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { SessionStore } from "./sessions.js";
|
|
2
|
+
import { Runner } from "./runner.js";
|
|
3
|
+
import { getDevice, loadDevices, saveDevice } from "./devices.js";
|
|
4
|
+
import { listScripts, readScript, writeScript } from "./workspace.js";
|
|
5
|
+
import { collect } from "./sandbox.js";
|
|
6
|
+
import { AgentError } from "./types.js";
|
|
7
|
+
import { RecorderStore } from "./recorder.js";
|
|
8
|
+
import { performAction, snapshot } from "./control.js";
|
|
9
|
+
import { readGuide } from "./guide.js";
|
|
10
|
+
export function buildRoutes(deps) {
|
|
11
|
+
const workspace = deps.workspace;
|
|
12
|
+
const sessions = deps.sessions ?? new SessionStore();
|
|
13
|
+
const trawlProxyPort = deps.trawlProxyPort ?? 8080;
|
|
14
|
+
const runner = deps.runner ?? new Runner({ sessions, workspace, trawlProxyPort });
|
|
15
|
+
const recorder = new RecorderStore({ sessions, workspace });
|
|
16
|
+
const body = (value) => {
|
|
17
|
+
if (!value || typeof value !== "object")
|
|
18
|
+
throw new AgentError("script", "a JSON body is required");
|
|
19
|
+
return value;
|
|
20
|
+
};
|
|
21
|
+
return [
|
|
22
|
+
{
|
|
23
|
+
method: "GET",
|
|
24
|
+
path: "/devices",
|
|
25
|
+
handler: async () => ({ devices: await loadDevices(workspace), sessions: sessions.list() }),
|
|
26
|
+
},
|
|
27
|
+
{ method: "POST", path: "/devices", handler: async (_r, _p, b) => ({ device: await saveDevice(workspace, b) }) },
|
|
28
|
+
{
|
|
29
|
+
method: "POST",
|
|
30
|
+
path: "/sessions",
|
|
31
|
+
handler: async (_r, _p, b) => {
|
|
32
|
+
const { deviceId, headless } = body(b);
|
|
33
|
+
const device = await getDevice(workspace, deviceId);
|
|
34
|
+
return { session: await sessions.start(device, { trawlProxyPort, headless }) };
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{ method: "GET", path: "/sessions", handler: async () => ({ sessions: sessions.list() }) },
|
|
38
|
+
{
|
|
39
|
+
method: "DELETE",
|
|
40
|
+
path: "/sessions/:id",
|
|
41
|
+
handler: async (_r, p) => {
|
|
42
|
+
await sessions.stop(p.id);
|
|
43
|
+
return { ok: true };
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{ method: "GET", path: "/scripts", handler: async () => ({ scripts: await listScripts(workspace) }) },
|
|
47
|
+
{
|
|
48
|
+
method: "GET",
|
|
49
|
+
path: "/scripts/read",
|
|
50
|
+
handler: async (_r, p) => ({ code: await readScript(workspace, p.path) }),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
method: "POST",
|
|
54
|
+
path: "/scripts/write",
|
|
55
|
+
handler: async (_r, _p, b) => {
|
|
56
|
+
const { path: rel, code } = body(b);
|
|
57
|
+
const validation = await collect(code);
|
|
58
|
+
if (validation.errors.length) {
|
|
59
|
+
throw new AgentError("script", `refusing to write: ${validation.errors.map((e) => e.message).join("; ")}`);
|
|
60
|
+
}
|
|
61
|
+
await writeScript(workspace, rel, code);
|
|
62
|
+
return { path: rel, steps: validation.steps.length };
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
method: "POST",
|
|
67
|
+
path: "/scripts/validate",
|
|
68
|
+
handler: async (_r, _p, b) => {
|
|
69
|
+
const { code, path: rel } = body(b);
|
|
70
|
+
const source = code ?? (await readScript(workspace, rel));
|
|
71
|
+
return collect(source);
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
method: "POST",
|
|
76
|
+
path: "/runs",
|
|
77
|
+
handler: async (_r, _p, b) => {
|
|
78
|
+
const input = body(b);
|
|
79
|
+
const code = input.code ?? (await readScript(workspace, input.path));
|
|
80
|
+
const device = await getDevice(workspace, input.deviceId);
|
|
81
|
+
return runner.start({
|
|
82
|
+
code,
|
|
83
|
+
scriptPath: input.path,
|
|
84
|
+
device,
|
|
85
|
+
sessionId: input.sessionId,
|
|
86
|
+
env: input.env ?? {},
|
|
87
|
+
secrets: input.secrets ?? {},
|
|
88
|
+
headless: input.headless,
|
|
89
|
+
});
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{ method: "GET", path: "/runs", handler: async (_r, p) => ({ runs: runner.list(Number(p.limit ?? 20)) }) },
|
|
93
|
+
{
|
|
94
|
+
method: "GET",
|
|
95
|
+
path: "/runs/:id",
|
|
96
|
+
handler: async (_r, p) => {
|
|
97
|
+
const report = runner.get(p.id);
|
|
98
|
+
if (!report)
|
|
99
|
+
throw new AgentError("agent", `unknown run: ${p.id}`);
|
|
100
|
+
return report;
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
{ method: "DELETE", path: "/runs/:id", handler: async (_r, p) => ({ cancelled: runner.cancel(p.id) }) },
|
|
104
|
+
{
|
|
105
|
+
method: "POST",
|
|
106
|
+
path: "/record/start",
|
|
107
|
+
handler: async (_r, _p, b) => {
|
|
108
|
+
const { sessionId, deviceId, url } = body(b);
|
|
109
|
+
if (!sessionId && !deviceId)
|
|
110
|
+
throw new AgentError("script", "deviceId or sessionId is required");
|
|
111
|
+
const id = sessionId ?? (await sessions.start(await getDevice(workspace, deviceId), { trawlProxyPort })).sessionId;
|
|
112
|
+
return recorder.start(id, url);
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
{ method: "GET", path: "/record/:id", handler: async (_r, p) => recorder.get(p.id) },
|
|
116
|
+
{
|
|
117
|
+
method: "POST",
|
|
118
|
+
path: "/record/:id/stop",
|
|
119
|
+
handler: async (_r, p, b) => recorder.stop(p.id, (b ?? {})),
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
method: "POST",
|
|
123
|
+
path: "/control/snapshot",
|
|
124
|
+
handler: async (_r, _p, b) => {
|
|
125
|
+
const { sessionId } = body(b);
|
|
126
|
+
return { nodes: await snapshot(sessions.get(sessionId).page) };
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
method: "POST",
|
|
131
|
+
path: "/control/do",
|
|
132
|
+
handler: async (_r, _p, b) => {
|
|
133
|
+
const { sessionId, ...action } = body(b);
|
|
134
|
+
return performAction(sessions.get(sessionId).page, action);
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
{ method: "GET", path: "/guide", handler: async () => ({ guide: await readGuide() }) },
|
|
138
|
+
];
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
|