Skip to content

feat(deepseek-web): full DeepSeek web API executor with PoW solver - #2295

Merged
diegosouzapw merged 1 commit into
cheaper-inference:release/v3.8.0from
oyi77:feature/deepseek-web-executor-v2
May 16, 2026
Merged

diegosouzapw merged 1 commit into
cheaper-inference:release/v3.8.0from
oyi77:feature/deepseek-web-executor-v2

Conversation

@oyi77

@oyi77 oyi77 commented May 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a complete executor for DeepSeek's native web API (deepseek-web provider) with full feature support:

  • Authentication: ds_session_id cookie → Bearer token from /api/v0/users/current
  • Proof-of-Work: DeepSeekHashV1 solver using custom Keccak sponge (exact port from DeepSeek's Web Worker)
  • SSE Streaming: Parses DeepSeek's native fragment format → OpenAI-compatible SSE output
  • Web Search: Toggle via search_enabled in request body
  • Deep Thinking: Toggle via thinking_enabled + x-thinking-enabled header
  • File Attachments: Pass file IDs via ref_file_ids in request body
  • Auto-refresh: Session validation and retry on auth failures

API Flow

ds_session_id cookie
  → GET /api/v0/users/current → Bearer token
  → POST /api/v0/chat_session/create → session ID
  → POST /api/v0/chat/create_pow_challenge → PoW challenge
  → Solve PoW (DeepSeekHashV1 custom Keccak)
  → POST /api/v0/chat/completion with x-ds-pow-response header
  → SSE stream → OpenAI-compatible chunks

Files Changed

File Description
open-sse/executors/deepseek-web.ts Main executor (530 lines)
open-sse/executors/deepseek-web-with-auto-refresh.ts Auto-refresh wrapper
open-sse/lib/deepseek-pow.ts PoW solver TypeScript wrapper
open-sse/lib/deepseek-pow-solver.cjs Exact Keccak sponge from DeepSeek worker
open-sse/executors/index.ts Executor registration
src/shared/constants/providers.ts Provider constant
src/lib/providers/wrappers/deepseekWeb.ts Provider wrapper
tests/unit/deepseek-web.test.ts 23 unit tests (all passing)
tests/live/deepseek-web-live.test.ts Live integration test

Test Plan

  • 23/23 unit tests pass
  • TypeScript compilation clean
  • ESLint clean
  • Live test: DeepSeek returns "Hello" via Playwright + Node.js PoW solver
  • PoW solver verified against captured DeepSeek worker output
  • SSE stream parsing verified with real DeepSeek response

Live Test Proof

[1] Token: KvJNH5/Ns8DFcZrNaShwwYg+/2ZPWJMpw7HdbfSvz0gmOfHFmfOPXMYuIIaf...
[2] Session: 3e48e74f-1ed0-42ee-a736-f52ce48c5c81
[3] Challenge: difficulty=144000, algo=DeepSeekHashV1
[4] PoW solved: nonce=65112
[5] Verify: hash(65112) = a77891f7a3020f6abc44cc932f0c48d3... ✅ Match
[6] Status: 200
[7] Content: 'Hello'

✅ LIVE TEST PASSED! DeepSeek says: 'Hello'

Unit Test Results

ok 1 - DeepSeekWebExecutor registered as deepseek-web and ds-web
ok 2 - getExecutor returns DeepSeekWebWithAutoRefreshExecutor
ok 3 - alias ds-web resolves same executor
ok 4 - provider name is deepseek-web
ok 5 - execute returns 400 without ds_session_id cookie
ok 6 - execute returns 400 with empty credentials
ok 7 - testConnection returns false with empty credentials
ok 8 - testConnection returns false without ds_session_id
ok 9 - execute: full flow with mocked API (streaming)
ok 10 - execute: full flow with mocked API (non-streaming)
ok 11 - execute: sends PoW response header
ok 12 - execute: handles API error (token fetch fails)
ok 13 - execute: handles 401 from DeepSeek
ok 14 - execute: handles DeepSeek JSON error (40003 INVALID_TOKEN)
ok 15 - execute: maps model to deepseek_r1 with thinking
ok 16 - DeepSeekWebWithAutoRefresh extends DeepSeekWebExecutor
ok 17 - isSessionValid starts false
ok 18 - execute: handles abort signal gracefully
ok 19 - execute: passes search_enabled from body
ok 20 - execute: search_enabled defaults to false
ok 21 - execute: thinking_enabled from body overrides model mapping
ok 22 - execute: passes ref_file_ids from body
ok 23 - execute: maps expert model with thinking

🤖 Generated with OpenClaude

Adds a complete executor for DeepSeek's native web API with:

- Authentication via ds_session_id cookie → Bearer token from /users/current
- Proof-of-Work (DeepSeekHashV1) solver using custom Keccak sponge
- SSE stream response parsing with OpenAI-compatible output
- Web search toggle (search_enabled)
- Deep thinking toggle (thinking_enabled + x-thinking-enabled header)
- File attachment support (ref_file_ids)
- Auto-refresh executor for session management
- 23 unit tests covering all features + live integration test

API flow: /users/current → /chat_session/create → /create_pow_challenge
→ PoW solve → /chat/completion with native DeepSeek body format

Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the DeepSeekWebExecutor and DeepSeekWebWithAutoRefreshExecutor to support the DeepSeek web API, including handling Proof-of-Work (PoW) challenges and session management. Feedback highlights several critical improvements: ensuring SSE stream errors are propagated rather than swallowed (violating Rule 6), offloading the synchronous PoW solver to a worker thread to prevent blocking the Node.js event loop, and using Zod schemas for request body validation as per Rule 8. Additionally, the reviewer recommended removing empty code blocks and replacing any types with specific interfaces for better type safety.

Comment on lines +176 to +178
} catch (err) {
// Stream error — emit what we have
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This block violates the repository style guide (Rule 6), which prohibits silently swallowing errors in SSE streams. Instead of just catching the error and allowing the stream to close normally, you should propagate the error to the controller so the client is aware of the failure.

Suggested change
} catch (err) {
// Stream error — emit what we have
}
} catch (err) {
controller.error(err);
}
References
  1. Never silently swallow errors in SSE streams — propagate them or abort the stream cleanly.

