Files
app/backend/build.py
T
2026-10-04 02:47:11 +00:00

57 lines
5.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Extract accepted assets without changing the Tea fallback; deterministic ZIP."""
from pathlib import Path
import zipfile
import json
import re
ROOT = Path(__file__).resolve().parent
REPO = ROOT.parent
(ROOT / 'human_vault.py').write_bytes((REPO / 'tea_mcp/human_vault.py').read_bytes())
html = (REPO / 'tea/web/🍊/index.html').read_text()
html = html.replace('<script src="./app.js"', '<script type="module" src="./app.js"')
html = html.replace('src="./app.js"', 'src="/assets/app.js"')
html = html.replace('Available to you across Teahub.', '')
html = re.sub(r'<div class="heroSupport">.*?</div>', '', html, flags=re.S)
html = re.sub(r'<div class="scrim".*?<script', '<script', html, flags=re.S)
html = re.sub(r'<div class="vaultGroup">\s*<div class="groupHead">\s*<div><strong>📦.*?</section>', '</section>', html, flags=re.S)
html = html.replace('<div><h2>Your Persimmons</h2><div class="hint"><span id="userIdentity">Resolving signed-in user…</span></div></div>', '<h2>👤 My vault</h2>')
html = html.replace('<button class="primary" id="addButton">+ Add</button>', '<a id="signInLink" class="buttonLink" href="/signin" hidden>Sign in</a>')
html = re.sub(r'<div class="groupHead">\s*<div><strong>👤 My vault</strong>.*?<div class="groupRule" aria-hidden="true"></div>', '', html, count=1, flags=re.S)
html = html.replace('<div id="userState" class="state">Loading…</div>', '<div id="userState" class="state" hidden></div>')
html = html.replace('<span class="heroName">Persimmons</span>', '<span class="heroName"><span class="heroFruit">🍊</span>Persimmons</span>')
html = html.replace('<div class="heroFlow" aria-label="Orange to water to robot">🍊 → 💧 → 🤖</div>', '')
html = html.replace('</section>\n\n\n</main>', '''<div class="vaultGroup" id="namedVaults" hidden>
<div class="groupHead"><div><strong>📦 Vaults</strong><div class="hint">Private spaces for scoped Persimmons.</div></div><button id="newVault" class="primary">+ New vault</button></div>
<div class="groupRule" aria-hidden="true"></div>
<div id="namedVaultList" class="list" aria-live="polite"></div>
</div>
</section>
<footer class="persimmonsFooter"><strong>Passwords, PATs &amp; plenty of other useful P’s.</strong><div class="vaultFlow" aria-label="Orange to water to robot">🍊 → 💧 → 🤖</div></footer>
</main>''')
html = html.replace(
'<div class="shellTop">\n <h2>👤 My vault</h2>\n <div class="shellActions"><button id="refreshAll">Refresh</button><button id="signOutButton" hidden>Sign out</button><a id="signInLink" class="buttonLink" href="/signin" hidden>Sign in</a></div>\n</div>',
'<div class="shellTop">\n <div><h2>Vault</h2><div id="userIdentity" class="hint"></div></div>\n <div class="shellActions"><button class="primary" id="addCredential" hidden>+ Add credential</button><button id="signOutButton" hidden>Sign out</button><a id="signInLink" class="buttonLink" href="/signin" hidden>Sign in</a></div>\n</div>'
)
html = html.replace('</style>', '''
.juiceHover{outline:3px solid #ed9238;background:#fff1df}.connection[draggable=true]{cursor:grab}.juiceCard{padding:12px;margin-top:10px;border:1px solid var(--line);border-radius:10px}.juiceCard p{margin:6px 0;overflow-wrap:anywhere}\n.persimmonsFooter{text-align:center;margin:26px 0 0;color:var(--muted);font-size:12px;line-height:1.5}.persimmonsFooter strong{display:block;color:var(--ink);font-size:13px;margin-bottom:4px}.vaultFlow{font-size:15px;line-height:1.4;opacity:.72}
.vaultSummary{display:flex;align-items:center;gap:10px;margin-bottom:12px}.lockIcon{font-size:22px;line-height:1}.vaultCount{color:var(--muted);font-size:12px}
.credentialSource{display:flex;gap:6px;align-items:baseline;margin-top:10px;color:var(--muted);font-size:12px;overflow-wrap:anywhere}.credentialSource a{color:inherit}.credentialId{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;text-transform:uppercase}
#namedVaultList{display:grid;gap:10px}.namedVaultCard{padding:14px 16px}.namedVaultMeta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px}.namedVaultBadge{display:inline-flex;align-items:center;padding:3px 7px;border:1px solid var(--line);border-radius:999px;color:var(--muted);font-size:11px}.namedVaultActions{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}.namedVaultBody{margin-top:12px;padding:14px;border:1px dashed var(--line);border-radius:11px;color:var(--muted);font-size:12px;line-height:1.5}.namedVaultBody strong{display:block;color:var(--ink);margin-bottom:3px}
@media(max-width:720px){.vaultSummary{align-items:flex-start}.shellActions .buttonLink,.shellActions button{flex:1}}
</style>''')
html = html.replace('<h2>Vault</h2>', '<h2>Master vault</h2>')
# Keep the hero visually clean; supporting product copy lives in the footer.
(ROOT / 'web/index.html').write_text(html)
version = json.loads((REPO / 'persimmons-extension/manifest.json').read_text())['version']
(ROOT / 'web/version.json').write_text(json.dumps({'version': version}) + '\n')
with zipfile.ZipFile(ROOT / 'web/extension.zip', 'w', compression=zipfile.ZIP_DEFLATED) as archive:
for path in sorted((REPO / 'persimmons-extension').rglob('*')):
if 'tests' not in path.relative_to(REPO / 'persimmons-extension').parts and path.is_file() and path.suffix in {'.mjs', '.json', '.html', '.css', '.png'}:
entry = zipfile.ZipInfo('persimmons-extension/' + path.relative_to(REPO / 'persimmons-extension').as_posix(), (2026, 1, 1, 0, 0, 0))
entry.compress_type = zipfile.ZIP_DEFLATED
entry.external_attr = 0o644 << 16
archive.writestr(entry, path.read_bytes())
(ROOT / 'web/version.mjs').write_bytes((REPO / 'persimmons-extension/version.mjs').read_bytes())