mirror of
https://github.com/browseros-ai/BrowserOS.git
synced 2026-05-14 16:14:28 +00:00
Compare commits
1 Commits
hermes-age
...
fix/cache-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f504702ec |
@@ -2,7 +2,7 @@
|
||||
R2_ACCOUNT_ID=
|
||||
R2_ACCESS_KEY_ID=
|
||||
R2_SECRET_ACCESS_KEY=
|
||||
R2_BUCKET=browseros-artifacts
|
||||
R2_BUCKET=browseros
|
||||
|
||||
# Public CDN base - used by cache:sync to GET manifest and artifacts
|
||||
R2_PUBLIC_BASE_URL=https://cdn.browseros.com
|
||||
|
||||
@@ -67,4 +67,13 @@ bun run --filter @browseros/build-tools emit-manifest -- --slice agents:openclaw
|
||||
NODE_ENV=development bun run --filter @browseros/build-tools cache:sync
|
||||
```
|
||||
|
||||
Development cache files land under `~/.browseros-dev/cache/vm/images/`. Production-mode cache files land under `~/.browseros/cache/vm/images/`.
|
||||
Pulls the published manifest and tarballs from R2 (`cdn.browseros.com/vm/`). Development cache files land under `~/.browseros-dev/cache/vm/images/`. Production-mode cache files land under `~/.browseros/cache/vm/images/`.
|
||||
|
||||
## Seed the dev cache from a local build
|
||||
|
||||
```bash
|
||||
bun run --filter @browseros/build-tools build:tarball -- --agent openclaw --arch arm64
|
||||
NODE_ENV=development bun run --filter @browseros/build-tools cache:sync:dev
|
||||
```
|
||||
|
||||
`cache:sync:dev` hardcodes `arm64` (all devs are on Apple Silicon), skips R2 entirely, and writes an arm64-only manifest + tarball into `~/.browseros-dev/cache/vm/` from `./dist/`. It refuses to run unless `NODE_ENV=development`. Use this when you want to test the server against a local tarball without publishing.
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"upload": "bun run scripts/upload-to-r2.ts",
|
||||
"download": "bun run scripts/download-from-r2.ts",
|
||||
"cache:sync": "bun run scripts/cache-sync.ts",
|
||||
"cache:sync:dev": "bun run scripts/cache-sync-dev.ts",
|
||||
"smoke:tarball": "bun run scripts/smoke-tarball.ts",
|
||||
"test": "bun test",
|
||||
"typecheck": "tsc --noEmit"
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env bun
|
||||
import { copyFile, mkdir, readFile, stat, writeFile } from 'node:fs/promises'
|
||||
import { homedir } from 'node:os'
|
||||
import path from 'node:path'
|
||||
import { PATHS } from '@browseros/shared/constants/paths'
|
||||
import type { Arch } from './common/arch'
|
||||
import {
|
||||
type AgentEntry,
|
||||
type AgentManifest,
|
||||
type Bundle,
|
||||
tarballKey,
|
||||
} from './common/manifest'
|
||||
import { sha256File, verifySha256 } from './common/sha256'
|
||||
|
||||
const ARM64: Arch = 'arm64'
|
||||
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
throw new Error(
|
||||
'cache:sync:dev refuses to run without NODE_ENV=development — it writes to ~/.browseros-dev/cache/vm/',
|
||||
)
|
||||
}
|
||||
|
||||
const pkgRoot = path.resolve(import.meta.dir, '..')
|
||||
const distDir = path.join(pkgRoot, 'dist')
|
||||
const bundle = JSON.parse(
|
||||
await readFile(path.join(pkgRoot, 'bundle.json'), 'utf8'),
|
||||
) as Bundle
|
||||
|
||||
const cacheRoot = path.join(
|
||||
homedir(),
|
||||
PATHS.DEV_BROWSEROS_DIR_NAME,
|
||||
PATHS.CACHE_DIR_NAME,
|
||||
)
|
||||
const imagesDir = path.join(cacheRoot, 'vm', 'images')
|
||||
const manifestPath = path.join(cacheRoot, 'vm', 'manifest.json')
|
||||
await mkdir(imagesDir, { recursive: true })
|
||||
|
||||
const agents: Record<string, AgentEntry> = {}
|
||||
for (const agent of bundle.agents) {
|
||||
const key = tarballKey(agent.name, agent.version, ARM64)
|
||||
const srcTarball = path.join(distDir, 'images', path.basename(key))
|
||||
await assertExists(srcTarball)
|
||||
|
||||
const sha256 = await sha256File(srcTarball)
|
||||
const sizeBytes = (await stat(srcTarball)).size
|
||||
const destTarball = path.join(cacheRoot, key)
|
||||
|
||||
if (await matchesExisting(destTarball, sha256)) {
|
||||
console.log(`cache hit: ${key}`)
|
||||
} else {
|
||||
await mkdir(path.dirname(destTarball), { recursive: true })
|
||||
await copyFile(srcTarball, destTarball)
|
||||
await verifySha256(destTarball, sha256)
|
||||
console.log(`seeded ${key}`)
|
||||
}
|
||||
|
||||
agents[agent.name] = {
|
||||
image: agent.image,
|
||||
version: agent.version,
|
||||
tarballs: { arm64: { key, sha256, sizeBytes } } as AgentEntry['tarballs'],
|
||||
}
|
||||
}
|
||||
|
||||
const manifest: AgentManifest = {
|
||||
schemaVersion: 2,
|
||||
updatedAt: new Date().toISOString(),
|
||||
agents,
|
||||
}
|
||||
await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`)
|
||||
console.log(`manifest written to ${manifestPath}`)
|
||||
|
||||
async function assertExists(filePath: string): Promise<void> {
|
||||
try {
|
||||
await stat(filePath)
|
||||
} catch {
|
||||
throw new Error(
|
||||
`missing ${filePath} — run: bun run build:tarball -- --agent <name> --arch arm64`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
async function matchesExisting(
|
||||
filePath: string,
|
||||
expectedSha: string,
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
await stat(filePath)
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
return (await sha256File(filePath)) === expectedSha
|
||||
}
|
||||
Reference in New Issue
Block a user