@poolzin/pool-bot 2026.2.23 → 2026.2.25
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/CHANGELOG.md +29 -0
- package/dist/acp/client.js +207 -18
- package/dist/acp/secret-file.js +22 -0
- package/dist/agents/agent-scope.js +10 -0
- package/dist/agents/bash-process-registry.test-helpers.js +29 -0
- package/dist/agents/bash-tools.exec-approval-request.js +20 -0
- package/dist/agents/bash-tools.exec-host-gateway.js +230 -0
- package/dist/agents/bash-tools.exec-host-node.js +235 -0
- package/dist/agents/bash-tools.exec-types.js +1 -0
- package/dist/agents/bash-tools.process.js +224 -218
- package/dist/agents/content-blocks.js +16 -0
- package/dist/agents/model-fallback.js +96 -101
- package/dist/agents/models-config.providers.js +299 -182
- package/dist/agents/pi-embedded-payloads.js +1 -0
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.fixture.js +34 -0
- package/dist/agents/skills.test-helpers.js +13 -0
- package/dist/agents/stable-stringify.js +12 -0
- package/dist/agents/subagent-registry.mocks.shared.js +12 -0
- package/dist/agents/test-helpers/assistant-message-fixtures.js +29 -0
- package/dist/agents/test-helpers/pi-tools-sandbox-context.js +27 -0
- package/dist/agents/tool-policy-shared.js +108 -0
- package/dist/agents/tools/browser-tool.js +160 -54
- package/dist/agents/tools/cron-tool.test-helpers.js +12 -0
- package/dist/agents/tools/discord-actions-moderation-shared.js +27 -0
- package/dist/agents/tools/image-tool.js +214 -99
- package/dist/agents/tools/sessions-history-tool.js +140 -108
- package/dist/agents/workspace.js +222 -46
- package/dist/auto-reply/commands-registry.js +15 -18
- package/dist/auto-reply/fallback-state.js +114 -0
- package/dist/auto-reply/model-runtime.js +68 -0
- package/dist/auto-reply/reply/agent-runner-execution.js +36 -4
- package/dist/auto-reply/reply/agent-runner.js +165 -39
- package/dist/auto-reply/reply/commands-setunset-standard.js +13 -0
- package/dist/browser/config.js +26 -0
- package/dist/browser/navigation-guard.js +31 -0
- package/dist/browser/routes/agent.act.js +431 -424
- package/dist/browser/routes/agent.shared.js +47 -3
- package/dist/browser/routes/agent.snapshot.js +122 -116
- package/dist/browser/routes/agent.storage.js +303 -297
- package/dist/browser/routes/tabs.js +154 -100
- package/dist/browser/server-lifecycle.js +37 -0
- package/dist/build-info.json +3 -3
- package/dist/channels/allow-from.js +25 -0
- package/dist/channels/plugins/account-action-gate.js +13 -0
- package/dist/channels/plugins/message-actions.js +10 -0
- package/dist/channels/telegram/api.js +18 -0
- package/dist/cli/argv.js +84 -21
- package/dist/cli/banner.js +2 -1
- package/dist/cli/exec-approvals-cli.js +92 -124
- package/dist/cli/memory-cli.js +158 -61
- package/dist/cli/nodes-cli/register.push.js +63 -0
- package/dist/cli/nodes-media-utils.js +21 -0
- package/dist/cli/plugins-cli.js +245 -61
- package/dist/cli/program/build-program.js +3 -1
- package/dist/cli/program/command-registry.js +223 -136
- package/dist/cli/program/help.js +43 -12
- package/dist/cli/route.js +1 -1
- package/dist/cli/test-runtime-capture.js +24 -0
- package/dist/commands/agent.js +163 -87
- package/dist/commands/channels.mock-harness.js +23 -0
- package/dist/commands/daemon-install-runtime-warning.js +11 -0
- package/dist/commands/onboard-helpers.js +4 -4
- package/dist/commands/sessions.test-helpers.js +61 -0
- package/dist/compat/legacy-names.js +2 -2
- package/dist/config/commands.js +3 -0
- package/dist/config/config.js +1 -1
- package/dist/config/env-substitution.js +62 -34
- package/dist/config/env-vars.js +9 -0
- package/dist/config/io.js +571 -171
- package/dist/config/merge-patch.js +50 -4
- package/dist/config/redact-snapshot.js +404 -76
- package/dist/config/schema.js +58 -570
- package/dist/config/validation.js +140 -85
- package/dist/config/zod-schema.hooks.js +40 -11
- package/dist/config/zod-schema.installs.js +20 -0
- package/dist/config/zod-schema.js +8 -7
- package/dist/control-ui/assets/{index-HRr1grwl.js → index-Dvkl4Xlx.js} +2 -1
- package/dist/control-ui/assets/{index-HRr1grwl.js.map → index-Dvkl4Xlx.js.map} +1 -1
- package/dist/control-ui/index.html +1 -1
- package/dist/daemon/cmd-argv.js +21 -0
- package/dist/daemon/cmd-set.js +58 -0
- package/dist/daemon/service-types.js +1 -0
- package/dist/discord/monitor/exec-approvals.js +357 -162
- package/dist/gateway/auth.js +38 -3
- package/dist/gateway/call.js +149 -68
- package/dist/gateway/canvas-capability.js +75 -0
- package/dist/gateway/control-plane-audit.js +28 -0
- package/dist/gateway/control-plane-rate-limit.js +53 -0
- package/dist/gateway/events.js +1 -0
- package/dist/gateway/hooks.js +109 -54
- package/dist/gateway/http-common.js +22 -0
- package/dist/gateway/method-scopes.js +169 -0
- package/dist/gateway/net.js +23 -0
- package/dist/gateway/openresponses-http.js +120 -110
- package/dist/gateway/probe-auth.js +2 -0
- package/dist/gateway/protocol/index.js +3 -2
- package/dist/gateway/protocol/schema/protocol-schemas.js +2 -0
- package/dist/gateway/protocol/schema/push.js +18 -0
- package/dist/gateway/protocol/schema.js +1 -0
- package/dist/gateway/server-http.js +236 -52
- package/dist/gateway/server-methods/agent.js +162 -24
- package/dist/gateway/server-methods/chat.js +461 -130
- package/dist/gateway/server-methods/config.js +193 -150
- package/dist/gateway/server-methods/nodes.helpers.js +12 -0
- package/dist/gateway/server-methods/nodes.js +251 -69
- package/dist/gateway/server-methods/push.js +53 -0
- package/dist/gateway/server-reload-handlers.js +2 -3
- package/dist/gateway/server-runtime-config.js +5 -0
- package/dist/gateway/server-runtime-state.js +2 -0
- package/dist/gateway/server-ws-runtime.js +1 -0
- package/dist/gateway/server.impl.js +296 -139
- package/dist/gateway/session-preview.test-helpers.js +11 -0
- package/dist/gateway/startup-auth.js +126 -0
- package/dist/gateway/test-helpers.agent-results.js +15 -0
- package/dist/gateway/test-helpers.mocks.js +37 -14
- package/dist/gateway/test-helpers.server.js +161 -77
- package/dist/hooks/bundled/session-memory/handler.js +165 -34
- package/dist/hooks/gmail-watcher-lifecycle.js +23 -0
- package/dist/infra/archive-path.js +49 -0
- package/dist/infra/device-pairing.js +148 -167
- package/dist/infra/exec-approvals-allowlist.js +19 -70
- package/dist/infra/exec-approvals-analysis.js +44 -17
- package/dist/infra/exec-safe-bin-policy.js +269 -0
- package/dist/infra/fixed-window-rate-limit.js +33 -0
- package/dist/infra/git-root.js +61 -0
- package/dist/infra/heartbeat-active-hours.js +2 -2
- package/dist/infra/heartbeat-reason.js +40 -0
- package/dist/infra/heartbeat-runner.js +72 -32
- package/dist/infra/install-source-utils.js +91 -7
- package/dist/infra/node-pairing.js +50 -105
- package/dist/infra/npm-integrity.js +45 -0
- package/dist/infra/npm-pack-install.js +40 -0
- package/dist/infra/outbound/channel-adapters.js +20 -7
- package/dist/infra/outbound/message-action-runner.js +107 -327
- package/dist/infra/outbound/message.js +59 -36
- package/dist/infra/outbound/outbound-policy.js +52 -25
- package/dist/infra/outbound/outbound-send-service.js +58 -71
- package/dist/infra/pairing-files.js +10 -0
- package/dist/infra/plain-object.js +9 -0
- package/dist/infra/push-apns.js +365 -0
- package/dist/infra/restart-sentinel.js +16 -1
- package/dist/infra/restart.js +229 -26
- package/dist/infra/scp-host.js +54 -0
- package/dist/infra/update-startup.js +86 -9
- package/dist/media/inbound-path-policy.js +114 -0
- package/dist/media/input-files.js +16 -0
- package/dist/memory/test-manager.js +8 -0
- package/dist/plugin-sdk/temp-path.js +47 -0
- package/dist/plugins/discovery.js +217 -23
- package/dist/plugins/hook-runner-global.js +16 -0
- package/dist/plugins/loader.js +192 -26
- package/dist/plugins/logger.js +8 -0
- package/dist/plugins/manifest-registry.js +3 -0
- package/dist/plugins/path-safety.js +34 -0
- package/dist/plugins/registry.js +5 -2
- package/dist/plugins/runtime/index.js +271 -206
- package/dist/providers/github-copilot-models.js +4 -1
- package/dist/security/audit-channel.js +8 -19
- package/dist/security/audit-extra.async.js +354 -182
- package/dist/security/audit-extra.js +11 -1
- package/dist/security/audit-extra.sync.js +340 -33
- package/dist/security/audit-fs.js +31 -13
- package/dist/security/audit.js +145 -371
- package/dist/security/dm-policy-shared.js +24 -0
- package/dist/security/external-content.js +20 -8
- package/dist/security/fix.js +49 -85
- package/dist/security/scan-paths.js +20 -0
- package/dist/security/secret-equal.js +3 -7
- package/dist/security/windows-acl.js +30 -15
- package/dist/shared/node-list-parse.js +13 -0
- package/dist/shared/operator-scope-compat.js +37 -0
- package/dist/shared/text-chunking.js +29 -0
- package/dist/slack/blocks.test-helpers.js +31 -0
- package/dist/slack/monitor/mrkdwn.js +8 -0
- package/dist/telegram/bot-message-dispatch.js +366 -164
- package/dist/telegram/draft-stream.js +30 -7
- package/dist/telegram/reasoning-lane-coordinator.js +128 -0
- package/dist/terminal/prompt-select-styled.js +9 -0
- package/dist/test-utils/command-runner.js +6 -0
- package/dist/test-utils/internal-hook-event-payload.js +10 -0
- package/dist/test-utils/model-auth-mock.js +12 -0
- package/dist/test-utils/provider-usage-fetch.js +14 -0
- package/dist/test-utils/temp-home.js +33 -0
- package/dist/tui/components/chat-log.js +9 -0
- package/dist/tui/tui-command-handlers.js +36 -27
- package/dist/tui/tui-event-handlers.js +122 -32
- package/dist/tui/tui.js +181 -45
- package/dist/utils/mask-api-key.js +10 -0
- package/dist/utils/run-with-concurrency.js +39 -0
- package/dist/web/media.js +4 -0
- package/docs/tools/slash-commands.md +5 -1
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/discord/package.json +1 -1
- package/extensions/feishu/package.json +1 -1
- package/extensions/feishu/src/external-keys.ts +19 -0
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/lobster/src/windows-spawn.ts +193 -0
- package/extensions/matrix/CHANGELOG.md +5 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/matrix/src/matrix/actions/limits.ts +6 -0
- package/extensions/mattermost/package.json +1 -1
- package/extensions/mattermost/src/mattermost/reactions.test-helpers.ts +83 -0
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +5 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +5 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/openai-codex-auth/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/slack/package.json +1 -1
- package/extensions/telegram/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +5 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +5 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +5 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +5 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +1 -1
|
@@ -1,386 +1,392 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readBody, resolveTargetIdFromBody, resolveTargetIdFromQuery, withPlaywrightRouteContext, } from "./agent.shared.js";
|
|
2
2
|
import { jsonError, toBoolean, toNumber, toStringOrEmpty } from "./utils.js";
|
|
3
|
+
export function parseStorageKind(raw) {
|
|
4
|
+
if (raw === "local" || raw === "session") {
|
|
5
|
+
return raw;
|
|
6
|
+
}
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
export function parseStorageMutationRequest(kindParam, body) {
|
|
10
|
+
return {
|
|
11
|
+
kind: parseStorageKind(toStringOrEmpty(kindParam)),
|
|
12
|
+
targetId: resolveTargetIdFromBody(body),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function parseRequiredStorageMutationRequest(kindParam, body) {
|
|
16
|
+
const parsed = parseStorageMutationRequest(kindParam, body);
|
|
17
|
+
if (!parsed.kind) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
kind: parsed.kind,
|
|
22
|
+
targetId: parsed.targetId,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function parseStorageMutationOrRespond(res, kindParam, body) {
|
|
26
|
+
const parsed = parseRequiredStorageMutationRequest(kindParam, body);
|
|
27
|
+
if (!parsed) {
|
|
28
|
+
jsonError(res, 400, "kind must be local|session");
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
return parsed;
|
|
32
|
+
}
|
|
33
|
+
function parseStorageMutationFromRequest(req, res) {
|
|
34
|
+
const body = readBody(req);
|
|
35
|
+
const parsed = parseStorageMutationOrRespond(res, req.params.kind, body);
|
|
36
|
+
if (!parsed) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return { body, parsed };
|
|
40
|
+
}
|
|
3
41
|
export function registerBrowserAgentStorageRoutes(app, ctx) {
|
|
4
42
|
app.get("/cookies", async (req, res) => {
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
catch (err) {
|
|
21
|
-
handleRouteError(ctx, res, err);
|
|
22
|
-
}
|
|
43
|
+
const targetId = resolveTargetIdFromQuery(req.query);
|
|
44
|
+
await withPlaywrightRouteContext({
|
|
45
|
+
req,
|
|
46
|
+
res,
|
|
47
|
+
ctx,
|
|
48
|
+
targetId,
|
|
49
|
+
feature: "cookies",
|
|
50
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
51
|
+
const result = await pw.cookiesGetViaPlaywright({
|
|
52
|
+
cdpUrl,
|
|
53
|
+
targetId: tab.targetId,
|
|
54
|
+
});
|
|
55
|
+
res.json({ ok: true, targetId: tab.targetId, ...result });
|
|
56
|
+
},
|
|
57
|
+
});
|
|
23
58
|
});
|
|
24
59
|
app.post("/cookies/set", async (req, res) => {
|
|
25
|
-
const profileCtx = resolveProfileContext(req, res, ctx);
|
|
26
|
-
if (!profileCtx)
|
|
27
|
-
return;
|
|
28
60
|
const body = readBody(req);
|
|
29
|
-
const targetId =
|
|
61
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
30
62
|
const cookie = body.cookie && typeof body.cookie === "object" && !Array.isArray(body.cookie)
|
|
31
63
|
? body.cookie
|
|
32
64
|
: null;
|
|
33
|
-
if (!cookie)
|
|
65
|
+
if (!cookie) {
|
|
34
66
|
return jsonError(res, 400, "cookie is required");
|
|
35
|
-
try {
|
|
36
|
-
const tab = await profileCtx.ensureTabAvailable(targetId);
|
|
37
|
-
const pw = await requirePwAi(res, "cookies set");
|
|
38
|
-
if (!pw)
|
|
39
|
-
return;
|
|
40
|
-
await pw.cookiesSetViaPlaywright({
|
|
41
|
-
cdpUrl: profileCtx.profile.cdpUrl,
|
|
42
|
-
targetId: tab.targetId,
|
|
43
|
-
cookie: {
|
|
44
|
-
name: toStringOrEmpty(cookie.name),
|
|
45
|
-
value: toStringOrEmpty(cookie.value),
|
|
46
|
-
url: toStringOrEmpty(cookie.url) || undefined,
|
|
47
|
-
domain: toStringOrEmpty(cookie.domain) || undefined,
|
|
48
|
-
path: toStringOrEmpty(cookie.path) || undefined,
|
|
49
|
-
expires: toNumber(cookie.expires) ?? undefined,
|
|
50
|
-
httpOnly: toBoolean(cookie.httpOnly) ?? undefined,
|
|
51
|
-
secure: toBoolean(cookie.secure) ?? undefined,
|
|
52
|
-
sameSite: cookie.sameSite === "Lax" || cookie.sameSite === "None" || cookie.sameSite === "Strict"
|
|
53
|
-
? cookie.sameSite
|
|
54
|
-
: undefined,
|
|
55
|
-
},
|
|
56
|
-
});
|
|
57
|
-
res.json({ ok: true, targetId: tab.targetId });
|
|
58
|
-
}
|
|
59
|
-
catch (err) {
|
|
60
|
-
handleRouteError(ctx, res, err);
|
|
61
67
|
}
|
|
68
|
+
await withPlaywrightRouteContext({
|
|
69
|
+
req,
|
|
70
|
+
res,
|
|
71
|
+
ctx,
|
|
72
|
+
targetId,
|
|
73
|
+
feature: "cookies set",
|
|
74
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
75
|
+
await pw.cookiesSetViaPlaywright({
|
|
76
|
+
cdpUrl,
|
|
77
|
+
targetId: tab.targetId,
|
|
78
|
+
cookie: {
|
|
79
|
+
name: toStringOrEmpty(cookie.name),
|
|
80
|
+
value: toStringOrEmpty(cookie.value),
|
|
81
|
+
url: toStringOrEmpty(cookie.url) || undefined,
|
|
82
|
+
domain: toStringOrEmpty(cookie.domain) || undefined,
|
|
83
|
+
path: toStringOrEmpty(cookie.path) || undefined,
|
|
84
|
+
expires: toNumber(cookie.expires) ?? undefined,
|
|
85
|
+
httpOnly: toBoolean(cookie.httpOnly) ?? undefined,
|
|
86
|
+
secure: toBoolean(cookie.secure) ?? undefined,
|
|
87
|
+
sameSite: cookie.sameSite === "Lax" ||
|
|
88
|
+
cookie.sameSite === "None" ||
|
|
89
|
+
cookie.sameSite === "Strict"
|
|
90
|
+
? cookie.sameSite
|
|
91
|
+
: undefined,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
res.json({ ok: true, targetId: tab.targetId });
|
|
95
|
+
},
|
|
96
|
+
});
|
|
62
97
|
});
|
|
63
98
|
app.post("/cookies/clear", async (req, res) => {
|
|
64
|
-
const profileCtx = resolveProfileContext(req, res, ctx);
|
|
65
|
-
if (!profileCtx)
|
|
66
|
-
return;
|
|
67
99
|
const body = readBody(req);
|
|
68
|
-
const targetId =
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
100
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
101
|
+
await withPlaywrightRouteContext({
|
|
102
|
+
req,
|
|
103
|
+
res,
|
|
104
|
+
ctx,
|
|
105
|
+
targetId,
|
|
106
|
+
feature: "cookies clear",
|
|
107
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
108
|
+
await pw.cookiesClearViaPlaywright({
|
|
109
|
+
cdpUrl,
|
|
110
|
+
targetId: tab.targetId,
|
|
111
|
+
});
|
|
112
|
+
res.json({ ok: true, targetId: tab.targetId });
|
|
113
|
+
},
|
|
114
|
+
});
|
|
83
115
|
});
|
|
84
116
|
app.get("/storage/:kind", async (req, res) => {
|
|
85
|
-
const
|
|
86
|
-
if (!
|
|
87
|
-
return;
|
|
88
|
-
const kind = toStringOrEmpty(req.params.kind);
|
|
89
|
-
if (kind !== "local" && kind !== "session")
|
|
117
|
+
const kind = parseStorageKind(toStringOrEmpty(req.params.kind));
|
|
118
|
+
if (!kind) {
|
|
90
119
|
return jsonError(res, 400, "kind must be local|session");
|
|
91
|
-
const targetId = typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
|
92
|
-
const key = typeof req.query.key === "string" ? req.query.key : "";
|
|
93
|
-
try {
|
|
94
|
-
const tab = await profileCtx.ensureTabAvailable(targetId || undefined);
|
|
95
|
-
const pw = await requirePwAi(res, "storage get");
|
|
96
|
-
if (!pw)
|
|
97
|
-
return;
|
|
98
|
-
const result = await pw.storageGetViaPlaywright({
|
|
99
|
-
cdpUrl: profileCtx.profile.cdpUrl,
|
|
100
|
-
targetId: tab.targetId,
|
|
101
|
-
kind,
|
|
102
|
-
key: key.trim() || undefined,
|
|
103
|
-
});
|
|
104
|
-
res.json({ ok: true, targetId: tab.targetId, ...result });
|
|
105
|
-
}
|
|
106
|
-
catch (err) {
|
|
107
|
-
handleRouteError(ctx, res, err);
|
|
108
120
|
}
|
|
121
|
+
const targetId = resolveTargetIdFromQuery(req.query);
|
|
122
|
+
const key = toStringOrEmpty(req.query.key);
|
|
123
|
+
await withPlaywrightRouteContext({
|
|
124
|
+
req,
|
|
125
|
+
res,
|
|
126
|
+
ctx,
|
|
127
|
+
targetId,
|
|
128
|
+
feature: "storage get",
|
|
129
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
130
|
+
const result = await pw.storageGetViaPlaywright({
|
|
131
|
+
cdpUrl,
|
|
132
|
+
targetId: tab.targetId,
|
|
133
|
+
kind,
|
|
134
|
+
key: key.trim() || undefined,
|
|
135
|
+
});
|
|
136
|
+
res.json({ ok: true, targetId: tab.targetId, ...result });
|
|
137
|
+
},
|
|
138
|
+
});
|
|
109
139
|
});
|
|
110
140
|
app.post("/storage/:kind/set", async (req, res) => {
|
|
111
|
-
const
|
|
112
|
-
if (!
|
|
141
|
+
const mutation = parseStorageMutationFromRequest(req, res);
|
|
142
|
+
if (!mutation) {
|
|
113
143
|
return;
|
|
114
|
-
const kind = toStringOrEmpty(req.params.kind);
|
|
115
|
-
if (kind !== "local" && kind !== "session")
|
|
116
|
-
return jsonError(res, 400, "kind must be local|session");
|
|
117
|
-
const body = readBody(req);
|
|
118
|
-
const targetId = toStringOrEmpty(body.targetId) || undefined;
|
|
119
|
-
const key = toStringOrEmpty(body.key);
|
|
120
|
-
if (!key)
|
|
121
|
-
return jsonError(res, 400, "key is required");
|
|
122
|
-
const value = typeof body.value === "string" ? body.value : "";
|
|
123
|
-
try {
|
|
124
|
-
const tab = await profileCtx.ensureTabAvailable(targetId);
|
|
125
|
-
const pw = await requirePwAi(res, "storage set");
|
|
126
|
-
if (!pw)
|
|
127
|
-
return;
|
|
128
|
-
await pw.storageSetViaPlaywright({
|
|
129
|
-
cdpUrl: profileCtx.profile.cdpUrl,
|
|
130
|
-
targetId: tab.targetId,
|
|
131
|
-
kind,
|
|
132
|
-
key,
|
|
133
|
-
value,
|
|
134
|
-
});
|
|
135
|
-
res.json({ ok: true, targetId: tab.targetId });
|
|
136
144
|
}
|
|
137
|
-
|
|
138
|
-
|
|
145
|
+
const key = toStringOrEmpty(mutation.body.key);
|
|
146
|
+
if (!key) {
|
|
147
|
+
return jsonError(res, 400, "key is required");
|
|
139
148
|
}
|
|
149
|
+
const value = typeof mutation.body.value === "string" ? mutation.body.value : "";
|
|
150
|
+
await withPlaywrightRouteContext({
|
|
151
|
+
req,
|
|
152
|
+
res,
|
|
153
|
+
ctx,
|
|
154
|
+
targetId: mutation.parsed.targetId,
|
|
155
|
+
feature: "storage set",
|
|
156
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
157
|
+
await pw.storageSetViaPlaywright({
|
|
158
|
+
cdpUrl,
|
|
159
|
+
targetId: tab.targetId,
|
|
160
|
+
kind: mutation.parsed.kind,
|
|
161
|
+
key,
|
|
162
|
+
value,
|
|
163
|
+
});
|
|
164
|
+
res.json({ ok: true, targetId: tab.targetId });
|
|
165
|
+
},
|
|
166
|
+
});
|
|
140
167
|
});
|
|
141
168
|
app.post("/storage/:kind/clear", async (req, res) => {
|
|
142
|
-
const
|
|
143
|
-
if (!
|
|
169
|
+
const mutation = parseStorageMutationFromRequest(req, res);
|
|
170
|
+
if (!mutation) {
|
|
144
171
|
return;
|
|
145
|
-
const kind = toStringOrEmpty(req.params.kind);
|
|
146
|
-
if (kind !== "local" && kind !== "session")
|
|
147
|
-
return jsonError(res, 400, "kind must be local|session");
|
|
148
|
-
const body = readBody(req);
|
|
149
|
-
const targetId = toStringOrEmpty(body.targetId) || undefined;
|
|
150
|
-
try {
|
|
151
|
-
const tab = await profileCtx.ensureTabAvailable(targetId);
|
|
152
|
-
const pw = await requirePwAi(res, "storage clear");
|
|
153
|
-
if (!pw)
|
|
154
|
-
return;
|
|
155
|
-
await pw.storageClearViaPlaywright({
|
|
156
|
-
cdpUrl: profileCtx.profile.cdpUrl,
|
|
157
|
-
targetId: tab.targetId,
|
|
158
|
-
kind,
|
|
159
|
-
});
|
|
160
|
-
res.json({ ok: true, targetId: tab.targetId });
|
|
161
|
-
}
|
|
162
|
-
catch (err) {
|
|
163
|
-
handleRouteError(ctx, res, err);
|
|
164
172
|
}
|
|
173
|
+
await withPlaywrightRouteContext({
|
|
174
|
+
req,
|
|
175
|
+
res,
|
|
176
|
+
ctx,
|
|
177
|
+
targetId: mutation.parsed.targetId,
|
|
178
|
+
feature: "storage clear",
|
|
179
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
180
|
+
await pw.storageClearViaPlaywright({
|
|
181
|
+
cdpUrl,
|
|
182
|
+
targetId: tab.targetId,
|
|
183
|
+
kind: mutation.parsed.kind,
|
|
184
|
+
});
|
|
185
|
+
res.json({ ok: true, targetId: tab.targetId });
|
|
186
|
+
},
|
|
187
|
+
});
|
|
165
188
|
});
|
|
166
189
|
app.post("/set/offline", async (req, res) => {
|
|
167
|
-
const profileCtx = resolveProfileContext(req, res, ctx);
|
|
168
|
-
if (!profileCtx)
|
|
169
|
-
return;
|
|
170
190
|
const body = readBody(req);
|
|
171
|
-
const targetId =
|
|
191
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
172
192
|
const offline = toBoolean(body.offline);
|
|
173
|
-
if (offline === undefined)
|
|
193
|
+
if (offline === undefined) {
|
|
174
194
|
return jsonError(res, 400, "offline is required");
|
|
175
|
-
try {
|
|
176
|
-
const tab = await profileCtx.ensureTabAvailable(targetId);
|
|
177
|
-
const pw = await requirePwAi(res, "offline");
|
|
178
|
-
if (!pw)
|
|
179
|
-
return;
|
|
180
|
-
await pw.setOfflineViaPlaywright({
|
|
181
|
-
cdpUrl: profileCtx.profile.cdpUrl,
|
|
182
|
-
targetId: tab.targetId,
|
|
183
|
-
offline,
|
|
184
|
-
});
|
|
185
|
-
res.json({ ok: true, targetId: tab.targetId });
|
|
186
|
-
}
|
|
187
|
-
catch (err) {
|
|
188
|
-
handleRouteError(ctx, res, err);
|
|
189
195
|
}
|
|
196
|
+
await withPlaywrightRouteContext({
|
|
197
|
+
req,
|
|
198
|
+
res,
|
|
199
|
+
ctx,
|
|
200
|
+
targetId,
|
|
201
|
+
feature: "offline",
|
|
202
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
203
|
+
await pw.setOfflineViaPlaywright({
|
|
204
|
+
cdpUrl,
|
|
205
|
+
targetId: tab.targetId,
|
|
206
|
+
offline,
|
|
207
|
+
});
|
|
208
|
+
res.json({ ok: true, targetId: tab.targetId });
|
|
209
|
+
},
|
|
210
|
+
});
|
|
190
211
|
});
|
|
191
212
|
app.post("/set/headers", async (req, res) => {
|
|
192
|
-
const profileCtx = resolveProfileContext(req, res, ctx);
|
|
193
|
-
if (!profileCtx)
|
|
194
|
-
return;
|
|
195
213
|
const body = readBody(req);
|
|
196
|
-
const targetId =
|
|
214
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
197
215
|
const headers = body.headers && typeof body.headers === "object" && !Array.isArray(body.headers)
|
|
198
216
|
? body.headers
|
|
199
217
|
: null;
|
|
200
|
-
if (!headers)
|
|
218
|
+
if (!headers) {
|
|
201
219
|
return jsonError(res, 400, "headers is required");
|
|
220
|
+
}
|
|
202
221
|
const parsed = {};
|
|
203
222
|
for (const [k, v] of Object.entries(headers)) {
|
|
204
|
-
if (typeof v === "string")
|
|
223
|
+
if (typeof v === "string") {
|
|
205
224
|
parsed[k] = v;
|
|
225
|
+
}
|
|
206
226
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
227
|
+
await withPlaywrightRouteContext({
|
|
228
|
+
req,
|
|
229
|
+
res,
|
|
230
|
+
ctx,
|
|
231
|
+
targetId,
|
|
232
|
+
feature: "headers",
|
|
233
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
234
|
+
await pw.setExtraHTTPHeadersViaPlaywright({
|
|
235
|
+
cdpUrl,
|
|
236
|
+
targetId: tab.targetId,
|
|
237
|
+
headers: parsed,
|
|
238
|
+
});
|
|
239
|
+
res.json({ ok: true, targetId: tab.targetId });
|
|
240
|
+
},
|
|
241
|
+
});
|
|
222
242
|
});
|
|
223
243
|
app.post("/set/credentials", async (req, res) => {
|
|
224
|
-
const profileCtx = resolveProfileContext(req, res, ctx);
|
|
225
|
-
if (!profileCtx)
|
|
226
|
-
return;
|
|
227
244
|
const body = readBody(req);
|
|
228
|
-
const targetId =
|
|
245
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
229
246
|
const clear = toBoolean(body.clear) ?? false;
|
|
230
247
|
const username = toStringOrEmpty(body.username) || undefined;
|
|
231
248
|
const password = typeof body.password === "string" ? body.password : undefined;
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
+
await withPlaywrightRouteContext({
|
|
250
|
+
req,
|
|
251
|
+
res,
|
|
252
|
+
ctx,
|
|
253
|
+
targetId,
|
|
254
|
+
feature: "http credentials",
|
|
255
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
256
|
+
await pw.setHttpCredentialsViaPlaywright({
|
|
257
|
+
cdpUrl,
|
|
258
|
+
targetId: tab.targetId,
|
|
259
|
+
username,
|
|
260
|
+
password,
|
|
261
|
+
clear,
|
|
262
|
+
});
|
|
263
|
+
res.json({ ok: true, targetId: tab.targetId });
|
|
264
|
+
},
|
|
265
|
+
});
|
|
249
266
|
});
|
|
250
267
|
app.post("/set/geolocation", async (req, res) => {
|
|
251
|
-
const profileCtx = resolveProfileContext(req, res, ctx);
|
|
252
|
-
if (!profileCtx)
|
|
253
|
-
return;
|
|
254
268
|
const body = readBody(req);
|
|
255
|
-
const targetId =
|
|
269
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
256
270
|
const clear = toBoolean(body.clear) ?? false;
|
|
257
271
|
const latitude = toNumber(body.latitude);
|
|
258
272
|
const longitude = toNumber(body.longitude);
|
|
259
273
|
const accuracy = toNumber(body.accuracy) ?? undefined;
|
|
260
274
|
const origin = toStringOrEmpty(body.origin) || undefined;
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
275
|
+
await withPlaywrightRouteContext({
|
|
276
|
+
req,
|
|
277
|
+
res,
|
|
278
|
+
ctx,
|
|
279
|
+
targetId,
|
|
280
|
+
feature: "geolocation",
|
|
281
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
282
|
+
await pw.setGeolocationViaPlaywright({
|
|
283
|
+
cdpUrl,
|
|
284
|
+
targetId: tab.targetId,
|
|
285
|
+
latitude,
|
|
286
|
+
longitude,
|
|
287
|
+
accuracy,
|
|
288
|
+
origin,
|
|
289
|
+
clear,
|
|
290
|
+
});
|
|
291
|
+
res.json({ ok: true, targetId: tab.targetId });
|
|
292
|
+
},
|
|
293
|
+
});
|
|
280
294
|
});
|
|
281
295
|
app.post("/set/media", async (req, res) => {
|
|
282
|
-
const profileCtx = resolveProfileContext(req, res, ctx);
|
|
283
|
-
if (!profileCtx)
|
|
284
|
-
return;
|
|
285
296
|
const body = readBody(req);
|
|
286
|
-
const targetId =
|
|
297
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
287
298
|
const schemeRaw = toStringOrEmpty(body.colorScheme);
|
|
288
299
|
const colorScheme = schemeRaw === "dark" || schemeRaw === "light" || schemeRaw === "no-preference"
|
|
289
300
|
? schemeRaw
|
|
290
301
|
: schemeRaw === "none"
|
|
291
302
|
? null
|
|
292
303
|
: undefined;
|
|
293
|
-
if (colorScheme === undefined)
|
|
304
|
+
if (colorScheme === undefined) {
|
|
294
305
|
return jsonError(res, 400, "colorScheme must be dark|light|no-preference|none");
|
|
295
|
-
try {
|
|
296
|
-
const tab = await profileCtx.ensureTabAvailable(targetId);
|
|
297
|
-
const pw = await requirePwAi(res, "media emulation");
|
|
298
|
-
if (!pw)
|
|
299
|
-
return;
|
|
300
|
-
await pw.emulateMediaViaPlaywright({
|
|
301
|
-
cdpUrl: profileCtx.profile.cdpUrl,
|
|
302
|
-
targetId: tab.targetId,
|
|
303
|
-
colorScheme,
|
|
304
|
-
});
|
|
305
|
-
res.json({ ok: true, targetId: tab.targetId });
|
|
306
|
-
}
|
|
307
|
-
catch (err) {
|
|
308
|
-
handleRouteError(ctx, res, err);
|
|
309
306
|
}
|
|
307
|
+
await withPlaywrightRouteContext({
|
|
308
|
+
req,
|
|
309
|
+
res,
|
|
310
|
+
ctx,
|
|
311
|
+
targetId,
|
|
312
|
+
feature: "media emulation",
|
|
313
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
314
|
+
await pw.emulateMediaViaPlaywright({
|
|
315
|
+
cdpUrl,
|
|
316
|
+
targetId: tab.targetId,
|
|
317
|
+
colorScheme,
|
|
318
|
+
});
|
|
319
|
+
res.json({ ok: true, targetId: tab.targetId });
|
|
320
|
+
},
|
|
321
|
+
});
|
|
310
322
|
});
|
|
311
323
|
app.post("/set/timezone", async (req, res) => {
|
|
312
|
-
const profileCtx = resolveProfileContext(req, res, ctx);
|
|
313
|
-
if (!profileCtx)
|
|
314
|
-
return;
|
|
315
324
|
const body = readBody(req);
|
|
316
|
-
const targetId =
|
|
325
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
317
326
|
const timezoneId = toStringOrEmpty(body.timezoneId);
|
|
318
|
-
if (!timezoneId)
|
|
327
|
+
if (!timezoneId) {
|
|
319
328
|
return jsonError(res, 400, "timezoneId is required");
|
|
320
|
-
try {
|
|
321
|
-
const tab = await profileCtx.ensureTabAvailable(targetId);
|
|
322
|
-
const pw = await requirePwAi(res, "timezone");
|
|
323
|
-
if (!pw)
|
|
324
|
-
return;
|
|
325
|
-
await pw.setTimezoneViaPlaywright({
|
|
326
|
-
cdpUrl: profileCtx.profile.cdpUrl,
|
|
327
|
-
targetId: tab.targetId,
|
|
328
|
-
timezoneId,
|
|
329
|
-
});
|
|
330
|
-
res.json({ ok: true, targetId: tab.targetId });
|
|
331
|
-
}
|
|
332
|
-
catch (err) {
|
|
333
|
-
handleRouteError(ctx, res, err);
|
|
334
329
|
}
|
|
330
|
+
await withPlaywrightRouteContext({
|
|
331
|
+
req,
|
|
332
|
+
res,
|
|
333
|
+
ctx,
|
|
334
|
+
targetId,
|
|
335
|
+
feature: "timezone",
|
|
336
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
337
|
+
await pw.setTimezoneViaPlaywright({
|
|
338
|
+
cdpUrl,
|
|
339
|
+
targetId: tab.targetId,
|
|
340
|
+
timezoneId,
|
|
341
|
+
});
|
|
342
|
+
res.json({ ok: true, targetId: tab.targetId });
|
|
343
|
+
},
|
|
344
|
+
});
|
|
335
345
|
});
|
|
336
346
|
app.post("/set/locale", async (req, res) => {
|
|
337
|
-
const profileCtx = resolveProfileContext(req, res, ctx);
|
|
338
|
-
if (!profileCtx)
|
|
339
|
-
return;
|
|
340
347
|
const body = readBody(req);
|
|
341
|
-
const targetId =
|
|
348
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
342
349
|
const locale = toStringOrEmpty(body.locale);
|
|
343
|
-
if (!locale)
|
|
350
|
+
if (!locale) {
|
|
344
351
|
return jsonError(res, 400, "locale is required");
|
|
345
|
-
try {
|
|
346
|
-
const tab = await profileCtx.ensureTabAvailable(targetId);
|
|
347
|
-
const pw = await requirePwAi(res, "locale");
|
|
348
|
-
if (!pw)
|
|
349
|
-
return;
|
|
350
|
-
await pw.setLocaleViaPlaywright({
|
|
351
|
-
cdpUrl: profileCtx.profile.cdpUrl,
|
|
352
|
-
targetId: tab.targetId,
|
|
353
|
-
locale,
|
|
354
|
-
});
|
|
355
|
-
res.json({ ok: true, targetId: tab.targetId });
|
|
356
|
-
}
|
|
357
|
-
catch (err) {
|
|
358
|
-
handleRouteError(ctx, res, err);
|
|
359
352
|
}
|
|
353
|
+
await withPlaywrightRouteContext({
|
|
354
|
+
req,
|
|
355
|
+
res,
|
|
356
|
+
ctx,
|
|
357
|
+
targetId,
|
|
358
|
+
feature: "locale",
|
|
359
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
360
|
+
await pw.setLocaleViaPlaywright({
|
|
361
|
+
cdpUrl,
|
|
362
|
+
targetId: tab.targetId,
|
|
363
|
+
locale,
|
|
364
|
+
});
|
|
365
|
+
res.json({ ok: true, targetId: tab.targetId });
|
|
366
|
+
},
|
|
367
|
+
});
|
|
360
368
|
});
|
|
361
369
|
app.post("/set/device", async (req, res) => {
|
|
362
|
-
const profileCtx = resolveProfileContext(req, res, ctx);
|
|
363
|
-
if (!profileCtx)
|
|
364
|
-
return;
|
|
365
370
|
const body = readBody(req);
|
|
366
|
-
const targetId =
|
|
371
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
367
372
|
const name = toStringOrEmpty(body.name);
|
|
368
|
-
if (!name)
|
|
373
|
+
if (!name) {
|
|
369
374
|
return jsonError(res, 400, "name is required");
|
|
370
|
-
try {
|
|
371
|
-
const tab = await profileCtx.ensureTabAvailable(targetId);
|
|
372
|
-
const pw = await requirePwAi(res, "device emulation");
|
|
373
|
-
if (!pw)
|
|
374
|
-
return;
|
|
375
|
-
await pw.setDeviceViaPlaywright({
|
|
376
|
-
cdpUrl: profileCtx.profile.cdpUrl,
|
|
377
|
-
targetId: tab.targetId,
|
|
378
|
-
name,
|
|
379
|
-
});
|
|
380
|
-
res.json({ ok: true, targetId: tab.targetId });
|
|
381
|
-
}
|
|
382
|
-
catch (err) {
|
|
383
|
-
handleRouteError(ctx, res, err);
|
|
384
375
|
}
|
|
376
|
+
await withPlaywrightRouteContext({
|
|
377
|
+
req,
|
|
378
|
+
res,
|
|
379
|
+
ctx,
|
|
380
|
+
targetId,
|
|
381
|
+
feature: "device emulation",
|
|
382
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
383
|
+
await pw.setDeviceViaPlaywright({
|
|
384
|
+
cdpUrl,
|
|
385
|
+
targetId: tab.targetId,
|
|
386
|
+
name,
|
|
387
|
+
});
|
|
388
|
+
res.json({ ok: true, targetId: tab.targetId });
|
|
389
|
+
},
|
|
390
|
+
});
|
|
385
391
|
});
|
|
386
392
|
}
|