@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.
Files changed (30) hide show
  1. package/README.md +15 -6
  2. package/THIRD-PARTY-RUNTIME-NOTICES.md +16 -0
  3. package/docs/PUBLIC-BETA-READINESS.md +53 -0
  4. package/docs/WINDOWS-BETA-ACCEPTANCE.md +70 -0
  5. package/experience/linux/README.md +5 -6
  6. package/experience/linux/prepare.sh +7 -9
  7. package/lib/atomic-json.js +41 -0
  8. package/lib/client.js +25 -4
  9. package/lib/index.js +93 -29
  10. package/lib/python-runtime.js +339 -0
  11. package/lib/remote-descriptor.js +1 -0
  12. package/lib/version.js +5 -0
  13. package/package.json +6 -3
  14. package/skills/foggy-deepseek-onboarding/SKILL.md +9 -3
  15. package/skills/foggy-deepseek-onboarding/assets/versions.json +46 -2
  16. package/skills/foggy-deepseek-onboarding/scripts/doctor.ps1 +2 -2
  17. package/skills/foggy-deepseek-onboarding/scripts/doctor.sh +1 -2
  18. package/skills/foggy-deepseek-onboarding/scripts/install.ps1 +2 -2
  19. package/skills/foggy-deepseek-onboarding/scripts/install.sh +1 -2
  20. package/skills/foggy-deepseek-onboarding/scripts/invoke-onboarding.ps1 +30 -0
  21. package/skills/foggy-deepseek-onboarding/scripts/invoke-onboarding.sh +24 -0
  22. package/skills/foggy-deepseek-onboarding/scripts/onboard.ps1 +2 -2
  23. package/skills/foggy-deepseek-onboarding/scripts/onboard.sh +1 -2
  24. package/skills/foggy-deepseek-onboarding/scripts/onboarding.py +59 -25
  25. package/skills/foggy-deepseek-onboarding/scripts/runtime-start.ps1 +2 -2
  26. package/skills/foggy-deepseek-onboarding/scripts/runtime-start.sh +1 -2
  27. package/skills/foggy-deepseek-onboarding/scripts/runtime-stop.ps1 +2 -2
  28. package/skills/foggy-deepseek-onboarding/scripts/runtime-stop.sh +1 -2
  29. package/skills/foggy-deepseek-onboarding/scripts/uninstall.ps1 +2 -2
  30. package/skills/foggy-deepseek-onboarding/scripts/uninstall.sh +1 -2
@@ -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
@@ -47,7 +48,7 @@ ACTIVE_PROGRESS: "ProgressReporter | None" = None
47
48
 
48
49
 
49
50
  class ProgressReporter:
50
- total_steps = 6
51
+ total_steps = 7
51
52
 
52
53
  def __init__(self, path: str | None, operation_id: str | None, kind: str) -> None:
53
54
  self.path = Path(path).expanduser() if path else None
@@ -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
- temporary = path.with_name(path.name + ".tmp")
343
- temporary.write_text(json.dumps(payload, indent=2, ensure_ascii=False), encoding="utf-8")
344
- os.replace(temporary, path)
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:
@@ -996,7 +1025,7 @@ def install_command(args: argparse.Namespace) -> dict:
996
1025
  "workspaceMode": "dsh-session-cwd",
997
1026
  "versions": {name: value.get("version") for name, value in components.items()},
998
1027
  "repairComponent": repair_component,
999
- "operations": ["install isolated CLI", "verify Launcher assets", "install global analysis Skill", "write install state"],
1028
+ "operations": ["verify private Python", "install isolated CLI", "verify Launcher assets", "install global analysis Skill", "write install state"],
1000
1029
  "productionReady": False,
1001
1030
  }
1002
1031
  if args.dry_run:
@@ -1008,7 +1037,7 @@ def install_command(args: argparse.Namespace) -> dict:
1008
1037
  getattr(args, "operation_kind", "initialize"),
1009
1038
  )
1010
1039
  ACTIVE_PROGRESS = progress
1011
- progress.update("preflight", 0, "Checking prerequisites")
1040
+ progress.update("python", 1, "Managed Python ready", fraction=1.0, current_file=sys.executable)
1012
1041
  if sys.version_info < (3, 11):
1013
1042
  raise OnboardingError(f"Python 3.11+ required, got {sys.version.split()[0]}")
1014
1043
  install_root.mkdir(parents=True, exist_ok=True)
