MiniCPM5-2B-WebGPU-Pi / scripts /prepare_space.py
Mike0021's picture
Deploy latest UI: loading flow, paws, resizer and cat interactions
10b437c verified
Raw History Blame Contribute Delete
7.04 kB
"""Stage the Pi browser workspace for the existing static Hugging Face Space.
Run `cd app && npm ci && npm run build` first. Model weights remain in the
pinned companion model repository; only static assets and selected source
and validation files are published here.
"""
from pathlib import Path
import hashlib
import json
import shutil
root = Path(__file__).resolve().parent.parent
out = root / '.space-agent'
built = root / 'app/dist'
if not (built / 'index.html').is_file():
raise SystemExit('Build app/ first: npm ci && npm run build')
if out.exists():
shutil.rmtree(out)
shutil.copytree(built, out)
# Include reproducible browser source; never include environments or weights.
app_out = out / 'app'
app_out.mkdir()
for name in ['package.json', 'package-lock.json', 'index.html', 'vite.config.mjs', 'README.md']:
shutil.copyfile(root / 'app' / name, app_out / name)
for name in ['src', 'scripts', 'public', 'tests', 'vendor']:
shutil.copytree(root / 'app' / name, app_out / name)
modal_design = out / 'design' / 'modal-cat'
modal_design.mkdir(parents=True)
shutil.copyfile(root / 'design/modal-cat/prompt.md', modal_design / 'prompt.md')
validation = out / 'validation'
validation.mkdir()
for name in [
'package-manifest.json', 'onnx-validation.json', 'webgpu-parity.json',
'benchmark-summary.json', 'checksum-verification.json', 'template-tests.json',
'control-equivalence.json', 'chinese-arithmetic-investigation.json',
'browser-integration.json', 'space-deployment.json', 'hub-checksums.json',
'agent-browser-hub.json', 'agent-browser-limit128.json', 'agent-browser-dev.json',
'agent-browser-no-gpu.json', 'agent-completion.json',
'agent-space-deployment.json', 'agent-space-embedded.json', 'agent-space-restricted.json',
'agent-space-checksums.json',
'agent-terminal.json', 'agent-terminal-model.json', 'agent-terminal-dev.json',
'agent-terminal-space.json', 'agent-terminal-space-embedded.json',
'agent-terminal-space-checksums.json',
'agent-terminal-dark.json', 'agent-terminal-dark-dev.json',
'agent-terminal-dark-render.json', 'agent-terminal-dark-render-dev.json',
'agent-terminal-dark-model.json', 'agent-terminal-dark-conversation.json',
'agent-terminal-dark-space.json', 'agent-terminal-dark-space-render.json',
'agent-terminal-dark-space-embedded.json',
'agent-terminal-dark-space-checksums.json',
'agent-app-dark-render.json', 'agent-app-dark-terminal.json',
'agent-first-message.json', 'agent-first-message-space-embedded.json',
'agent-app-dark-space-render.json', 'agent-first-message-space-checksums.json',
'agent-shell.json', 'agent-shell-layout.json', 'agent-shell-terminal.json',
'agent-shell-first-message.json', 'agent-shell-space.json',
'agent-shell-space-embedded.json',
'agent-shell-space-checksums.json',
'agent-rounded-header.json', 'agent-rounded-header-render.json',
'agent-local-demo-modal.json', 'agent-compact-header.json',
'agent-context-render.json', 'agent-context-usage.json',
'agent-compact-shell.json', 'agent-white-action-modal.json',
'agent-thinking-context.json', 'agent-thinking-conversation.json', 'agent-thinking-render.json',
'agent-thinking-space.json', 'agent-thinking-space-checksums.json',
'agent-cached-start.json', 'agent-cached-first-message.json',
'agent-runtime-meter.json', 'agent-runtime-meter-render.json', 'agent-nested-radius.json',
'agent-runtime-meter-adaptive.json', 'agent-adaptive-width.json',
'agent-mascot.json', 'agent-mascot-render.json',
'agent-modal-cat.json', 'agent-modal-cat-space.json',
'agent-loading-paws.json', 'agent-loading-paws-webkit.json',
'agent-credits-send.json',
'agent-mascot-motion.json', 'agent-mascot-motion-layout.json',
'agent-editor-focus.json',
'agent-editor.json',
'agent-starter-products.json', 'agent-products-mascot.json',
'agent-products-json.json', 'agent-json-mascot.json', 'agent-safari-cat.json',
'agent-profit-demo-review.md', 'agent-profit-demo.json', 'agent-profit-demo-guidance.json',
'agent-profit-demo-verified.json', 'agent-profit-demo-clear.json', 'agent-profit-demo-cost-change.json',
'agent-profit-demo-focused.json', 'agent-profit-demo-focused-cost.json', 'agent-profit-starter.json',
'agent-profit-onboarding.json', 'agent-profit-mascot-final.json',
'agent-sales-demo.json',
'agent-follow-read.json', 'agent-workspace-runtime.json',
'load-flow.json', 'column-resizer.json', 'cat-interactions.json',
'modal-paws-open.json', 'terminal-paws.json', 'thinking-spacing.json',
]:
source = root / 'validation' / name
if source.is_file():
shutil.copyfile(source, validation / name)
scripts = out / 'scripts'
scripts.mkdir()
for name in ['download_source.py', 'build.sh', 'package_model.py', 'reference.py',
'validate_onnx.py', 'validate_webgpu.py', 'serve.py', 'prepare_space.py']:
shutil.copyfile(root / 'scripts' / name, scripts / name)
for folder in ['browser-agent', 'download-audit']:
report = out / 'research' / folder
report.mkdir(parents=True)
shutil.copyfile(root / 'research' / folder / 'REPORT.md', report / 'REPORT.md')
for name in ['pi-agent-README.md', 'pi-ai-README.md', 'just-bash-README.md']:
shutil.copyfile(root / 'research/browser-agent' / name, out / 'research/browser-agent' / name)
audit = out / 'research/multiturn-audit'
audit.mkdir(parents=True)
for source in sorted((root / 'research/multiturn-audit').iterdir()):
if source.is_file() and (source.name == 'REPORT.md' or source.suffix in {'.json', '.py', '.mjs'}):
shutil.copyfile(source, audit / source.name)
shutil.copyfile(root / 'requirements-convert.txt', out / 'requirements-convert.txt')
shutil.copyfile('/usr/share/common-licenses/Apache-2.0', out / 'LICENSE')
shutil.copyfile(root / 'SPACE_README.md', out / 'README.md')
shutil.copyfile(root / 'SPACE_README.md', out / 'SPACE_README.md')
(out / 'NOTICE').write_text(
'Base model: OpenBMB MiniCPM5-2B, Apache-2.0. Independently converted and quantized.\n'
'Agent: Pi, earendil-works. Virtual shell: just-bash, Vercel.\n'
'Inference: Hugging Face Transformers.js and Microsoft ONNX Runtime.\n'
'Bundled dependency licenses and notices are in licenses/.\n'
)
(out / '.gitattributes').write_text(
'*.onnx filter=lfs diff=lfs merge=lfs -text\n'
'*.onnx_data* filter=lfs diff=lfs merge=lfs -text\n'
'*.wasm filter=lfs diff=lfs merge=lfs -text\n'
)
files = {str(p.relative_to(out)): {'bytes': p.stat().st_size,
'sha256': hashlib.sha256(p.read_bytes()).hexdigest()}
for p in sorted(out.rglob('*')) if p.is_file()}
(out / 'deployment-manifest.json').write_text(json.dumps({'files': files}, indent=2) + '\n')
assert not any('.onnx_data' in name or 'node_modules/' in name for name in files)
print('Staged', len(files) + 1, 'files;', sum(f['bytes'] for f in files.values()), 'bytes')
print('Upload:', 'hf upload townbox/MiniCPM5-2B-WebGPU-Pi .space-agent . --type space')