File size: 6,891 Bytes
4ac3af3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""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',
]:
    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 Mike0021/MiniCPM5-2B-WebGPU-Pi .space-agent . --type space')