@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.
Files changed (109) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +2 -2
  3. package/README.zh-CN.md +2 -2
  4. package/dist/browser/protocol.d.ts +6 -1
  5. package/dist/browser/protocol.d.ts.map +1 -1
  6. package/dist/browser/protocol.js.map +1 -1
  7. package/dist/commands/browser/actions.d.ts.map +1 -1
  8. package/dist/commands/browser/actions.js +428 -5
  9. package/dist/commands/browser/actions.js.map +1 -1
  10. package/dist/commands/compute.js +12 -1
  11. package/dist/commands/compute.js.map +1 -1
  12. package/dist/commands/schema.d.ts.map +1 -1
  13. package/dist/commands/schema.js +22 -0
  14. package/dist/commands/schema.js.map +1 -1
  15. package/dist/commands/search.d.ts.map +1 -1
  16. package/dist/commands/search.js +14 -3
  17. package/dist/commands/search.js.map +1 -1
  18. package/dist/compute/contracts.d.ts +55 -0
  19. package/dist/compute/contracts.d.ts.map +1 -0
  20. package/dist/compute/contracts.js +487 -0
  21. package/dist/compute/contracts.js.map +1 -0
  22. package/dist/discovery/aliases.d.ts +8 -1
  23. package/dist/discovery/aliases.d.ts.map +1 -1
  24. package/dist/discovery/aliases.js +125 -20
  25. package/dist/discovery/aliases.js.map +1 -1
  26. package/dist/discovery/core-catalog.d.ts.map +1 -1
  27. package/dist/discovery/core-catalog.js +39 -67
  28. package/dist/discovery/core-catalog.js.map +1 -1
  29. package/dist/discovery/intents.d.ts +1 -0
  30. package/dist/discovery/intents.d.ts.map +1 -1
  31. package/dist/discovery/intents.js +26 -0
  32. package/dist/discovery/intents.js.map +1 -1
  33. package/dist/discovery/macos-dynamic.d.ts +1 -0
  34. package/dist/discovery/macos-dynamic.d.ts.map +1 -1
  35. package/dist/discovery/macos-dynamic.js +20 -1
  36. package/dist/discovery/macos-dynamic.js.map +1 -1
  37. package/dist/discovery/search.d.ts.map +1 -1
  38. package/dist/discovery/search.js +12 -5
  39. package/dist/discovery/search.js.map +1 -1
  40. package/dist/engine/browser/evidence.d.ts +34 -1
  41. package/dist/engine/browser/evidence.d.ts.map +1 -1
  42. package/dist/engine/browser/evidence.js +141 -6
  43. package/dist/engine/browser/evidence.js.map +1 -1
  44. package/dist/engine/steps/fetch-text.d.ts.map +1 -1
  45. package/dist/engine/steps/fetch-text.js +2 -2
  46. package/dist/engine/steps/fetch-text.js.map +1 -1
  47. package/dist/engine/steps/fetch.d.ts +1 -0
  48. package/dist/engine/steps/fetch.d.ts.map +1 -1
  49. package/dist/engine/steps/fetch.js +24 -4
  50. package/dist/engine/steps/fetch.js.map +1 -1
  51. package/dist/fast-path/handlers/discovery.d.ts +5 -5
  52. package/dist/fast-path/handlers/discovery.d.ts.map +1 -1
  53. package/dist/fast-path/handlers/discovery.js +61 -8
  54. package/dist/fast-path/handlers/discovery.js.map +1 -1
  55. package/dist/fast-path/render.d.ts +2 -0
  56. package/dist/fast-path/render.d.ts.map +1 -1
  57. package/dist/fast-path/render.js +9 -0
  58. package/dist/fast-path/render.js.map +1 -1
  59. package/dist/manifest-compact.txt +1 -1
  60. package/dist/manifest.json +174 -1
  61. package/dist/mcp/handler.d.ts +2 -16
  62. package/dist/mcp/handler.d.ts.map +1 -1
  63. package/dist/mcp/handler.js.map +1 -1
  64. package/dist/mcp/http-transport.d.ts +7 -1
  65. package/dist/mcp/http-transport.d.ts.map +1 -1
  66. package/dist/mcp/http-transport.js +20 -1
  67. package/dist/mcp/http-transport.js.map +1 -1
  68. package/dist/mcp/jsonrpc.d.ts +27 -0
  69. package/dist/mcp/jsonrpc.d.ts.map +1 -0
  70. package/dist/mcp/jsonrpc.js +12 -0
  71. package/dist/mcp/jsonrpc.js.map +1 -0
  72. package/dist/mcp/origin-guard.d.ts +26 -0
  73. package/dist/mcp/origin-guard.d.ts.map +1 -0
  74. package/dist/mcp/origin-guard.js +42 -0
  75. package/dist/mcp/origin-guard.js.map +1 -0
  76. package/dist/mcp/profiles/computer-use.d.ts.map +1 -1
  77. package/dist/mcp/profiles/computer-use.js +30 -270
  78. package/dist/mcp/profiles/computer-use.js.map +1 -1
  79. package/dist/mcp/streamable-http/session.d.ts +4 -22
  80. package/dist/mcp/streamable-http/session.d.ts.map +1 -1
  81. package/dist/mcp/streamable-http/session.js +4 -24
  82. package/dist/mcp/streamable-http/session.js.map +1 -1
  83. package/dist/mcp/tools.d.ts.map +1 -1
  84. package/dist/mcp/tools.js +74 -54
  85. package/dist/mcp/tools.js.map +1 -1
  86. package/dist/output/envelope.d.ts +2 -0
  87. package/dist/output/envelope.d.ts.map +1 -1
  88. package/dist/output/envelope.js.map +1 -1
  89. package/dist/output/error-map.d.ts +14 -0
  90. package/dist/output/error-map.d.ts.map +1 -1
  91. package/dist/output/error-map.js +20 -0
  92. package/dist/output/error-map.js.map +1 -1
  93. package/dist/transport/cascade.d.ts.map +1 -1
  94. package/dist/transport/cascade.js +77 -5
  95. package/dist/transport/cascade.js.map +1 -1
  96. package/dist/transport/refs.d.ts +33 -1
  97. package/dist/transport/refs.d.ts.map +1 -1
  98. package/dist/transport/refs.js +40 -1
  99. package/dist/transport/refs.js.map +1 -1
  100. package/package.json +1 -1
  101. package/server.json +2 -2
  102. package/skills/unicli/SKILL.md +1 -1
  103. package/skills/unicli-claude-code/SKILL.md +1 -1
  104. package/skills/unicli-hermes/SKILL.md +1 -1
  105. package/src/adapters/defuddle/read.yaml +30 -0
  106. package/src/adapters/jina/read.yaml +30 -0
  107. package/src/adapters/markdown-new/read.yaml +50 -0
  108. package/src/adapters/ollama-cloud/fetch.yaml +39 -0
  109. 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 -->313<!-- /STATS --> sites, <!-- STATS:command_count -->1767<!-- /STATS --> commands, <!-- STATS:pipeline_step_count -->103<!-- /STATS --> pipeline steps, BM25 bilingual search. `npm install -g @zenalexa/unicli`
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), +74 more (`unicli list`)
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.1 — Apollo · Conrad
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 -->313<!-- /STATS --> surfaces · <!-- STATS:test_count -->9117<!-- /STATS --> tests</sub>
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.1 — Apollo · Conrad</sub>
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 -->313<!-- /STATS --> 个 surface · <!-- STATS:test_count -->9117<!-- /STATS --> 个测试</sub>
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.1 — Apollo · Conrad</sub>
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;AA0FlC,MAAM,UAAU,0BAA0B,CAAC,KAAqB;IAC9D,OAAO,KAAK,CAAC,OAAO,KAAK,cAAc,IAAI,KAAK,CAAC,QAAQ,KAAK,eAAe,CAAC;AAChF,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;AAIH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,OAAO,EAUL,sBAAsB,EACvB,MAAM,cAAc,CAAC;AAwBtB,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAQlC,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4BtE;AA4FD,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,GAAG,SAAS,GAC/B,IAAI,CAqoBN"}
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
- .action(() => operatorAction(program, root, namespace, "close", async () => {
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 { ok: true, workspace: resolveWorkspace(root, namespace) };
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