@zenalexa/unicli 0.225.1 → 0.225.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/AGENTS.md +3 -3
- package/README.md +2 -2
- package/README.zh-CN.md +2 -2
- package/dist/browser/protocol.d.ts +6 -1
- package/dist/browser/protocol.d.ts.map +1 -1
- package/dist/browser/protocol.js.map +1 -1
- package/dist/commands/browser/actions.d.ts.map +1 -1
- package/dist/commands/browser/actions.js +428 -5
- package/dist/commands/browser/actions.js.map +1 -1
- package/dist/commands/compute.js +12 -1
- package/dist/commands/compute.js.map +1 -1
- package/dist/commands/schema.d.ts.map +1 -1
- package/dist/commands/schema.js +22 -0
- package/dist/commands/schema.js.map +1 -1
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +14 -3
- package/dist/commands/search.js.map +1 -1
- package/dist/compute/contracts.d.ts +55 -0
- package/dist/compute/contracts.d.ts.map +1 -0
- package/dist/compute/contracts.js +487 -0
- package/dist/compute/contracts.js.map +1 -0
- package/dist/discovery/aliases.d.ts +8 -1
- package/dist/discovery/aliases.d.ts.map +1 -1
- package/dist/discovery/aliases.js +125 -20
- package/dist/discovery/aliases.js.map +1 -1
- package/dist/discovery/core-catalog.d.ts.map +1 -1
- package/dist/discovery/core-catalog.js +39 -67
- package/dist/discovery/core-catalog.js.map +1 -1
- package/dist/discovery/intents.d.ts +1 -0
- package/dist/discovery/intents.d.ts.map +1 -1
- package/dist/discovery/intents.js +26 -0
- package/dist/discovery/intents.js.map +1 -1
- package/dist/discovery/macos-dynamic.d.ts +1 -0
- package/dist/discovery/macos-dynamic.d.ts.map +1 -1
- package/dist/discovery/macos-dynamic.js +20 -1
- package/dist/discovery/macos-dynamic.js.map +1 -1
- package/dist/discovery/search.d.ts.map +1 -1
- package/dist/discovery/search.js +12 -5
- package/dist/discovery/search.js.map +1 -1
- package/dist/engine/browser/evidence.d.ts +34 -1
- package/dist/engine/browser/evidence.d.ts.map +1 -1
- package/dist/engine/browser/evidence.js +141 -6
- package/dist/engine/browser/evidence.js.map +1 -1
- package/dist/engine/steps/fetch-text.d.ts.map +1 -1
- package/dist/engine/steps/fetch-text.js +2 -2
- package/dist/engine/steps/fetch-text.js.map +1 -1
- package/dist/engine/steps/fetch.d.ts +1 -0
- package/dist/engine/steps/fetch.d.ts.map +1 -1
- package/dist/engine/steps/fetch.js +24 -4
- package/dist/engine/steps/fetch.js.map +1 -1
- package/dist/fast-path/handlers/discovery.d.ts +5 -5
- package/dist/fast-path/handlers/discovery.d.ts.map +1 -1
- package/dist/fast-path/handlers/discovery.js +61 -8
- package/dist/fast-path/handlers/discovery.js.map +1 -1
- package/dist/fast-path/render.d.ts +2 -0
- package/dist/fast-path/render.d.ts.map +1 -1
- package/dist/fast-path/render.js +9 -0
- package/dist/fast-path/render.js.map +1 -1
- package/dist/manifest-compact.txt +1 -1
- package/dist/manifest.json +174 -1
- package/dist/mcp/handler.d.ts +2 -16
- package/dist/mcp/handler.d.ts.map +1 -1
- package/dist/mcp/handler.js.map +1 -1
- package/dist/mcp/http-transport.d.ts +7 -1
- package/dist/mcp/http-transport.d.ts.map +1 -1
- package/dist/mcp/http-transport.js +20 -1
- package/dist/mcp/http-transport.js.map +1 -1
- package/dist/mcp/jsonrpc.d.ts +27 -0
- package/dist/mcp/jsonrpc.d.ts.map +1 -0
- package/dist/mcp/jsonrpc.js +12 -0
- package/dist/mcp/jsonrpc.js.map +1 -0
- package/dist/mcp/origin-guard.d.ts +26 -0
- package/dist/mcp/origin-guard.d.ts.map +1 -0
- package/dist/mcp/origin-guard.js +42 -0
- package/dist/mcp/origin-guard.js.map +1 -0
- package/dist/mcp/profiles/computer-use.d.ts.map +1 -1
- package/dist/mcp/profiles/computer-use.js +30 -270
- package/dist/mcp/profiles/computer-use.js.map +1 -1
- package/dist/mcp/streamable-http/session.d.ts +4 -22
- package/dist/mcp/streamable-http/session.d.ts.map +1 -1
- package/dist/mcp/streamable-http/session.js +4 -24
- package/dist/mcp/streamable-http/session.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +74 -54
- package/dist/mcp/tools.js.map +1 -1
- package/dist/output/envelope.d.ts +2 -0
- package/dist/output/envelope.d.ts.map +1 -1
- package/dist/output/envelope.js.map +1 -1
- package/dist/output/error-map.d.ts +14 -0
- package/dist/output/error-map.d.ts.map +1 -1
- package/dist/output/error-map.js +20 -0
- package/dist/output/error-map.js.map +1 -1
- package/dist/transport/cascade.d.ts.map +1 -1
- package/dist/transport/cascade.js +77 -5
- package/dist/transport/cascade.js.map +1 -1
- package/dist/transport/refs.d.ts +33 -1
- package/dist/transport/refs.d.ts.map +1 -1
- package/dist/transport/refs.js +40 -1
- package/dist/transport/refs.js.map +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/skills/unicli/SKILL.md +1 -1
- package/skills/unicli-claude-code/SKILL.md +1 -1
- package/skills/unicli-hermes/SKILL.md +1 -1
- package/src/adapters/defuddle/read.yaml +30 -0
- package/src/adapters/jina/read.yaml +30 -0
- package/src/adapters/markdown-new/read.yaml +50 -0
- package/src/adapters/ollama-cloud/fetch.yaml +39 -0
- package/src/adapters/ollama-cloud/search.yaml +43 -0
package/AGENTS.md
CHANGED
|
@@ -36,7 +36,7 @@ it starts only the Uni-CLI automation profile.
|
|
|
36
36
|
|
|
37
37
|
<!-- BEGIN COUNTS -->
|
|
38
38
|
|
|
39
|
-
> <!-- STATS:site_count -->
|
|
39
|
+
> <!-- STATS:site_count -->317<!-- /STATS --> sites, <!-- STATS:command_count -->1772<!-- /STATS --> commands, <!-- STATS:pipeline_step_count -->103<!-- /STATS --> pipeline steps, BM25 bilingual search. `npm install -g @zenalexa/unicli`
|
|
40
40
|
|
|
41
41
|
<!-- END COUNTS -->
|
|
42
42
|
|
|
@@ -48,7 +48,7 @@ it starts only the Uni-CLI automation profile.
|
|
|
48
48
|
|
|
49
49
|
**Chinese**: zhihu (27), xiaohongshu (22), bilibili (20), douyin (13), douban (12), v2ex (12), weibo (12), linux-do (11), +28 more (`unicli list`)
|
|
50
50
|
|
|
51
|
-
**International**: twitter (47), instagram (29), reddit (24), tiktok (18), youtube (17), nowcoder (16), discord-app (15), facebook (15), +
|
|
51
|
+
**International**: twitter (47), instagram (29), reddit (24), tiktok (18), youtube (17), nowcoder (16), discord-app (15), facebook (15), +78 more (`unicli list`)
|
|
52
52
|
|
|
53
53
|
**AI / ML**: chatgpt (17), antigravity (16), chatwise (16), notebooklm (15), claude (14), doubao-app (13), yollomi (12), deepseek (9), +16 more (`unicli list`)
|
|
54
54
|
|
|
@@ -128,7 +128,7 @@ allowlist entry without a one-line `// REASON:` justification in
|
|
|
128
128
|
|
|
129
129
|
## Version
|
|
130
130
|
|
|
131
|
-
0.225.
|
|
131
|
+
0.225.2 — Apollo · Gordon
|
|
132
132
|
|
|
133
133
|
## MCP one-liner (Claude Desktop / Cursor / Continue)
|
|
134
134
|
|
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
</p>
|
|
42
42
|
|
|
43
43
|
<p align="center">
|
|
44
|
-
<sub>Native CLI · MCP · ACP · JSON/Markdown envelopes · browser CDP · visual fallback · macOS desktop AX · <!-- STATS:site_count -->
|
|
44
|
+
<sub>Native CLI · MCP · ACP · JSON/Markdown envelopes · browser CDP · visual fallback · macOS desktop AX · <!-- STATS:site_count -->317<!-- /STATS --> surfaces · <!-- STATS:test_count -->9181<!-- /STATS --> tests</sub>
|
|
45
45
|
</p>
|
|
46
46
|
|
|
47
47
|
<p align="center">
|
|
@@ -552,5 +552,5 @@ npm run verify
|
|
|
552
552
|
[Apache-2.0](./LICENSE)
|
|
553
553
|
|
|
554
554
|
<p align="center">
|
|
555
|
-
<sub>v0.225.
|
|
555
|
+
<sub>v0.225.2 — Apollo · Gordon</sub>
|
|
556
556
|
</p>
|
package/README.zh-CN.md
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
</p>
|
|
41
41
|
|
|
42
42
|
<p align="center">
|
|
43
|
-
<sub>Native CLI · MCP · ACP · JSON/Markdown envelope · browser CDP · visual fallback · macOS desktop AX · <!-- STATS:site_count -->
|
|
43
|
+
<sub>Native CLI · MCP · ACP · JSON/Markdown envelope · browser CDP · visual fallback · macOS desktop AX · <!-- STATS:site_count -->317<!-- /STATS --> 个 surface · <!-- STATS:test_count -->9181<!-- /STATS --> 个测试</sub>
|
|
44
44
|
</p>
|
|
45
45
|
|
|
46
46
|
<p align="center">
|
|
@@ -496,5 +496,5 @@ npm run verify
|
|
|
496
496
|
[Apache-2.0](./LICENSE)
|
|
497
497
|
|
|
498
498
|
<p align="center">
|
|
499
|
-
<sub>v0.225.
|
|
499
|
+
<sub>v0.225.2 — Apollo · Gordon</sub>
|
|
500
500
|
</p>
|
|
@@ -17,7 +17,7 @@ export declare const WS_RECONNECT_MAX_DELAY = 5000;
|
|
|
17
17
|
export declare const MAX_EAGER_RECONNECT_ATTEMPTS = 6;
|
|
18
18
|
export declare const HEARTBEAT_INTERVAL = 15000;
|
|
19
19
|
export declare const MAX_MISSED_PONGS = 2;
|
|
20
|
-
export type DaemonAction = "exec" | "navigate" | "tabs" | "cookies" | "screenshot" | "close-window" | "sessions" | "set-file-input" | "insert-text" | "bind-current" | "network-capture-start" | "network-capture-read" | "cdp";
|
|
20
|
+
export type DaemonAction = "exec" | "navigate" | "tabs" | "cookies" | "screenshot" | "close-window" | "sessions" | "set-file-input" | "insert-text" | "bind-current" | "network-capture-start" | "network-capture-read" | "downloads-read" | "dialog-read" | "dialog-respond" | "cdp";
|
|
21
21
|
export interface DaemonCommand {
|
|
22
22
|
id: string;
|
|
23
23
|
action: DaemonAction;
|
|
@@ -30,6 +30,11 @@ export interface DaemonCommand {
|
|
|
30
30
|
matchDomain?: string;
|
|
31
31
|
matchPathPrefix?: string;
|
|
32
32
|
pattern?: string;
|
|
33
|
+
clearRecent?: boolean;
|
|
34
|
+
downloadLimit?: number;
|
|
35
|
+
dialogAction?: "accept" | "dismiss";
|
|
36
|
+
dialogId?: string;
|
|
37
|
+
promptText?: string;
|
|
33
38
|
cdpMethod?: string;
|
|
34
39
|
cdpParams?: Record<string, unknown>;
|
|
35
40
|
cdpSessionId?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/browser/protocol.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/browser/protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/browser/protocol.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,uEAAuE;AAEvE,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC;AACjC,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAC1E,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC;AACvC,MAAM,CAAC,MAAM,eAAe,GAAG,uBAAuB,CAAC;AACvD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,kBAAkB;AACzE,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AACrC,MAAM,CAAC,MAAM,sBAAsB,GAAG,OAAO,CAAC,CAAC,oBAAoB;AACnE,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,kBAAkB;AAC9D,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,CAAC,kBAAkB;AAC7D,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAC5C,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC;AAC9C,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,CAAC,oBAAoB;AAC9D,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/browser/protocol.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,uEAAuE;AAEvE,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC;AACjC,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAC1E,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC;AACvC,MAAM,CAAC,MAAM,eAAe,GAAG,uBAAuB,CAAC;AACvD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,kBAAkB;AACzE,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AACrC,MAAM,CAAC,MAAM,sBAAsB,GAAG,OAAO,CAAC,CAAC,oBAAoB;AACnE,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,kBAAkB;AAC9D,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,CAAC,kBAAkB;AAC7D,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAC5C,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC;AAC9C,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,CAAC,oBAAoB;AAC9D,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAkGlC,MAAM,UAAU,0BAA0B,CAAC,KAAqB;IAC9D,OAAO,KAAK,CAAC,OAAO,KAAK,cAAc,IAAI,KAAK,CAAC,QAAQ,KAAK,eAAe,CAAC;AAChF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/commands/browser/actions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/commands/browser/actions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,OAAO,EAUL,sBAAsB,EACvB,MAAM,cAAc,CAAC;AA0BtB,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAYlC,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4BtE;AA6jBD,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,GAAG,SAAS,GAC/B,IAAI,CA8wBN"}
|
|
@@ -6,20 +6,21 @@
|
|
|
6
6
|
* @breaks Action, lease, daemon, and evidence failures propagate as command errors or evidence envelopes. No fallback.
|
|
7
7
|
*/
|
|
8
8
|
import { appendFileSync, mkdirSync } from "node:fs";
|
|
9
|
-
import { dirname as pathDirname, join } from "node:path";
|
|
9
|
+
import { basename as pathBasename, dirname as pathDirname, join, } from "node:path";
|
|
10
10
|
import chalk from "chalk";
|
|
11
11
|
import { userHome } from "../../engine/user-home.js";
|
|
12
12
|
import { FINGERPRINT_PERSIST_JS, verifyRef, } from "../../browser/snapshot-identity.js";
|
|
13
13
|
import { rankCandidates } from "../../browser/observe.js";
|
|
14
14
|
import { buildExtractJs, buildFindJs, ensureNetworkCapture, getOperatorPage, operatorAction, readFrames, resolveAllowedUploadPath, resolveWorkspace, validateRef, withBrowserOperatorEnv, } from "./runtime.js";
|
|
15
|
-
import { sendCommand } from "../../browser/daemon-client.js";
|
|
15
|
+
import { listSessions, sendCommand } from "../../browser/daemon-client.js";
|
|
16
16
|
import { registerBrowserAuthoringSubcommands } from "./authoring.js";
|
|
17
|
-
import { captureBrowserEvidencePacket, captureRenderAwareBrowserEvidence, installBrowserEvidenceHooks, } from "../../engine/browser/evidence.js";
|
|
17
|
+
import { captureBrowserEvidencePacket, captureRenderAwareBrowserEvidence, installBrowserEvidenceHooks, readBrowserConsole, } from "../../engine/browser/evidence.js";
|
|
18
18
|
import { assertBrowserSessionLeaseUrlGuard, createBrowserSessionLease, } from "../../engine/browser/session-lease.js";
|
|
19
19
|
import { assertBrowserSessionLeaseTargetCurrent, enrichBrowserSessionLease, } from "../../engine/browser/session-runtime.js";
|
|
20
20
|
import { isBrowserActionEvidenceEnabled, withBrowserActionEvidence, } from "../../engine/browser/action-evidence.js";
|
|
21
21
|
import { withBrowserSessionLeaseLock } from "../../engine/browser/session-lock.js";
|
|
22
22
|
export { withBrowserOperatorEnv };
|
|
23
|
+
const BROWSER_DOM_QUERY_RESULT_MAX_CHARS = 20_000;
|
|
23
24
|
export function applyBrowserOperatorRootOptions(command) {
|
|
24
25
|
command
|
|
25
26
|
.option("--workspace <name>", "Reuse a named automation workspace instead of the default shared session")
|
|
@@ -91,6 +92,330 @@ function browserActionWatchdogMode(value) {
|
|
|
91
92
|
return "off";
|
|
92
93
|
}
|
|
93
94
|
}
|
|
95
|
+
const BROWSER_CDP_READ_ONLY_METHODS = new Set([
|
|
96
|
+
"Page.getFrameTree",
|
|
97
|
+
"Target.getTargetInfo",
|
|
98
|
+
]);
|
|
99
|
+
const BROWSER_CDP_RESULT_MAX_CHARS = 20_000;
|
|
100
|
+
async function closeAllBrowserSessions() {
|
|
101
|
+
const sessions = await listSessions();
|
|
102
|
+
const reports = [];
|
|
103
|
+
for (const session of sessions) {
|
|
104
|
+
await sendCommand("close-window", { workspace: session.workspace });
|
|
105
|
+
reports.push({
|
|
106
|
+
workspace: session.workspace,
|
|
107
|
+
action: closeActionForSession(session),
|
|
108
|
+
status: "completed",
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
ok: true,
|
|
113
|
+
scope: "all_managed_sessions",
|
|
114
|
+
session_count: sessions.length,
|
|
115
|
+
closed_count: reports.filter((report) => report.action === "closed_window")
|
|
116
|
+
.length,
|
|
117
|
+
released_count: reports.filter((report) => report.action === "released_binding").length,
|
|
118
|
+
failed_count: 0,
|
|
119
|
+
sessions: reports,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function closeActionForSession(session) {
|
|
123
|
+
return session.owned === false ? "released_binding" : "closed_window";
|
|
124
|
+
}
|
|
125
|
+
function normalizeBrowserDialogProviderResult(result, workspace) {
|
|
126
|
+
if (!isRecord(result) ||
|
|
127
|
+
result.evidence_type !== "browser-dialog-supervision" ||
|
|
128
|
+
result.supervision !== "active") {
|
|
129
|
+
throw new Error("Browser dialog supervisor returned an invalid payload.");
|
|
130
|
+
}
|
|
131
|
+
const respondedDialog = readDialogEntries([result.responded_dialog])[0];
|
|
132
|
+
return {
|
|
133
|
+
ok: true,
|
|
134
|
+
evidence_type: "browser-dialog-supervision",
|
|
135
|
+
workspace,
|
|
136
|
+
captured_at: readString(result.captured_at) ?? new Date().toISOString(),
|
|
137
|
+
supervision: "active",
|
|
138
|
+
pending_count: readNonNegativeInteger(result.pending_count),
|
|
139
|
+
recent_count: readNonNegativeInteger(result.recent_count),
|
|
140
|
+
pending_dialogs: readDialogEntries(result.pending_dialogs),
|
|
141
|
+
recent_dialogs: readDialogRecords(result.recent_dialogs),
|
|
142
|
+
...(respondedDialog === undefined
|
|
143
|
+
? {}
|
|
144
|
+
: { responded_dialog: respondedDialog }),
|
|
145
|
+
...(readString(result.url) === undefined
|
|
146
|
+
? {}
|
|
147
|
+
: { url: readString(result.url) }),
|
|
148
|
+
...(readString(result.title) === undefined
|
|
149
|
+
? {}
|
|
150
|
+
: { title: readString(result.title) }),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function normalizeBrowserDownloadsProviderResult(result, workspace, limit) {
|
|
154
|
+
if (!isRecord(result) || result.evidence_type !== "browser-downloads") {
|
|
155
|
+
throw new Error("Browser downloads provider returned an invalid payload.");
|
|
156
|
+
}
|
|
157
|
+
const downloads = readDownloadEntries(result.downloads);
|
|
158
|
+
return {
|
|
159
|
+
ok: true,
|
|
160
|
+
evidence_type: "browser-downloads",
|
|
161
|
+
workspace,
|
|
162
|
+
captured_at: readString(result.captured_at) ?? new Date().toISOString(),
|
|
163
|
+
limit,
|
|
164
|
+
count: downloads.length,
|
|
165
|
+
downloads,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function parseBrowserDialogAction(action) {
|
|
169
|
+
if (action === "accept" || action === "dismiss")
|
|
170
|
+
return action;
|
|
171
|
+
throw new Error("Browser dialog action must be accept or dismiss.");
|
|
172
|
+
}
|
|
173
|
+
function parseBrowserDomQueryKind(rawKind) {
|
|
174
|
+
if (rawKind === undefined || rawKind === "text")
|
|
175
|
+
return "text";
|
|
176
|
+
if (rawKind === "value" || rawKind === "attributes")
|
|
177
|
+
return rawKind;
|
|
178
|
+
throw new Error("Browser query kind must be text, value, or attributes.");
|
|
179
|
+
}
|
|
180
|
+
function buildBrowserDomQueryJs(ref, kind) {
|
|
181
|
+
const refJson = JSON.stringify(ref);
|
|
182
|
+
const kindJson = JSON.stringify(kind);
|
|
183
|
+
return `(() => {
|
|
184
|
+
const __unicli_dom_query = true;
|
|
185
|
+
const ref = ${refJson};
|
|
186
|
+
const kind = ${kindJson};
|
|
187
|
+
const el = document.querySelector('[data-unicli-ref="' + ref + '"]');
|
|
188
|
+
if (!el) throw new Error('Ref not found: ' + ref);
|
|
189
|
+
const readText = () => {
|
|
190
|
+
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) {
|
|
191
|
+
return String(el.value || '');
|
|
192
|
+
}
|
|
193
|
+
const text = 'innerText' in el ? el.innerText : el.textContent;
|
|
194
|
+
return String(text || '').trim();
|
|
195
|
+
};
|
|
196
|
+
if (kind === 'text') {
|
|
197
|
+
const value = readText();
|
|
198
|
+
return { value, original_length: value.length, truncated: false };
|
|
199
|
+
}
|
|
200
|
+
if (kind === 'value') {
|
|
201
|
+
const value = 'value' in el ? String(el.value || '') : String(el.getAttribute('value') || '');
|
|
202
|
+
return { value, original_length: value.length, truncated: false };
|
|
203
|
+
}
|
|
204
|
+
const allowed = new Set(['href', 'src', 'alt', 'title', 'aria-label', 'role', 'name', 'placeholder', 'type']);
|
|
205
|
+
const attrs = {};
|
|
206
|
+
for (const attr of Array.from(el.attributes || [])) {
|
|
207
|
+
const name = attr.name.toLowerCase();
|
|
208
|
+
if (name === 'data-unicli-ref') continue;
|
|
209
|
+
if (!allowed.has(name) && !name.startsWith('aria-')) continue;
|
|
210
|
+
attrs[name] = String(attr.value || '').slice(0, 500);
|
|
211
|
+
}
|
|
212
|
+
const value = JSON.stringify(attrs);
|
|
213
|
+
return { value, original_length: value.length, truncated: false };
|
|
214
|
+
})()`;
|
|
215
|
+
}
|
|
216
|
+
function normalizeBrowserDomQueryResult({ kind, rawResult, ref, url, }) {
|
|
217
|
+
if (!isRecord(rawResult)) {
|
|
218
|
+
throw new Error("Browser query provider returned an invalid payload.");
|
|
219
|
+
}
|
|
220
|
+
const value = readStringAllowEmpty(rawResult.value);
|
|
221
|
+
if (value === undefined) {
|
|
222
|
+
throw new Error("Browser query provider returned no result value.");
|
|
223
|
+
}
|
|
224
|
+
const originalLength = readNonNegativeInteger(rawResult.original_length) || value.length;
|
|
225
|
+
const truncatedValue = value.length <= BROWSER_DOM_QUERY_RESULT_MAX_CHARS
|
|
226
|
+
? value
|
|
227
|
+
: value.slice(0, BROWSER_DOM_QUERY_RESULT_MAX_CHARS);
|
|
228
|
+
return {
|
|
229
|
+
ok: true,
|
|
230
|
+
evidence_type: "browser-dom-query",
|
|
231
|
+
authority: "ref_read_only",
|
|
232
|
+
kind,
|
|
233
|
+
ref,
|
|
234
|
+
result: truncatedValue,
|
|
235
|
+
result_chars: Math.max(originalLength, value.length),
|
|
236
|
+
result_truncated: rawResult.truncated === true ||
|
|
237
|
+
value.length > BROWSER_DOM_QUERY_RESULT_MAX_CHARS,
|
|
238
|
+
url,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function readDialogEntries(value) {
|
|
242
|
+
if (!Array.isArray(value))
|
|
243
|
+
return [];
|
|
244
|
+
return value.flatMap((entry) => {
|
|
245
|
+
if (!isRecord(entry))
|
|
246
|
+
return [];
|
|
247
|
+
const id = readString(entry.id);
|
|
248
|
+
const type = readString(entry.type);
|
|
249
|
+
const message = readString(entry.message);
|
|
250
|
+
const openedAt = readString(entry.opened_at);
|
|
251
|
+
if (id === undefined ||
|
|
252
|
+
type === undefined ||
|
|
253
|
+
message === undefined ||
|
|
254
|
+
openedAt === undefined) {
|
|
255
|
+
return [];
|
|
256
|
+
}
|
|
257
|
+
const url = readString(entry.url);
|
|
258
|
+
const defaultPrompt = readString(entry.default_prompt);
|
|
259
|
+
return [
|
|
260
|
+
{
|
|
261
|
+
id: id.slice(0, 120),
|
|
262
|
+
type: type.slice(0, 40),
|
|
263
|
+
message: message.slice(0, 1_000),
|
|
264
|
+
opened_at: openedAt,
|
|
265
|
+
...(url === undefined ? {} : { url: url.slice(0, 2_000) }),
|
|
266
|
+
...(defaultPrompt === undefined
|
|
267
|
+
? {}
|
|
268
|
+
: { default_prompt: defaultPrompt.slice(0, 1_000) }),
|
|
269
|
+
},
|
|
270
|
+
];
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
function readDialogRecords(value) {
|
|
274
|
+
if (!Array.isArray(value))
|
|
275
|
+
return [];
|
|
276
|
+
return value.flatMap((record) => {
|
|
277
|
+
if (!isRecord(record))
|
|
278
|
+
return [];
|
|
279
|
+
const entry = readDialogEntries([record])[0];
|
|
280
|
+
const closedAt = readString(record.closed_at);
|
|
281
|
+
const closedBy = readString(record.closed_by);
|
|
282
|
+
if (entry === undefined ||
|
|
283
|
+
closedAt === undefined ||
|
|
284
|
+
(closedBy !== "agent" &&
|
|
285
|
+
closedBy !== "remote" &&
|
|
286
|
+
closedBy !== "tab_closed")) {
|
|
287
|
+
return [];
|
|
288
|
+
}
|
|
289
|
+
return [
|
|
290
|
+
{
|
|
291
|
+
...entry,
|
|
292
|
+
closed_at: closedAt,
|
|
293
|
+
closed_by: closedBy,
|
|
294
|
+
...(record.action === "accept" || record.action === "dismiss"
|
|
295
|
+
? { action: record.action }
|
|
296
|
+
: {}),
|
|
297
|
+
},
|
|
298
|
+
];
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
function readDownloadEntries(value) {
|
|
302
|
+
if (!Array.isArray(value))
|
|
303
|
+
return [];
|
|
304
|
+
return value.slice(0, 50).flatMap((entry) => {
|
|
305
|
+
if (!isRecord(entry))
|
|
306
|
+
return [];
|
|
307
|
+
const id = readNonNegativeInteger(entry.id);
|
|
308
|
+
const state = readString(entry.state);
|
|
309
|
+
const danger = readString(entry.danger);
|
|
310
|
+
const filenameBasename = readString(entry.filename_basename);
|
|
311
|
+
if (state === undefined ||
|
|
312
|
+
danger === undefined ||
|
|
313
|
+
filenameBasename === undefined) {
|
|
314
|
+
return [];
|
|
315
|
+
}
|
|
316
|
+
return [
|
|
317
|
+
{
|
|
318
|
+
id,
|
|
319
|
+
state: state.slice(0, 40),
|
|
320
|
+
danger: danger.slice(0, 80),
|
|
321
|
+
exists: entry.exists === true,
|
|
322
|
+
paused: entry.paused === true,
|
|
323
|
+
incognito: entry.incognito === true,
|
|
324
|
+
bytes_received: readNonNegativeInteger(entry.bytes_received),
|
|
325
|
+
total_bytes: readNonNegativeInteger(entry.total_bytes),
|
|
326
|
+
file_size: readNonNegativeInteger(entry.file_size),
|
|
327
|
+
filename_basename: pathBasename(filenameBasename).slice(0, 240),
|
|
328
|
+
...(readString(entry.mime) === undefined
|
|
329
|
+
? {}
|
|
330
|
+
: { mime: readString(entry.mime).slice(0, 160) }),
|
|
331
|
+
...(readString(entry.url) === undefined
|
|
332
|
+
? {}
|
|
333
|
+
: { url: readString(entry.url).slice(0, 2_000) }),
|
|
334
|
+
...(readString(entry.final_url) === undefined
|
|
335
|
+
? {}
|
|
336
|
+
: { final_url: readString(entry.final_url).slice(0, 2_000) }),
|
|
337
|
+
...(readString(entry.started_at) === undefined
|
|
338
|
+
? {}
|
|
339
|
+
: { started_at: readString(entry.started_at) }),
|
|
340
|
+
...(readString(entry.ended_at) === undefined
|
|
341
|
+
? {}
|
|
342
|
+
: { ended_at: readString(entry.ended_at) }),
|
|
343
|
+
...(readString(entry.error) === undefined
|
|
344
|
+
? {}
|
|
345
|
+
: { error: readString(entry.error).slice(0, 160) }),
|
|
346
|
+
},
|
|
347
|
+
];
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
function parseDownloadLimit(rawLimit) {
|
|
351
|
+
const parsed = Number.parseInt(rawLimit ?? "20", 10);
|
|
352
|
+
if (!Number.isFinite(parsed))
|
|
353
|
+
return 20;
|
|
354
|
+
return Math.max(1, Math.min(50, Math.trunc(parsed)));
|
|
355
|
+
}
|
|
356
|
+
function readNonNegativeInteger(value) {
|
|
357
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0
|
|
358
|
+
? Math.trunc(value)
|
|
359
|
+
: 0;
|
|
360
|
+
}
|
|
361
|
+
function readString(value) {
|
|
362
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
363
|
+
}
|
|
364
|
+
function readStringAllowEmpty(value) {
|
|
365
|
+
return typeof value === "string" ? value : undefined;
|
|
366
|
+
}
|
|
367
|
+
function isRecord(value) {
|
|
368
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
369
|
+
}
|
|
370
|
+
function parseBrowserCdpParams(rawParams) {
|
|
371
|
+
if (rawParams === undefined)
|
|
372
|
+
return {};
|
|
373
|
+
let parsed;
|
|
374
|
+
try {
|
|
375
|
+
parsed = JSON.parse(rawParams);
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
throw new Error("CDP params must be a JSON object.");
|
|
379
|
+
}
|
|
380
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
381
|
+
throw new Error("CDP params must be a JSON object.");
|
|
382
|
+
}
|
|
383
|
+
return parsed;
|
|
384
|
+
}
|
|
385
|
+
function assertBrowserCdpReadOnlyMethod(method) {
|
|
386
|
+
if (BROWSER_CDP_READ_ONLY_METHODS.has(method))
|
|
387
|
+
return;
|
|
388
|
+
throw new Error(`CDP method ${method} is not in the read-only allowlist. Supported methods: ${[
|
|
389
|
+
...BROWSER_CDP_READ_ONLY_METHODS,
|
|
390
|
+
].join(", ")}`);
|
|
391
|
+
}
|
|
392
|
+
function createBrowserCdpReadOnlyResult(input) {
|
|
393
|
+
const resultJson = JSON.stringify(input.result ?? null);
|
|
394
|
+
if (resultJson.length <= BROWSER_CDP_RESULT_MAX_CHARS) {
|
|
395
|
+
return {
|
|
396
|
+
ok: true,
|
|
397
|
+
evidence_type: "browser-cdp-readonly",
|
|
398
|
+
workspace: input.workspace,
|
|
399
|
+
method: input.method,
|
|
400
|
+
authority: "read_only_allowlist",
|
|
401
|
+
params_keys: Object.keys(input.params).sort(),
|
|
402
|
+
result_json_chars: resultJson.length,
|
|
403
|
+
result_truncated: false,
|
|
404
|
+
result: input.result,
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
return {
|
|
408
|
+
ok: true,
|
|
409
|
+
evidence_type: "browser-cdp-readonly",
|
|
410
|
+
workspace: input.workspace,
|
|
411
|
+
method: input.method,
|
|
412
|
+
authority: "read_only_allowlist",
|
|
413
|
+
params_keys: Object.keys(input.params).sort(),
|
|
414
|
+
result_json_chars: resultJson.length,
|
|
415
|
+
result_truncated: true,
|
|
416
|
+
result_preview: resultJson.slice(0, BROWSER_CDP_RESULT_MAX_CHARS),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
94
419
|
export function registerBrowserOperatorSubcommands(root, program, namespace) {
|
|
95
420
|
root
|
|
96
421
|
.command("open <url>")
|
|
@@ -136,6 +461,27 @@ export function registerBrowserOperatorSubcommands(root, program, namespace) {
|
|
|
136
461
|
return { url, snapshot };
|
|
137
462
|
});
|
|
138
463
|
}));
|
|
464
|
+
root
|
|
465
|
+
.command("query <ref>")
|
|
466
|
+
.description("Read bounded DOM data from a verified snapshot ref")
|
|
467
|
+
.option("--kind <kind>", "Query kind: text, value, or attributes", "text")
|
|
468
|
+
.action((ref, opts) => operatorAction(program, root, namespace, "query", async () => {
|
|
469
|
+
validateRef(ref);
|
|
470
|
+
const kind = parseBrowserDomQueryKind(opts.kind);
|
|
471
|
+
const page = await getOperatorPage(root, namespace);
|
|
472
|
+
const selector = `[data-unicli-ref="${ref}"]`;
|
|
473
|
+
return await withRecordedBrowserAction(program, root, namespace, "query", page, { ref, kind }, async () => {
|
|
474
|
+
await verifyRef(page, selector);
|
|
475
|
+
const url = await page.url();
|
|
476
|
+
const rawResult = await page.evaluate(buildBrowserDomQueryJs(ref, kind));
|
|
477
|
+
return normalizeBrowserDomQueryResult({
|
|
478
|
+
kind,
|
|
479
|
+
rawResult,
|
|
480
|
+
ref,
|
|
481
|
+
url,
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
}));
|
|
139
485
|
root
|
|
140
486
|
.command("screenshot [path]")
|
|
141
487
|
.description("Capture page screenshot")
|
|
@@ -192,6 +538,62 @@ export function registerBrowserOperatorSubcommands(root, program, namespace) {
|
|
|
192
538
|
screenshotDir,
|
|
193
539
|
});
|
|
194
540
|
}));
|
|
541
|
+
root
|
|
542
|
+
.command("console")
|
|
543
|
+
.description("Read bounded browser console messages and page errors")
|
|
544
|
+
.option("--clear", "Clear captured console entries after reading")
|
|
545
|
+
.option("--max <n>", "Maximum console entries to return", "50")
|
|
546
|
+
.option("--text-max <n>", "Maximum text characters per entry", "1000")
|
|
547
|
+
.action((opts) => operatorAction(program, root, namespace, "console", async () => {
|
|
548
|
+
const page = await getOperatorPage(root, namespace);
|
|
549
|
+
return await readBrowserConsole(page, {
|
|
550
|
+
clear: opts.clear === true,
|
|
551
|
+
maxEntries: parseInt(opts.max, 10),
|
|
552
|
+
maxTextChars: parseInt(opts.textMax, 10),
|
|
553
|
+
});
|
|
554
|
+
}));
|
|
555
|
+
root
|
|
556
|
+
.command("cdp <method> [params]")
|
|
557
|
+
.description("Run a read-only allowlisted Chrome DevTools Protocol command")
|
|
558
|
+
.action((method, paramsJson) => operatorAction(program, root, namespace, "cdp", async () => {
|
|
559
|
+
assertBrowserCdpReadOnlyMethod(method);
|
|
560
|
+
const params = parseBrowserCdpParams(paramsJson);
|
|
561
|
+
const page = await getOperatorPage(root, namespace);
|
|
562
|
+
const result = await page.sendCDP(method, params);
|
|
563
|
+
return createBrowserCdpReadOnlyResult({
|
|
564
|
+
workspace: resolveWorkspace(root, namespace),
|
|
565
|
+
method,
|
|
566
|
+
params,
|
|
567
|
+
result,
|
|
568
|
+
});
|
|
569
|
+
}));
|
|
570
|
+
root
|
|
571
|
+
.command("dialogs")
|
|
572
|
+
.description("Start and read provider-owned browser dialog supervision")
|
|
573
|
+
.option("--clear-recent", "Clear recent dialog records after reading")
|
|
574
|
+
.action((opts) => operatorAction(program, root, namespace, "dialogs", async () => {
|
|
575
|
+
const workspace = resolveWorkspace(root, namespace);
|
|
576
|
+
const result = await sendCommand("dialog-read", {
|
|
577
|
+
workspace,
|
|
578
|
+
clearRecent: opts.clearRecent === true,
|
|
579
|
+
});
|
|
580
|
+
return normalizeBrowserDialogProviderResult(result, workspace);
|
|
581
|
+
}));
|
|
582
|
+
root
|
|
583
|
+
.command("dialog <action> [dialogId]")
|
|
584
|
+
.description("Respond to a pending browser JavaScript dialog")
|
|
585
|
+
.option("--prompt <text>", "Prompt text for prompt() dialogs")
|
|
586
|
+
.action((actionRaw, dialogId, opts) => operatorAction(program, root, namespace, "dialog", async () => {
|
|
587
|
+
const action = parseBrowserDialogAction(actionRaw);
|
|
588
|
+
const workspace = resolveWorkspace(root, namespace);
|
|
589
|
+
const result = await sendCommand("dialog-respond", {
|
|
590
|
+
workspace,
|
|
591
|
+
dialogAction: action,
|
|
592
|
+
...(dialogId === undefined ? {} : { dialogId }),
|
|
593
|
+
...(opts.prompt === undefined ? {} : { promptText: opts.prompt }),
|
|
594
|
+
});
|
|
595
|
+
return normalizeBrowserDialogProviderResult(result, workspace);
|
|
596
|
+
}));
|
|
195
597
|
root
|
|
196
598
|
.command("click <ref>")
|
|
197
599
|
.description("Click element by ref number from state")
|
|
@@ -456,6 +858,19 @@ export function registerBrowserOperatorSubcommands(root, program, namespace) {
|
|
|
456
858
|
const page = await getOperatorPage(root, namespace);
|
|
457
859
|
return await readFrames(page);
|
|
458
860
|
}));
|
|
861
|
+
root
|
|
862
|
+
.command("downloads")
|
|
863
|
+
.description("List recent browser downloads without exposing local file paths")
|
|
864
|
+
.option("--limit <n>", "Maximum download records to return", "20")
|
|
865
|
+
.action((opts) => operatorAction(program, root, namespace, "downloads", async () => {
|
|
866
|
+
const workspace = resolveWorkspace(root, namespace);
|
|
867
|
+
const limit = parseDownloadLimit(opts.limit);
|
|
868
|
+
const result = await sendCommand("downloads-read", {
|
|
869
|
+
workspace,
|
|
870
|
+
downloadLimit: limit,
|
|
871
|
+
});
|
|
872
|
+
return normalizeBrowserDownloadsProviderResult(result, workspace, limit);
|
|
873
|
+
}));
|
|
459
874
|
root
|
|
460
875
|
.command("extract")
|
|
461
876
|
.description("Extract long-form page text with chunked pagination")
|
|
@@ -516,10 +931,18 @@ export function registerBrowserOperatorSubcommands(root, program, namespace) {
|
|
|
516
931
|
root
|
|
517
932
|
.command("close")
|
|
518
933
|
.description("Close the automation browser window")
|
|
519
|
-
.
|
|
934
|
+
.option("--all", "Close or release all managed browser sessions")
|
|
935
|
+
.action((opts) => operatorAction(program, root, namespace, "close", async () => {
|
|
936
|
+
if (opts.all === true) {
|
|
937
|
+
return await closeAllBrowserSessions();
|
|
938
|
+
}
|
|
520
939
|
const page = await getOperatorPage(root, namespace);
|
|
521
940
|
await page.closeWindow();
|
|
522
|
-
return {
|
|
941
|
+
return {
|
|
942
|
+
ok: true,
|
|
943
|
+
scope: "current_managed_session",
|
|
944
|
+
workspace: resolveWorkspace(root, namespace),
|
|
945
|
+
};
|
|
523
946
|
}));
|
|
524
947
|
}
|
|
525
948
|
//# sourceMappingURL=actions.js.map
|