Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
42 changes: 37 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ concurrency:
jobs:
validate:
name: Typecheck, smoke, and build
runs-on: ubuntu-24.04
# Profile migration uses macOS shlock; validate on the supported desktop OS.
runs-on: macos-15
timeout-minutes: 20

steps:
Expand All @@ -26,6 +27,14 @@ jobs:
with:
persist-credentials: false

- name: Check out pinned Harness
uses: actions/checkout@v6
with:
repository: deepseek-ai/deepseek-harness
ref: 639ed015397290b3745d163aafe02ffee4aa3f84
path: upstream/deepseek-harness
persist-credentials: false

- name: Install pnpm
uses: pnpm/action-setup@v6

Expand All @@ -41,9 +50,32 @@ jobs:
- name: Typecheck
run: pnpm typecheck

# Development snapshots use bounded smoke coverage; full regression is separate.
- name: Smoke
- name: Validate pinned adapter contracts
run: node apps/deepviewer-desktop/scripts/bootstrap-native-upstream.mjs

- name: Install Harness dependencies
run: pnpm --dir upstream/deepseek-harness install --frozen-lockfile

- name: Build Harness and DeepViewer plugins
run: node apps/deepviewer-desktop/scripts/build-native-desktop.mjs --core-only

- name: Bounded smoke coverage
run: pnpm desktop:smoke

- name: Build
run: pnpm desktop:build
- name: Native Synapse integration and UI regression smoke
run: |
pnpm --filter @deepviewer/desktop smoke:synapse
pnpm --filter @deepviewer/desktop smoke:ui-regression

