voyager
Nagi-ovo
Enhancement suite for Gemini, AI Studio, Claude & ChatGPT — plus a prompt manager for any websites, DeepSeek Harness included. / 面向 Gemini、AI Studio、Claude 与 ChatGPT 的增强套件;其中的提示词管理器可用于任意网站,如 DeepSeek Harness。
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:twilightt1/dsh-llm-chatgpt-web
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
ChatGPT Web as a DeepSeek Harness (dsh) provider — standalone. The plugin
owns its Chromium and signs in once. Text turns use a fresh Temporary Chat
page; opt-in native MCP turns use a normal connector-enabled chat whose
physical response can span several compatible DSH tool-result steps. The
adapter-owned conversation is deleted when that physical response settles; an
explicit compatibility change or page loss uses safe fresh replay only after
durable results are proven. The default text transport needs no external
bridge; an opt-in Unix MCP transport adds a local broker and stdio MCP server;
a separately provisioned connector/tunnel makes it reachable without changing
DSH's agent loop.
dsh plugin --profile web add github:twilightt1/dsh-llm-chatgpt-web
dsh web
# Model picker → provider "chatgpt-web"
pnpm ≥10 blocks dependency build scripts by default; this package ships prebuilt
lib/and needs noallowBuildsentry. If your client still prompts, decline it — nothing here needs to run at install time.
DSH agent-loop → GenerateOptions → ChatGptWebAdapter.stream()
→ text: fresh Temporary Chat page
→ native: one connector-enabled physical response + broker request
→ select effort → attach prompt → one Send
→ poll answer DOM (persistent Markdown buffer)
→ logical StreamChunks → usage + finish/tool boundary
Default text tools: JSON envelope + fenced tool-call contract.
Opt-in native tools: local broker ← stdio MCP façade ← connector/tunnel
← exact ChatGPT connector;
broker batches become ordinary DSH tool-call chunks, then the next compatible
step resolves exact results into the same physical response. Incompatible
history/configuration or a recoverable page loss fences the old response
before one canonical fresh replay. The adapter deletes each exact owned
native conversation after settlement.
Text turns carry the full visible history in their prompt and remain stateless across turns. Native tool turns use a normal chat because ChatGPT disables connectors in Temporary Chat; one physical response retains its assistant identity, broker request, DOM/Markdown cursor, deadlines, and append-only logical-boundary journals while DSH executes tools. A compatible next request must contain the exact assistant call and one text-only result per call; it does not allocate a page, compile a prompt, select a connector, or press Send again. A private restart-safe ledger retries failed cleanup before the next native turn. Turns are serialized: at most one page is ever active.
The prompt transport follows codex-chatgpt-web's proven design: the DSH
conversation is wrapped in a <dsh_context_json> envelope with an explicit
transport contract (role semantics, read-before-acting, never echo), which
replaced the old plaintext transcript that made ChatGPT echo instructions
back. Answer extraction binds the newly-created assistant turn by its stable
DOM identity, then converts only that turn's answer-root HTML into Markdown
(turndown). It never falls back to an older turn or the whole document. An
append-only buffer with source ranges preserves code fences (including
The session is persisted back to the profile after every completed turn
because ChatGPT rotates session tokens.
### Native continuation safety
Native continuation is experimental and remains opt-in. The replay envelope
contains only a versioned non-secret execution hash, logical boundary, and
opaque call IDs. Changes to provider-visible history, model, system prompt,
tool schemas, generation options, steering, or physical-page health select an
explicit fresh-replay path only when every prior tool result is durable and no
side effect is uncertain. A transport failure after submission, ambiguous tool
outcome, correlation conflict, or cleanup failure stops without resubmitting.
`RATE_LIMIT` opens a fixed five-minute adapter-local cooldown and is never
automatically retried. Text transport and auxiliary title/compaction calls do
not use this lifetime.
### Transition compatibility
The transition release keeps the existing `correlateToolResults`,
`nativeCheckpointRawResultHash`, and `nativeCheckpointProjectionHash` exports,
plus the source-level `hasExactNativeToolResults` helper, as deprecated
compatibility adapters. New code should rely on the continuation-owned durable
result evidence behavior; the compatibility adapters are scheduled for removal
in the following release after the transition behavior has been reviewed.
## Prerequisites
- Google Chrome installed (or set `chromeExecutablePath`).
- A `deepseek-harness` checkout for the Cordis peers (see below).
## Install (pick one)
**A. Local checkout (dev, no build step needed — `lib/` ships in the repo):**
```sh
dsh plugin --profile web add /absolute/path/to/dsh-llm-chatgpt-web
dsh web
The CLI registers dsh.bundle.patch, links the checkout, and appends the
bundle to the profile automatically (--dump-config shows the
llm-chatgpt-web row). Keep the checkout in place — the profile links it.
B. Prebuilt tarball (no build permission asked):
pnpm pack # → dsh-llm-chatgpt-web-0.7.0.tgz
dsh plugin --profile web add ./dsh-llm-chatgpt-web-0.7.0.tgz
C. GitHub (prebuilt lib/ committed — no build permission needed):
dsh plugin --profile web add github:twilightt1/dsh-llm-chatgpt-web
Then select provider chatgpt-web (model chatgpt-web/high or per your
account) in the Web UI model picker, or set it in an agent config. Requires
Google Chrome/Brave installed and one manual ChatGPT sign-in on first use.
Minimum harness peers are declared in peerDependencies
(cordis ^4.0.1, dsh-llm ^0.1.1-rc.2, schemastery ^3.18.1).
Runtime dependencies include playwright-core (drives system Chrome; no
browser download needed), the MCP SDK, and Zod.
The first turn with no saved session opens a headed window at
chatgpt.com. Sign in manually inside that window; the plugin waits for the
composer (proof of session), saves it under profileDir
(~/.dsh-chatgpt-web/storage-state.json), and continues from then on.
Nothing is copied between browsers. If the session expires later, delete
the profile directory and run again.
Headed-hidden daemon (current status). Turns run as tabs in one shared browser daemon (
lib/chatgpt/daemon-main.js, auto-spawned detached on first use, endpoint inbrowser-endpoint.json, idle shutdown afterdaemonIdleMs). The daemon's single window is hidden+minimized at birth, so turns after the first never flash — attach, stream, detach, done. True headless was tried twice (Brave, then real Chrome): ChatGPT answers with an interactive Cloudflare checkbox that never clears headless (screenshot-proven), so the daemon stays headed-hidden. The adapter never closes the shared browser — only its own context, plus an internal connection detach so hosts exit cleanly.
- id: llm-chatgpt-web
name: '/abs/path/to/dsh-llm-chatgpt-web/src/index.ts'
config:
profileDir: ~/.dsh-chatgpt-web
headed: true
# connectorTransport: text # default; use mcp for native tools (Unix only)
# Existing externally owned MCP runtime:
# connectorTransport: mcp
# connectorRuntime: external
# connectorName: DSH Native # exact Personalized connector title
# brokerSocketPath: ~/.dsh-chatgpt-web/native-broker.sock
# mcpInvocationTimeoutMs: 90000
# Managed tunnel-client runtime (replace the block above):
# connectorTransport: mcp
# connectorRuntime: managed
# connectorName: DSH Native
# brokerSocketPath: ~/.dsh-chatgpt-web/native-broker.sock
# nativeRuntimeConfigPath: ~/.dsh-chatgpt-web/native-runtime.json
# mcpInvocationTimeoutMs: 90000
# Secure policy example (use an absolute workspace path and exact DSH tool names):
# nativeSecurity:
# toolPolicy: evidence-only
# workspaceRoot: /absolute/path/to/workspace
# approval: workspace-policy
# evidenceLimits:
# maxBytes: 65536
# maxLines: 200
# rules:
# - tool: read_file
# capability: workspace.read
# pathArguments: [/path]
# result: sanitized-evidence
# chromeExecutablePath: /usr/bin/google-chrome
- id: agent-loop
name: '@deepseek-ai/dsh-agent-loop'
config:
agents:
- id: main
provider: chatgpt-web
model: chatgpt-web/high
Models (effort is fixed per model): chatgpt-web/luna, chatgpt-web/think,
chatgpt-web/light, chatgpt-web/medium, chatgpt-web/high,
chatgpt-web/extra-high, chatgpt-web/pro (last two only if your account
exposes them — the effort probe fails closed otherwise).
Auto-detect order for the browser binary: explicit config →
$CHROME_EXECUTABLE_PATH → platform Chrome → Brave (macOS) → Playwright's
bundled Chromium. Call adapter.dispose() on host unload to release the
owned browser (the dev scripts/live-turn.ts shows the pattern).
Native MCP has two ownership modes. connectorRuntime: external keeps the
existing contract: an operator owns the tunnel process and launches the
package's stdio MCP child. connectorRuntime: managed makes this plugin own
the pinned tunnel-client lifecycle. Text transport remains the default.
Create or select an OpenAI Secure MCP Tunnel and create a restricted runtime API key with Tunnels Read and Use permissions. Keep the tunnel ID and runtime key separate: the ID is metadata, while the key authenticates the local tunnel client. Use the official Secure MCP Tunnel guide, Platform Tunnels settings, and Runtime API keys.
This package does not create the account tunnel, runtime key, or ChatGPT connector. It only installs a verified local client and configures the local runtime after you supply those account-level values.
Run setup on Darwin/Linux arm64 or x64. The client is pinned to
openai/tunnel-client 0.0.12; setup verifies the release checksum, binary
version, private permissions, and a real connect/status/stop cycle before
writing the final runtime configuration:
dsh-chatgpt-web-native setup \
--profile-dir "$HOME/.dsh-chatgpt-web" \
--connector-name "DSH Native" \
--tunnel-id "$TUNNEL_ID"
Without --runtime-key-file, setup asks for the runtime key through a hidden
TTY prompt. To read an existing private key file instead:
dsh-chatgpt-web-native setup \
--profile-dir "$HOME/.dsh-chatgpt-web" \
--connector-name "DSH Native" \
--tunnel-id "$TUNNEL_ID" \
--runtime-key-file /private/path/to/runtime-key
Setup copies the key to
~/.dsh-chatgpt-web/secrets/tunnel-runtime.key (0600) and stores only that
path in native-runtime.json (0600). It does not edit Cordis YAML or
account settings. A source key passed with --runtime-key-file is retained;
remove or rotate that source yourself after confirming the managed copy.
In ChatGPT connector settings,
create or select the Personalized connector with the exact name
DSH Native (or the configured connectorName). Use the tunnel connection,
select the same tunnel ID, and set Authentication: None. The account
connector must point at this tunnel; a healthy local process alone does not
prove ChatGPT can discover or call it.
After setup succeeds, mount the provider with the matching local paths:
config:
connectorTransport: mcp
connectorRuntime: managed
connectorName: DSH Native
brokerSocketPath: ~/.dsh-chatgpt-web/native-broker.sock
nativeRuntimeConfigPath: ~/.dsh-chatgpt-web/native-runtime.json
mcpInvocationTimeoutMs: 90000
The plugin listens on the private broker socket before starting the tunnel,
then requires process_running=true, healthy=true, and ready=true before
it opens a ChatGPT turn. In managed mode, do not separately launch
dsh-chatgpt-web-mcp; the managed runtime launches the built stdio MCP
command itself.
Native policy is opt-in and defaults to toolPolicy: full with
approval: none; secure deployments should use toolPolicy: evidence-only or
allowlist, an explicit absolute workspaceRoot, and
approval: workspace-policy. Tool names and RFC 6901 pathArguments must
match the actual DSH inventory exactly. The configured tool must accept the
canonical absolute paths supplied by the adapter. If workspaceRoot is omitted,
it falls back to process.cwd; doctor warns about that weaker, launch-location
dependent boundary. Rule capabilities are operator-declared labels, not
inferences from a tool name, description, or schema.
A workspace-local .dsh-chatgptignore is an optional UTF-8 file no larger than
64 KiB. Its v1 grammar is deliberately literal: blank lines and # comments
are ignored, and each other line is one workspace-relative POSIX path; a
trailing / covers that directory subtree. Absolute paths, .., globs,
negation, duplicate entries, control bytes, malformed UTF-8, and symlinks are
rejected. Built-in sensitive-file rules cannot be negated.
evidence-only and allowlist provide exact inventory filtering,
authorization-time path validation/rewrite, and deterministic text result
projection. They are not a sandbox, DLP boundary, or provenance proof:
tools can ignore declared arguments, a path can change after authorization
(the remaining TOCTOU limitation), and broad output may not originate only from
approved files. The sanitizer emits text-only, bounded, deterministic output;
it can redact secrets, replace home paths, and withhold content, while preserving
isError, but it cannot prove where broad tool output originated. Output
provenance is an operator declaration, not an adapter proof. Full mode preserves
the existing unrestricted output behavior and is marked with an
output-provenance warning by doctor.
Continuation keeps a canonical DSH history/result view for exact durability proof and a separate sanitized/rebased provider view for ChatGPT. Checkpoint, grant, and security files store hashes and bounded metadata only—not prompts, raw arguments, raw result bodies, cookies, credentials, or conversation IDs.
When a secure policy has effective tools, the first request creates a private
approval challenge. Review the exact summary and type approve through the
interactive command before any provider submission:
dsh-chatgpt-web-native approve \
--profile-dir "$HOME/.dsh-chatgpt-web" \
--challenge challenge_<challenge-id>
Policy, implementation, connector, schema inventory, workspace, and limit
changes invalidate the grant. Native journals and the ownership ledger are
private and fail closed on malformed or uncertain state. The checkpoint-writer
lease is profile-wide: a live, stale-but-unproven, or ambiguous owner blocks
mutation and recovery. A blocked checkpoint must not be replayed merely because
a page or process disappeared; use
recover --abandon only with the runtime stopped, an interactive TTY, the
exact checkpoint hash, and the exact abandon confirmation. Abandonment never
claims that an uncertain side effect did or did not happen.
A package rollback is safe only after the v0.7.0 runtime is stopped and
doctor --json proves the runtime is offline, no checkpoint writer is held,
every checkpoint is terminal, no replay is consumed-but-unresolved, and the
owned-conversation ledger is empty. Preserve that clean report before
installing an older package.
Legacy v1 checkpoint journals are migrated to the v2 event format eagerly on
writer-lease acquisition, in sorted filename order, before any recovery or
lifecycle decision. Migration is lossless and atomic: the replacement is
written durably and re-validated, decoded lifecycle facts are compared against
the legacy journal, and only then is the canonical path replaced. A journal
that cannot be mapped safely is left untouched and blocks native startup and
recovery rather than being reinterpreted, and an interrupted migration
artifact is never promoted as authoritative. The legacy NativeCheckpoint
surface remains aliased onto the lifecycle owner for one lifecycle-transition
release; internal callers use the actor-scoped capability seam in
src/native/lifecycle.ts.
doctor is read-only and never prints the runtime-key value. Use --json
for a stable, redacted report suitable for an operator check:
dsh-chatgpt-web-native doctor \
--profile-dir "$HOME/.dsh-chatgpt-web" \
--connector-name "DSH Native" \
--json
dsh-chatgpt-web-native stop \
--profile-dir "$HOME/.dsh-chatgpt-web" \
--connector-name "DSH Native"
stop stops only the configured local tunnel alias; it does not delete the
runtime key, config, tunnel, or ChatGPT connector.
For an externally owned tunnel, keep the plugin opt-in but select the external owner explicitly:
config:
connectorTransport: mcp
connectorRuntime: external
connectorName: DSH Native
brokerSocketPath: ~/.dsh-chatgpt-web/native-broker.sock
Launch the stdio MCP child from the external tunnel runtime:
dsh-chatgpt-web-mcp --broker-socket "$HOME/.dsh-chatgpt-web/native-broker.sock"
The package does not authenticate or supervise that external tunnel. Existing external MCP deployments remain supported; no managed config or account setup is required for them.
Native mode exposes only dsh_round_start, dsh_tool_inventory, and
dsh_tool_call. The broker snapshots the current DSH tool schemas, and all
invocations return to the ordinary DSH ToolRuntime/agent loop as standard
tool/call and matching tool/result events. No nested agent loop,
ctx.tools.execute(), fenced-text fallback, or prose-to-call inference exists.
The first dsh_tool_inventory response includes a bounded discovery catalog
for the complete current inventory: names without an MCP namespace are listed,
while mcp__<server>__ tools are grouped by namespace with their exact names
and count. Schemas and arguments are not included in this catalog. The normal
page remains bounded and paginated. Search by a task keyword or namespace, use
next_offset until the match is found, and request include_schema: true for
the exact tool before calling it; a missing first-page entry is not evidence
that a tool is unavailable.
Before Send, invalid private files, checksum/version drift, tunnel unreadiness, connector-name mismatch, or an incorrectly selected connector fail closed. After Send, the adapter never switches transport. A sentence claiming that a command ran is not evidence; only the DSH call/result events count.
Do not call native E2E live or successful unless all of these are verified:
web profile;doctor --json is successful;DSH Native Personalized connector uses the same tunnel and has
Authentication set to None;ChatGPT Web High selected;bash proves pwd and
git rev-parse --show-toplevel through actual DSH calls;tool/call and tool/result events and at
least two agent steps; and/ or model-authored prose.If the account connector, tunnel, aligned artifacts, or session evidence cannot be verified, report that blocker and do not claim live native E2E.
Runtime keys must stay outside this repository, Cordis YAML, prompts, logs,
screenshots, and session history. Remove temporary source key files and
rotate any credential that was previously stored in plaintext profile config
before a live run. The stop command does not remove credentials; clean up
or retain the managed key intentionally and document the remaining risk.
stop sequences, and temperature
throw UNSUPPORTED* instead of being silently dropped.reasoningEffort throws —
pick the effort via the model id.0600 Unix-socket broker. ChatGPT must use a
Personalized connector named exactly DSH Native (or connectorName) and
call dsh_round_start, dsh_tool_inventory, and dsh_tool_call. Broker
batches are emitted through the normal DSH loop; no nested loop or direct
ctx.tools.execute() path exists. Native results are text-only. Compatible
tool-result steps continue the same connector-enabled physical response,
broker request, conversation, and Send. Context/model/schema/options changes
and recoverable page loss use canonical fresh replay only after durable
results and cleanup safety are proven; uncertain effects fail without a
hidden resubmit. Exact adapter-created conversation IDs are deleted after
settlement, and failed deletions remain in a private ledger for retry. A
tunnel/connector is required for live native E2E; this repository's local
MCP and broker tests do not claim that external setup.The DOM selectors, effort-slider mechanics, Temporary Chat flow
(src/chatgpt/session.ts, src/chatgpt/model.ts), composer insertion, and
completion predicate derive from
codex-chatgpt-web
(MIT, © 2026 codex-chatgpt-web contributors). Only the ChatGPT-Web driving
surface was taken; the native broker, MCP façade, connector selection, and
adapter lifecycle are local additions. Each vendored file carries a
provenance header.
Local adaptations (live-verified Sep 2026): ProseMirror composer selectors
(upstream targeted Lexical only), whitespace-insensitive attach readback
(ProseMirror renders each newline as its own paragraph), settle-wait before
auth asserts (SPA hydration lags domcontentloaded).
Proven against a real Plus-class account (Sep 2026, after the JSON-envelope
scripts/live-lib.mjs / scripts/live-turn.ts: fresh Temporary Chat →
effort slider → attach JSON-envelope prompt → submit → streamed Markdown
deltas (headings, lists, bold all survive) → usage + stop finish, on
both the src (tsx) and built lib/ paths.bash schema attached but no connector call completed in
27.439 s with a terminal stop and no broker invocation after the completion
fence fix; the owned-conversation ledger was empty and no tunnel/MCP child
remained. This validates no-tool completion only, not connector execution.storage-state.json mtime advances per turn.| File | Responsibility |
|---|---|
src/chatgpt/session.ts |
Vendored selectors / effort menu / auth / capability probe |
src/chatgpt/model.ts |
Vendored backend+effort resolution |
src/chatgpt/browser.ts |
Daemon attach, login, per-turn fresh page, session persist |
src/chatgpt/conversation-cleanup.ts |
Exact native conversation identity, private ownership ledger, deletion verification |
src/chatgpt/markdown.ts |
Vendored HTML→Markdown + append-only streaming buffer |
src/chatgpt/guards.ts |
Rate-limit / session / onboarding / terminal guards |
src/chatgpt/effort.ts |
Effort slider + Think toggle per turn |
src/chatgpt/prompt.ts |
DSH history → JSON envelope + transport contract |
src/chatgpt/turn.ts |
Attach → send → block-segment stream loop |
src/chatgpt/connector.ts |
Exact Personalized connector selection and native arbitration |
src/chatgpt/usage.ts |
Char-based usage estimates |
src/native/broker.ts |
In-memory provider-round batching, fences, TTL, retirement |
src/native/broker-socket.ts |
Private Unix JSON-line RPC transport |
src/native/mcp-server.ts |
Fixed MCP façade and handshake |
src/native/coordinator.ts |
Parked-page/session ownership transitions |
src/native/continuation.ts |
Execution identity, result correlation, and replay decisions |
src/native/lifecycle.ts |
Sole lifecycle owner: transition table, closed v2 codec, generation-bound capabilities |
src/native/checkpoint.ts |
Private journal persistence, writer lease, v1-to-v2 migration, recovery verdicts |
src/native/physical-response.ts |
Persistent native response journals and uncertainty state |
src/native/plugin-runtime.ts |
Broker, tunnel readiness, and unload lifecycle |
src/native/mcp-main.ts |
Stdio MCP executable entry point |
src/native/setup-main.ts |
Managed runtime setup, doctor, and stop executable |
src/adapter.ts |
ChatGptWebAdapter (seam, queue, chunk protocol) |
src/index.ts |
Cordis plugin (registerAdapter(['chatgpt-web'])) |
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: chatgpt-web。