@foggy-projects/deepseek-harness-plugin 0.4.0-beta.7 → 0.4.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -6
- package/THIRD-PARTY-RUNTIME-NOTICES.md +16 -0
- package/docs/PUBLIC-BETA-READINESS.md +53 -0
- package/docs/WINDOWS-BETA-ACCEPTANCE.md +70 -0
- package/experience/linux/README.md +5 -6
- package/experience/linux/prepare.sh +7 -9
- package/lib/atomic-json.js +41 -0
- package/lib/client.js +25 -4
- package/lib/index.js +93 -29
- package/lib/python-runtime.js +339 -0
- package/lib/remote-descriptor.js +1 -0
- package/lib/version.js +5 -0
- package/package.json +6 -3
- package/skills/foggy-deepseek-onboarding/SKILL.md +9 -3
- package/skills/foggy-deepseek-onboarding/assets/versions.json +46 -2
- package/skills/foggy-deepseek-onboarding/scripts/doctor.ps1 +2 -2
- package/skills/foggy-deepseek-onboarding/scripts/doctor.sh +1 -2
- package/skills/foggy-deepseek-onboarding/scripts/install.ps1 +2 -2
- package/skills/foggy-deepseek-onboarding/scripts/install.sh +1 -2
- package/skills/foggy-deepseek-onboarding/scripts/invoke-onboarding.ps1 +30 -0
- package/skills/foggy-deepseek-onboarding/scripts/invoke-onboarding.sh +24 -0
- package/skills/foggy-deepseek-onboarding/scripts/onboard.ps1 +2 -2
- package/skills/foggy-deepseek-onboarding/scripts/onboard.sh +1 -2
- package/skills/foggy-deepseek-onboarding/scripts/onboarding.py +59 -25
- package/skills/foggy-deepseek-onboarding/scripts/runtime-start.ps1 +2 -2
- package/skills/foggy-deepseek-onboarding/scripts/runtime-start.sh +1 -2
- package/skills/foggy-deepseek-onboarding/scripts/runtime-stop.ps1 +2 -2
- package/skills/foggy-deepseek-onboarding/scripts/runtime-stop.sh +1 -2
- package/skills/foggy-deepseek-onboarding/scripts/uninstall.ps1 +2 -2
- package/skills/foggy-deepseek-onboarding/scripts/uninstall.sh +1 -2
package/README.md
CHANGED
|
@@ -2,13 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
This package is the lightweight DeepSeek Harness Bundle for Foggy's Java data
|
|
4
4
|
analysis engine. Installing the Bundle adds a native Foggy tab under **Settings
|
|
5
|
-
→ Plugins**. The
|
|
6
|
-
only when the user selects **Initialize Foggy**.
|
|
5
|
+
→ Plugins**. The private Python runtime, Launcher, and isolated CLI environment
|
|
6
|
+
are downloaded only when the user selects **Initialize Foggy**.
|
|
7
|
+
|
|
8
|
+
DeepSeek Harness uses a system Node.js (`^22.19.0 || >=24.0.0`) and Foggy's Java
|
|
9
|
+
Launcher uses a system Java 17+. Foggy manages its own pinned Python 3.12 runtime
|
|
10
|
+
inside the per-user component directory; it does not require a system Python,
|
|
11
|
+
modify `PATH`, or register Python globally. Advanced users may explicitly set
|
|
12
|
+
`FOGGY_PYTHON` to a compatible Python 3.11+ executable.
|
|
7
13
|
|
|
8
14
|
## Local beta installation
|
|
9
15
|
|
|
10
16
|
```powershell
|
|
11
|
-
dsh plugin --profile web add --workspace-root ./foggy-projects-deepseek-harness-plugin-0.4.0-beta.
|
|
17
|
+
dsh plugin --profile web add --workspace-root ./foggy-projects-deepseek-harness-plugin-0.4.0-beta.9.tgz
|
|
12
18
|
```
|
|
13
19
|
|
|
14
20
|
Restart `dsh web`, open Settings → Plugins → Foggy Data Analysis, and initialize
|
|
@@ -44,8 +50,8 @@ persistent store. A completed profile can also be bound non-destructively to an
|
|
|
44
50
|
additional DSH workspace when its reviewed connection contract and published
|
|
45
51
|
semantic digest are unchanged.
|
|
46
52
|
|
|
47
|
-
CLI, Launcher, the analysis Skill, install state, and Runtime
|
|
48
|
-
user-level Foggy component directories. The managed CLI is intentionally isolated
|
|
53
|
+
Private Python, CLI, Launcher, the analysis Skill, install state, and Runtime
|
|
54
|
+
state live in the user-level Foggy component directories. The managed CLI is intentionally isolated
|
|
49
55
|
and does not need to be on `PATH`. **Re-download / Repair** verifies the global
|
|
50
56
|
analysis Skill, backs up modified or outdated managed content, restores it, and
|
|
51
57
|
invalidates DSH's Skill catalog. The onboarding Skill is bundled with the plugin
|
|
@@ -53,7 +59,7 @@ and is restored by reinstalling or upgrading the plugin package.
|
|
|
53
59
|
|
|
54
60
|
The Foggy settings tab shows the persisted database/semantic onboarding stages,
|
|
55
61
|
offers pinned checks and repair for CLI, Launcher, and the managed analysis
|
|
56
|
-
Skill, and exports a private redacted diagnostics report. Runtime start is
|
|
62
|
+
Skill, private Python, and exports a private redacted diagnostics report. Runtime start is
|
|
57
63
|
idempotent: an already-recorded process is verified with `wait-ready` and
|
|
58
64
|
`capabilities` instead of being treated as a failed second start.
|
|
59
65
|
|
|
@@ -63,6 +69,9 @@ a production service.
|
|
|
63
69
|
|
|
64
70
|
See [`docs/PUBLIC-BETA-READINESS.md`](./docs/PUBLIC-BETA-READINESS.md) for the
|
|
65
71
|
tested public Beta scope, release gates, and stable-release blockers.
|
|
72
|
+
Native Windows acceptance instructions are in
|
|
73
|
+
[`docs/WINDOWS-BETA-ACCEPTANCE.md`](./docs/WINDOWS-BETA-ACCEPTANCE.md); database
|
|
74
|
+
credentials intentionally remain outside the public repository.
|
|
66
75
|
|
|
67
76
|
## Linux and WSL2 experience
|
|
68
77
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Third-party runtime notices
|
|
2
|
+
|
|
3
|
+
Foggy for DeepSeek Harness downloads a pinned CPython runtime on first
|
|
4
|
+
initialization. The runtime is not included in the npm package and is installed
|
|
5
|
+
only inside Foggy's per-user component directory.
|
|
6
|
+
|
|
7
|
+
- CPython is provided under the Python Software Foundation License Version 2.
|
|
8
|
+
- Portable distributions are produced by
|
|
9
|
+
[astral-sh/python-build-standalone](https://github.com/astral-sh/python-build-standalone),
|
|
10
|
+
whose build tooling is provided under MPL-2.0.
|
|
11
|
+
- The downloaded distribution contains its own license and attribution files.
|
|
12
|
+
|
|
13
|
+
The exact build release, platform assets, sizes, URLs, and SHA256 digests are
|
|
14
|
+
recorded in `skills/foggy-deepseek-onboarding/assets/versions.json`. Foggy
|
|
15
|
+
verifies the selected digest before extraction and does not add the interpreter
|
|
16
|
+
to `PATH` or register it as a system Python installation.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Public beta readiness: 0.4.0-beta.9
|
|
2
|
+
|
|
3
|
+
Assessment date: 2026-09-04
|
|
4
|
+
|
|
5
|
+
## Verdict
|
|
6
|
+
|
|
7
|
+
`0.4.0-beta.9` is suitable for a scoped public beta on Windows 10/11 x64 and
|
|
8
|
+
Linux/WSL2 x64. It is not a general-availability release.
|
|
9
|
+
|
|
10
|
+
The plugin package stays small and downloads large components only during
|
|
11
|
+
initialization. Node.js and Java remain system prerequisites. Python 3.12.13 is
|
|
12
|
+
installed privately below Foggy's component directory and does not change the
|
|
13
|
+
system PATH, registry, or a user's existing Python installation.
|
|
14
|
+
|
|
15
|
+
## Verified behavior
|
|
16
|
+
|
|
17
|
+
- The npm tarball is about 67 KB compressed and contains no Python or Java
|
|
18
|
+
runtime binary.
|
|
19
|
+
- Managed CPython assets are pinned by URL, byte size, and SHA256 for Windows,
|
|
20
|
+
Linux, and macOS on x64 and arm64.
|
|
21
|
+
- Windows x64 completed a cold Python download, checksum verification,
|
|
22
|
+
extraction, initialization, forced Python repair, and doctor run.
|
|
23
|
+
- Linux/WSL2 x64 completed managed Python extraction, initialization, and a live
|
|
24
|
+
DeepSeek Harness `0.1.1-rc.2` UI status check.
|
|
25
|
+
- The UI reported Python 3.12.13 as `Foggy private`, and CLI 0.1.23, Launcher
|
|
26
|
+
0.1.18, analysis Skill 0.1.17, and onboarding Skill 0.4.0-beta.9 as installed.
|
|
27
|
+
- Interrupted downloads resume with HTTP Range when the server supports it;
|
|
28
|
+
downloaded artifacts are not trusted until the complete SHA256 matches.
|
|
29
|
+
- Windows progress writes tolerate transient sharing violations without losing
|
|
30
|
+
the previous valid progress document or leaving temporary files behind.
|
|
31
|
+
- Automated regression passed under Node 22.23.2: 17 Node tests and 10 Python
|
|
32
|
+
tests, plus shell and PowerShell syntax checks.
|
|
33
|
+
|
|
34
|
+
## Beta boundaries
|
|
35
|
+
|
|
36
|
+
- Supported public-beta targets: Windows 10/11 x64 and Linux/WSL2 x64.
|
|
37
|
+
- Windows users must install a supported system Node.js line (`^22.19.0` or
|
|
38
|
+
`>=24.0.0`) and Java 17 or later. They do not need to install Python.
|
|
39
|
+
- macOS and arm64 assets are pinned and integrity-checked but have not received
|
|
40
|
+
the same end-to-end host validation; treat those targets as experimental.
|
|
41
|
+
- DeepSeek Harness itself is still consumed at `0.1.1-rc.2`, so its plugin
|
|
42
|
+
installation and supply-chain policy behavior may change before a stable
|
|
43
|
+
Harness release.
|
|
44
|
+
- Runtime production authentication is outside this beta's default local
|
|
45
|
+
onboarding mode. The UI and doctor continue to report `productionReady=false`
|
|
46
|
+
for the development-only no-auth mode.
|
|
47
|
+
|
|
48
|
+
## Release gate after publication
|
|
49
|
+
|
|
50
|
+
Before broad announcement, complete the native Windows fresh-machine checklist
|
|
51
|
+
in [WINDOWS-BETA-ACCEPTANCE.md](./WINDOWS-BETA-ACCEPTANCE.md). Record the exact
|
|
52
|
+
Node, Java, DeepSeek Harness, and plugin versions and confirm that initialization
|
|
53
|
+
works without a system Python executable.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Native Windows Beta acceptance
|
|
2
|
+
|
|
3
|
+
This runbook validates DeepSeek Harness `0.1.1-rc.2` with Foggy plugin
|
|
4
|
+
`0.4.0-beta.9` on a clean 64-bit Windows 10 or Windows 11 machine. Use a local
|
|
5
|
+
directory that is not synchronized by OneDrive.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
Install a system Node.js matching `^22.19.0 || >=24.0.0` and a system Java 17+
|
|
10
|
+
JRE/JDK. Windows must also provide `tar` (included in supported Windows 10/11
|
|
11
|
+
versions). A system Python is neither required nor used by default.
|
|
12
|
+
|
|
13
|
+
```powershell
|
|
14
|
+
node --version
|
|
15
|
+
npm --version
|
|
16
|
+
java -version
|
|
17
|
+
tar --version
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Foggy downloads a pinned private CPython 3.12.13 runtime during initialization.
|
|
21
|
+
It remains below `%LOCALAPPDATA%\Foggy\DeepSeekHarness`, is not added to `PATH`,
|
|
22
|
+
and is not registered as a system Python.
|
|
23
|
+
|
|
24
|
+
## Install and start
|
|
25
|
+
|
|
26
|
+
```powershell
|
|
27
|
+
New-Item -ItemType Directory -Force C:\FoggyAcceptance | Out-Null
|
|
28
|
+
Set-Location C:\FoggyAcceptance
|
|
29
|
+
|
|
30
|
+
npx --yes --package=@deepseek-ai/dsh@0.1.1-rc.2 --package=pnpm@11.7.0 `
|
|
31
|
+
dsh plugin --profile web add --workspace-root `
|
|
32
|
+
"@foggy-projects/deepseek-harness-plugin@beta"
|
|
33
|
+
|
|
34
|
+
npx --yes --package=@deepseek-ai/dsh@0.1.1-rc.2 --package=pnpm@11.7.0 dsh web
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Open `http://127.0.0.1:3080/`, configure an LLM provider, select the
|
|
38
|
+
`C:\FoggyAcceptance` workspace, then open **Settings → Plugins → Foggy Data
|
|
39
|
+
Analysis** and choose **Initialize Foggy**.
|
|
40
|
+
|
|
41
|
+
Expected component state:
|
|
42
|
+
|
|
43
|
+
- Python 3.12.13, source `Foggy private`;
|
|
44
|
+
- CLI 0.1.23;
|
|
45
|
+
- Launcher 0.1.18;
|
|
46
|
+
- analysis Skill 0.1.17;
|
|
47
|
+
- onboarding Skill 0.4.0-beta.9;
|
|
48
|
+
- Java 17+ available;
|
|
49
|
+
- native DSH Skill registration available.
|
|
50
|
+
|
|
51
|
+
## Database and semantic-layer acceptance
|
|
52
|
+
|
|
53
|
+
Keep database credentials out of this public repository. Create a private CLI
|
|
54
|
+
profile outside the DSH conversation, pass only its opaque profile ID and
|
|
55
|
+
revision to the onboarding workflow, and use a test-only database account with
|
|
56
|
+
read-only permissions.
|
|
57
|
+
|
|
58
|
+
Use a natural prompt such as:
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
请帮我用 Foggy 分析这个测试数据库。我已经按验收手册创建了私有连接
|
|
62
|
+
profile。请先确认连接和表结构,再围绕订单数据创建一个简单的语义层,
|
|
63
|
+
包含订单数量、状态和开单时间,最后执行一个不超过 20 行的只读查询。
|
|
64
|
+
不要修改数据库,也不要在对话或验收文件中输出密码。
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Pass only when Runtime readiness and capabilities succeed, datasource metadata
|
|
68
|
+
can be discovered, TM/QM models validate and publish, the bounded read-only
|
|
69
|
+
query succeeds, diagnostics contain no credentials, and stopping Runtime frees
|
|
70
|
+
port 18066.
|
|
@@ -5,14 +5,13 @@ It has been designed for Ubuntu 22.04/24.04 x86_64 and WSL2.
|
|
|
5
5
|
|
|
6
6
|
## Prerequisites
|
|
7
7
|
|
|
8
|
-
- Node.js 22.19 or
|
|
9
|
-
- Python 3.11 or newer with `venv`
|
|
8
|
+
- Node.js `^22.19.0` or `>=24.0.0`
|
|
10
9
|
- Java 17 or newer
|
|
11
|
-
- Git and
|
|
10
|
+
- Git, npm, and `tar`
|
|
12
11
|
- At least 4 GiB free disk space and 2 GiB available memory; 4 GiB memory is recommended
|
|
13
12
|
|
|
14
13
|
Keep the experience root on the Linux-native filesystem, such as under `$HOME`. In WSL2, do not
|
|
15
|
-
put DSH, `node_modules`,
|
|
14
|
+
put DSH, `node_modules`, Foggy's private Python environment, or Foggy data under `/mnt/c` or `/mnt/d`.
|
|
16
15
|
|
|
17
16
|
## Prepare
|
|
18
17
|
|
|
@@ -35,8 +34,8 @@ Start the prepared profile with:
|
|
|
35
34
|
```
|
|
36
35
|
|
|
37
36
|
Open the URL printed by DSH, then choose **Settings → Plugins → Foggy Data Analysis** and select
|
|
38
|
-
**Initialize Foggy**.
|
|
39
|
-
Releases and verified before installation.
|
|
37
|
+
**Initialize Foggy**. Private Python, the CLI, Launcher, and analysis Skill are downloaded from their
|
|
38
|
+
pinned public Releases and verified before installation. A system Python is not required.
|
|
40
39
|
|
|
41
40
|
Provider configuration remains a separate DSH setup step. Store API keys in a private environment
|
|
42
41
|
file or secret manager; do not add them to the DSH settings document or the project repository.
|
|
@@ -3,7 +3,7 @@ set -euo pipefail
|
|
|
3
3
|
|
|
4
4
|
DSH_VERSION="0.1.1-rc.2"
|
|
5
5
|
PNPM_VERSION="11.7.0"
|
|
6
|
-
PLUGIN_VERSION="0.4.0-beta.
|
|
6
|
+
PLUGIN_VERSION="0.4.0-beta.9"
|
|
7
7
|
PLUGIN_REF="v${PLUGIN_VERSION}"
|
|
8
8
|
PLUGIN_REPOSITORY="https://github.com/foggy-projects/foggy-deepseek-harness-plugin.git"
|
|
9
9
|
|
|
@@ -62,22 +62,19 @@ require_command() {
|
|
|
62
62
|
|
|
63
63
|
[[ "$(uname -s)" == "Linux" ]] || fail "this entry supports Linux and WSL2 only"
|
|
64
64
|
case "$(uname -m)" in
|
|
65
|
-
x86_64|amd64) ;;
|
|
66
|
-
*) fail "
|
|
65
|
+
x86_64|amd64|aarch64|arm64) ;;
|
|
66
|
+
*) fail "supported architectures are x86_64 and arm64; detected $(uname -m)" ;;
|
|
67
67
|
esac
|
|
68
68
|
|
|
69
69
|
require_command node
|
|
70
70
|
require_command npm
|
|
71
|
-
require_command python3
|
|
72
71
|
require_command java
|
|
73
72
|
require_command git
|
|
74
73
|
require_command df
|
|
74
|
+
require_command tar
|
|
75
75
|
|
|
76
|
-
node -e 'const [major, minor] = process.versions.node.split(".").map(Number); if (
|
|
77
|
-
|| fail "Node 22.19
|
|
78
|
-
python3 -c 'import sys; raise SystemExit(0 if sys.version_info >= (3, 11) else 1)' \
|
|
79
|
-
|| fail "Python 3.11+ required; detected $(python3 --version 2>/dev/null || echo unknown)"
|
|
80
|
-
python3 -m venv --help >/dev/null 2>&1 || fail "Python venv support is required"
|
|
76
|
+
node -e 'const [major, minor] = process.versions.node.split(".").map(Number); if (!((major === 22 && minor >= 19) || major >= 24)) process.exit(1)' \
|
|
77
|
+
|| fail "Node ^22.19.0 or >=24 required; detected $(node --version 2>/dev/null || echo unknown)"
|
|
81
78
|
|
|
82
79
|
java_major="$(java -version 2>&1 | awk -F'[\".]' '/version/ { print $2; exit }')"
|
|
83
80
|
[[ "$java_major" =~ ^[0-9]+$ ]] || fail "could not detect Java version"
|
|
@@ -121,6 +118,7 @@ Foggy Linux experience plan
|
|
|
121
118
|
DSH: $DSH_VERSION
|
|
122
119
|
pnpm: $PNPM_VERSION
|
|
123
120
|
Foggy Bundle: $PLUGIN_VERSION
|
|
121
|
+
Python: private managed 3.12.13 (downloaded during Foggy initialization)
|
|
124
122
|
Experience root: $experience_root
|
|
125
123
|
Project root: $project_root
|
|
126
124
|
Filesystem: Linux-native
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import { mkdir, rename, rm, writeFile } from 'node:fs/promises'
|
|
3
|
+
import { dirname } from 'node:path'
|
|
4
|
+
|
|
5
|
+
const TRANSIENT_REPLACE_CODES = new Set(['EACCES', 'EBUSY', 'EPERM'])
|
|
6
|
+
const TRANSIENT_WINERRORS = new Set([5, 32, 33])
|
|
7
|
+
|
|
8
|
+
function wait(milliseconds) {
|
|
9
|
+
return new Promise((resolve) => setTimeout(resolve, milliseconds))
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function transientReplaceError(error) {
|
|
13
|
+
return TRANSIENT_REPLACE_CODES.has(error?.code) || TRANSIENT_WINERRORS.has(error?.winerror)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function replaceWithRetry(source, destination, {
|
|
17
|
+
replace = rename,
|
|
18
|
+
sleep = wait,
|
|
19
|
+
attempts = 12,
|
|
20
|
+
} = {}) {
|
|
21
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
22
|
+
try {
|
|
23
|
+
await replace(source, destination)
|
|
24
|
+
return
|
|
25
|
+
} catch (error) {
|
|
26
|
+
if (!transientReplaceError(error) || attempt === attempts - 1) throw error
|
|
27
|
+
await sleep(Math.min(25 * (2 ** attempt), 400))
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function writeJsonAtomic(path, payload, options = {}) {
|
|
33
|
+
await mkdir(dirname(path), { recursive: true })
|
|
34
|
+
const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`
|
|
35
|
+
try {
|
|
36
|
+
await writeFile(temporary, `${JSON.stringify(payload, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 })
|
|
37
|
+
await replaceWithRetry(temporary, path, options)
|
|
38
|
+
} finally {
|
|
39
|
+
await rm(temporary, { force: true })
|
|
40
|
+
}
|
|
41
|
+
}
|
package/lib/client.js
CHANGED
|
@@ -11,7 +11,7 @@ window.__ModuleLoader__.load({
|
|
|
11
11
|
const TYPERT_REMOTE = {
|
|
12
12
|
package: '@foggy-projects/deepseek-harness-plugin',
|
|
13
13
|
descriptors: [
|
|
14
|
-
'status', 'plan', 'initialize', 'repair', 'repairCli', 'repairLauncher', 'repairAnalysisSkill',
|
|
14
|
+
'status', 'plan', 'initialize', 'repair', 'repairPython', 'repairCli', 'repairLauncher', 'repairAnalysisSkill',
|
|
15
15
|
'migrateProfiles', 'diagnostics', 'runtimeStart', 'runtimeStop',
|
|
16
16
|
].map((method) => ({
|
|
17
17
|
id: `@foggy-projects/deepseek-harness-plugin#foggyIntegration/${method}`,
|
|
@@ -32,7 +32,7 @@ window.__ModuleLoader__.load({
|
|
|
32
32
|
const zh = {
|
|
33
33
|
tab: 'Foggy 数据分析',
|
|
34
34
|
title: 'Foggy Java 数据分析引擎',
|
|
35
|
-
intro: '在 DeepSeek Harness 内管理 Foggy CLI、Launcher、Skills 和本地 Runtime。大型组件在首次初始化时按需下载。',
|
|
35
|
+
intro: '在 DeepSeek Harness 内管理 Foggy 私有 Python、CLI、Launcher、Skills 和本地 Runtime。大型组件在首次初始化时按需下载。',
|
|
36
36
|
refresh: '刷新状态',
|
|
37
37
|
loading: '正在读取 Foggy 状态…',
|
|
38
38
|
failed: '暂时无法读取 Foggy 状态。',
|
|
@@ -55,6 +55,7 @@ window.__ModuleLoader__.load({
|
|
|
55
55
|
initialize: '初始化 Foggy',
|
|
56
56
|
repair: '重新下载 / 修复',
|
|
57
57
|
repairTitle: '分组件检查与修复',
|
|
58
|
+
repairPython: '检查 / 修复私有 Python',
|
|
58
59
|
repairCli: '检查 / 修复 CLI',
|
|
59
60
|
repairLauncher: '检查 / 修复 Launcher',
|
|
60
61
|
repairAnalysisSkill: '检查 / 修复分析 Skill',
|
|
@@ -65,6 +66,7 @@ window.__ModuleLoader__.load({
|
|
|
65
66
|
working: '操作进行中…',
|
|
66
67
|
progressWorking: '正在初始化 Foggy…',
|
|
67
68
|
progressPreflight: '检查运行环境',
|
|
69
|
+
progressPython: '准备私有 Python',
|
|
68
70
|
progressCli: '准备 CLI',
|
|
69
71
|
progressLauncher: '准备 Launcher',
|
|
70
72
|
progressAnalysis: '准备分析 Skill',
|
|
@@ -72,6 +74,8 @@ window.__ModuleLoader__.load({
|
|
|
72
74
|
progressState: '写入安装状态',
|
|
73
75
|
progressComplete: '初始化完成',
|
|
74
76
|
progressFiles: '文件',
|
|
77
|
+
managedPrivate: 'Foggy 私有',
|
|
78
|
+
configuredOverride: '外部指定',
|
|
75
79
|
accepted: '操作已开始;页面会自动刷新状态。',
|
|
76
80
|
actionFailed: '操作失败',
|
|
77
81
|
roots: '本地目录',
|
|
@@ -103,7 +107,7 @@ window.__ModuleLoader__.load({
|
|
|
103
107
|
const en = {
|
|
104
108
|
tab: 'Foggy Data Analysis',
|
|
105
109
|
title: 'Foggy Java Data Analysis Engine',
|
|
106
|
-
intro: 'Manage
|
|
110
|
+
intro: 'Manage Foggy private Python, CLI, Launcher, Skills, and the local Runtime inside DeepSeek Harness. Large components are downloaded on first initialization.',
|
|
107
111
|
refresh: 'Refresh status',
|
|
108
112
|
loading: 'Reading Foggy status…',
|
|
109
113
|
failed: 'Foggy status is temporarily unavailable.',
|
|
@@ -126,6 +130,7 @@ window.__ModuleLoader__.load({
|
|
|
126
130
|
initialize: 'Initialize Foggy',
|
|
127
131
|
repair: 'Re-download / Repair',
|
|
128
132
|
repairTitle: 'Component checks and repair',
|
|
133
|
+
repairPython: 'Check / repair private Python',
|
|
129
134
|
repairCli: 'Check / repair CLI',
|
|
130
135
|
repairLauncher: 'Check / repair Launcher',
|
|
131
136
|
repairAnalysisSkill: 'Check / repair analysis Skill',
|
|
@@ -136,6 +141,7 @@ window.__ModuleLoader__.load({
|
|
|
136
141
|
working: 'Operation in progress…',
|
|
137
142
|
progressWorking: 'Initializing Foggy…',
|
|
138
143
|
progressPreflight: 'Checking prerequisites',
|
|
144
|
+
progressPython: 'Preparing private Python',
|
|
139
145
|
progressCli: 'Preparing CLI',
|
|
140
146
|
progressLauncher: 'Preparing Launcher',
|
|
141
147
|
progressAnalysis: 'Preparing analysis Skill',
|
|
@@ -143,6 +149,8 @@ window.__ModuleLoader__.load({
|
|
|
143
149
|
progressState: 'Writing install state',
|
|
144
150
|
progressComplete: 'Initialization complete',
|
|
145
151
|
progressFiles: 'files',
|
|
152
|
+
managedPrivate: 'Foggy private',
|
|
153
|
+
configuredOverride: 'Configured override',
|
|
146
154
|
accepted: 'The operation started; this page will refresh automatically.',
|
|
147
155
|
actionFailed: 'Operation failed',
|
|
148
156
|
roots: 'Local directories',
|
|
@@ -204,6 +212,16 @@ window.__ModuleLoader__.load({
|
|
|
204
212
|
const stateText = kind === 'runtime'
|
|
205
213
|
? t(available ? 'installed' : 'missing')
|
|
206
214
|
: t(available ? 'available' : 'unavailable')
|
|
215
|
+
const source = component?.source === 'managed'
|
|
216
|
+
? t('managedPrivate')
|
|
217
|
+
: component?.source === 'override'
|
|
218
|
+
? t('configuredOverride')
|
|
219
|
+
: null
|
|
220
|
+
const detail = [
|
|
221
|
+
component?.version || component?.output || '—',
|
|
222
|
+
component?.minimum ? `≥${component.minimum}` : null,
|
|
223
|
+
source,
|
|
224
|
+
].filter(Boolean).join(' · ')
|
|
207
225
|
return jsxs('div', {
|
|
208
226
|
className: 'foggy-card',
|
|
209
227
|
children: [
|
|
@@ -211,7 +229,8 @@ window.__ModuleLoader__.load({
|
|
|
211
229
|
jsx('strong', { children: label }),
|
|
212
230
|
jsx('span', { className: 'foggy-badge', children: stateText }),
|
|
213
231
|
] }),
|
|
214
|
-
jsx('code', { children:
|
|
232
|
+
jsx('code', { children: detail }),
|
|
233
|
+
component?.path ? jsx('code', { title: component.path, children: component.path }) : null,
|
|
215
234
|
],
|
|
216
235
|
})
|
|
217
236
|
}
|
|
@@ -221,6 +240,7 @@ window.__ModuleLoader__.load({
|
|
|
221
240
|
const percent = Math.max(0, Math.min(100, Number(progress.percent) || 0))
|
|
222
241
|
const phaseKeys = {
|
|
223
242
|
preflight: 'progressPreflight',
|
|
243
|
+
python: 'progressPython',
|
|
224
244
|
cli: 'progressCli',
|
|
225
245
|
launcher: 'progressLauncher',
|
|
226
246
|
'analysis-skill': 'progressAnalysis',
|
|
@@ -376,6 +396,7 @@ window.__ModuleLoader__.load({
|
|
|
376
396
|
jsxs('div', { className: 'foggy-section', children: [
|
|
377
397
|
jsx('h4', { children: t('repairTitle') }),
|
|
378
398
|
jsx('div', { className: 'foggy-section-actions', children: [
|
|
399
|
+
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairPython'), children: t('repairPython') }),
|
|
379
400
|
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairCli'), children: t('repairCli') }),
|
|
380
401
|
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairLauncher'), children: t('repairLauncher') }),
|
|
381
402
|
jsx('button', { className: 'foggy-button', type: 'button', disabled: busy, onClick: () => run('repairAnalysisSkill'), children: t('repairAnalysisSkill') }),
|
package/lib/index.js
CHANGED
|
@@ -6,7 +6,9 @@ import { fileURLToPath } from 'node:url'
|
|
|
6
6
|
import { promisify } from 'node:util'
|
|
7
7
|
import { Remote, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'
|
|
8
8
|
import { createFoggySkillProvider } from './skill-provider.js'
|
|
9
|
-
import {
|
|
9
|
+
import { writeJsonAtomic } from './atomic-json.js'
|
|
10
|
+
import { ensurePythonRuntime, probePythonRuntime } from './python-runtime.js'
|
|
11
|
+
import { compatible, compatibleNode } from './version.js'
|
|
10
12
|
|
|
11
13
|
const execFileAsync = promisify(execFile)
|
|
12
14
|
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)))
|
|
@@ -71,16 +73,6 @@ async function commandVersion(command, args) {
|
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
|
|
74
|
-
async function pythonCommand() {
|
|
75
|
-
const configured = process.env.FOGGY_PYTHON
|
|
76
|
-
const candidates = configured ? [configured] : process.platform === 'win32' ? ['python', 'py'] : ['python3', 'python']
|
|
77
|
-
for (const command of candidates) {
|
|
78
|
-
const probe = await commandVersion(command, ['--version'])
|
|
79
|
-
if (probe.available) return command
|
|
80
|
-
}
|
|
81
|
-
throw new Error('Python 3.11+ was not found; set FOGGY_PYTHON to its executable')
|
|
82
|
-
}
|
|
83
|
-
|
|
84
76
|
function parseOutput(stdout, stderr) {
|
|
85
77
|
const text = String(stdout ?? '').trim()
|
|
86
78
|
if (!text) throw new Error(String(stderr ?? '').trim() || 'Foggy onboarding returned no JSON')
|
|
@@ -91,14 +83,34 @@ function parseOutput(stdout, stderr) {
|
|
|
91
83
|
}
|
|
92
84
|
}
|
|
93
85
|
|
|
94
|
-
async function runOnboarding(args, timeout = 15 * 60_000) {
|
|
95
|
-
const
|
|
86
|
+
async function runOnboarding(args, timeout = 15 * 60_000, options = {}) {
|
|
87
|
+
const roots = defaultRoots()
|
|
88
|
+
const manifest = await readJson(versionsFile)
|
|
89
|
+
const cacheDirs = (process.env.FOGGY_ASSET_CACHE_DIRS || '').split(delimiter).filter(Boolean)
|
|
90
|
+
const python = options.ensurePython
|
|
91
|
+
? await ensurePythonRuntime({
|
|
92
|
+
installRoot: roots.installRoot,
|
|
93
|
+
manifest,
|
|
94
|
+
cacheDirs,
|
|
95
|
+
force: options.forcePython,
|
|
96
|
+
onProgress: options.onPythonProgress,
|
|
97
|
+
})
|
|
98
|
+
: await probePythonRuntime({ installRoot: roots.installRoot, manifest })
|
|
99
|
+
if (!python.available) {
|
|
100
|
+
throw new Error('Foggy managed Python is unavailable; initialize or repair the Python component')
|
|
101
|
+
}
|
|
102
|
+
await options.flushPythonProgress?.()
|
|
96
103
|
try {
|
|
97
|
-
const { stdout, stderr } = await execFileAsync(python, [onboardingScript, ...args], {
|
|
104
|
+
const { stdout, stderr } = await execFileAsync(python.path, [onboardingScript, ...args], {
|
|
98
105
|
windowsHide: true,
|
|
99
106
|
timeout,
|
|
100
107
|
maxBuffer: 4 * 1024 * 1024,
|
|
101
108
|
cwd: process.env.FOGGY_PROJECT_ROOT || process.cwd(),
|
|
109
|
+
env: {
|
|
110
|
+
...process.env,
|
|
111
|
+
FOGGY_ONBOARDING_PYTHON: python.path,
|
|
112
|
+
FOGGY_ONBOARDING_PYTHON_SOURCE: python.source,
|
|
113
|
+
},
|
|
102
114
|
})
|
|
103
115
|
return parseOutput(stdout, stderr)
|
|
104
116
|
} catch (error) {
|
|
@@ -107,6 +119,44 @@ async function runOnboarding(args, timeout = 15 * 60_000) {
|
|
|
107
119
|
}
|
|
108
120
|
}
|
|
109
121
|
|
|
122
|
+
async function assertSystemPrerequisites(kind) {
|
|
123
|
+
if (kind === 'initialize' && !compatibleNode(process.versions.node)) {
|
|
124
|
+
throw new Error(`DeepSeek Harness requires Node.js ^22.19.0 or >=24.0.0; detected ${process.versions.node}`)
|
|
125
|
+
}
|
|
126
|
+
if (kind === 'initialize' || kind === 'runtime-start') {
|
|
127
|
+
const java = compatible(await commandVersion(process.env.JAVA_EXE || 'java', ['-version']), '17.0')
|
|
128
|
+
if (!java.available) throw new Error('Java 17+ is required; install a system JRE/JDK or set JAVA_EXE')
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function createPythonProgressReporter(operation, path) {
|
|
133
|
+
let pending = Promise.resolve()
|
|
134
|
+
return {
|
|
135
|
+
update(detail) {
|
|
136
|
+
const fraction = Math.max(0, Math.min(1, Number(detail.fraction) || 0))
|
|
137
|
+
const payload = {
|
|
138
|
+
schemaVersion: 'foggy-deepseek-onboarding-progress/v1',
|
|
139
|
+
operationId: operation.id,
|
|
140
|
+
kind: operation.kind,
|
|
141
|
+
state: 'running',
|
|
142
|
+
phase: 'python',
|
|
143
|
+
message: detail.message || 'Preparing managed Python',
|
|
144
|
+
currentFile: detail.currentFile || null,
|
|
145
|
+
percent: Math.round(((1 + fraction) / 7) * 100),
|
|
146
|
+
step: { index: 2, total: 7 },
|
|
147
|
+
startedAt: operation.startedAt,
|
|
148
|
+
updatedAt: new Date().toISOString(),
|
|
149
|
+
}
|
|
150
|
+
if (detail.bytes) payload.bytes = detail.bytes
|
|
151
|
+
operation.progress = payload
|
|
152
|
+
pending = pending.then(() => writeJsonAtomic(path, payload))
|
|
153
|
+
},
|
|
154
|
+
flush() {
|
|
155
|
+
return pending
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
110
160
|
function processRunning(pid) {
|
|
111
161
|
if (!Number.isInteger(pid) || pid <= 0) return false
|
|
112
162
|
try {
|
|
@@ -145,13 +195,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
145
195
|
const runtimeStatePath = join(roots.dataRoot, 'runtime-state.json')
|
|
146
196
|
const progressPath = join(roots.dataRoot, 'operation-progress.json')
|
|
147
197
|
const manifest = await readJson(versionsFile)
|
|
148
|
-
|
|
149
|
-
try {
|
|
150
|
-
pythonProbe = await commandVersion(await pythonCommand(), ['--version'])
|
|
151
|
-
} catch (error) {
|
|
152
|
-
pythonProbe = { available: false, output: '', error: String(error.message ?? error) }
|
|
153
|
-
}
|
|
154
|
-
const python = compatible(pythonProbe, '3.11')
|
|
198
|
+
const python = await probePythonRuntime({ installRoot: roots.installRoot, manifest })
|
|
155
199
|
const java = compatible(await commandVersion(process.env.JAVA_EXE || 'java', ['-version']), '17.0')
|
|
156
200
|
let state = null
|
|
157
201
|
let runtime = null
|
|
@@ -197,7 +241,8 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
197
241
|
provider: 'foggy-managed-skills',
|
|
198
242
|
},
|
|
199
243
|
}
|
|
200
|
-
const installed = components.
|
|
244
|
+
const installed = components.python.available
|
|
245
|
+
&& components.cli.installed
|
|
201
246
|
&& components.launcher.installed
|
|
202
247
|
&& components.analysisSkill.installed
|
|
203
248
|
&& components.onboardingSkill.installed
|
|
@@ -243,6 +288,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
243
288
|
workspaceMode: 'dsh-session-cwd',
|
|
244
289
|
versions: Object.fromEntries(Object.entries(manifest.components).map(([name, value]) => [name, value.version])),
|
|
245
290
|
operations: [
|
|
291
|
+
'download and verify a pinned private Python runtime',
|
|
246
292
|
'create isolated Python environment',
|
|
247
293
|
'download and verify pinned CLI and Launcher assets',
|
|
248
294
|
'install the Foggy analysis Skill into the global managed component directory',
|
|
@@ -265,6 +311,10 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
265
311
|
return this.startOperation('repair-cli', false, ['install', '--repair-component', 'cli'])
|
|
266
312
|
}
|
|
267
313
|
|
|
314
|
+
async repairPython() {
|
|
315
|
+
return this.startOperation('repair-python', false, ['install'])
|
|
316
|
+
}
|
|
317
|
+
|
|
268
318
|
async repairLauncher() {
|
|
269
319
|
return this.startOperation('repair-launcher', false, ['install', '--repair-component', 'launcher'])
|
|
270
320
|
}
|
|
@@ -279,10 +329,13 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
279
329
|
|
|
280
330
|
async diagnostics() {
|
|
281
331
|
const roots = defaultRoots()
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
332
|
+
const status = await this.status()
|
|
333
|
+
let doctor
|
|
334
|
+
try {
|
|
335
|
+
doctor = await runOnboarding(['doctor', '--no-fail'])
|
|
336
|
+
} catch (error) {
|
|
337
|
+
doctor = { success: false, error: String(error.message ?? error), bootstrapOnly: true }
|
|
338
|
+
}
|
|
286
339
|
const report = {
|
|
287
340
|
schemaVersion: 'foggy-deepseek-diagnostics/v1',
|
|
288
341
|
generatedAt: new Date().toISOString(),
|
|
@@ -344,11 +397,22 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
344
397
|
message: 'Starting Foggy initialization',
|
|
345
398
|
currentFile: null,
|
|
346
399
|
percent: 0,
|
|
347
|
-
step: { index: 1, total:
|
|
400
|
+
step: { index: 1, total: 7 },
|
|
348
401
|
} : null,
|
|
349
402
|
promise: null,
|
|
350
403
|
}
|
|
351
|
-
|
|
404
|
+
const pythonProgress = reportsProgress
|
|
405
|
+
? createPythonProgressReporter(operation, join(defaultRoots().dataRoot, 'operation-progress.json'))
|
|
406
|
+
: null
|
|
407
|
+
operation.promise = (async () => {
|
|
408
|
+
await assertSystemPrerequisites(kind)
|
|
409
|
+
return runOnboarding(args, 15 * 60_000, {
|
|
410
|
+
ensurePython: true,
|
|
411
|
+
forcePython: kind === 'repair-python',
|
|
412
|
+
onPythonProgress: (detail) => pythonProgress?.update(detail),
|
|
413
|
+
flushPythonProgress: () => pythonProgress?.flush(),
|
|
414
|
+
})
|
|
415
|
+
})()
|
|
352
416
|
.then((result) => {
|
|
353
417
|
operation.state = result.success === false ? 'failed' : 'succeeded'
|
|
354
418
|
operation.result = result
|
|
@@ -384,7 +448,7 @@ export class FoggyIntegrationGateway extends TypertRemoteService {
|
|
|
384
448
|
|
|
385
449
|
const markerInitializers = []
|
|
386
450
|
for (const method of [
|
|
387
|
-
'status', 'plan', 'initialize', 'repair', 'repairCli', 'repairLauncher', 'repairAnalysisSkill',
|
|
451
|
+
'status', 'plan', 'initialize', 'repair', 'repairPython', 'repairCli', 'repairLauncher', 'repairAnalysisSkill',
|
|
388
452
|
'migrateProfiles', 'diagnostics', 'runtimeStart', 'runtimeStop',
|
|
389
453
|
]) {
|
|
390
454
|
Remote(method)(FoggyIntegrationGateway.prototype[method], {
|