Documentation
¶
Overview ¶
Package lp provides web page reading via lightpanda browser with CDP.
Architecture ¶
url(req) +------------+ wss +---------------+ http +-------------+
-------->| Web +--------->| +------>| |
| chromedp | | Lightpanda | | WebServer |
<--------+ |<---------+ |<------+ |
markdown +------------+ markdown +---------------+ rep +-------------+
The package replaces the previous approach of using Go's net/http client directly. Lightpanda provides a headless browser with CDP support, solving these problems:
- JavaScript-rendered pages that return empty content via HTTP
- Geo-restricted sites (e.g. google.com) inaccessible from local network
- Better HTML-to-markdown conversion via LP.getMarkdown CDP command
Remote vs Local ¶
Lightpanda runs in two modes:
- Local: ws://127.2.2.9:9227 (no auth, user runs lightpanda serve)
- Remote: wss://euwest.cloud.lightpanda.io/ws (token auth, 8h/month limit)
Routing decision: if the target host is in the remoteHosts list (geo-restricted sites), use remote; otherwise use local.
Auto-start ¶
When local lightpanda is not running, Get automatically starts it:
- Preferred: user service via internal/userservice - Linux: systemd user service (dscli-lightpanda.service) - macOS: LaunchAgent (dscli-lightpanda.plist) - Lifecycle independent of dscli — survives dscli process exit - Allows multiple dscli instances to share one lightpanda
- Fallback: child process (if user service is unavailable) - Lifecycle tied to dscli — exits when dscli exits
Config keys (~/.dscli/config.dscli):
lightpanda-local-url = ws://127.2.2.9:9227 lightpanda-remote-url = wss://euwest.cloud.lightpanda.io/ws lightpanda-remote-token = <token>
Usage ¶
import "github.com/dscli/dscli/internal/lp" markdown, err := lp.Get(ctx, "https://example.com")
Future work ¶
- Web writer support (e.g. interacting with chat.deepseek.com)
Index ¶
- Variables
- func DefaultCookiePath() string
- func Get(ctx context.Context, rawURL string) (string, error)
- func GetRemote(ctx context.Context, rawURL string) (string, error)
- func NetworkCheck(rawURL string) error
- func NewChromium(ctx context.Context) (context.Context, func(), error)
- func ReadCodeFromStdin() (string, error)
- func WebChat(ctx context.Context, message string) (string, error)
Constants ¶
This section is empty.
Variables ¶
var ErrLoginRequired = errors.New("login required — open visible browser to complete login")
ErrLoginRequired is returned when the browser is not logged in to DeepSeek. Callers should trigger a visible login flow and retry.
Functions ¶
func DefaultCookiePath ¶
func DefaultCookiePath() string
DefaultCookiePath returns the default path for the DeepSeek cookie file.
func Get ¶
Get fetches a web page via lightpanda CDP and returns its markdown content.
It automatically routes to remote lightpanda for geo-restricted hosts (listed in remoteHosts), and uses local lightpanda for all other URLs. If remote is not configured, even remoteHosts fall back to local.
If local lightpanda is not running but the lightpanda command is available, Get will auto-start lightpanda serve in the background before fetching.
Config keys used (from ~/.dscli/config.dscli):
- lightpanda-local-url (default: ws://127.2.2.9:9227)
- lightpanda-remote-url (default: "")
- lightpanda-remote-token (default: "")
Get fetches a web page via lightpanda CDP and returns its markdown content.
It automatically routes to remote lightpanda for geo-restricted hosts (listed in remoteHosts), and uses local lightpanda for all other URLs. If remote is not configured, even remoteHosts fall back to local.
If local lightpanda is not running but the lightpanda command is available, Get will auto-start lightpanda serve in the background before fetching.
Config keys used (from ~/.dscli/config.dscli):
- lightpanda-local-url (default: ws://127.2.2.9:9227)
- lightpanda-remote-url (default: "")
- lightpanda-remote-token (default: "")
func GetRemote ¶
GetRemote fetches a web page via remote lightpanda CDP regardless of the target host. Returns an error if remote is not configured.
Unlike Get, GetRemote skips the host-based routing and local lightpanda auto-start — it always uses the configured remote endpoint.
Config keys used:
- lightpanda-remote-url (required)
- lightpanda-remote-token (optional)
func NetworkCheck ¶ added in v0.8.5
NetworkCheck verifies that the target URL's host is reachable via TCP before launching a browser. This avoids wasting time on a truly down network — Chrome would otherwise report ERR_INTERNET_DISCONNECTED and fail after a much longer timeout.
The check connects directly from the host, bypassing Chrome's network stack, so it only fails when the host actually has no connectivity. On URL parse errors the check is skipped (assume reachable).
func NewChromium ¶ added in v0.8.5
NewChromium creates a new chromedp ExecAllocator backed by a local Chrome/Chromium browser. The caller must call the returned cancel func to shut down the browser when done.
Usage:
ctx, cancel, err := NewChromium(parentCtx)
if err != nil { return err }
defer cancel()
tabCtx, tabCancel := chromedp.NewContext(ctx)
defer tabCancel()
func ReadCodeFromStdin ¶
ReadCodeFromStdin reads a verification code from stdin with a prompt. In non-interactive environments (stdin not a terminal), it falls back to polling codeFilePath every 2 seconds for up to 5 minutes.
func WebChat ¶
WebChat sends a message to chat.deepseek.com via a local Chrome/Chromium browser and returns the assistant's text response.
The browser is launched fresh for each call and closed after the response is received. Cookies persist via the shared Chrome profile directory, so prior login state is available across calls.
If ctx carries context.KeepKey set to true, WebChat attempts to continue the last saved conversation (loaded from the profile directory) rather than starting a new one. New conversations automatically enable expert mode (V4 Pro).
Types ¶
This section is empty.