Een agentische ontwikkelomgeving.
Het is open source en werkt met de modellen die u al gebruikt. Start een agent op de ene machine en ga verder met dezelfde sessie op een andere.
Ik heb 100 uploads gedraaid op een verbinding die één op de vijf verzoeken verliest. Mislukte uploads daalden van 23 naar 1.
De ene fout was een bestand dat de server weigerde, dus opnieuw proberen hielp niet.
De uploadsnelheid staat nu in de header naast de bestandsnaam en verdwijnt als de wachtrij leeg is.
Ik ga ermee aan de slag. Ik meld me hier zodra er iets te zien is.
Nagebootst en de oorzaak gevonden. De fix is klaar voor review.
Exponentiële backoff toegevoegd aan de uploadwachtrij. Een mislukt stuk wordt tot vijf keer opnieuw geprobeerd en de voortgangsbalk toont de poging. De tests dekken de timeout en het 503-geval.
Vroeger werd een mislukt stuk weggegooid. Nu vraagt de wachtrij het backoff-beleid om een wachttijd en plant de nieuwe poging, zodat elke retry via één plek loopt.
Na vijf mislukte pogingen faalt de chunk definitief en stopt de upload met een duidelijke fout, zodat een dode verbinding niet eindeloos opnieuw probeert.
De wijziging aan de wachtrij staat in src/upload/queue.ts, en src/upload/backoff.ts bevat de wachttijden.
De wachtrij schrijft de status van elke chunk naar schijf. Nu koppel ik het pad na een herstart.
Bij het starten leest de wachtrij de bewaarde status en stuurt alleen onafgemaakte chunks, dus een bestand van 2 GB begint niet opnieuw.
De strategie zegt dat we de markt op moeten, dus daar heb ik een functie voor toegevoegd.
1export async function goToMarket() {2await ship();3await tellDenis();4}
Eén test slaagt. De markt heeft nog niet gereageerd.
De test las het bestand voordat de watcher het had geschreven. Nu wacht hij op de flush, en 200 runs op rij slagen.
1test('reads the synced file', async () => {2await writeFile(path, 'hello');3await watcher.flushed(path);4const text = await readFile(path);5expect(text).toBe('hello');6});
Het wachten zit in de testhelper, dus de andere sync-tests krijgen de fix ook.
De nieuwe pagina is klaar. Ik moet de migratie van de instellingen uitvoeren voordat ik de tabbladen verwijder.
| Oud tabblad | Nieuwe sectie |
|---|---|
| Algemeen | Werkruimte |
| Weergave | Werkruimte |
| Accounts | Profiel |
De migratie verwerkte 212 instellingen zonder fouten en de oude tabbladen zijn weg. Alle instellingen staan nu op één pagina.
Ik stop hier. De oude tabbladen blijven tot u de migratie wilt uitvoeren.
Twee bevindingen. De sessiecookie verloopt nooit, en de redirect na het inloggen accepteert elke URL. De rest ziet er goed uit.
Klaar. De gekozen fixes zijn doorgevoerd, elk met een test, en wat u hebt uitgesteld blijft als opmerking op de pull request.
Begrepen. Er is niets veranderd, en de bevindingen blijven als opmerkingen op de pull request.
Ik heb het nieuwe commando op een schone machine geprobeerd en het werkt.
1bun add -g uploader2uploader --help
Het oude curl-commando werkt ook nog, dus dat kan als alternatief blijven.
Klaar. Het nieuwe commando staat waar u het wilde, en het oude blijft als alternatief.
De meeste tijd gaat op aan het lezen van alle bestanden bij elke zoekopdracht. Een index verkort dat, en kleine repo's veranderen nauwelijks.
De index werkt bij wanneer een bestand verandert, dus een volledige herbouw is nooit nodig.
De boom laadt nu uit een cache op schijf en vernieuwt op de achtergrond. Alleen de wachttijd verandert.
- Cachetreffers
- 94%
- Grootte op schijf
- 2.1 MB
- Laadtijd van de boom
- 40 ms
De cache leegt zichzelf als de branch verandert.
Gevonden. Een leeg bestand wordt null, en de code leest er meteen een veld uit.
1export function loadConfig(path: string) {2const text = readFileSync(path, 'utf8');3if (text.trim() === '') return defaults;4return { ...defaults, ...parse(text) };5}
Nu telt een leeg bestand als standaardconfiguratie, en een kapot bestand geeft een duidelijke fout.
Vijf nieuwe issues. Drie zijn echte bugs, en één daarvan kan wachten tot de volgende release.
| Issue | Soort |
|---|---|
| Upload stalls at 99% on Safari | bug |
| Crash on a file named final_final_v2_🦆.mov | bug |
| Progress bar jumps back after resume | bug |
| Drag a folder into the upload list | feature |
| Is there a size limit? Asking for a 400 GB log file | question |
Ik heb ze allemaal gelabeld en het duplicaat aan de oudere melding gekoppeld.
Waar werken we aan in uploader?
Mislukte uploads opnieuw proberen
Exponentiële backoff toegevoegd aan de uploadwachtrij. Een mislukt stuk wordt tot vijf keer opnieuw geprobeerd en de voortgangsbalk toont de poging. De tests dekken de timeout en het 503-geval.
Vroeger werd een mislukt stuk weggegooid. Nu vraagt de wachtrij het backoff-beleid om een wachttijd en plant de nieuwe poging, zodat elke retry via één plek loopt.
const result = await sendChunk(chunk); if (!result.ok) return fail(chunk); if (!result.ok) { const delay = backoff.next(chunk.attempt); if (delay === null) return fail(chunk); return schedule(chunk, delay); } progress.advance(chunk.size); const DELAYS = [500, 1000, 2000, 4000, 8000]; export const backoff = { next(attempt: number) { return DELAYS[attempt] ?? null; } }; 1import { backoff } from './backoff';2import { sendChunk } from './client';3import { progress } from './progress';4import type { Chunk, UploadResult } from './types';56// TODO: remove before launch (added in 2023)7const MAX_PARALLEL = 4;8const queue: Chunk[] = [];9let running = 0;1011export function enqueue(chunks: Chunk[]) {12queue.push(...chunks);13void drain();14}1516async function drain() {17while (running < MAX_PARALLEL && queue.length > 0) {18const chunk = queue.shift();19if (!chunk) return;20running += 1;21await upload(chunk);22running -= 1;23}24}2526export async function upload(chunk: Chunk): Promise<UploadResult> {27const result = await sendChunk(chunk);28if (!result.ok) {29const delay = backoff.next(chunk.attempt);30if (delay === null) return fail(chunk);31return schedule(chunk, delay);32}33progress.advance(chunk.size);34return done(chunk);35}3637function schedule(chunk: Chunk, delay: number) {38chunk.attempt += 1;39progress.retrying(chunk);40setTimeout(() => enqueue([chunk]), delay);41}
Draait op uw machine. Bereikbaar vanaf elke plek.
De desktopapp draait agents op uw computer en maakt verbinding met uw servers. Koppel een telefoon één keer met een QR-code; daarna bereikt die ze via Private Relay, end-to-end versleuteld en zonder open poort.
Waar werken we aan in uploader?
Waar werken we aan in uploader?
Waar werken we aan in uploader?
Geen sessies gevonden.
const result = await sendChunk(chunk); if (!result.ok) { const delay = backoff.next(chunk.attempt); if (delay === null) return fail(chunk); return schedule(chunk, delay); }
const DELAYS = [500, 1000, 2000, 4000, 8000]; export const backoff = { next(attempt: number) { return DELAYS[attempt] ?? null; } };
test('retries a chunk after a 503', async () => { server.respondWith(503); await upload(chunk); clock.tick(500); expect(server.calls).toBe(2); });
Eén taak, meerdere modellen.
Stuur dezelfde prompt tegelijk naar meerdere modellen. Elke uitvoering kan een eigen worktree en branch krijgen. Houd het resultaat dat u het best bevalt, of voeg de antwoorden samen tot één.
Lees een grote diff als rondleiding.
De walkthrough zet een grote diff in de volgorde waarin hij logisch is, legt elke stap in één zin uit en markeert de belangrijkste wijziging, zodat u weet wat u eerst leest.
Uw tickets en tools, één klik verderop.
Start een sessie vanuit een GitHub-issue, een pull request of een Linear-ticket, en de agent krijgt de hele discussie. De integratiecatalogus heeft meer dan 160 diensten, waaronder Figma en Sentry, en elk installeert u met één klik.
Geef het een doel of een planning.
Stel een doel in en de agent werkt beurt na beurt door, tot een aparte controle zegt dat het klaar is of vastzit. Geplande taken starten zelf een sessie, elke ochtend of één keer volgende dinsdag.
Van mensen die het gebruiken.
Berichten waar we niet om vroegen.
I've had a deep experience with openchamber. I think my choice was right. This thing is really useful, smooth and silky. Go try it out quick, I strongly recommend it, no more messing around blindly.
@realchendahuang Was looking for a way to run agents from my phone, remotely on my server, other than tmux. Found OpenChamber. It is INSANELY good, highly recommended.
@NihilSineTheo Seriously, I've spent almost the whole week trying to find a tool that made sense to orchestrate agents and, as a dev (actually, a devops), openchamber is the only one that felt natural and logical.
@1un4rPunk I just want to say the app itself is phenomenal. The level of polish is just unreal. I saw OpenChamber back when it was a small project, I think maybe a couple months ago, and now it is unrecognizable. Truly amazing work. The latest release with its streaming feature is everything I could have possibly asked for and more. It is gorgeous and smooth.
Installeer het op de machine die u al hebt.
De desktopapp op macOS, Windows of Linux, of één opdracht op een server. Open het daarna vanaf waar u ook bent.
OpenChamber verzamelt niets over uw werk. De code valt onder de MIT-licentie, dus iedereen kan het controleren.
Activiteit
Kunnen de wachttijden in de config? Op mobiel willen we misschien langere.
Goed idee. De wachttijden zijn nu één array, dus dat kan in een vervolg-PR.