Skip to content

Commit 1639746

Browse files
feat(deepseek): add DeepSeek browser adapter with ask, new, status, read, history (#1088)
Closes #548
1 parent be2c1cd commit 1639746

8 files changed

Lines changed: 590 additions & 0 deletions

File tree

cli-manifest.json

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4065,6 +4065,147 @@
40654065
"sourceFile": "cursor/send.js",
40664066
"navigateBefore": true
40674067
},
4068+
{
4069+
"site": "deepseek",
4070+
"name": "ask",
4071+
"description": "Send a prompt to DeepSeek and get the response",
4072+
"domain": "chat.deepseek.com",
4073+
"strategy": "cookie",
4074+
"browser": true,
4075+
"args": [
4076+
{
4077+
"name": "prompt",
4078+
"type": "str",
4079+
"required": true,
4080+
"positional": true,
4081+
"help": "Prompt to send"
4082+
},
4083+
{
4084+
"name": "timeout",
4085+
"type": "int",
4086+
"default": 120,
4087+
"required": false,
4088+
"help": "Max seconds to wait for response"
4089+
},
4090+
{
4091+
"name": "new",
4092+
"type": "boolean",
4093+
"default": false,
4094+
"required": false,
4095+
"help": "Start a new chat before sending"
4096+
},
4097+
{
4098+
"name": "model",
4099+
"type": "str",
4100+
"default": "instant",
4101+
"required": false,
4102+
"help": "Model to use: instant or expert",
4103+
"choices": [
4104+
"instant",
4105+
"expert"
4106+
]
4107+
},
4108+
{
4109+
"name": "think",
4110+
"type": "boolean",
4111+
"default": false,
4112+
"required": false,
4113+
"help": "Enable DeepThink mode"
4114+
},
4115+
{
4116+
"name": "search",
4117+
"type": "boolean",
4118+
"default": false,
4119+
"required": false,
4120+
"help": "Enable web search"
4121+
}
4122+
],
4123+
"columns": [
4124+
"response"
4125+
],
4126+
"timeout": 180,
4127+
"type": "js",
4128+
"modulePath": "deepseek/ask.js",
4129+
"sourceFile": "deepseek/ask.js",
4130+
"navigateBefore": false
4131+
},
4132+
{
4133+
"site": "deepseek",
4134+
"name": "history",
4135+
"description": "List conversation history from DeepSeek sidebar",
4136+
"domain": "chat.deepseek.com",
4137+
"strategy": "cookie",
4138+
"browser": true,
4139+
"args": [
4140+
{
4141+
"name": "limit",
4142+
"type": "int",
4143+
"default": 20,
4144+
"required": false,
4145+
"help": "Max conversations to show"
4146+
}
4147+
],
4148+
"columns": [
4149+
"Index",
4150+
"Title",
4151+
"Url"
4152+
],
4153+
"type": "js",
4154+
"modulePath": "deepseek/history.js",
4155+
"sourceFile": "deepseek/history.js",
4156+
"navigateBefore": false
4157+
},
4158+
{
4159+
"site": "deepseek",
4160+
"name": "new",
4161+
"description": "Start a new conversation in DeepSeek",
4162+
"domain": "chat.deepseek.com",
4163+
"strategy": "cookie",
4164+
"browser": true,
4165+
"args": [],
4166+
"columns": [
4167+
"Status"
4168+
],
4169+
"type": "js",
4170+
"modulePath": "deepseek/new.js",
4171+
"sourceFile": "deepseek/new.js",
4172+
"navigateBefore": false
4173+
},
4174+
{
4175+
"site": "deepseek",
4176+
"name": "read",
4177+
"description": "Read the current DeepSeek conversation",
4178+
"domain": "chat.deepseek.com",
4179+
"strategy": "cookie",
4180+
"browser": true,
4181+
"args": [],
4182+
"columns": [
4183+
"Role",
4184+
"Text"
4185+
],
4186+
"type": "js",
4187+
"modulePath": "deepseek/read.js",
4188+
"sourceFile": "deepseek/read.js",
4189+
"navigateBefore": false
4190+
},
4191+
{
4192+
"site": "deepseek",
4193+
"name": "status",
4194+
"description": "Check DeepSeek page availability and login state",
4195+
"domain": "chat.deepseek.com",
4196+
"strategy": "cookie",
4197+
"browser": true,
4198+
"args": [],
4199+
"columns": [
4200+
"Status",
4201+
"Login",
4202+
"Url"
4203+
],
4204+
"type": "js",
4205+
"modulePath": "deepseek/status.js",
4206+
"sourceFile": "deepseek/status.js",
4207+
"navigateBefore": false
4208+
},
40684209
{
40694210
"site": "devto",
40704211
"name": "tag",

clis/deepseek/ask.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { cli, Strategy } from '@jackwener/opencli/registry';
2+
import { CommandExecutionError } from '@jackwener/opencli/errors';
3+
import {
4+
DEEPSEEK_DOMAIN, DEEPSEEK_URL, ensureOnDeepSeek, selectModel, setFeature,
5+
sendMessage, getBubbleCount, waitForResponse, parseBoolFlag, withRetry,
6+
} from './utils.js';
7+
8+
export const askCommand = cli({
9+
site: 'deepseek',
10+
name: 'ask',
11+
description: 'Send a prompt to DeepSeek and get the response',
12+
domain: DEEPSEEK_DOMAIN,
13+
strategy: Strategy.COOKIE,
14+
browser: true,
15+
navigateBefore: false,
16+
timeoutSeconds: 180,
17+
args: [
18+
{ name: 'prompt', positional: true, required: true, help: 'Prompt to send' },
19+
{ name: 'timeout', type: 'int', default: 120, help: 'Max seconds to wait for response' },
20+
{ name: 'new', type: 'boolean', default: false, help: 'Start a new chat before sending' },
21+
{ name: 'model', default: 'instant', choices: ['instant', 'expert'], help: 'Model to use: instant or expert' },
22+
{ name: 'think', type: 'boolean', default: false, help: 'Enable DeepThink mode' },
23+
{ name: 'search', type: 'boolean', default: false, help: 'Enable web search' },
24+
],
25+
columns: ['response'],
26+
27+
func: async (page, kwargs) => {
28+
const prompt = kwargs.prompt;
29+
const timeoutMs = (kwargs.timeout || 120) * 1000;
30+
const wantThink = parseBoolFlag(kwargs.think);
31+
const wantSearch = parseBoolFlag(kwargs.search);
32+
33+
if (parseBoolFlag(kwargs.new)) {
34+
await page.goto(DEEPSEEK_URL);
35+
await page.wait(3);
36+
} else {
37+
await ensureOnDeepSeek(page);
38+
}
39+
40+
await page.wait(2);
41+
42+
const wantModel = kwargs.model || 'instant';
43+
const modelResult = await withRetry(() => selectModel(page, wantModel));
44+
if (!modelResult?.ok) {
45+
throw new CommandExecutionError(`Could not switch to ${wantModel} model`);
46+
}
47+
if (modelResult.toggled) await page.wait(0.5);
48+
49+
const thinkResult = await withRetry(() => setFeature(page, 'DeepThink', wantThink));
50+
if (!thinkResult?.ok) {
51+
throw new CommandExecutionError('Could not toggle DeepThink');
52+
}
53+
54+
const searchResult = await withRetry(() => setFeature(page, 'Search', wantSearch));
55+
if (!searchResult?.ok) {
56+
throw new CommandExecutionError('Could not toggle Search');
57+
}
58+
59+
if (thinkResult.toggled || searchResult.toggled) await page.wait(0.5);
60+
61+
const baseline = await withRetry(() => getBubbleCount(page));
62+
const sendResult = await withRetry(() => sendMessage(page, prompt));
63+
if (!sendResult?.ok) {
64+
throw new CommandExecutionError(sendResult?.reason || 'Failed to send message');
65+
}
66+
67+
const response = await waitForResponse(page, baseline, prompt, timeoutMs);
68+
if (!response) {
69+
return [{ response: `[NO RESPONSE] No reply within ${kwargs.timeout}s.` }];
70+
}
71+
72+
return [{ response }];
73+
},
74+
});

clis/deepseek/history.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { cli, Strategy } from '@jackwener/opencli/registry';
2+
import { DEEPSEEK_DOMAIN, getConversationList } from './utils.js';
3+
4+
export const historyCommand = cli({
5+
site: 'deepseek',
6+
name: 'history',
7+
description: 'List conversation history from DeepSeek sidebar',
8+
domain: DEEPSEEK_DOMAIN,
9+
strategy: Strategy.COOKIE,
10+
browser: true,
11+
navigateBefore: false,
12+
args: [
13+
{ name: 'limit', type: 'int', default: 20, help: 'Max conversations to show' },
14+
],
15+
columns: ['Index', 'Title', 'Url'],
16+
17+
func: async (page, kwargs) => {
18+
const limit = Math.max(1, kwargs.limit || 20);
19+
const conversations = await getConversationList(page);
20+
if (conversations.length === 0) {
21+
return [{ Index: 0, Title: 'No conversation history found.', Url: '' }];
22+
}
23+
return conversations.slice(0, limit);
24+
},
25+
});

clis/deepseek/new.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { cli, Strategy } from '@jackwener/opencli/registry';
2+
import { DEEPSEEK_DOMAIN, DEEPSEEK_URL } from './utils.js';
3+
4+
export const newCommand = cli({
5+
site: 'deepseek',
6+
name: 'new',
7+
description: 'Start a new conversation in DeepSeek',
8+
domain: DEEPSEEK_DOMAIN,
9+
strategy: Strategy.COOKIE,
10+
browser: true,
11+
navigateBefore: false,
12+
args: [],
13+
columns: ['Status'],
14+
15+
func: async (page) => {
16+
await page.goto(DEEPSEEK_URL);
17+
await page.wait(2);
18+
return [{ Status: 'New chat started' }];
19+
},
20+
});

clis/deepseek/read.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { cli, Strategy } from '@jackwener/opencli/registry';
2+
import { DEEPSEEK_DOMAIN, ensureOnDeepSeek, getVisibleMessages } from './utils.js';
3+
4+
export const readCommand = cli({
5+
site: 'deepseek',
6+
name: 'read',
7+
description: 'Read the current DeepSeek conversation',
8+
domain: DEEPSEEK_DOMAIN,
9+
strategy: Strategy.COOKIE,
10+
browser: true,
11+
navigateBefore: false,
12+
args: [],
13+
columns: ['Role', 'Text'],
14+
15+
func: async (page) => {
16+
await ensureOnDeepSeek(page);
17+
await page.wait(5);
18+
const messages = await getVisibleMessages(page);
19+
if (messages.length > 0) return messages;
20+
return [{ Role: 'system', Text: 'No visible messages found.' }];
21+
},
22+
});

clis/deepseek/status.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { cli, Strategy } from '@jackwener/opencli/registry';
2+
import { DEEPSEEK_DOMAIN, ensureOnDeepSeek, getPageState } from './utils.js';
3+
4+
export const statusCommand = cli({
5+
site: 'deepseek',
6+
name: 'status',
7+
description: 'Check DeepSeek page availability and login state',
8+
domain: DEEPSEEK_DOMAIN,
9+
strategy: Strategy.COOKIE,
10+
browser: true,
11+
navigateBefore: false,
12+
args: [],
13+
columns: ['Status', 'Login', 'Url'],
14+
15+
func: async (page) => {
16+
await ensureOnDeepSeek(page);
17+
const state = await getPageState(page);
18+
return [{
19+
Status: state.hasTextarea ? 'Connected' : 'Page not ready',
20+
Login: state.isLoggedIn ? 'Yes' : 'No',
21+
Url: state.url,
22+
}];
23+
},
24+
});

0 commit comments

Comments
 (0)