@@ -1020,19 +1049,19 @@ def install_command(args: argparse.Namespace) -> dict:
1020
1049
  cli_assets = [cli_component[role] for role in ("wheel", "checksums")]
1021
1050
  for index, asset in enumerate(cli_assets):
1022
1051
  progress.update(
1023
- "cli", 1, "Downloading and verifying CLI",
1052
+ "cli", 2, "Downloading and verifying CLI",
1024
1053
  fraction=index / len(cli_assets), current_file=asset["file"],
1025
1054
  completed_files=index, total_files=len(cli_assets),
1026
1055
  )
1027
1056
  verified.append(materialize(
1028
1057
  asset, downloads / "cli" / asset["file"], cache_dirs,
1029
- progress=progress, progress_phase="cli", progress_step=1,
1058
+ progress=progress, progress_phase="cli", progress_step=2,
1030
1059
  progress_index=index, progress_total=len(cli_assets),
1031
1060
  progress_message="Downloading and verifying CLI",
1032
1061
  replace_corrupt=repair_component == "cli",
1033
1062
  ))
1034
1063
  progress.update(
1035
- "cli", 1, "Downloading and verifying CLI",
1064
+ "cli", 2, "Downloading and verifying CLI",
1036
1065
  fraction=(index + 1) / len(cli_assets), current_file=asset["file"],
1037
1066
  completed_files=index + 1, total_files=len(cli_assets),
1038
1067
  )
@@ -1042,13 +1071,13 @@ def install_command(args: argparse.Namespace) -> dict:
1042
1071
  if checksum_entries.get(wheel_asset["file"]) != wheel_asset["sha256"]:
1043
1072
  raise OnboardingError("Pinned CLI SHA256SUMS does not match the pinned wheel hash")
1044
1073
  if args.skip_cli_install:
1045
- progress.update("cli", 1, "Using existing CLI", fraction=0.65, current_file="foggy-runtime")
1074
+ progress.update("cli", 2, "Using existing CLI", fraction=0.65, current_file="foggy-runtime")
1046
1075
  cli_command = normalized(args.cli_command or shutil.which("foggy-runtime") or "")
1047
1076
  if not cli_command.is_file():
1048
1077
  raise OnboardingError("--skip-cli-install requires --cli-command or foggy-runtime on PATH")
1049
1078
  cli_mode = "external"
1050
1079
  else:
1051
- progress.update("cli", 1, "Installing CLI", fraction=0.65, current_file="Python virtual environment")
1080
+ progress.update("cli", 2, "Installing CLI", fraction=0.65, current_file="Python virtual environment")
1052
1081
  python_path = venv_python(install_root)
1053
1082
  if not python_path.is_file():
1054
1083
  venv.EnvBuilder(with_pip=True).create(install_root / "venv")
@@ -1063,66 +1092,66 @@ def install_command(args: argparse.Namespace) -> dict:
1063
1092
  )
1064
1093
  cli_command = venv_cli(install_root)
1065
1094
  cli_mode = "managed-venv"
1066
- progress.update("cli", 1, "Verifying CLI version", fraction=0.9, current_file="foggy-runtime")
1095
+ progress.update("cli", 2, "Verifying CLI version", fraction=0.9, current_file="foggy-runtime")
1067
1096
  cli_version = command_result([str(cli_command), "--version"], check=True)
1068
1097
  actual_cli_version = version_tuple(cli_version["stdout"])[:3]
1069
1098
  pinned_cli_version = version_tuple(cli_component["version"])[:3]
1070
1099
  version_matches = actual_cli_version >= pinned_cli_version if cli_mode == "external" else actual_cli_version == pinned_cli_version
1071
1100
  if not version_matches:
1072
1101
  raise OnboardingError(f"Unexpected CLI version: {cli_version['stdout']}")
1073
- progress.update("cli", 1, "CLI ready", fraction=1.0)
1102
+ progress.update("cli", 2, "CLI ready", fraction=1.0)
1074
1103
 
1075
1104
  launcher_dir = install_root / "launcher"
1076
1105
  launcher_assets = components["launcher"]["assets"]
1077
1106
  for index, asset in enumerate(launcher_assets):
1078
1107
  progress.update(
1079
- "launcher", 2, "Downloading and verifying Launcher",
1108
+ "launcher", 3, "Downloading and verifying Launcher",
1080
1109
  fraction=index / len(launcher_assets), current_file=asset["file"],
1081
1110
  completed_files=index, total_files=len(launcher_assets),
1082
1111
  )
1083
1112
  verified.append(materialize(
1084
1113
  asset, launcher_dir / asset["file"], cache_dirs,
1085
- progress=progress, progress_phase="launcher", progress_step=2,
1114
+ progress=progress, progress_phase="launcher", progress_step=3,
1086
1115
  progress_index=index, progress_total=len(launcher_assets),
1087
1116
  progress_message="Downloading and verifying Launcher",
1088
1117
  replace_corrupt=repair_component == "launcher",
1089
1118
  ))
1090
1119
  progress.update(
1091
- "launcher", 2, "Downloading and verifying Launcher",
1120
+ "launcher", 3, "Downloading and verifying Launcher",
1092
1121
  fraction=(index + 1) / len(launcher_assets), current_file=asset["file"],
1093
1122
  completed_files=index + 1, total_files=len(launcher_assets),
1094
1123
  )
1095
1124
  if os.name != "nt":
1096
1125
  (launcher_dir / "start-foggy-runtime.sh").chmod(0o755)
1097
- progress.update("launcher", 2, "Launcher ready", fraction=1.0)
1126
+ progress.update("launcher", 3, "Launcher ready", fraction=1.0)
1098
1127
 
1099
1128
  analysis_assets = components["analysisSkill"]["assets"]
1100
1129
  for index, asset in enumerate(analysis_assets):
1101
1130
  progress.update(
1102
- "analysis-skill", 3, "Downloading and verifying analysis Skill",
1131
+ "analysis-skill", 4, "Downloading and verifying analysis Skill",
1103
1132
  fraction=index / len(analysis_assets), current_file=asset["file"],
1104
1133
  completed_files=index, total_files=len(analysis_assets),
1105
1134
  )
1106
1135
  verified.append(materialize(
1107
1136
  asset, downloads / "skill" / asset["file"], cache_dirs,
1108
- progress=progress, progress_phase="analysis-skill", progress_step=3,
1137
+ progress=progress, progress_phase="analysis-skill", progress_step=4,
1109
1138
  progress_index=index, progress_total=len(analysis_assets),
1110
1139
  progress_message="Downloading and verifying analysis Skill",
1111
1140
  replace_corrupt=repair_component == "analysis-skill",
1112
1141
  ))
1113
1142
  progress.update(
1114
- "analysis-skill", 3, "Downloading and verifying analysis Skill",
1143
+ "analysis-skill", 4, "Downloading and verifying analysis Skill",
1115
1144
  fraction=(index + 1) / len(analysis_assets), current_file=asset["file"],
1116
1145
  completed_files=index + 1, total_files=len(analysis_assets),
1117
1146
  )
1118
1147
  zip_asset = next(item for item in analysis_assets if item["role"] == "zip")
1119
- progress.update("analysis-skill", 3, "Installing analysis Skill", fraction=0.9, current_file=zip_asset["file"])
1148
+ progress.update("analysis-skill", 4, "Installing analysis Skill", fraction=0.9, current_file=zip_asset["file"])
1120
1149
  analysis_skill = install_analysis_skill(
1121
1150
  downloads / "skill" / zip_asset["file"], install_root, components["analysisSkill"]["version"],
1122
1151
  zip_asset["sha256"], versions["packageVersion"], args.replace_skill or repair_component == "analysis-skill",
1123
1152
  )
1124
- progress.update("analysis-skill", 3, "Analysis Skill ready", fraction=1.0)
1125
- progress.update("workspace-skills", 4, "Registering native DSH Skills", fraction=0.1)
1153
+ progress.update("analysis-skill", 4, "Analysis Skill ready", fraction=1.0)
1154
+ progress.update("workspace-skills", 5, "Registering native DSH Skills", fraction=0.1)
1126
1155
  onboarding_skill = {
1127
1156
  "path": str(skill_root()),
1128
1157
  "version": versions["packageVersion"],
@@ -1130,7 +1159,7 @@ def install_command(args: argparse.Namespace) -> dict:
1130
1159
  "action": "provided-by-plugin",
1131
1160
  "provider": "foggy-managed-skills",
1132
1161
  }
