feat: add Chinese UI, Responses models, and mirrored Windows setup
CI / Python 3.12 / ubuntu-latest (push) Canceled after 0s
CI / Python 3.12 / windows-latest (push) Canceled after 0s
CI / Frontend tests and production build (push) Canceled after 0s
CI / Build and smoke-test Python packages (push) Canceled after 0s

Localize the web console and persist custom model and capability settings.
Use OpenAI Responses exclusively and move runtime limits into environment configuration.
Bootstrap uv and the virtual environment on Windows, support optional China mirrors,
and package source distributions without environments, build output, or credentials.

Update regression tests and repository quality checks for the new behavior.
This commit is contained in:
chenmingxuan committed 2026-09-22 19:16:17 +08:00
1 parent 371aa6df56
commit 2ddec53954
183 files changed
+3427 -11857

No files matched your search

+154
View File
@@ -0,0 +1,154 @@
"""Create a portable source ZIP without environments, builds, or local credentials."""
import argparse
from datetime import datetime
import hashlib
import os
from pathlib import Path
import zipfile
EXCLUDED_DIRS = {
".git",
".venv",
"venv",
"env",
"node_modules",
"__pycache__",
"__pypackages__",
".angular",
".gradle",
".pytest_cache",
".ruff_cache",
".mypy_cache",
".cache",
".tox",
".nox",
".hypothesis",
".eggs",
".idea",
".vscode",
".vs",
".codex",
".claude",
".gemini",
".cursor",
".ipynb_checkpoints",
"build",
"dist",
"out",
"coverage",
"htmlcov",
"artifacts",
"traces",
"scratch",
"outputs",
"trace_output",
}
EXCLUDED_SUFFIXES = {
".pyc",
".pyo",
".pyd",
".so",
".dll",
".exe",
".o",
".obj",
".a",
".lib",
".class",
".jar",
".apk",
".aab",
".wasm",
".map",
".tsbuildinfo",
".egg",
".whl",
".zip",
".7z",
".tar",
".gz",
".log",
".db",
".sqlite",
".sqlite3",
".pem",
".key",
".keystore",
".p12",
".pfx",
".swp",
".swo",
}
def excluded(path: Path) -> bool:
parts = tuple(part.lower() for part in path.parts)
name = parts[-1]
if any(part in EXCLUDED_DIRS or part.endswith(".egg-info") for part in parts):
return True
# This tracked directory also contains generated Angular bundles.
if parts[:3] == ("artemis", "resources", "showcase_ui"):
return True
if (name == ".env" or name.startswith(".env.")) and name != ".env.example":
return True
if name.startswith((".artemis_", ".jetski_", ".coverage")):
return True
if name in {".ds_store", "thumbs.db", ".ipc_port", ".ls_address", ".npmrc", ".pypirc"}:
return True
return path.suffix.lower() in EXCLUDED_SUFFIXES or name.endswith((".db-wal", ".db-shm", "~"))
def source_files(root: Path):
for directory, dirs, files in os.walk(root, followlinks=False):
current = Path(directory)
dirs[:] = sorted(
name
for name in dirs
if not (current / name).is_symlink()
and not excluded((current / name).relative_to(root))
)
for name in sorted(files):
path = current / name
if not path.is_symlink() and not excluded(path.relative_to(root)):
yield path
def package_source(root: Path, output: Path) -> tuple[int, str]:
root = root.resolve()
output = output.resolve()
output.parent.mkdir(parents=True, exist_ok=True)
temporary = output.with_suffix(".zip.tmp")
files = [p for p in source_files(root) if p.resolve() not in {output, temporary}]
try:
with zipfile.ZipFile(temporary, "w", zipfile.ZIP_DEFLATED, compresslevel=6) as archive:
for path in files:
archive.write(path, Path("artemis") / path.relative_to(root))
with zipfile.ZipFile(temporary) as archive:
bad_file = archive.testzip()
if bad_file:
raise RuntimeError(f"ZIP integrity check failed: {bad_file}")
if any(excluded(Path(name).relative_to("artemis")) for name in archive.namelist()):
raise RuntimeError("An excluded file was found in the source archive")
temporary.replace(output)
finally:
temporary.unlink(missing_ok=True)
with output.open("rb") as stream:
digest = hashlib.file_digest(stream, "sha256").hexdigest()
return len(files), digest
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--root", type=Path, default=Path(__file__).resolve().parents[1])
parser.add_argument("--output", type=Path)
args = parser.parse_args()
output = (
args.output
or args.root / "artifacts" / f"artemis-source-{datetime.now():%Y%m%d-%H%M%S}.zip"
)
count, digest = package_source(args.root, output)
print(f"Archive: {output.resolve()}")
print(f"Files: {count}; size: {output.stat().st_size / (1024 * 1024):.2f} MiB")
print(f"SHA256: {digest}")