@foggy-projects/deepseek-harness-plugin 0.4.0-beta.8 → 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 +1 -1
- package/docs/PUBLIC-BETA-READINESS.md +7 -5
- package/docs/WINDOWS-BETA-ACCEPTANCE.md +2 -3
- package/experience/linux/prepare.sh +1 -1
- package/lib/atomic-json.js +41 -0
- package/lib/index.js +2 -8
- package/package.json +2 -2
- package/skills/foggy-deepseek-onboarding/assets/versions.json +1 -1
- package/skills/foggy-deepseek-onboarding/scripts/onboarding.py +32 -3
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ modify `PATH`, or register Python globally. Advanced users may explicitly set
|
|
|
14
14
|
## Local beta installation
|
|
15
15
|
|
|
16
16
|
```powershell
|
|
17
|
-
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
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
Restart `dsh web`, open Settings → Plugins → Foggy Data Analysis, and initialize
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Public beta readiness: 0.4.0-beta.
|
|
1
|
+
# Public beta readiness: 0.4.0-beta.9
|
|
2
2
|
|
|
3
|
-
Assessment date: 2026-09-
|
|
3
|
+
Assessment date: 2026-09-04
|
|
4
4
|
|
|
5
5
|
## Verdict
|
|
6
6
|
|
|
7
|
-
`0.4.0-beta.
|
|
7
|
+
`0.4.0-beta.9` is suitable for a scoped public beta on Windows 10/11 x64 and
|
|
8
8
|
Linux/WSL2 x64. It is not a general-availability release.
|
|
9
9
|
|
|
10
10
|
The plugin package stays small and downloads large components only during
|
|
@@ -23,10 +23,12 @@ system PATH, registry, or a user's existing Python installation.
|
|
|
23
23
|
- Linux/WSL2 x64 completed managed Python extraction, initialization, and a live
|
|
24
24
|
DeepSeek Harness `0.1.1-rc.2` UI status check.
|
|
25
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.
|
|
26
|
+
0.1.18, analysis Skill 0.1.17, and onboarding Skill 0.4.0-beta.9 as installed.
|
|
27
27
|
- Interrupted downloads resume with HTTP Range when the server supports it;
|
|
28
28
|
downloaded artifacts are not trusted until the complete SHA256 matches.
|
|
29
|
-
-
|
|
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
|
|
30
32
|
tests, plus shell and PowerShell syntax checks.
|
|
31
33
|
|
|
32
34
|
## Beta boundaries
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Native Windows Beta acceptance
|
|
2
2
|
|
|
3
3
|
This runbook validates DeepSeek Harness `0.1.1-rc.2` with Foggy plugin
|
|
4
|
-
`0.4.0-beta.
|
|
4
|
+
`0.4.0-beta.9` on a clean 64-bit Windows 10 or Windows 11 machine. Use a local
|
|
5
5
|
directory that is not synchronized by OneDrive.
|
|
6
6
|
|
|
7
7
|
## Prerequisites
|
|
@@ -44,7 +44,7 @@ Expected component state:
|
|
|
44
44
|
- CLI 0.1.23;
|
|
45
45
|
- Launcher 0.1.18;
|
|
46
46
|
- analysis Skill 0.1.17;
|
|
47
|
-
- onboarding Skill 0.4.0-beta.
|
|
47
|
+
- onboarding Skill 0.4.0-beta.9;
|
|
48
48
|
- Java 17+ available;
|
|
49
49
|
- native DSH Skill registration available.
|
|
50
50
|
|
|
@@ -68,4 +68,3 @@ Pass only when Runtime readiness and capabilities succeed, datasource metadata
|
|
|
68
68
|
can be discovered, TM/QM models validate and publish, the bounded read-only
|
|
69
69
|
query succeeds, diagnostics contain no credentials, and stopping Runtime frees
|
|
70
70
|
port 18066.
|
|
71
|
-
|
|
@@ -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/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process'
|
|
2
|
-
import { access, mkdir, readFile,
|
|
2
|
+
import { access, mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
3
3
|
import { constants as fsConstants } from 'node:fs'
|
|
4
4
|
import { dirname, join, delimiter } from 'node:path'
|
|
5
5
|
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 { writeJsonAtomic } from './atomic-json.js'
|
|
9
10
|
import { ensurePythonRuntime, probePythonRuntime } from './python-runtime.js'
|
|
10
11
|
import { compatible, compatibleNode } from './version.js'
|
|
11
12
|
|
|
@@ -128,13 +129,6 @@ async function assertSystemPrerequisites(kind) {
|
|
|
128
129
|
}
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
async function writeJsonAtomic(path, payload) {
|
|
132
|
-
await mkdir(dirname(path), { recursive: true })
|
|
133
|
-
const temporary = `${path}.${process.pid}.${Date.now()}.tmp`
|
|
134
|
-
await writeFile(temporary, `${JSON.stringify(payload, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 })
|
|
135
|
-
await rename(temporary, path)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
132
|
function createPythonProgressReporter(operation, path) {
|
|
139
133
|
let pending = Promise.resolve()
|
|
140
134
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foggy-projects/deepseek-harness-plugin",
|
|
3
|
-
"version": "0.4.0-beta.
|
|
3
|
+
"version": "0.4.0-beta.9",
|
|
4
4
|
"description": "Foggy Java data analysis engine integration for DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@deepseek-ai/dsh-typert-protocol": "^0.1.1-rc.2"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
60
|
-
"check": "node --check lib/index.js && node --check lib/python-runtime.js && node --check lib/skill-provider.js && node --check lib/client.js && node --check lib/typert.js && node --check lib/remote.js",
|
|
60
|
+
"check": "node --check lib/index.js && node --check lib/atomic-json.js && node --check lib/python-runtime.js && node --check lib/skill-provider.js && node --check lib/client.js && node --check lib/typert.js && node --check lib/remote.js",
|
|
61
61
|
"test": "node --test test/package.test.js && python test/onboarding_unit.py"
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
|
|
6
6
|
import argparse
|
|
7
7
|
import datetime as dt
|
|
8
|
+
import errno
|
|
8
9
|
import hashlib
|
|
9
10
|
import json
|
|
10
11
|
import os
|
|
@@ -337,11 +338,39 @@ def venv_cli(install_root: Path) -> Path:
|
|
|
337
338
|
return install_root / "venv" / ("Scripts/foggy-runtime.exe" if os.name == "nt" else "bin/foggy-runtime")
|
|
338
339
|
|
|
339
340
|
|
|
341
|
+
def replace_with_retry(source: Path, destination: Path, attempts: int = 12) -> None:
|
|
342
|
+
transient_errno = {errno.EACCES, errno.EBUSY, errno.EPERM}
|
|
343
|
+
transient_winerror = {5, 32, 33}
|
|
344
|
+
for attempt in range(attempts):
|
|
345
|
+
try:
|
|
346
|
+
os.replace(source, destination)
|
|
347
|
+
return
|
|
348
|
+
except OSError as exc:
|
|
349
|
+
transient = exc.errno in transient_errno or getattr(exc, "winerror", None) in transient_winerror
|
|
350
|
+
if not transient or attempt == attempts - 1:
|
|
351
|
+
raise
|
|
352
|
+
time.sleep(min(0.025 * (2 ** attempt), 0.4))
|
|
353
|
+
|
|
354
|
+
|
|
340
355
|
def atomic_json(path: Path, payload: dict) -> None:
|
|
341
356
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
357
|
+
handle = tempfile.NamedTemporaryFile(
|
|
358
|
+
mode="w",
|
|
359
|
+
encoding="utf-8",
|
|
360
|
+
dir=path.parent,
|
|
361
|
+
prefix=f".{path.name}.",
|
|
362
|
+
suffix=".tmp",
|
|
363
|
+
delete=False,
|
|
364
|
+
)
|
|
365
|
+
temporary = Path(handle.name)
|
|
366
|
+
try:
|
|
367
|
+
with handle:
|
|
368
|
+
json.dump(payload, handle, indent=2, ensure_ascii=False)
|
|
369
|
+
handle.flush()
|
|
370
|
+
os.fsync(handle.fileno())
|
|
371
|
+
replace_with_retry(temporary, path)
|
|
372
|
+
finally:
|
|
373
|
+
temporary.unlink(missing_ok=True)
|
|
345
374
|
|
|
346
375
|
|
|
347
376
|
def skill_tree_digest(root: Path) -> str:
|