Comment on lines +54 to +58
for (let nonce = 0; nonce < difficulty; nonce++) {
if (h.copy().update(String(nonce)).digest("hex") === challenge) {
return nonce;
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The PoW solver is a CPU-intensive task that runs synchronously on the main thread. In a Node.js environment, this will block the event loop for the duration of the calculation, significantly impacting the server's ability to handle concurrent requests. For a production-grade executor, this should be offloaded to a Worker Thread. If a worker is not feasible, at least consider yielding the event loop periodically using setImmediate or process.nextTick within the loop.

Comment on lines +316 to +320
const bodyObj = (body || {}) as Record<string, unknown>;
const messages = (Array.isArray(bodyObj.messages) ? bodyObj.messages : []) as Array<{
role: string;
content: string;
}>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Adhere to the repository style guide (Rule 8) by validating the request body using Zod schemas from src/shared/validation/schemas.ts. Manual extraction and casting of fields from an unknown body bypasses type safety and validation logic.

References
  1. Always validate inputs with Zod schemas from src/shared/validation/schemas.ts.

Comment on lines +171 to +174
if ((data as any)?.click_behavior !== undefined) {
// close event — emit [DONE] if not already
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This block is empty and serves no functional purpose. It should either be implemented to handle the click_behavior event or removed to keep the code clean.

}

// Extract content from DeepSeek fragments
const fragments = (data as any)?.v?.response?.fragments;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Avoid using any for type casting when processing API responses. Defining a specific interface for the DeepSeek response structure would improve type safety and maintainability.

@diegosouzapw
diegosouzapw changed the base branch from main to release/v3.8.0 May 16, 2026 03:07
diegosouzapw added a commit that referenced this pull request May 16, 2026
…2295)

- DeepSeekWebExecutor with ds_session_id cookie auth
- DeepSeekWebWithAutoRefreshExecutor for session management
- Keccak-based PoW solver (DeepSeekHashV1)
- SSE stream transformation to OpenAI format
- Provider constant and alias (ds-web)
- 23 unit tests + live integration test

Authored-by: Paijo <oyi77@users.noreply.github.com>
@diegosouzapw

Copy link
Copy Markdown
Collaborator

✅ Merged into release/v3.8.0 — DeepSeek Web executor with PoW solver fully integrated. Thanks @oyi77!

@diegosouzapw diegosouzapw reopened this May 16, 2026
@diegosouzapw
diegosouzapw merged commit 3046705 into cheaper-inference:release/v3.8.0 May 16, 2026
3 checks passed
diegosouzapw added a commit that referenced this pull request May 16, 2026
…, #2291, #2294, #2295, #2299

- Add 8 missing contributor PR entries to [Unreleased] section
- Add 3 new contributors to the community table:
  @thepigdestroyer (2 PRs), @josephvoxone (1 PR), @mrmm (1 PR)
- Update counts: @oyi77 12→14, @backryun 8→9, @ddarkr 3→4,
  @hartmark 2→4
- Compensates for cherry-picked PRs that couldn't be properly
  merged via GitHub (branch deleted or fork restriction)
@Rahulsharma0810

Copy link
Copy Markdown
Contributor

@oyi77 it not accepting

ds_session_id=YOUR_NEW_FRESH_VALUE_HERE

@oyi77

oyi77 commented May 20, 2026

Copy link
Copy Markdown
Contributor Author

@oyi77 it not accepting

ds_session_id=YOUR_NEW_FRESH_VALUE_HERE

try paste your full cookie string

@Rahulsharma0810

Rahulsharma0810 commented May 21, 2026 •

Copy link
Copy Markdown
Contributor

Not working with any model in Deepseek Web

image image

HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
…heaper-inference#2295)

- DeepSeekWebExecutor with ds_session_id cookie auth
- DeepSeekWebWithAutoRefreshExecutor for session management
- Keccak-based PoW solver (DeepSeekHashV1)
- SSE stream transformation to OpenAI format
- Provider constant and alias (ds-web)
- 23 unit tests + live integration test

Authored-by: Paijo <oyi77@users.noreply.github.com>
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
…-web-executor-v2

Integrated into release/v3.8.0
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
…heaper-inference#2288, cheaper-inference#2289, cheaper-inference#2290, cheaper-inference#2291, cheaper-inference#2294, cheaper-inference#2295, cheaper-inference#2299

- Add 8 missing contributor PR entries to [Unreleased] section
- Add 3 new contributors to the community table:
  @thepigdestroyer (2 PRs), @josephvoxone (1 PR), @mrmm (1 PR)
- Update counts: @oyi77 12→14, @backryun 8→9, @ddarkr 3→4,
  @hartmark 2→4
- Compensates for cherry-picked PRs that couldn't be properly
  merged via GitHub (branch deleted or fork restriction)
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
…heaper-inference#2295)

- DeepSeekWebExecutor with ds_session_id cookie auth
- DeepSeekWebWithAutoRefreshExecutor for session management
- Keccak-based PoW solver (DeepSeekHashV1)
- SSE stream transformation to OpenAI format
- Provider constant and alias (ds-web)
- 23 unit tests + live integration test

Authored-by: Paijo <oyi77@users.noreply.github.com>
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
…-web-executor-v2

Integrated into release/v3.8.0
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
…heaper-inference#2288, cheaper-inference#2289, cheaper-inference#2290, cheaper-inference#2291, cheaper-inference#2294, cheaper-inference#2295, cheaper-inference#2299

- Add 8 missing contributor PR entries to [Unreleased] section
- Add 3 new contributors to the community table:
  @thepigdestroyer (2 PRs), @josephvoxone (1 PR), @mrmm (1 PR)
- Update counts: @oyi77 12→14, @backryun 8→9, @ddarkr 3→4,
  @hartmark 2→4
- Compensates for cherry-picked PRs that couldn't be properly
  merged via GitHub (branch deleted or fork restriction)
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…heaper-inference#2295)

- DeepSeekWebExecutor with ds_session_id cookie auth
- DeepSeekWebWithAutoRefreshExecutor for session management
- Keccak-based PoW solver (DeepSeekHashV1)
- SSE stream transformation to OpenAI format
- Provider constant and alias (ds-web)
- 23 unit tests + live integration test

Authored-by: Paijo <oyi77@users.noreply.github.com>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…-web-executor-v2

Integrated into release/v3.8.0
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…heaper-inference#2288, cheaper-inference#2289, cheaper-inference#2290, cheaper-inference#2291, cheaper-inference#2294, cheaper-inference#2295, cheaper-inference#2299

- Add 8 missing contributor PR entries to [Unreleased] section
- Add 3 new contributors to the community table:
  @thepigdestroyer (2 PRs), @josephvoxone (1 PR), @mrmm (1 PR)
- Update counts: @oyi77 12→14, @backryun 8→9, @ddarkr 3→4,
  @hartmark 2→4
- Compensates for cherry-picked PRs that couldn't be properly
  merged via GitHub (branch deleted or fork restriction)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants