gologin-web-access 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +344 -0
  4. package/dist/cli.js +173 -0
  5. package/dist/commands/back.js +13 -0
  6. package/dist/commands/batch.js +81 -0
  7. package/dist/commands/batchChangeTrack.js +99 -0
  8. package/dist/commands/batchExtract.js +97 -0
  9. package/dist/commands/batchScrape.js +140 -0
  10. package/dist/commands/changeTrack.js +65 -0
  11. package/dist/commands/check.js +14 -0
  12. package/dist/commands/click.js +14 -0
  13. package/dist/commands/close.js +19 -0
  14. package/dist/commands/configInit.js +77 -0
  15. package/dist/commands/configShow.js +23 -0
  16. package/dist/commands/cookies.js +22 -0
  17. package/dist/commands/cookiesClear.js +13 -0
  18. package/dist/commands/cookiesImport.js +14 -0
  19. package/dist/commands/crawl.js +71 -0
  20. package/dist/commands/crawlErrors.js +20 -0
  21. package/dist/commands/crawlResult.js +27 -0
  22. package/dist/commands/crawlStart.js +56 -0
  23. package/dist/commands/crawlStatus.js +25 -0
  24. package/dist/commands/current.js +14 -0
  25. package/dist/commands/dblclick.js +14 -0
  26. package/dist/commands/eval.js +20 -0
  27. package/dist/commands/extract.js +44 -0
  28. package/dist/commands/fill.js +15 -0
  29. package/dist/commands/find.js +16 -0
  30. package/dist/commands/focus.js +14 -0
  31. package/dist/commands/forward.js +13 -0
  32. package/dist/commands/get.js +15 -0
  33. package/dist/commands/hover.js +14 -0
  34. package/dist/commands/jobs.js +47 -0
  35. package/dist/commands/map.js +61 -0
  36. package/dist/commands/open.js +22 -0
  37. package/dist/commands/parseDocument.js +34 -0
  38. package/dist/commands/pdf.js +14 -0
  39. package/dist/commands/press.js +15 -0
  40. package/dist/commands/read.js +51 -0
  41. package/dist/commands/reload.js +13 -0
  42. package/dist/commands/run.js +76 -0
  43. package/dist/commands/scrape.js +19 -0
  44. package/dist/commands/scrapeJson.js +24 -0
  45. package/dist/commands/scrapeMarkdown.js +37 -0
  46. package/dist/commands/scrapeScreenshot.js +65 -0
  47. package/dist/commands/scrapeText.js +37 -0
  48. package/dist/commands/screenshot.js +23 -0
  49. package/dist/commands/scroll.js +23 -0
  50. package/dist/commands/scrollIntoView.js +14 -0
  51. package/dist/commands/search.js +39 -0
  52. package/dist/commands/searchBrowser.js +28 -0
  53. package/dist/commands/select.js +15 -0
  54. package/dist/commands/sessions.js +14 -0
  55. package/dist/commands/shared.js +102 -0
  56. package/dist/commands/snapshot.js +18 -0
  57. package/dist/commands/storageClear.js +18 -0
  58. package/dist/commands/storageExport.js +26 -0
  59. package/dist/commands/storageImport.js +23 -0
  60. package/dist/commands/tabClose.js +18 -0
  61. package/dist/commands/tabFocus.js +15 -0
  62. package/dist/commands/tabOpen.js +19 -0
  63. package/dist/commands/tabs.js +13 -0
  64. package/dist/commands/type.js +15 -0
  65. package/dist/commands/uncheck.js +14 -0
  66. package/dist/commands/upload.js +15 -0
  67. package/dist/commands/wait.js +27 -0
  68. package/dist/config.js +260 -0
  69. package/dist/doctor.js +86 -0
  70. package/dist/internal-agent/cli.js +336 -0
  71. package/dist/internal-agent/commands/back.js +12 -0
  72. package/dist/internal-agent/commands/check.js +17 -0
  73. package/dist/internal-agent/commands/click.js +17 -0
  74. package/dist/internal-agent/commands/close.js +12 -0
  75. package/dist/internal-agent/commands/cookies.js +23 -0
  76. package/dist/internal-agent/commands/cookiesClear.js +12 -0
  77. package/dist/internal-agent/commands/cookiesImport.js +18 -0
  78. package/dist/internal-agent/commands/current.js +9 -0
  79. package/dist/internal-agent/commands/dblclick.js +17 -0
  80. package/dist/internal-agent/commands/doctor.js +53 -0
  81. package/dist/internal-agent/commands/eval.js +30 -0
  82. package/dist/internal-agent/commands/fill.js +18 -0
  83. package/dist/internal-agent/commands/find.js +86 -0
  84. package/dist/internal-agent/commands/focus.js +17 -0
  85. package/dist/internal-agent/commands/forward.js +12 -0
  86. package/dist/internal-agent/commands/get.js +19 -0
  87. package/dist/internal-agent/commands/hover.js +17 -0
  88. package/dist/internal-agent/commands/open.js +67 -0
  89. package/dist/internal-agent/commands/pdf.js +18 -0
  90. package/dist/internal-agent/commands/press.js +19 -0
  91. package/dist/internal-agent/commands/reload.js +12 -0
  92. package/dist/internal-agent/commands/screenshot.js +22 -0
  93. package/dist/internal-agent/commands/scroll.js +25 -0
  94. package/dist/internal-agent/commands/scrollIntoView.js +17 -0
  95. package/dist/internal-agent/commands/select.js +18 -0
  96. package/dist/internal-agent/commands/sessions.js +15 -0
  97. package/dist/internal-agent/commands/shared.js +51 -0
  98. package/dist/internal-agent/commands/snapshot.js +16 -0
  99. package/dist/internal-agent/commands/storageClear.js +13 -0
  100. package/dist/internal-agent/commands/storageExport.js +24 -0
  101. package/dist/internal-agent/commands/storageImport.js +20 -0
  102. package/dist/internal-agent/commands/tabClose.js +21 -0
  103. package/dist/internal-agent/commands/tabFocus.js +21 -0
  104. package/dist/internal-agent/commands/tabOpen.js +13 -0
  105. package/dist/internal-agent/commands/tabs.js +17 -0
  106. package/dist/internal-agent/commands/type.js +18 -0
  107. package/dist/internal-agent/commands/uncheck.js +17 -0
  108. package/dist/internal-agent/commands/upload.js +18 -0
  109. package/dist/internal-agent/commands/wait.js +41 -0
  110. package/dist/internal-agent/daemon/browser.js +818 -0
  111. package/dist/internal-agent/daemon/refStore.js +26 -0
  112. package/dist/internal-agent/daemon/server.js +330 -0
  113. package/dist/internal-agent/daemon/sessionManager.js +684 -0
  114. package/dist/internal-agent/daemon/snapshot.js +285 -0
  115. package/dist/internal-agent/lib/config.js +59 -0
  116. package/dist/internal-agent/lib/daemon.js +300 -0
  117. package/dist/internal-agent/lib/errors.js +63 -0
  118. package/dist/internal-agent/lib/types.js +2 -0
  119. package/dist/internal-agent/lib/utils.js +165 -0
  120. package/dist/jobRunner.js +56 -0
  121. package/dist/lib/agentCli.js +158 -0
  122. package/dist/lib/browserRead.js +125 -0
  123. package/dist/lib/browserStructured.js +77 -0
  124. package/dist/lib/changeTracking.js +117 -0
  125. package/dist/lib/cloudApi.js +41 -0
  126. package/dist/lib/concurrency.js +15 -0
  127. package/dist/lib/crawl.js +313 -0
  128. package/dist/lib/document.js +170 -0
  129. package/dist/lib/errors.js +55 -0
  130. package/dist/lib/extract.js +65 -0
  131. package/dist/lib/extractRunner.js +22 -0
  132. package/dist/lib/jobRegistry.js +164 -0
  133. package/dist/lib/output.js +122 -0
  134. package/dist/lib/readSource.js +297 -0
  135. package/dist/lib/runbooks.js +193 -0
  136. package/dist/lib/search.js +727 -0
  137. package/dist/lib/selfCli.js +136 -0
  138. package/dist/lib/structuredScrape.js +83 -0
  139. package/dist/lib/types.js +2 -0
  140. package/dist/lib/unlocker.js +383 -0
  141. package/package.json +67 -0
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildBatchChangeTrackCommand = buildBatchChangeTrackCommand;
7
+ const fs_1 = require("fs");
8
+ const path_1 = __importDefault(require("path"));
9
+ const commander_1 = require("commander");
10
+ const config_1 = require("../config");
11
+ const changeTracking_1 = require("../lib/changeTracking");
12
+ const concurrency_1 = require("../lib/concurrency");
13
+ const output_1 = require("../lib/output");
14
+ const shared_1 = require("./shared");
15
+ function buildBatchChangeTrackCommand() {
16
+ return (0, shared_1.addUnlockerRequestOptions)(new commander_1.Command("batch-change-track")
17
+ .description("Track multiple pages over time and report which ones are new, same, or changed.")
18
+ .argument("<urls...>", "One or more URLs")
19
+ .option("--format <format>", "html, markdown, text, or json", "markdown")
20
+ .option("--concurrency <count>", "Number of concurrent requests", "4")
21
+ .option("--output <path>", "Write the full batch result JSON to a file")
22
+ .option("--summary", "Print one-line status counts to stderr after the JSON output")
23
+ .action(async (urls, options) => {
24
+ const config = await (0, config_1.loadConfig)();
25
+ const apiKey = (0, config_1.requireWebUnlockerKey)(config);
26
+ const format = (0, changeTracking_1.normalizeTrackingFormat)(options.format);
27
+ const concurrency = Math.max(1, Number(options.concurrency) || 4);
28
+ const requestOptions = (0, shared_1.normalizeUnlockerRequestOptions)(options);
29
+ const results = await (0, concurrency_1.mapWithConcurrency)(urls, concurrency, async (url) => {
30
+ try {
31
+ const key = (0, changeTracking_1.buildTrackingKey)(url);
32
+ const snapshot = await (0, changeTracking_1.scrapeForTracking)(url, apiKey, format, requestOptions);
33
+ const result = await (0, changeTracking_1.compareAndPersistSnapshot)(config, {
34
+ key,
35
+ url,
36
+ format,
37
+ title: snapshot.title,
38
+ content: snapshot.content,
39
+ });
40
+ return {
41
+ ok: true,
42
+ ...result,
43
+ request: snapshot.request,
44
+ };
45
+ }
46
+ catch (error) {
47
+ return {
48
+ url,
49
+ ok: false,
50
+ error: error instanceof Error ? error.message : "Unknown error",
51
+ status: extractStatusCode(error),
52
+ request: extractRequestMeta(error),
53
+ };
54
+ }
55
+ });
56
+ if (options.output) {
57
+ const outputPath = path_1.default.resolve(options.output);
58
+ await fs_1.promises.mkdir(path_1.default.dirname(outputPath), { recursive: true });
59
+ await fs_1.promises.writeFile(outputPath, `${JSON.stringify(results, null, 2)}\n`, "utf8");
60
+ process.stdout.write(`${outputPath}\n`);
61
+ }
62
+ else {
63
+ (0, output_1.printJson)(results);
64
+ }
65
+ if (options.summary) {
66
+ process.stderr.write(formatBatchChangeTrackSummary(results) + "\n");
67
+ }
68
+ if (results.some((result) => !result.ok)) {
69
+ process.exitCode = 1;
70
+ }
71
+ }));
72
+ }
73
+ function formatBatchChangeTrackSummary(results) {
74
+ const requested = results.length;
75
+ const failed = results.filter((result) => !result.ok).length;
76
+ const successful = results.filter((result) => result.ok);
77
+ const created = successful.filter((result) => result.status === "new").length;
78
+ const same = successful.filter((result) => result.status === "same").length;
79
+ const changed = successful.filter((result) => result.status === "changed").length;
80
+ return `Summary: ${requested} requested, ${created} new, ${same} same, ${changed} changed, ${failed} failed.`;
81
+ }
82
+ function extractStatusCode(error) {
83
+ if (typeof error === "object" &&
84
+ error !== null &&
85
+ "status" in error &&
86
+ typeof error.status === "number") {
87
+ return error.status;
88
+ }
89
+ return undefined;
90
+ }
91
+ function extractRequestMeta(error) {
92
+ if (typeof error === "object" &&
93
+ error !== null &&
94
+ "request" in error &&
95
+ typeof error.request === "object") {
96
+ return error.request;
97
+ }
98
+ return undefined;
99
+ }
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildBatchExtractCommand = buildBatchExtractCommand;
7
+ const fs_1 = require("fs");
8
+ const path_1 = __importDefault(require("path"));
9
+ const commander_1 = require("commander");
10
+ const config_1 = require("../config");
11
+ const extractRunner_1 = require("../lib/extractRunner");
12
+ const concurrency_1 = require("../lib/concurrency");
13
+ const output_1 = require("../lib/output");
14
+ const readSource_1 = require("../lib/readSource");
15
+ const shared_1 = require("./shared");
16
+ function buildBatchExtractCommand() {
17
+ return (0, shared_1.addProfileOption)((0, shared_1.addUnlockerRequestOptions)(new commander_1.Command("batch-extract")
18
+ .description("Extract structured data from multiple pages using one selector schema.")
19
+ .argument("<urls...>", "One or more URLs")
20
+ .requiredOption("--schema <path>", "Path to a JSON extraction schema")
21
+ .option("--source <source>", "Read source: auto, unlocker, or browser", "auto")
22
+ .option("--concurrency <count>", "Number of concurrent requests", "4")
23
+ .option("--output <path>", "Write the full batch result JSON to a file")
24
+ .option("--summary", "Print one-line summary stats to stderr after the JSON output")
25
+ .action(async (urls, options) => {
26
+ const config = await (0, config_1.loadConfig)();
27
+ const source = (0, readSource_1.normalizeReadSourceMode)(options.source, "auto");
28
+ const apiKey = source === "browser" ? "" : (0, config_1.requireWebUnlockerKey)(config);
29
+ const schema = await readSchema(path_1.default.resolve(options.schema));
30
+ const concurrency = Math.max(1, Number(options.concurrency) || 4);
31
+ const request = (0, shared_1.normalizeUnlockerRequestOptions)(options);
32
+ const results = await (0, concurrency_1.mapWithConcurrency)(urls, concurrency, async (url) => {
33
+ try {
34
+ return {
35
+ ok: true,
36
+ ...(await (0, extractRunner_1.extractUrlWithSchema)(url, config, apiKey, schema, {
37
+ source,
38
+ request,
39
+ profile: options.profile,
40
+ })),
41
+ };
42
+ }
43
+ catch (error) {
44
+ return {
45
+ url,
46
+ ok: false,
47
+ error: error instanceof Error ? error.message : "Unknown error",
48
+ status: extractStatusCode(error),
49
+ request: extractRequestMeta(error),
50
+ };
51
+ }
52
+ });
53
+ if (options.output) {
54
+ const outputPath = path_1.default.resolve(options.output);
55
+ await fs_1.promises.mkdir(path_1.default.dirname(outputPath), { recursive: true });
56
+ await fs_1.promises.writeFile(outputPath, `${JSON.stringify(results, null, 2)}\n`, "utf8");
57
+ process.stdout.write(`${outputPath}\n`);
58
+ }
59
+ else {
60
+ (0, output_1.printJson)(results);
61
+ }
62
+ if (options.summary) {
63
+ process.stderr.write(formatBatchExtractSummary(results) + "\n");
64
+ }
65
+ if (results.some((result) => !result.ok)) {
66
+ process.exitCode = 1;
67
+ }
68
+ })));
69
+ }
70
+ async function readSchema(schemaPath) {
71
+ const raw = await fs_1.promises.readFile(schemaPath, "utf8");
72
+ return JSON.parse(raw);
73
+ }
74
+ function formatBatchExtractSummary(results) {
75
+ const requested = results.length;
76
+ const ok = results.filter((result) => result.ok).length;
77
+ const failed = requested - ok;
78
+ return `Summary: ${requested} requested, ${ok} ok, ${failed} failed.`;
79
+ }
80
+ function extractStatusCode(error) {
81
+ if (typeof error === "object" &&
82
+ error !== null &&
83
+ "status" in error &&
84
+ typeof error.status === "number") {
85
+ return error.status;
86
+ }
87
+ return undefined;
88
+ }
89
+ function extractRequestMeta(error) {
90
+ if (typeof error === "object" &&
91
+ error !== null &&
92
+ "request" in error &&
93
+ typeof error.request === "object") {
94
+ return error.request;
95
+ }
96
+ return undefined;
97
+ }
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildBatchScrapeCommand = buildBatchScrapeCommand;
4
+ const commander_1 = require("commander");
5
+ const config_1 = require("../config");
6
+ const output_1 = require("../lib/output");
7
+ const readSource_1 = require("../lib/readSource");
8
+ const structuredScrape_1 = require("../lib/structuredScrape");
9
+ const unlocker_1 = require("../lib/unlocker");
10
+ const shared_1 = require("./shared");
11
+ function buildBatchScrapeCommand() {
12
+ return (0, shared_1.addProfileOption)((0, shared_1.addUnlockerRequestOptions)(new commander_1.Command("batch-scrape")
13
+ .description("Fetch multiple pages through Web Unlocker and print a JSON array of results.")
14
+ .argument("<urls...>", "One or more URLs")
15
+ .option("--format <format>", "html, markdown, text, or json", "html")
16
+ .option("--concurrency <count>", "Number of concurrent requests", "4")
17
+ .option("--fallback <mode>", "Structured scrape fallback: none or browser", "none")
18
+ .option("--source <source>", "Read source for --only-main-content mode: auto, unlocker, or browser", "auto")
19
+ .option("--only-main-content", "For html, markdown, or text formats, isolate the most readable content block per page")
20
+ .option("--summary", "Print one-line summary stats to stderr after the JSON output")
21
+ .action(async (urls, options) => {
22
+ const config = await (0, config_1.loadConfig)();
23
+ const format = normalizeFormat(options.format);
24
+ const source = (0, readSource_1.normalizeReadSourceMode)(options.source, "auto");
25
+ const usingBrowserOnlyMainContent = Boolean(options.onlyMainContent) && format !== "json" && source === "browser";
26
+ const apiKey = usingBrowserOnlyMainContent ? "" : (0, config_1.requireWebUnlockerKey)(config);
27
+ const concurrency = Math.max(1, Number(options.concurrency) || 4);
28
+ const requestOptions = (0, shared_1.normalizeUnlockerRequestOptions)(options);
29
+ const fallback = (0, structuredScrape_1.normalizeStructuredFallbackMode)(options.fallback);
30
+ const results = await mapWithConcurrency(urls, concurrency, async (url) => {
31
+ try {
32
+ const output = await formatOutput(url, config, apiKey, format, requestOptions, fallback, {
33
+ source,
34
+ onlyMainContent: Boolean(options.onlyMainContent),
35
+ profile: options.profile,
36
+ });
37
+ return {
38
+ url,
39
+ ok: true,
40
+ format,
41
+ output,
42
+ };
43
+ }
44
+ catch (error) {
45
+ const request = extractRequestMeta(error);
46
+ return {
47
+ url,
48
+ ok: false,
49
+ format,
50
+ error: error instanceof Error ? error.message : "Unknown error",
51
+ status: extractStatusCode(error),
52
+ request,
53
+ };
54
+ }
55
+ });
56
+ (0, output_1.printJson)(results);
57
+ if (options.summary) {
58
+ process.stderr.write(formatBatchSummary(results) + "\n");
59
+ }
60
+ if (results.some((result) => !result.ok)) {
61
+ process.exitCode = 1;
62
+ }
63
+ })));
64
+ }
65
+ function normalizeFormat(value) {
66
+ if (value === "html" || value === "markdown" || value === "text" || value === "json") {
67
+ return value;
68
+ }
69
+ throw new Error(`Unsupported batch scrape format: ${value}`);
70
+ }
71
+ async function formatOutput(url, config, apiKey, format, requestOptions, fallback, options) {
72
+ if (options.onlyMainContent && format !== "json") {
73
+ const readOptions = {
74
+ source: options.source,
75
+ profile: options.profile,
76
+ request: requestOptions,
77
+ };
78
+ switch (format) {
79
+ case "html":
80
+ return (await (0, readSource_1.readHtmlContent)(url, config, apiKey, readOptions)).content;
81
+ case "markdown":
82
+ return (await (0, readSource_1.readMarkdownContent)(url, config, apiKey, readOptions)).content;
83
+ case "text":
84
+ return (await (0, readSource_1.readTextContent)(url, config, apiKey, readOptions)).content;
85
+ default:
86
+ break;
87
+ }
88
+ }
89
+ switch (format) {
90
+ case "html":
91
+ return (await (0, unlocker_1.scrapeRenderedHtml)(url, apiKey, requestOptions)).content;
92
+ case "markdown":
93
+ return (await (0, unlocker_1.scrapeMarkdown)(url, apiKey, requestOptions)).markdown;
94
+ case "text":
95
+ return (await (0, unlocker_1.scrapeText)(url, apiKey, requestOptions)).text;
96
+ case "json":
97
+ return await (0, structuredScrape_1.scrapeStructuredJson)(url, config, apiKey, {
98
+ fallback,
99
+ request: requestOptions,
100
+ });
101
+ default:
102
+ return (await (0, unlocker_1.scrapeRenderedHtml)(url, apiKey, requestOptions)).content;
103
+ }
104
+ }
105
+ async function mapWithConcurrency(items, concurrency, mapper) {
106
+ const results = new Array(items.length);
107
+ let nextIndex = 0;
108
+ await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, async () => {
109
+ while (nextIndex < items.length) {
110
+ const currentIndex = nextIndex;
111
+ nextIndex += 1;
112
+ results[currentIndex] = await mapper(items[currentIndex], currentIndex);
113
+ }
114
+ }));
115
+ return results;
116
+ }
117
+ function formatBatchSummary(results) {
118
+ const requested = results.length;
119
+ const ok = results.filter((result) => result.ok).length;
120
+ const failed = requested - ok;
121
+ return `Summary: ${requested} requested, ${ok} ok, ${failed} failed.`;
122
+ }
123
+ function extractStatusCode(error) {
124
+ if (typeof error === "object" &&
125
+ error !== null &&
126
+ "status" in error &&
127
+ typeof error.status === "number") {
128
+ return error.status;
129
+ }
130
+ return undefined;
131
+ }
132
+ function extractRequestMeta(error) {
133
+ if (typeof error === "object" &&
134
+ error !== null &&
135
+ "request" in error &&
136
+ typeof error.request === "object") {
137
+ return error.request;
138
+ }
139
+ return undefined;
140
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildChangeTrackCommand = buildChangeTrackCommand;
7
+ const fs_1 = require("fs");
8
+ const path_1 = __importDefault(require("path"));
9
+ const commander_1 = require("commander");
10
+ const config_1 = require("../config");
11
+ const changeTracking_1 = require("../lib/changeTracking");
12
+ const output_1 = require("../lib/output");
13
+ const shared_1 = require("./shared");
14
+ function buildChangeTrackCommand() {
15
+ return (0, shared_1.addUnlockerRequestOptions)(new commander_1.Command("change-track")
16
+ .description("Track a page over time and report whether it changed since the last snapshot.")
17
+ .argument("<url>", "Target URL")
18
+ .option("--format <format>", "html, markdown, text, or json", "markdown")
19
+ .option("--key <key>", "Custom tracking key instead of deriving one from the URL")
20
+ .option("--json", "Print JSON output")
21
+ .option("--output <path>", "Write the current tracking result to a file")
22
+ .action(async (url, options) => {
23
+ const config = await (0, config_1.loadConfig)();
24
+ const apiKey = (0, config_1.requireWebUnlockerKey)(config);
25
+ const format = (0, changeTracking_1.normalizeTrackingFormat)(options.format);
26
+ const key = (0, changeTracking_1.buildTrackingKey)(url, options.key);
27
+ const snapshot = await (0, changeTracking_1.scrapeForTracking)(url, apiKey, format, (0, shared_1.normalizeUnlockerRequestOptions)(options));
28
+ const result = await (0, changeTracking_1.compareAndPersistSnapshot)(config, {
29
+ key,
30
+ url,
31
+ format,
32
+ title: snapshot.title,
33
+ content: snapshot.content
34
+ });
35
+ if (options.output) {
36
+ const outputPath = path_1.default.resolve(options.output);
37
+ await fs_1.promises.mkdir(path_1.default.dirname(outputPath), { recursive: true });
38
+ await fs_1.promises.writeFile(outputPath, `${JSON.stringify(result, null, 2)}\n`, "utf8");
39
+ process.stdout.write(`${outputPath}\n`);
40
+ return;
41
+ }
42
+ if (options.json) {
43
+ (0, output_1.printJson)({
44
+ ...result,
45
+ request: snapshot.request,
46
+ });
47
+ return;
48
+ }
49
+ const lines = [
50
+ `key=${result.key}`,
51
+ `url=${result.url}`,
52
+ `format=${result.format}`,
53
+ `status=${result.status}`,
54
+ `currentHash=${result.currentHash}`
55
+ ];
56
+ if (result.previousHash) {
57
+ lines.push(`previousHash=${result.previousHash}`);
58
+ }
59
+ if (result.diff) {
60
+ lines.push("");
61
+ lines.push(result.diff);
62
+ }
63
+ (0, output_1.printText)(lines.join("\n"));
64
+ }));
65
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildCheckCommand = buildCheckCommand;
4
+ const commander_1 = require("commander");
5
+ const shared_1 = require("./shared");
6
+ function buildCheckCommand() {
7
+ const command = new commander_1.Command("check")
8
+ .description("Check an element by snapshot ref.")
9
+ .argument("<ref>", "Snapshot ref, for example e2")
10
+ .action(async (ref, options) => {
11
+ await (0, shared_1.runBrowserCommand)(["check", ref], { session: options.session });
12
+ });
13
+ return (0, shared_1.addSessionOption)(command);
14
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildClickCommand = buildClickCommand;
4
+ const commander_1 = require("commander");
5
+ const shared_1 = require("./shared");
6
+ function buildClickCommand() {
7
+ const command = new commander_1.Command("click")
8
+ .description("Click an element by snapshot ref.")
9
+ .argument("<ref>", "Snapshot ref, for example e3")
10
+ .action(async (ref, options) => {
11
+ await (0, shared_1.runBrowserCommand)(["click", ref], { session: options.session });
12
+ });
13
+ return (0, shared_1.addSessionOption)(command);
14
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildCloseCommand = buildCloseCommand;
4
+ const commander_1 = require("commander");
5
+ const config_1 = require("../config");
6
+ const agentCli_1 = require("../lib/agentCli");
7
+ function buildCloseCommand() {
8
+ return new commander_1.Command("close")
9
+ .description("Close the current browser session or a specific session.")
10
+ .option("--session <id>", "Session ID. Defaults to the current session.")
11
+ .action(async (options) => {
12
+ const config = await (0, config_1.loadConfig)();
13
+ const args = ["close"];
14
+ if (options.session) {
15
+ args.push("--session", options.session);
16
+ }
17
+ await (0, agentCli_1.runAgentCommand)(args, config);
18
+ });
19
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildConfigInitCommand = buildConfigInitCommand;
4
+ const commander_1 = require("commander");
5
+ const config_1 = require("../config");
6
+ const cloudApi_1 = require("../lib/cloudApi");
7
+ const output_1 = require("../lib/output");
8
+ const unlocker_1 = require("../lib/unlocker");
9
+ function buildConfigInitCommand() {
10
+ return new commander_1.Command("init")
11
+ .description("Write ~/.gologin-web-access/config.json with current values or placeholders. Recommended: persist both Web Unlocker and Cloud Browser credentials.")
12
+ .option("--web-unlocker-api-key <key>", "Persist a Web Unlocker API key")
13
+ .option("--web-unlocker-key <key>", "Alias for --web-unlocker-api-key")
14
+ .option("--cloud-token <token>", "Persist a Cloud Browser token")
15
+ .option("--default-profile-id <id>", "Persist a default Gologin profile ID")
16
+ .option("--daemon-port <port>", "Persist a daemon port", String(config_1.DEFAULT_DAEMON_PORT))
17
+ .option("--no-validate", "Skip live key validation after writing config")
18
+ .option("--force", "Overwrite an existing config file")
19
+ .action(async (options) => {
20
+ const webUnlockerApiKey = options.webUnlockerApiKey ?? options.webUnlockerKey ?? process.env[config_1.ENV_NAMES.webUnlockerApiKey];
21
+ const result = await (0, config_1.initConfigFile)({
22
+ webUnlockerApiKey,
23
+ cloudToken: options.cloudToken ?? process.env[config_1.ENV_NAMES.cloudToken],
24
+ defaultProfileId: options.defaultProfileId ?? process.env[config_1.ENV_NAMES.defaultProfileId],
25
+ daemonPort: Number(options.daemonPort ?? process.env[config_1.ENV_NAMES.daemonPort] ?? config_1.DEFAULT_DAEMON_PORT),
26
+ }, {
27
+ force: options.force,
28
+ });
29
+ if (!result.created) {
30
+ (0, output_1.printText)(`Config already exists at ${result.path}. Use --force to overwrite it.`);
31
+ return;
32
+ }
33
+ (0, output_1.printKeyValueRows)([
34
+ { label: "Config file", value: result.path },
35
+ {
36
+ label: "Web Unlocker key",
37
+ value: result.config.webUnlockerApiKey ? "written" : "left empty",
38
+ },
39
+ {
40
+ label: "Cloud token",
41
+ value: result.config.cloudToken ? "written" : "left empty",
42
+ },
43
+ {
44
+ label: "Default profile",
45
+ value: result.config.defaultProfileId ?? "not set",
46
+ },
47
+ {
48
+ label: "Daemon port",
49
+ value: String(result.config.daemonPort ?? config_1.DEFAULT_DAEMON_PORT),
50
+ },
51
+ ]);
52
+ if (!result.config.webUnlockerApiKey || !result.config.cloudToken) {
53
+ (0, output_1.printText)("Recommended next step: configure both GOLOGIN_WEB_UNLOCKER_API_KEY and GOLOGIN_CLOUD_TOKEN so agents can use scraping and browser flows without asking again.");
54
+ }
55
+ if (options.validate === false) {
56
+ return;
57
+ }
58
+ const validationRows = [];
59
+ if (result.config.webUnlockerApiKey) {
60
+ const validation = await (0, unlocker_1.validateWebUnlockerKey)(result.config.webUnlockerApiKey);
61
+ validationRows.push({
62
+ label: "Web Unlocker validation",
63
+ value: validation.ok ? "ok" : `failed${validation.status ? ` (${validation.status})` : ""}: ${validation.detail}`,
64
+ });
65
+ }
66
+ if (result.config.cloudToken) {
67
+ const validation = await (0, cloudApi_1.validateCloudToken)(result.config.cloudToken);
68
+ validationRows.push({
69
+ label: "Cloud token validation",
70
+ value: validation.ok ? "ok" : `failed${validation.status ? ` (${validation.status})` : ""}: ${validation.detail}`,
71
+ });
72
+ }
73
+ if (validationRows.length > 0) {
74
+ (0, output_1.printKeyValueRows)(validationRows);
75
+ }
76
+ });
77
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildConfigShowCommand = buildConfigShowCommand;
4
+ const commander_1 = require("commander");
5
+ const config_1 = require("../config");
6
+ const output_1 = require("../lib/output");
7
+ function buildConfigShowCommand() {
8
+ return new commander_1.Command("show")
9
+ .description("Show merged Gologin CLI configuration and whether the recommended two-key setup is complete.")
10
+ .option("--json", "Print JSON output")
11
+ .action(async (options) => {
12
+ const config = await (0, config_1.loadConfig)();
13
+ const rows = (0, config_1.getMaskedConfigRows)(config);
14
+ if (options.json) {
15
+ (0, output_1.printJson)({
16
+ configPath: config.configPath,
17
+ values: rows,
18
+ });
19
+ return;
20
+ }
21
+ (0, output_1.printKeyValueRows)(rows);
22
+ });
23
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildCookiesCommand = buildCookiesCommand;
4
+ const commander_1 = require("commander");
5
+ const shared_1 = require("./shared");
6
+ function buildCookiesCommand() {
7
+ const command = new commander_1.Command("cookies")
8
+ .description("Export cookies from the active Cloud Browser session.")
9
+ .option("--output <path>", "Write cookies JSON to a file")
10
+ .option("--json", "Print cookies as JSON")
11
+ .action(async (options) => {
12
+ const args = ["cookies"];
13
+ if (options.output) {
14
+ args.push("--output", options.output);
15
+ }
16
+ if (options.json) {
17
+ args.push("--json");
18
+ }
19
+ await (0, shared_1.runBrowserCommand)(args, { session: options.session });
20
+ });
21
+ return (0, shared_1.addSessionOption)(command);
22
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildCookiesClearCommand = buildCookiesClearCommand;
4
+ const commander_1 = require("commander");
5
+ const shared_1 = require("./shared");
6
+ function buildCookiesClearCommand() {
7
+ const command = new commander_1.Command("cookies-clear")
8
+ .description("Clear cookies from the active Cloud Browser session.")
9
+ .action(async (options) => {
10
+ await (0, shared_1.runBrowserCommand)(["cookies-clear"], { session: options.session });
11
+ });
12
+ return (0, shared_1.addSessionOption)(command);
13
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildCookiesImportCommand = buildCookiesImportCommand;
4
+ const commander_1 = require("commander");
5
+ const shared_1 = require("./shared");
6
+ function buildCookiesImportCommand() {
7
+ const command = new commander_1.Command("cookies-import")
8
+ .description("Import cookies into the active Cloud Browser session.")
9
+ .argument("<cookiesPath>", "Path to a cookies JSON file")
10
+ .action(async (cookiesPath, options) => {
11
+ await (0, shared_1.runBrowserCommand)(["cookies-import", cookiesPath], { session: options.session });
12
+ });
13
+ return (0, shared_1.addSessionOption)(command);
14
+ }