Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8eeeabd
desktop-agent: add macOS panel backend (tauri-nspanel, global-shortcu…
zrmarley Oct 5, 2026
89b0c2c
desktop-agent: add Berdy avatar media and retiming script
zrmarley Oct 5, 2026
75f7dd8
desktop-agent: add panel frontend, settings switch, shortcut, and exp…
zrmarley Oct 5, 2026
ba7f287
fix(styles): flatten `*`-led nested focus-visible rules
zrmarley Oct 8, 2026
0d221f3
desktop-agent: composer-first popover, custom avatar menu, and design…
zrmarley Oct 8, 2026
fe14c25
desktop-agent: fix avatar-stable regrow, menu placement, and menu races
zrmarley Oct 8, 2026
f75ec97
desktop-agent: keep late key-loss from cancelling menu open; close me…
zrmarley Oct 8, 2026
f0fd0b8
desktop-agent: New chat menu item and side-anchored composer bubble
zrmarley Oct 8, 2026
1646cc1
desktop-agent: keep agent identity on New chat; share side-room geometry
zrmarley Oct 8, 2026
f32ec12
desktop-agent: Start new chat label; grow chat from the composer bubble
zrmarley Oct 8, 2026
8b4208c
desktop-agent: read full-layout padding for grow-in-place; tidy grown…
zrmarley Oct 8, 2026
3b952c1
desktop-agent: open existing chats beside the avatar, composer level …
zrmarley Oct 8, 2026
e039692
desktop-agent: review cleanup (grow/reopen parity, perch-expanded gua…
zrmarley Oct 8, 2026
7e2fab0
desktop-agent: retry failed initial panel attach
zrmarley Oct 8, 2026
1dbe9eb
desktop-agent: follow streaming transcript updates
zrmarley Oct 8, 2026
5c5b48d
desktop-agent: open behavior settings
zrmarley Oct 8, 2026
62338e1
desktop-agent: make avatar menu keyboard accessible
zrmarley Oct 8, 2026
e9a51b1
desktop-agent: show pending perched capture
zrmarley Oct 8, 2026
64f6353
desktop-agent: scope panel colors to semantic tokens
zrmarley Oct 8, 2026
edb02d6
desktop-agent: rename Hide agent to Turn off agent
zrmarley Oct 8, 2026
b61fe8c
desktop-agent: restore markdown list markers; drop native outline on …
zrmarley Oct 8, 2026
72d9e10
desktop-agent: review fixes (token parity, capture state, focus, retr…
zrmarley Oct 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script>
(() => {
// Auxiliary panel webviews (?window=...) skip the startup canvas:
// the desktop-agent panel is a transparent always-on-top window,
// and painting the opaque themed background here would flash a
// solid square before React mounts. Session windows use
// ?sessionKey= and keep the canvas.
if (new URLSearchParams(window.location.search).has("window")) {
return;
}

const getDefaultAccent = (theme) =>
theme === "dark" ? "#ffffff" : "#1a1a1a";

Expand Down
Binary file added public/desktop-agent/berd-logo.mp4
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added public/desktop-agent/gloopies-22.mp4
Binary file not shown.
107 changes: 107 additions & 0 deletions scripts/berdy-media.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
{
"description": "Lossless 1.5x timing of existing HEVC-alpha MP4s. All encoded samples, alpha, edit/sample tables and endpoints unchanged; only mvhd/mdhd timescales 12288 -> 18432. Native rates: effective source speed / 1.5. No audio.",
"originalTimescale": 12288,
"timescale": 18432,
"sourceFrames": 122,
"sourceFps": 24,
"mediaFps": 36,
"durationTicks": 62472,
"assets": [
{
"file": "berdy_DangleToDangle_00001_.mp4",
"bytes": 842853,
"originalSha256": "4d9b4b7c1adb36420a45b45380ebbf8e487cd4f8df1775651aa74962e38304e6",
"sha256": "370f9b3a634c1cfa42bc36d3e0d68d6ee8dfd9ad910a21ef8224062d46ee3770",
"mdatSha256": "dad1b29f9e098b2dc556560f5e3cd68ab24e4a7368a08ffc8e01a30c94280010",
"timescaleOffsets": [56, 308]
},
{
"file": "berdy_DangleToIdle_00001_.mp4",
"bytes": 902187,
"originalSha256": "e8b0e7b34d238130ee069de81a9a9da886f22ffdfedc6e4ba584ab29e6a42fc7",
"sha256": "8f0ed09690ab00c9bf91314cadc09a2f22fa57af1382cde40f0a5530a28ed358",
"mdatSha256": "d25c45c3e0158ffb471c7170f26f29fc7d566f841d12cf7df6a901c1c07432e0",
"timescaleOffsets": [56, 308]
},
{
"file": "berdy_DangleToSit_00001_.mp4",
"bytes": 1050978,
"originalSha256": "6dd93e1e53ca8f5c8d0df6265f4c84825f8f81faf81d37a0868ed7849dafae1e",
"sha256": "eddb6a098f21c75dcd5cbdc08e7699f164453b6d34c6132abfc3b8312551771d",
"mdatSha256": "a2736f6a372b9f4542f96d71f5d4a06f394d3c66d93b3a5257faf7df0cd3e64d",
"timescaleOffsets": [56, 308]
},
{
"file": "berdy_IdleToDangle_00001_.mp4",
"bytes": 1064141,
"originalSha256": "1d8e63eeab2d2fa3c8bfa216ceb4154a761b7f850cbe7f9e76adc65b47c3eea3",
"sha256": "ca4ff1ad04391ad4cee4ca5b32738da86905b4d6e5f94a72b817b8a15de2698e",
"mdatSha256": "419085b141f5b9b2de18e5fc404fc93ef06bb59d0e96ad52750374cb986a9169",
"timescaleOffsets": [56, 308]
},
{
"file": "berdy_Idle_01_00001_.mp4",
"bytes": 905500,
"originalSha256": "6c7ac32132c1238799e1f0aba1d54ae2597310fb13727a920333d023fbb3128d",
"sha256": "feb86e8c635301a83561e9c73cf0a1aa4a14f8460a7b5297c9503133e1ca8237",
"mdatSha256": "0db7b0c5c39a087e3789057a60fad40ba12962aea469ef60f63d8cece7eea724",
"timescaleOffsets": [56, 308]
},
{
"file": "berdy_Idle_02_00001_.mp4",
"bytes": 815724,
"originalSha256": "916d4084d29415b499be26a34fc5b9f01caf83aba4970106365529903a5aaeb5",
"sha256": "877de4b6e447d10606bf6d197edf31bca5954236f0674baa9ac1b44189e03f6c",
"mdatSha256": "6bc86a040517b0bf8da004727f9ac91fd194ab17174ca1ceb17167924ab56634",
"timescaleOffsets": [56, 308]
},
{
"file": "berdy_Idle_03_00001_.mp4",
"bytes": 793758,
"originalSha256": "d64c8020654c3bc9546f421aff50526477bad4f6222402c43187b8640030fbef",
"sha256": "a08e08ab1da193103118493e3c70354eda3b7b54b2df54c4a06104748d25ba2f",
"mdatSha256": "96d2d5ff43d6de8c3344f2c96ffb2ee5e7b2fcd5c03cad784d66fd8d09687691",
"timescaleOffsets": [56, 308]
},
{
"file": "berdy_Idle_04_00001_.mp4",
"bytes": 710787,
"originalSha256": "d51fb9a85f065ff52735fff11a1e564e0fd2696626fb9ebb5b15a1447d4e8c60",
"sha256": "7d369d86e7ddddf791a4d23905f24131fca8a69700549e4246a0ba623921adfc",
"mdatSha256": "8401018f83ad13eb7bfd641a065763f8a01a2dcc2f4151dc115530a5ffacbfd2",
"timescaleOffsets": [56, 308]
},
{
"file": "berdy_SitToDangle_00001_.mp4",
"bytes": 1020745,
"originalSha256": "5e5db8f51097dee17c0f3591516f96e933dcb080ec89fef64a9ddacba7dd444a",
"sha256": "b940eb090971cdc11d0975be7b0022a49d39ca41e765bf000d90a0684cb7048b",
"mdatSha256": "d097e4ca66141357a519266ef76223dbd02e5ed4fffc60b418016e9c18b53e93",
"timescaleOffsets": [56, 308]
},
{
"file": "berdy_Sit_Idle_01_00001_.mp4",
"bytes": 787190,
"originalSha256": "308101f2854671e091d31646acda4c429153461673d22a6e4989953103080fbe",
"sha256": "34afaaff93dbeae5f27db6bdbffe5bf18f0c3c0edbc16aa7686b341b3be9b172",
"mdatSha256": "78019926feef1882127fc98fc4c6ca7bbf8a7fb8c18e667f59bd9d9c2c9cd2de",
"timescaleOffsets": [56, 308]
},
{
"file": "berdy_Sit_Idle_02_00001_.mp4",
"bytes": 925222,
"originalSha256": "980002a70f779e4e57b8340f78a7c3aa9e470134813726f4ba181f9a28a99d26",
"sha256": "f90e2c722cb01c3dbb9b9e265f4466d73d8d7d5d18a9f92e390ba74041217f8a",
"mdatSha256": "09ebf4098dca3dbf4a6d825d1c80df24bc12403740037f05e07d43acd97bc1b3",
"timescaleOffsets": [56, 308]
},
{
"file": "berdy_Sit_Idle_03_00001_.mp4",
"bytes": 881085,
"originalSha256": "187baf7ba514f1f89a7ccf30733a86981b6efc3a4607c3e27e92c0b2d5e93930",
"sha256": "4a52b20f0895bc19c4e1652ba45169b00a605deea977407df9e0274460edcc9f",
"mdatSha256": "42db502f5bfd5902451266023377aac9d0159f46ad80f83e5991086a865cf51f",
"timescaleOffsets": [56, 308]
}
]
}
1 change: 1 addition & 0 deletions scripts/check-i18n-strings.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const CHECKED_PATHS = [
"src/features/agents",
"src/features/automations",
"src/features/chat/ui",
"src/features/desktop-agent",
"src/features/experiments",
"src/features/home",
"src/features/projects",
Expand Down
98 changes: 98 additions & 0 deletions scripts/retime-berdy-media.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/usr/bin/env python3
"""Verify/reproduce the lossless HEVC-alpha cadence fix (Python standard library).

Run from any directory:
python3 scripts/retime-berdy-media.py # verify checked-in assets
python3 scripts/retime-berdy-media.py --apply # retime original assets, idempotent
python3 scripts/retime-berdy-media.py --restore # restore exact original bytes

The manifest pins original/output hashes and validated timescale field offsets.
Only mvhd/mdhd timescales change, NOT durations in ticks, sample/edit tables,
HEVC configuration or mdat. Movie/media clocks both speed up by 1.5. Retaining
all samples (including alpha and endpoints) avoids re-encoding or frame removal.
Native playback uses effective source speed / 1.5; never exceeds WebKit's 2x
full-frame threshold. No second variant, per-frame seeks, or extra media bytes.
"""

import argparse
import hashlib
import json
from pathlib import Path
import struct


def sha(data):
return hashlib.sha256(data).hexdigest()


def mdat_sha(data):
"""Hash media payloads, including MP4 boxes with 64-bit extended sizes."""
digest = hashlib.sha256()
offset = 0
payload_bytes = 0
while offset < len(data):
if len(data) - offset < 8:
raise ValueError("Truncated MP4 box")
size, kind = struct.unpack_from(">I4s", data, offset)
header = 8
if size == 1:
if len(data) - offset < 16:
raise ValueError("Truncated extended MP4 box")
size = struct.unpack_from(">Q", data, offset + 8)[0]
header = 16
elif size == 0:
size = len(data) - offset
if size < header or offset + size > len(data):
raise ValueError("Invalid MP4 box size")
if kind == b"mdat":
digest.update(data[offset + header:offset + size])
payload_bytes += size - header
offset += size
if not payload_bytes:
raise ValueError("Missing media payload")
return digest.hexdigest()


def main():
parser = argparse.ArgumentParser(description=__doc__)
modes = parser.add_mutually_exclusive_group()
modes.add_argument("--apply", action="store_true")
modes.add_argument("--restore", action="store_true")
args = parser.parse_args()
root = Path(__file__).resolve().parent.parent
manifest = json.loads((root / "scripts/berdy-media.json").read_text())
directory = root / "public/desktop-agent/berdy"
pending = []
for entry in manifest["assets"]:
path = directory / entry["file"]
data = path.read_bytes()
digest = sha(data)
if len(data) != entry["bytes"] or digest not in (
entry["originalSha256"], entry["sha256"]
):
raise SystemExit(f"Refusing unknown media: {path}")
if not args.apply and not args.restore and digest != entry["sha256"]:
raise SystemExit(f"Original media needs --apply: {path}")
# Validate each transformation in both directions, even in verify mode.
original = bytearray(data)
retimed = bytearray(data)
for offset in entry["timescaleOffsets"]:
if data[offset - 16:offset - 12] not in (b"mvhd", b"mdhd"):
raise SystemExit(f"Invalid clock offset: {path}")
struct.pack_into(">I", original, offset, manifest["originalTimescale"])
struct.pack_into(">I", retimed, offset, manifest["timescale"])
if sha(original) != entry["originalSha256"] or sha(retimed) != entry["sha256"]:
raise SystemExit(f"Unexpected timing transformation: {path}")
if mdat_sha(original) != entry["mdatSha256"] or mdat_sha(retimed) != entry["mdatSha256"]:
raise SystemExit(f"Unexpected media payload: {path}")
output = original if args.restore else retimed
if (args.apply or args.restore) and output != data:
pending.append((path, output))
# Fail validation of the entire catalog before writing any file.
for path, data in pending:
path.write_bytes(data)
print(f"Verified {len(manifest['assets'])} HEVC-alpha clips; changed {len(pending)}.")


if __name__ == "__main__":
main()
Loading
Loading