File size: 7,035 Bytes
8dd0d51 aba5de3 8dd0d51 068f05c 8dd0d51 e319717 aba5de3 34a6a12 4e83552 6e4bff0 98010fc 4a83a8e 56b95fb 7bc6f17 5b8c924 bc5f822 7725fd6 2848ae7 dcfbd5f d87bc9c 3e43fab 503cc93 2fd97ff 257081e c6c2458 34784df d501176 18d42b7 8d35e43 e6f21d9 480d3f3 5704599 ddbf659 372b496 10b437c 8dd0d51 2848ae7 8dd0d51 10b437c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | """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')
|