surf-cli 2.2.0 → 2.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.
- package/README.md +13 -2
- package/dist/service-worker/index.js +11 -11
- package/dist/service-worker/index.js.map +1 -1
- package/native/chatgpt-client.cjs +29 -22
- package/native/cli.cjs +23 -1
- package/native/config.cjs +12 -0
- package/native/grok-client.cjs +906 -0
- package/native/host-helpers.cjs +58 -1
- package/native/host.cjs +198 -0
- package/native/perplexity-client.cjs +26 -22
- package/package.json +1 -1
|
@@ -150,22 +150,23 @@ async function selectModel(cdp, desiredModel, timeoutMs = 8000) {
|
|
|
150
150
|
})()`
|
|
151
151
|
);
|
|
152
152
|
await delay(300);
|
|
153
|
+
// Select from menu - loop in Node.js to avoid CDP timeout issues
|
|
153
154
|
const normalizedModel = desiredModel.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
155
|
+
const deadline = Date.now() + timeoutMs;
|
|
156
|
+
|
|
157
|
+
while (Date.now() < deadline) {
|
|
158
|
+
const result = await evaluate(
|
|
159
|
+
cdp,
|
|
160
|
+
`(() => {
|
|
161
|
+
${buildClickDispatcher()}
|
|
162
|
+
const targetModel = ${JSON.stringify(normalizedModel)};
|
|
163
|
+
const menuSelector = '${SELECTORS.menuContainer}';
|
|
164
|
+
const itemSelector = '${SELECTORS.menuItem}';
|
|
165
|
+
const normalize = (text) => (text || '').toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
166
|
+
|
|
165
167
|
const menu = document.querySelector(menuSelector);
|
|
166
168
|
if (!menu) {
|
|
167
|
-
|
|
168
|
-
continue;
|
|
169
|
+
return { found: false, waiting: true };
|
|
169
170
|
}
|
|
170
171
|
const items = Array.from(menu.querySelectorAll(itemSelector));
|
|
171
172
|
let bestMatch = null;
|
|
@@ -183,18 +184,24 @@ async function selectModel(cdp, desiredModel, timeoutMs = 8000) {
|
|
|
183
184
|
}
|
|
184
185
|
if (bestMatch) {
|
|
185
186
|
dispatchClickSequence(bestMatch);
|
|
186
|
-
|
|
187
|
-
return { success: true, label: bestMatch.textContent?.trim() };
|
|
187
|
+
return { found: true, success: true, label: bestMatch.textContent?.trim() };
|
|
188
188
|
}
|
|
189
|
-
|
|
189
|
+
return { found: true, success: false, error: 'No matching model in menu' };
|
|
190
|
+
})()`
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
if (result && result.found) {
|
|
194
|
+
if (result.success) {
|
|
195
|
+
await delay(200);
|
|
196
|
+
return result.label;
|
|
190
197
|
}
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
throw new Error(`Model not found: ${desiredModel}`);
|
|
198
|
+
throw new Error(`Model not found: ${desiredModel}`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
await delay(100);
|
|
196
202
|
}
|
|
197
|
-
|
|
203
|
+
|
|
204
|
+
throw new Error(`Model not found: ${desiredModel} (timeout)`);
|
|
198
205
|
}
|
|
199
206
|
|
|
200
207
|
async function typePrompt(cdp, inputCdp, prompt) {
|
package/native/cli.cjs
CHANGED
|
@@ -146,6 +146,27 @@ const TOOLS = {
|
|
|
146
146
|
{ cmd: 'perplexity "latest AI news" --model sonar', desc: "Specify model (Pro)" },
|
|
147
147
|
]
|
|
148
148
|
},
|
|
149
|
+
"grok": {
|
|
150
|
+
desc: "Query Grok AI with real-time X/Twitter data access (uses browser session)",
|
|
151
|
+
args: ["query"],
|
|
152
|
+
opts: {
|
|
153
|
+
"with-page": "Include current page context",
|
|
154
|
+
model: "Model: auto, fast, expert, thinking (default)",
|
|
155
|
+
"deep-search": "Enable DeepSearch for X post searching",
|
|
156
|
+
timeout: "Timeout in seconds (default: 300 for thinking models)",
|
|
157
|
+
validate: "Check Grok UI and scrape available models (no query sent)",
|
|
158
|
+
"save-models": "Save discovered models to surf.json config"
|
|
159
|
+
},
|
|
160
|
+
examples: [
|
|
161
|
+
{ cmd: 'grok "what are the latest AI agent trends on X"', desc: "Search X posts" },
|
|
162
|
+
{ cmd: 'grok "analyze @username recent activity"', desc: "Profile analysis" },
|
|
163
|
+
{ cmd: 'grok "summarize this page" --with-page', desc: "With page context" },
|
|
164
|
+
{ cmd: 'grok "find viral AI posts" --deep-search', desc: "DeepSearch mode" },
|
|
165
|
+
{ cmd: 'grok "quick question" --model fast', desc: "Faster model" },
|
|
166
|
+
{ cmd: 'grok --validate', desc: "Check UI and list available models" },
|
|
167
|
+
{ cmd: 'grok --validate --save-models', desc: "Save discovered models to settings" },
|
|
168
|
+
]
|
|
169
|
+
},
|
|
149
170
|
"ai": {
|
|
150
171
|
desc: "Analyze page with AI (requires GOOGLE_API_KEY)",
|
|
151
172
|
args: ["query"],
|
|
@@ -1802,6 +1823,7 @@ const PRIMARY_ARG_MAP = {
|
|
|
1802
1823
|
gemini: "query",
|
|
1803
1824
|
chatgpt: "query",
|
|
1804
1825
|
perplexity: "query",
|
|
1826
|
+
grok: "query",
|
|
1805
1827
|
navigate: "url",
|
|
1806
1828
|
go: "url",
|
|
1807
1829
|
js: "code",
|
|
@@ -2168,7 +2190,7 @@ const socket = net.createConnection(SOCKET_PATH, () => {
|
|
|
2168
2190
|
socket.write(JSON.stringify(request) + "\n");
|
|
2169
2191
|
});
|
|
2170
2192
|
|
|
2171
|
-
const AI_TOOLS = ["smoke", "chatgpt", "gemini", "perplexity", "ai"];
|
|
2193
|
+
const AI_TOOLS = ["smoke", "chatgpt", "gemini", "perplexity", "grok", "ai"];
|
|
2172
2194
|
const requestTimeout = AI_TOOLS.includes(tool) ? 300000 : 30000;
|
|
2173
2195
|
const timeout = setTimeout(() => {
|
|
2174
2196
|
console.error(`Error: Request timed out (${requestTimeout / 1000}s)`);
|
package/native/config.cjs
CHANGED
|
@@ -21,6 +21,18 @@ const STARTER_CONFIG = {
|
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
+
// Grok models can be customized in surf.json if X.com UI changes:
|
|
25
|
+
// {
|
|
26
|
+
// "grok": {
|
|
27
|
+
// "models": {
|
|
28
|
+
// "thinking": { "id": "thinking", "name": "Grok 4.1 Thinking" },
|
|
29
|
+
// "auto": { "id": "auto", "name": "Auto" },
|
|
30
|
+
// "fast": { "id": "fast", "name": "Fast" },
|
|
31
|
+
// "expert": { "id": "expert", "name": "Expert" }
|
|
32
|
+
// }
|
|
33
|
+
// }
|
|
34
|
+
// }
|
|
35
|
+
|
|
24
36
|
function findConfigPath() {
|
|
25
37
|
const cwdPath = path.join(process.cwd(), CONFIG_NAME);
|
|
26
38
|
if (fs.existsSync(cwdPath)) {
|