1133
- progress.update("workspace-skills", 4, "Native DSH Skills ready", fraction=1.0)
1162
+ progress.update("workspace-skills", 5, "Native DSH Skills ready", fraction=1.0)
1134
1163
  state = {
1135
1164
  "schemaVersion": STATE_SCHEMA,
1136
1165
  "installedAt": now_utc(),
@@ -1139,6 +1168,11 @@ def install_command(args: argparse.Namespace) -> dict:
1139
1168
  "dataRoot": str(data_root),
1140
1169
  "profileStore": str(profile_store),
1141
1170
  "workspaceMode": "dsh-session-cwd",
1171
+ "python": {
1172
+ "version": components["python"]["version"],
1173
+ "command": sys.executable,
1174
+ "mode": os.environ.get("FOGGY_ONBOARDING_PYTHON_SOURCE", "managed"),
1175
+ },
1142
1176
  "cli": {"version": cli_component["version"], "command": str(cli_command), "mode": cli_mode},
1143
1177
  "launcher": {"version": components["launcher"]["version"], "path": str(launcher_dir)},
1144
1178
  "skills": {"onboarding": onboarding_skill, "analysis": analysis_skill},
@@ -1146,7 +1180,7 @@ def install_command(args: argparse.Namespace) -> dict:
1146
1180
  "securityMode": versions["defaults"]["securityMode"],
1147
1181
  "productionReady": False,
1148
1182
  }
1149
- progress.update("state", 5, "Writing install state", fraction=0.2, current_file="install-state.json")
1183
+ progress.update("state", 6, "Writing install state", fraction=0.2, current_file="install-state.json")
1150
1184
  atomic_json(install_root / "install-state.json", state)
1151
1185
  progress.finish()
1152
1186
  ACTIVE_PROGRESS = None
@@ -1,4 +1,4 @@
1
1
  $ErrorActionPreference = "Stop"
2
- $pythonCommand = if ($env:FOGGY_ONBOARDING_PYTHON) { $env:FOGGY_ONBOARDING_PYTHON } else { "python" }
3
- & $pythonCommand (Join-Path $PSScriptRoot "onboarding.py") runtime-start @args
2
+ & (Join-Path $PSScriptRoot 'invoke-onboarding.ps1') runtime-start @args
3
+ exit $LASTEXITCODE
4
4
  exit $LASTEXITCODE
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
4
- PYTHON_COMMAND="${FOGGY_ONBOARDING_PYTHON:-python3}"
5
- exec "$PYTHON_COMMAND" "$SCRIPT_DIR/onboarding.py" runtime-start "$@"
4
+ exec bash "$SCRIPT_DIR/invoke-onboarding.sh" runtime-start "$@"
@@ -1,4 +1,4 @@
1
1
  $ErrorActionPreference = "Stop"
2
- $pythonCommand = if ($env:FOGGY_ONBOARDING_PYTHON) { $env:FOGGY_ONBOARDING_PYTHON } else { "python" }
3
- & $pythonCommand (Join-Path $PSScriptRoot "onboarding.py") runtime-stop @args
2
+ & (Join-Path $PSScriptRoot 'invoke-onboarding.ps1') runtime-stop @args
3
+ exit $LASTEXITCODE
4
4
  exit $LASTEXITCODE
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
4
- PYTHON_COMMAND="${FOGGY_ONBOARDING_PYTHON:-python3}"
5
- exec "$PYTHON_COMMAND" "$SCRIPT_DIR/onboarding.py" runtime-stop "$@"
4
+ exec bash "$SCRIPT_DIR/invoke-onboarding.sh" runtime-stop "$@"
@@ -1,4 +1,4 @@
1
1
  $ErrorActionPreference = "Stop"
2
- $pythonCommand = if ($env:FOGGY_ONBOARDING_PYTHON) { $env:FOGGY_ONBOARDING_PYTHON } else { "python" }
3
- & $pythonCommand (Join-Path $PSScriptRoot "onboarding.py") uninstall @args
2
+ & (Join-Path $PSScriptRoot 'invoke-onboarding.ps1') uninstall @args
3
+ exit $LASTEXITCODE
4
4
  exit $LASTEXITCODE
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
4
- PYTHON_COMMAND="${FOGGY_ONBOARDING_PYTHON:-python3}"
5
- exec "$PYTHON_COMMAND" "$SCRIPT_DIR/onboarding.py" uninstall "$@"
4
+ exec bash "$SCRIPT_DIR/invoke-onboarding.sh" uninstall "$@"