docs: add DeepSeek monitoring completion design
This commit is contained in:
@@ -0,0 +1,277 @@
|
|||||||
|
# DeepSeek Monitoring Completion Design
|
||||||
|
|
||||||
|
**Date:** 2026-04-23
|
||||||
|
**Status:** Draft for Review
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Complete `deepseek` support in the desktop monitoring pipeline so it reaches practical parity with the existing AI monitoring platforms:
|
||||||
|
|
||||||
|
- visible in AI platform management
|
||||||
|
- bindable and probeable through the existing desktop auth flow
|
||||||
|
- executable as a hidden desktop monitoring task
|
||||||
|
- able to submit answer content back to the server
|
||||||
|
- able to extract and report citations when the DeepSeek web UI exposes them
|
||||||
|
|
||||||
|
`hunyuan` is explicitly out of scope for this work because the product decision is to treat it as `yuanbao`.
|
||||||
|
|
||||||
|
## Current State
|
||||||
|
|
||||||
|
The codebase already has the platform catalog entry and generic AI auth probing support for `deepseek`, but the desktop monitor execution layer does not provide a DeepSeek adapter and does not route monitor tasks to one.
|
||||||
|
|
||||||
|
That creates a partial implementation:
|
||||||
|
|
||||||
|
- AI platform management can show DeepSeek and attempt generic session probing.
|
||||||
|
- The runtime treats `deepseek` as a login-required monitor platform.
|
||||||
|
- Server-side monitoring tasks can reference `deepseek`.
|
||||||
|
- The desktop runtime cannot actually execute a `deepseek` monitor task because `selectMonitorAdapter()` returns `null`.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
| ID | Requirement |
|
||||||
|
| --- | --- |
|
||||||
|
| R1 | `deepseek` monitor tasks must execute through the desktop runtime instead of falling back to scaffold results |
|
||||||
|
| R2 | Existing generic AI platform bind/probe flow remains the authorization path for DeepSeek |
|
||||||
|
| R3 | The adapter must ask the configured monitoring question and wait for the final answer in a hidden browser context |
|
||||||
|
| R4 | The adapter must report `answer`, `provider_model`, and raw observation payload back through the existing monitoring callback API |
|
||||||
|
| R5 | The adapter must collect citations when the latest DeepSeek answer exposes external references or source/search links |
|
||||||
|
| R6 | Citation extraction failure must not fail an otherwise successful answer capture |
|
||||||
|
| R7 | Missing login, challenge, timeout, and transport failures must be surfaced in the same failure contract used by the existing adapters |
|
||||||
|
| R8 | The implementation must ship with adapter-level tests and at least one regression test covering DeepSeek result ingestion assumptions |
|
||||||
|
|
||||||
|
## Chosen Approach
|
||||||
|
|
||||||
|
Use a new Playwright-based monitor adapter for DeepSeek, matching the current desktop monitoring architecture used by `kimi`, `qwen`, `yuanbao`, `doubao`, and `wenxin`.
|
||||||
|
|
||||||
|
Why this approach:
|
||||||
|
|
||||||
|
- It fits the current runtime model with hidden pages, task progress reporting, and task result posting.
|
||||||
|
- It reuses the already-working generic AI authorization and session partition management.
|
||||||
|
- It is less risky than introducing a new DeepSeek-only HTTP/SSE client against undocumented web APIs.
|
||||||
|
- It lets us capture both rendered answer text and any citation UI that only exists in the browser.
|
||||||
|
|
||||||
|
Not chosen:
|
||||||
|
|
||||||
|
- Direct HTTP/SSE replay of private DeepSeek web APIs in this iteration
|
||||||
|
- A DeepSeek-specific auth subsystem separate from the generic AI platform probing path
|
||||||
|
|
||||||
|
## User-Facing Outcome
|
||||||
|
|
||||||
|
After this work:
|
||||||
|
|
||||||
|
- A tenant can bind a DeepSeek session from the desktop AI platforms page using the existing platform management flow.
|
||||||
|
- The desktop runtime can receive and execute `deepseek` monitor tasks.
|
||||||
|
- Successful DeepSeek runs write answer text and citations into the same server-side monitoring result path used by the other platforms.
|
||||||
|
- If DeepSeek returns an answer with no visible sources, the task still succeeds and stores an empty citation list.
|
||||||
|
|
||||||
|
## Design
|
||||||
|
|
||||||
|
### 1. Authorization Management
|
||||||
|
|
||||||
|
No new DeepSeek-only authorization flow will be introduced.
|
||||||
|
|
||||||
|
DeepSeek continues to use the existing generic AI platform detection path in `account-binder.ts` and `platform-auth-adapters.ts`:
|
||||||
|
|
||||||
|
- bind flow opens the DeepSeek console URL in a dedicated partition
|
||||||
|
- the generic AI page probe checks for logged-out, challenge, and authenticated states
|
||||||
|
- the periodic account health worker keeps using the generic platform adapter classification path
|
||||||
|
|
||||||
|
Implementation note:
|
||||||
|
|
||||||
|
- No schema or API change is required for auth management.
|
||||||
|
- This work may add small DeepSeek-specific failure text classification only if runtime evidence shows the generic rules miss a known DeepSeek auth/challenge string.
|
||||||
|
|
||||||
|
### 2. Desktop Monitor Adapter
|
||||||
|
|
||||||
|
Add `apps/desktop-client/src/main/adapters/deepseek.ts`.
|
||||||
|
|
||||||
|
Adapter contract:
|
||||||
|
|
||||||
|
- `provider: "deepseek"`
|
||||||
|
- `executionMode: "playwright"`
|
||||||
|
- `query(context, payload)` returns the standard `AdapterExecutionResult`
|
||||||
|
|
||||||
|
Execution flow:
|
||||||
|
|
||||||
|
1. Resolve the question text from the monitor payload using the same candidate field strategy as the existing adapters.
|
||||||
|
2. Ensure the hidden Playwright page is on `https://chat.deepseek.com/`.
|
||||||
|
3. Detect early terminal states before typing:
|
||||||
|
- login required
|
||||||
|
- human verification / challenge
|
||||||
|
- page bootstrap failure
|
||||||
|
4. Focus the current input editor and submit the monitoring question.
|
||||||
|
5. Poll the page for the newest assistant response until the answer is stable or a timeout is hit.
|
||||||
|
6. Extract answer text, provider metadata, citations, and source/search panels from the latest answer surface.
|
||||||
|
7. Return a successful payload even when citation arrays are empty, as long as answer capture succeeded.
|
||||||
|
|
||||||
|
### 3. Page Observation Model
|
||||||
|
|
||||||
|
The DeepSeek adapter will mirror the existing adapter pattern and keep a structured in-page snapshot instead of relying on one selector or one network response.
|
||||||
|
|
||||||
|
The snapshot will capture:
|
||||||
|
|
||||||
|
- current URL and page title
|
||||||
|
- login-required signals
|
||||||
|
- challenge/risk-control signals
|
||||||
|
- busy/generating signals
|
||||||
|
- latest assistant answer text
|
||||||
|
- latest reasoning text if present
|
||||||
|
- latest assistant message signature for stability polling
|
||||||
|
- explicit citation/source links associated with the latest answer
|
||||||
|
- raw link groups for fallback debugging
|
||||||
|
- provider metadata when discoverable from page state
|
||||||
|
|
||||||
|
This gives us a stable contract for:
|
||||||
|
|
||||||
|
- wait-until-complete logic
|
||||||
|
- answer completeness checks
|
||||||
|
- citation extraction
|
||||||
|
- regression tests that do not need a live DeepSeek account
|
||||||
|
|
||||||
|
### 4. Citation Extraction Strategy
|
||||||
|
|
||||||
|
DeepSeek citation support will be best-effort but first-class in the initial implementation.
|
||||||
|
|
||||||
|
The adapter will collect links in this order:
|
||||||
|
|
||||||
|
1. latest-answer inline reference anchors
|
||||||
|
2. latest-answer attached source cards / source lists / citation panels
|
||||||
|
3. explicit search/source side panels if the UI renders them for the current answer
|
||||||
|
|
||||||
|
Normalization rules:
|
||||||
|
|
||||||
|
- only keep non-empty external URLs
|
||||||
|
- strip URL hash fragments before dedupe
|
||||||
|
- preserve title and site name when present
|
||||||
|
- dedupe by normalized URL
|
||||||
|
- do not duplicate the same URL across `citations` and `search_results`
|
||||||
|
|
||||||
|
Classification rules:
|
||||||
|
|
||||||
|
- `citations`: links directly attached to the latest answer body or answer-level citation panel
|
||||||
|
- `search_results`: links rendered in a clearly separate search/source results surface for the answer
|
||||||
|
|
||||||
|
Fallback rules:
|
||||||
|
|
||||||
|
- if the answer exists but no links are discoverable, return success with empty `citations` and empty `search_results`
|
||||||
|
- if link extraction partially fails, keep the successfully parsed links and retain the raw observation in `raw_response_json`
|
||||||
|
- citation parsing must never convert a successful answer capture into a failed monitor task
|
||||||
|
|
||||||
|
### 5. Provider Metadata
|
||||||
|
|
||||||
|
The adapter should report:
|
||||||
|
|
||||||
|
- `provider_model`: page-derived model label when available, otherwise `"deepseek-chat"`
|
||||||
|
- `provider_request_id`: page-derived conversation/message/request identifier when available, otherwise omitted
|
||||||
|
|
||||||
|
This is intentionally softer than the answer requirement. Missing metadata is acceptable; missing final answer is not.
|
||||||
|
|
||||||
|
### 6. Runtime Registration
|
||||||
|
|
||||||
|
Wire the new adapter into the desktop runtime:
|
||||||
|
|
||||||
|
- export it from `apps/desktop-client/src/main/adapters/index.ts`
|
||||||
|
- import it in `apps/desktop-client/src/main/runtime-controller.ts`
|
||||||
|
- return it from `selectMonitorAdapter("deepseek")`
|
||||||
|
|
||||||
|
No server dispatch change is needed because the server already emits `deepseek` tasks and the runtime already treats DeepSeek as a login-required monitor platform.
|
||||||
|
|
||||||
|
### 7. Result Reporting
|
||||||
|
|
||||||
|
The adapter output will flow through the existing client and server result pipeline without adding new endpoints.
|
||||||
|
|
||||||
|
Successful DeepSeek result payloads will populate:
|
||||||
|
|
||||||
|
- `answer`
|
||||||
|
- `provider_model`
|
||||||
|
- optional `provider_request_id`
|
||||||
|
- `citations`
|
||||||
|
- `search_results`
|
||||||
|
- `raw_response_json`
|
||||||
|
|
||||||
|
Server-side ingestion behavior remains unchanged:
|
||||||
|
|
||||||
|
- `buildMonitoringRawPayload()` stores answer and source arrays
|
||||||
|
- existing citation source resolution consumes those arrays
|
||||||
|
- DeepSeek keeps the default non-Kimi behavior, meaning `search_results` remain eligible as citation source inputs when present
|
||||||
|
|
||||||
|
This avoids any schema or ingestion branching that is specific to DeepSeek.
|
||||||
|
|
||||||
|
### 8. Error Handling
|
||||||
|
|
||||||
|
The adapter will return `failed` with structured error payloads for:
|
||||||
|
|
||||||
|
- missing question text
|
||||||
|
- login required / session expired
|
||||||
|
- challenge required / captcha / human verification
|
||||||
|
- send action unavailable
|
||||||
|
- answer timeout
|
||||||
|
- aborted task
|
||||||
|
|
||||||
|
The adapter will return `succeeded` when:
|
||||||
|
|
||||||
|
- a stable final answer is captured, even if no citations are found
|
||||||
|
|
||||||
|
The adapter will return `unknown` only for ambiguous states where:
|
||||||
|
|
||||||
|
- the page remains reachable
|
||||||
|
- the task did not clearly fail auth
|
||||||
|
- the answer never reached a trustworthy terminal state
|
||||||
|
|
||||||
|
### 9. Testing
|
||||||
|
|
||||||
|
#### Adapter Tests
|
||||||
|
|
||||||
|
Add `apps/desktop-client/src/main/adapters/deepseek.test.ts`.
|
||||||
|
|
||||||
|
These tests will cover helper behavior without requiring a real DeepSeek session:
|
||||||
|
|
||||||
|
- question text resolution
|
||||||
|
- URL normalization and link dedupe
|
||||||
|
- citation classification from a synthetic page snapshot
|
||||||
|
- answer completion / stability rules
|
||||||
|
- failure classification for login/challenge/timeout cases
|
||||||
|
|
||||||
|
#### Runtime Wiring Regression
|
||||||
|
|
||||||
|
Add or extend a desktop runtime regression test so `selectMonitorAdapter("deepseek")` no longer returns `null`.
|
||||||
|
|
||||||
|
If direct unit coverage of `selectMonitorAdapter()` is awkward because it is file-local, extract a tiny adapter registry helper so the routing can be tested without spinning the whole runtime controller.
|
||||||
|
|
||||||
|
#### Server Ingestion Regression
|
||||||
|
|
||||||
|
Add a monitoring callback regression test confirming that DeepSeek payloads with `search_results` continue to feed the normal citation source input path and do not require DeepSeek-specific server branching.
|
||||||
|
|
||||||
|
## File Changes
|
||||||
|
|
||||||
|
Expected implementation touchpoints:
|
||||||
|
|
||||||
|
- `apps/desktop-client/src/main/adapters/deepseek.ts`
|
||||||
|
- `apps/desktop-client/src/main/adapters/deepseek.test.ts`
|
||||||
|
- `apps/desktop-client/src/main/adapters/index.ts`
|
||||||
|
- `apps/desktop-client/src/main/runtime-controller.ts`
|
||||||
|
- `apps/desktop-client/src/main/platform-auth-adapters.ts` only if DeepSeek-specific auth/challenge wording needs classification tuning
|
||||||
|
- `server/internal/tenant/app/monitoring_callback_service_test.go`
|
||||||
|
|
||||||
|
## Non-Goals
|
||||||
|
|
||||||
|
- separate `hunyuan` adapter or platform entry changes
|
||||||
|
- new monitoring database fields
|
||||||
|
- new callback APIs
|
||||||
|
- undocumented direct DeepSeek HTTP client support
|
||||||
|
- perfect citation recovery from every possible DeepSeek UI variant
|
||||||
|
|
||||||
|
## Risks And Mitigations
|
||||||
|
|
||||||
|
| Risk | Impact | Mitigation |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| DeepSeek page structure differs from Kimi/Qwen enough that one selector path is brittle | answer capture breaks | use multi-signal page snapshotting instead of single-selector extraction |
|
||||||
|
| Citation UI is conditional and not always present | sparse citation coverage | treat citations as best-effort and keep answer success independent from citation presence |
|
||||||
|
| DeepSeek challenge/risk-control copy is not fully covered by generic auth rules | false success or unclear failures | add DeepSeek-specific failure text classification only where runtime evidence shows a gap |
|
||||||
|
| Provider request identifiers are not consistently exposed in DOM state | weaker traceability | keep request id optional and fall back to stable model + raw response payload |
|
||||||
|
|
||||||
|
## Rollout Notes
|
||||||
|
|
||||||
|
- This is safe to ship behind the existing runtime because unsupported DeepSeek tasks currently fail at adapter selection time.
|
||||||
|
- No migration is required.
|
||||||
|
- The implementation should be verified first with one manually bound DeepSeek desktop account before treating it as generally available in production monitoring runs.
|
||||||
Reference in New Issue
Block a user