@apmantza/greedysearch-pi 1.9.0 → 1.9.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/CHANGELOG.md +46 -0
- package/README.md +11 -1
- package/bin/launch-visible.mjs +65 -0
- package/bin/launch.mjs +442 -417
- package/bin/search.mjs +757 -679
- package/extractors/bing-copilot.mjs +490 -374
- package/extractors/common.mjs +703 -596
- package/extractors/consent.mjs +421 -388
- package/extractors/selectors.mjs +55 -54
- package/index.ts +176 -177
- package/package.json +8 -3
- package/skills/greedy-search/skill.md +5 -19
- package/src/fetcher.mjs +666 -652
- package/src/formatters/synthesis.ts +1 -5
- package/src/search/output.mjs +23 -1
- package/src/search/research.mjs +1581 -0
- package/src/search/sources.mjs +488 -466
- package/src/search/synthesis-runner.mjs +52 -46
- package/src/tools/greedy-search-handler.ts +298 -124
- package/test.mjs +971 -534
package/extractors/selectors.mjs
CHANGED
|
@@ -1,54 +1,55 @@
|
|
|
1
|
-
// extractors/selectors.mjs
|
|
2
|
-
// Centralized CSS selectors for all engines.
|
|
3
|
-
// Update selectors here when a site changes its UI.
|
|
4
|
-
|
|
5
|
-
export const SELECTORS = {
|
|
6
|
-
// ──────────────────────────────────────────────
|
|
7
|
-
// Perplexity (perplexity.ai)
|
|
8
|
-
// ──────────────────────────────────────────────
|
|
9
|
-
perplexity: {
|
|
10
|
-
input: "#ask-input",
|
|
11
|
-
// Note: copy button found via JS in extractor (language-agnostic)
|
|
12
|
-
copyButton: null,
|
|
13
|
-
sourceItem: "[data-pplx-citation-url]",
|
|
14
|
-
sourceLink: "a",
|
|
15
|
-
consent: "#onetrust-accept-btn-handler",
|
|
16
|
-
},
|
|
17
|
-
|
|
18
|
-
// ──────────────────────────────────────────────
|
|
19
|
-
// Bing Copilot (copilot.microsoft.com)
|
|
20
|
-
// ──────────────────────────────────────────────
|
|
21
|
-
bing: {
|
|
22
|
-
input: "#userInput",
|
|
23
|
-
copyButton: 'button[data-testid="copy-ai-message-button"]',
|
|
24
|
-
sourceLink: 'a[href^="http"][target="_blank"]',
|
|
25
|
-
sourceExclude: "copilot.microsoft.com",
|
|
26
|
-
consent: "#onetrust-accept-btn-handler",
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
// ──────────────────────────────────────────────
|
|
30
|
-
// Google AI Mode (google.com/search?udm=50)
|
|
31
|
-
// ──────────────────────────────────────────────
|
|
32
|
-
google: {
|
|
33
|
-
answerContainer: ".pWvJNd",
|
|
34
|
-
sourceLink: 'a[href^="http"]',
|
|
35
|
-
sourceExclude: ["google.", "gstatic", "googleapis"],
|
|
36
|
-
sourceHeadingParent: "[data-snhf]",
|
|
37
|
-
consent: '#L2AGLb, button[jsname="b3VHJd"], .tHlp8d',
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
// ──────────────────────────────────────────────
|
|
41
|
-
// Gemini (gemini.google.com/app)
|
|
42
|
-
// ──────────────────────────────────────────────
|
|
43
|
-
gemini: {
|
|
44
|
-
input: "rich-textarea .ql-editor",
|
|
45
|
-
// Language-agnostic: use Material icon data attributes (work across locales)
|
|
46
|
-
copyButton: 'button:has(mat-icon[data-mat-icon-name="content_copy"])',
|
|
47
|
-
sendButton: 'button:has(mat-icon[data-mat-icon-name="send"]), .send-button',
|
|
48
|
-
sourcesSidebarButton: "button.legacy-sources-sidebar-button",
|
|
49
|
-
sourcesExclude: ["gemini.google", "gstatic", "google.com/search"],
|
|
50
|
-
citationButtonPattern: 'button[aria-label*="citation from"]',
|
|
51
|
-
// For parsing citation aria-labels: "View source details for citation from {name}. Opens side panel."
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
1
|
+
// extractors/selectors.mjs
|
|
2
|
+
// Centralized CSS selectors for all engines.
|
|
3
|
+
// Update selectors here when a site changes its UI.
|
|
4
|
+
|
|
5
|
+
export const SELECTORS = {
|
|
6
|
+
// ──────────────────────────────────────────────
|
|
7
|
+
// Perplexity (perplexity.ai)
|
|
8
|
+
// ──────────────────────────────────────────────
|
|
9
|
+
perplexity: {
|
|
10
|
+
input: "#ask-input",
|
|
11
|
+
// Note: copy button found via JS in extractor (language-agnostic)
|
|
12
|
+
copyButton: null,
|
|
13
|
+
sourceItem: "[data-pplx-citation-url]",
|
|
14
|
+
sourceLink: "a",
|
|
15
|
+
consent: "#onetrust-accept-btn-handler",
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
// ──────────────────────────────────────────────
|
|
19
|
+
// Bing Copilot (copilot.microsoft.com)
|
|
20
|
+
// ──────────────────────────────────────────────
|
|
21
|
+
bing: {
|
|
22
|
+
input: "#userInput",
|
|
23
|
+
copyButton: 'button[data-testid="copy-ai-message-button"]',
|
|
24
|
+
sourceLink: 'a[href^="http"][target="_blank"]',
|
|
25
|
+
sourceExclude: "copilot.microsoft.com",
|
|
26
|
+
consent: "#onetrust-accept-btn-handler",
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
// ──────────────────────────────────────────────
|
|
30
|
+
// Google AI Mode (google.com/search?udm=50)
|
|
31
|
+
// ──────────────────────────────────────────────
|
|
32
|
+
google: {
|
|
33
|
+
answerContainer: ".pWvJNd",
|
|
34
|
+
sourceLink: 'a[href^="http"]',
|
|
35
|
+
sourceExclude: ["google.", "gstatic", "googleapis"],
|
|
36
|
+
sourceHeadingParent: "[data-snhf]",
|
|
37
|
+
consent: '#L2AGLb, button[jsname="b3VHJd"], .tHlp8d',
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
// ──────────────────────────────────────────────
|
|
41
|
+
// Gemini (gemini.google.com/app)
|
|
42
|
+
// ──────────────────────────────────────────────
|
|
43
|
+
gemini: {
|
|
44
|
+
input: "rich-textarea .ql-editor",
|
|
45
|
+
// Language-agnostic: use Material icon data attributes (work across locales)
|
|
46
|
+
copyButton: 'button:has(mat-icon[data-mat-icon-name="content_copy"])',
|
|
47
|
+
sendButton: 'button:has(mat-icon[data-mat-icon-name="send"]), .send-button',
|
|
48
|
+
sourcesSidebarButton: "button.legacy-sources-sidebar-button",
|
|
49
|
+
sourcesExclude: ["gemini.google", "gstatic", "google.com/search"],
|
|
50
|
+
citationButtonPattern: 'button[aria-label*="citation from"]',
|
|
51
|
+
// For parsing citation aria-labels: "View source details for citation from {name}. Opens side panel."
|
|
52
|
+
// Bounded + non-overlapping character classes to prevent ReDoS
|
|
53
|
+
citationNameRegex: /from\s{1,20}([^.]{1,200})\.\s/,
|
|
54
|
+
},
|
|
55
|
+
};
|
package/index.ts
CHANGED
|
@@ -1,177 +1,176 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GreedySearch Pi Extension
|
|
3
|
-
*
|
|
4
|
-
* Adds `greedy_search` tool to Pi.
|
|
5
|
-
* Use depth: "deep" for deep research (source fetching + synthesis + confidence).
|
|
6
|
-
*
|
|
7
|
-
* Reports streaming progress as each engine completes.
|
|
8
|
-
* Requires Chrome to be running (or it auto-launches a dedicated instance).
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { spawn } from "node:child_process";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// ───
|
|
35
|
-
pi
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
proc.
|
|
149
|
-
proc.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* GreedySearch Pi Extension
|
|
3
|
+
*
|
|
4
|
+
* Adds `greedy_search` tool to Pi.
|
|
5
|
+
* Use depth: "deep" for deep research (source fetching + synthesis + confidence).
|
|
6
|
+
*
|
|
7
|
+
* Reports streaming progress as each engine completes.
|
|
8
|
+
* Requires Chrome to be running (or it auto-launches a dedicated instance).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { spawn } from "node:child_process";
|
|
12
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { homedir } from "node:os";
|
|
14
|
+
import { dirname, join } from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
|
|
17
|
+
import { registerGreedySearchTool } from "./src/tools/greedy-search-handler.js";
|
|
18
|
+
|
|
19
|
+
type ExtensionAPI = any;
|
|
20
|
+
import { cdpAvailable } from "./src/tools/shared.js";
|
|
21
|
+
|
|
22
|
+
const __dir = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
|
|
24
|
+
export default function greedySearchExtension(pi: ExtensionAPI) {
|
|
25
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
26
|
+
if (!cdpAvailable(__dir)) {
|
|
27
|
+
ctx.ui.notify(
|
|
28
|
+
"GreedySearch: cdp.mjs missing from package directory — try reinstalling: pi install git:github.com/apmantza/GreedySearch-pi",
|
|
29
|
+
"warning",
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// ─── greedy_search ────────────────────────────────────────────────────────
|
|
35
|
+
registerGreedySearchTool(pi, __dir);
|
|
36
|
+
|
|
37
|
+
// ─── GreedySearch Chrome commands ─────────────────────────────────────────
|
|
38
|
+
pi.registerCommand("greedy-visible", {
|
|
39
|
+
description:
|
|
40
|
+
"Launch GreedySearch Chrome in visible mode for captcha/login/cookie setup.",
|
|
41
|
+
handler: async (_args, ctx) => {
|
|
42
|
+
await runChromeCommand([], ctx, "Visible GreedySearch Chrome launched.");
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
pi.registerCommand("greedy-status", {
|
|
47
|
+
description: "Show GreedySearch Chrome status.",
|
|
48
|
+
handler: async (_args, ctx) => {
|
|
49
|
+
await runChromeCommand(["--status"], ctx);
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
pi.registerCommand("greedy-kill", {
|
|
54
|
+
description: "Stop GreedySearch Chrome.",
|
|
55
|
+
handler: async (_args, ctx) => {
|
|
56
|
+
await runChromeCommand(["--kill"], ctx, "GreedySearch Chrome stopped.");
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// ─── /set-greedy-locale command ───────────────────────────────────────────
|
|
61
|
+
pi.registerCommand("set-greedy-locale", {
|
|
62
|
+
description:
|
|
63
|
+
"Set default locale for GreedySearch results (e.g., /set-greedy-locale de, /set-greedy-locale --clear, /set-greedy-locale --show)",
|
|
64
|
+
handler: async (args, ctx) => {
|
|
65
|
+
const arg = args.trim() || "--show";
|
|
66
|
+
|
|
67
|
+
if (arg === "--show") {
|
|
68
|
+
const config = loadUserConfig();
|
|
69
|
+
if (config.locale) {
|
|
70
|
+
ctx.ui.notify(`Default locale: ${config.locale}`, "info");
|
|
71
|
+
} else {
|
|
72
|
+
ctx.ui.notify("No default locale (uses: en)", "info");
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (arg === "--clear") {
|
|
78
|
+
const config = loadUserConfig();
|
|
79
|
+
delete config.locale;
|
|
80
|
+
saveUserConfig(config);
|
|
81
|
+
ctx.ui.notify("Default locale cleared (now uses: en).", "info");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Set locale
|
|
86
|
+
const locale = arg.toLowerCase();
|
|
87
|
+
const VALID_LOCALES = [
|
|
88
|
+
"en",
|
|
89
|
+
"de",
|
|
90
|
+
"fr",
|
|
91
|
+
"es",
|
|
92
|
+
"it",
|
|
93
|
+
"pt",
|
|
94
|
+
"nl",
|
|
95
|
+
"pl",
|
|
96
|
+
"ru",
|
|
97
|
+
"ja",
|
|
98
|
+
"ko",
|
|
99
|
+
"zh",
|
|
100
|
+
"ar",
|
|
101
|
+
"hi",
|
|
102
|
+
"tr",
|
|
103
|
+
"sv",
|
|
104
|
+
"da",
|
|
105
|
+
"no",
|
|
106
|
+
"fi",
|
|
107
|
+
"cs",
|
|
108
|
+
"hu",
|
|
109
|
+
"ro",
|
|
110
|
+
"el",
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
if (!VALID_LOCALES.includes(locale)) {
|
|
114
|
+
ctx.ui.notify(
|
|
115
|
+
`Invalid locale "${locale}". Valid: ${VALID_LOCALES.join(", ")}`,
|
|
116
|
+
"error",
|
|
117
|
+
);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const config = loadUserConfig();
|
|
122
|
+
config.locale = locale;
|
|
123
|
+
saveUserConfig(config);
|
|
124
|
+
ctx.ui.notify(`Default locale set to: ${locale}`, "info");
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const USER_CONFIG_DIR = join(homedir(), ".config", "greedysearch");
|
|
130
|
+
const USER_CONFIG_FILE = join(USER_CONFIG_DIR, "config.json");
|
|
131
|
+
|
|
132
|
+
async function runChromeCommand(
|
|
133
|
+
args: string[],
|
|
134
|
+
ctx: any,
|
|
135
|
+
successMessage?: string,
|
|
136
|
+
): Promise<void> {
|
|
137
|
+
const visibleBin = join(__dir, "bin", "visible.mjs");
|
|
138
|
+
const { code, output } = await new Promise<{
|
|
139
|
+
code: number | null;
|
|
140
|
+
output: string;
|
|
141
|
+
}>((resolve) => {
|
|
142
|
+
const proc = spawn(process.execPath, [visibleBin, ...args], {
|
|
143
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
144
|
+
env: { ...process.env, GREEDY_SEARCH_VISIBLE: "1" },
|
|
145
|
+
});
|
|
146
|
+
let output = "";
|
|
147
|
+
proc.stdout.on("data", (d: Buffer) => (output += d.toString()));
|
|
148
|
+
proc.stderr.on("data", (d: Buffer) => (output += d.toString()));
|
|
149
|
+
proc.on("close", (code: number | null) => resolve({ code, output }));
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
if (code === 0) {
|
|
153
|
+
ctx.ui.notify((successMessage || output.trim() || "Done.").trim(), "info");
|
|
154
|
+
} else {
|
|
155
|
+
ctx.ui.notify(
|
|
156
|
+
output.trim() || `GreedySearch Chrome command failed (${code})`,
|
|
157
|
+
"error",
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function loadUserConfig(): Record<string, string> {
|
|
163
|
+
try {
|
|
164
|
+
if (existsSync(USER_CONFIG_FILE)) {
|
|
165
|
+
return JSON.parse(readFileSync(USER_CONFIG_FILE, "utf8"));
|
|
166
|
+
}
|
|
167
|
+
} catch {
|
|
168
|
+
// Ignore parse errors
|
|
169
|
+
}
|
|
170
|
+
return {};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function saveUserConfig(config: Record<string, string>): void {
|
|
174
|
+
mkdirSync(USER_CONFIG_DIR, { recursive: true });
|
|
175
|
+
writeFileSync(USER_CONFIG_FILE, JSON.stringify(config, null, 2), "utf8");
|
|
176
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apmantza/greedysearch-pi",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.2",
|
|
4
4
|
"description": "Headless multi-engine AI search (Perplexity, Bing Copilot, Google AI) via browser automation -- NO API KEYS needed. Extracts answers with sources, optional synthesis. Grounded AI answers from real browser interactions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -45,11 +45,16 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@mozilla/readability": "^0.6.0",
|
|
48
|
+
"@sinclair/typebox": "^0.34.48",
|
|
48
49
|
"jsdom": "^24.0.0",
|
|
49
50
|
"turndown": "^7.1.2"
|
|
50
51
|
},
|
|
51
52
|
"peerDependencies": {
|
|
52
|
-
"@
|
|
53
|
-
|
|
53
|
+
"@earendil-works/pi-coding-agent": "*"
|
|
54
|
+
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"@earendil-works/pi-coding-agent": {
|
|
57
|
+
"optional": true
|
|
58
|
+
}
|
|
54
59
|
}
|
|
55
60
|
}
|
|
@@ -1,26 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: greedy-search
|
|
3
|
-
description:
|
|
3
|
+
description: Web search via Perplexity, Bing, Google AI & Gemini. Current docs, recent changes, dependency choices. NOT codebase search.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
`greedy_search({ query, engine: "all"|"perplexity"|"bing"|"google"|"gemini", depth: "fast"|"standard"|"deep"|"research", breadth: 1-5, iterations: 1-3, maxSources: 3-12, visible: bool })`
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
greedy_search({ query: "React 19 changes", depth: "standard" });
|
|
10
|
-
```
|
|
8
|
+
**Depth:** `fast`(15-30s, no synthesis) · `standard`(30-90s, all+synthesis+sources) · `deep`(60-180s, stronger grounding) · `research`(slowest, iterative planning+follow-ups+learning extraction; uses breadth/iterations/maxSources)
|
|
11
9
|
|
|
12
|
-
**
|
|
10
|
+
**Auto-recovery:** Headless default. Bing/Perplexity auto-retry visible on CF block. Manual CAPTCHA → visible stays open; solve then rerun.
|
|
13
11
|
|
|
14
|
-
**
|
|
15
|
-
|
|
16
|
-
- `fast`: ~15-30s, single engine, no synthesis
|
|
17
|
-
- `standard`: ~30-90s, all engines + Gemini synthesis + sources
|
|
18
|
-
- `deep`: ~60-180s, stronger grounding + confidence metadata
|
|
19
|
-
|
|
20
|
-
**Captcha/blocks:** Headless by default. Bing/Perplexity auto-retry in visible mode when blocked. If human verification is needed, visible Chrome stays open — tell the user to solve it and rerun. Use `visible: true` proactively for repeated issues.
|
|
21
|
-
|
|
22
|
-
**Pi commands:** `/greedy-visible`, `/greedy-status`, `/greedy-kill`, `/set-greedy-locale`
|
|
23
|
-
|
|
24
|
-
**CDP safety:** Never call raw `bin/cdp.mjs`. Use `bin/cdp-greedy.mjs`, `bin/cdp-visible.mjs`, or `bin/cdp-headless.mjs`.
|
|
25
|
-
|
|
26
|
-
Old `coding_task`/`deep_research` folded into `greedy_search`. Use `engine: "gemini"` for one-off opinion, `depth: "deep"` for research.
|
|
12
|
+
**CDP safety:** Use `bin/cdp-greedy.mjs` only. Never raw `bin/cdp.mjs`.
|