- name: Fresh upstream contracts and policy fixtures
run: |
node apps/deepviewer-desktop/scripts/smoke-native-contract-source.mjs
node apps/deepviewer-desktop/scripts/smoke-native-header-placement.mjs
pnpm --filter @deepviewer/desktop smoke:contracts
node --test --test-timeout=15000 apps/dsh-plugin-model-capabilities/test/*.test.mjs
node --experimental-strip-types --test apps/deepviewer-adapter/tests/workflows.test.mjs

- name: Authenticated Host and model plugin smoke
run: |
node apps/deepviewer-desktop/scripts/smoke-model-capabilities-host.mjs
node apps/dsh-plugin-model-capabilities/scripts/smoke-runtime.mjs
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,14 @@ out/
# Local checkout of the official upstream source. The analyzed revision and
# refresh procedure are recorded in upstream/README.md.
upstream/deepseek-harness/

# Generated official desktop carrier and adapter bundles
apps/deepviewer-desktop/lib/
apps/deepviewer-desktop/renderer/
apps/deepviewer-adapter/lib/

# Generated official desktop launcher shims
/apps/deepviewer-desktop/scripts/node-bin/

# Local independent worktrees and inspection checkouts
.worktrees/
83 changes: 46 additions & 37 deletions README.md

Large diffs are not rendered by default.

82 changes: 45 additions & 37 deletions README.zh-CN.md

Large diffs are not rendered by default.

72 changes: 72 additions & 0 deletions apps/deepviewer-adapter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# DeepViewer native adapter

DeepViewer 0.5.0 uses DSH 0.2.0-rc.2 (`639ed015397290b3745d163aafe02ffee4aa3f84`) and its Electron/private DesktopHost. The upstream checkout is disposable build input. Product adaptations live here; the old 0.1.5 whole-file overlays are not replayed.

| Directory | Ownership |
| --- | --- |
| `desktop/` | Identity, data roots, Dock theme, system proxy/PAC and private-network authorization |
| `client/` | Branding/About, welcome mascot/font, Work/Chat and native-sidebar editor/Git tabs |
| `workflows/` | Chat isolation, generated-file delivery policy, workspace operations |
| `migrations/` | Profile conversion, version-bound kernel backup and allowlisted frontend state |
| `compatibility/` | Pinned native gaps, imported helper files and regression tests |
| `scripts/` | Validate contracts before modifying disposable upstream sources; stage native bundles |

Use native filesystem opening/reveal, document/browser previews, delivery cards, change review, PTY/browser/sidebar state, process folding and statistics. Better Sidebar and Taskboard are not runtime dependencies. The Git helper retains its upstream MIT attribution; editor libraries retain their licenses.

The adapter, subscriptions and model capabilities are application-owned native modules. The shipped Web application composition owns their rows and client settings registrations. Generated CLI metadata owns their dependencies; the upstream installation manifest and lockfile stay unchanged. Integrated manifests omit `dsh.bundle`, and user profiles contain neither their dependencies nor their bundle selections. They have no separate cards, enable switches or uninstall controls in Plugins. Standalone source packages retain their original plugin packaging.

## Reproduce from the repository root

Use Node 24 and the root's pinned pnpm. `bootstrap-native-upstream.mjs` checks the tag/commit and anchors without resetting unknown edits. Install the upstream's pinned dependencies after bootstrap.

```sh
pnpm install --frozen-lockfile
node apps/deepviewer-desktop/scripts/bootstrap-native-upstream.mjs
pnpm --dir upstream/deepseek-harness install --frozen-lockfile
pnpm desktop:build
pnpm typecheck
pnpm desktop:smoke
pnpm --filter @deepviewer/desktop smoke:source
pnpm --filter @deepviewer/desktop smoke:contracts
pnpm --filter @deepviewer/desktop smoke:plugins
pnpm --filter @deepviewer/desktop smoke:native
pnpm --filter @deepviewer/desktop smoke:payload
```

`smoke:native` uses private homes, fake APIs and local update feeds. `smoke:payload` materializes the production dependency closure and creates a temporary ASAR; it checks actual native loading and Office conversion without creating a distributable app or DMG. Source maps, development links and other-platform runtime packages are excluded. `smoke:source` applies all 106 contracts twice to a fresh checkout and rejects Agent-loop patches.

## Compatibility removal conditions

Every anchor is named and explains its purpose. A changed commit or anchor stops preparation before any source write. Preserve the matching tests when upstream provides an equivalent seam, then remove the contract family and its copied helper together.

| Contract family | Remove when the pinned upstream provides | Verification |
| --- | --- | --- |
| Dedicated RPC ownership | Explicit consumer-owned channel lifetime under Cordis 4 | RPC owner unload regression; authenticated Host/plugin smoke |
| Work/Chat creation, cold list/history/search and uploads | Cwd-free Chat preset authorization, persisted preset classification and mode-filtered search | Native Host create/prompt/restart/page/search and workspace rejection; attachment fixtures |
| Delivery preparation and source aliases | Hook to normalize generated files before native presentation | Delivery containment and producer-contract fixtures |
| Branding/locales, hero layout and stats slot | Product identity/locales/layout hooks | Native renderer smoke; visual acceptance remains manual |
| Protection tones | Structured warning tone for stale/unread filesystem guards | Native ToolRow 11-case regression |
| Desktop port/network readiness/web fetch | Product-owned launch/network policy seam | Native Host auth/shutdown and PAC/local-access fixtures |
| Update channel/version policy | Product-selected feed channel and release identity | Native updater tests and real HTTP Range reconstruction |
| External client bundling | Supported native module-table builder for external manifests | Native adapter/model/subscriptions builds |
| Native DeepViewer composition | Application-owned native-module composition and diagnostic disable hook | Host inventory/RPC/recovery, source contracts and staged manifest fixtures |

No contract changes the Agent loop. Native slots and services own sidebar state; DeepViewer owns only the added editor state and product mode selection. Editor saves reject stale content and retain typing made while a save is in flight. Git stage/unstage accepts one selected changed file and only discovered repositories inside the Session workspace.

## Data and recovery

Stable DeepViewer and DeepViewer Dev keep their existing independent roots. Explicit `DEEPVIEWER_DEV_USER_DATA` creates an isolated test profile. Scoder, Saidex and official DSH are not migration sources. Before the new kernel opens durable stores, DeepViewer snapshots its own home into private `migration-backups/kernel-v020` with SHA-256 verification; node_modules, locks and caches are excluded. Incomplete copies are never declared complete. `restoreKernelSnapshot(home, destination)` restores to a new separate home and refuses existing destinations, preserving newer sessions.

Profile conversion backs up metadata before removing retired bundles. The native-module checkpoint uses private `migration-backups/builtins-v1` metadata and keeps its previous migration journal. It removes the three modules' old dependency and bundle declarations, prunes their root lockfile entries and removes only unchanged application-owned links. Provider configuration and prior explicit disable selections become native row overrides. Completion follows successful writes; retry reads the backed-up selection. `rollbackDesktopProfile` restores the previous metadata/journal and owned links without touching accounts or sessions.

Official recovery disables external plugins while DeepViewer's native modules remain available. `DEEPVIEWER_DISABLE_BUILTINS=1` temporarily starts pure native core and wins over explicit enable overrides. Existing subscriptions/model disable flags remain supported; those individual switches persist row disable overrides. Re-enable by removing the diagnostic flag and the relevant `disabled: true` override in the desktop profile, rather than through Plugins. Frontend migration reads only recorded localhost origins from DeepViewer's own logs, backs up allowlisted drafts/view state and imports missing values into `dsh-app://app/`. It does not import browser credentials or overwrite new-origin drafts.

## Distribution and update qualification

The local update harness verifies consecutive/skipped releases, differential byte ranges, missing cache/no-Range/corrupt-blockmap fallback, SHA-512 rejection and HTTP failures. It does not invoke installation. Native task/Host shutdown coordination is retained. No signed application modules are overwritten in place.

`package-native.mjs --release` requires explicit signing identity/team/keychain notary profile, signs the native runtime, seals its inventory, checks the actual ASAR and notarizes the app and DMG. It builds ZIP/blockmap as the update transport and DMG for installation/recovery; it never publishes. Signed installation, data preservation and relaunch must still be qualified on real macOS installations before publication.

The signed output directory's `qualification.json` must bind the feed channel/version and ZIP SHA-512, with schemaVersion 1 and all scenarios true: `consecutive`, `skipped`, `fullDownload`, `differentialFallback`, `busyTaskDeferral`, `signedInstall`, `userDataPreserved`, `relaunch`. This is a release evidence record, not a substitute for running those scenarios. `publish-native-update.mjs --publish` rejects missing/stale qualification, verifies the ZIP's actual signed product/version, requires an intentionally provisioned channel Release, uploads immutable ZIP/blockmaps without replacement, and uploads the mutable feed last.

Stable uses `updates-stable/latest-mac.yml`; preview uses `updates-preview/preview-mac.yml`, with independent updater caches. Public releases increment semver; internal Build changes alone are not public update versions. This milestone has not published those endpoints.
21 changes: 21 additions & 0 deletions apps/deepviewer-adapter/UPSTREAM-LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 DeepSeek

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
6 changes: 6 additions & 0 deletions apps/deepviewer-adapter/assets/deepviewer-loading-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions apps/deepviewer-adapter/assets/fonts/NOTICE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Smiley Sans (得意黑) 2.0.1 — atelierAnchor
https://github.com/atelier-anchor/smiley-sans
Unmodified release asset: SmileySans-Oblique.ttf.woff2 (stored as SmileySans-Oblique.woff2).
License: SIL Open Font License 1.1; see OFL-SmileySans.txt in this directory.
Loading
Loading