AI Agent intervjujska pitanja šesta serija: TUI renderovanje, LSP dijagnostička injekcija, Git snapshot, Runtime API 13 pitanja
content
01, Koja rešenja postoje za terminal renderovanje Agent CLI
Tri.
Prvo je čisto tekstualni izlaz.
Direktno print. Dobra strana je najjača kompatibilnost, svaki terminal ga može normalno prikazati. Loša strana je takođe vrlo očigledna, nema boje, nema sažimanje, nema statusnu traku, mala gustina informacija, loše korisničko iskustvo.
Drugo je Inline striming izlaz, takođe PaiCLI podrazumevano rešenje. Dole je fiksirana statusna traka, prikazuje trenutni model, potrošnju tokena, udio kontekstnog prozora, vreme izvršenja.
Najvažnije je što poziv alata može da se sažme. Npr. Agent je pročitao 3 fajla, terminal prikazuje samo jednu liniju sažetka, pritisakom Ctrl+O se može proširiti i videti detaljan sadržaj. Izmena fajlova takođe ima inline diff poređenje, šta je izmenjeno odmah se vidi.

Treće je punoekranski TUI. Zauzima ceo prozor terminala, može napraviti stablo fajlova, raspored sa više kolona, iskačući prozor. Najbogatije korisničko iskustvo, ali zahteva punoekranski mod. PaiCLI na osnovu Lanterna biblioteke implementirao ovo rešenje, ima zonu za razgovor, statusnu traku i modalni iskačući prozor za odobrenje.
Konačno smo odabrali Inline kao podrazumevani način interakcije, jer postiže dobar balans između gustine informacija i korisničkog iskustva. Približno je Claude Code i Qoder CLI načinu interakcije.
02, Šta je DECSTBM? Kako se implementira statusna traka
DECSTBM puno ime je DEC Set Top and Bottom Margins, redosled prečeka definisan od VT100 terminala, koristi se za postavljanje zone klizanja terminala.
Može se jednom ESC[1;{n}r instrukcijom reći terminalu da samo linije 1 do n učestvuju u klizanju, preostale linije ostaju nepromenjive.

PaiCLI-jev pristup je da ostavi 2 linije na dnu terminala koje ne učestvuju u klizanju. Glavni sadržaj se na vrhu normalno kliza i prikazuje, 2 linije na dnu se uvek fiksirano prikazuju statusne informacije.
Prva linija je ključni status, uključuje HITL prekidač odobrenja, broj povezanih MCP Server-a, broj učitanih Skill-ova.
Druga linija su podaci o izvršenju, uključuje naziv trenutnog modela, fazu izvršenja, iskorišćenost kontekstnog prozora (vizuelno se prikazuje progres trakom), broj ulaznih i izlaznih tokena, broj keširanja, procenu troškova, vreme izvršenja i trenutni radni direktorijum.
Obrati pažnju, ne svi terminali podržavaju DECSTBM.
PaiCLI pri inicijalizaciji proverava mogućnosti terminala, proverava da li podržava ANSI, da li je veličina terminala dovoljna (najmanje 5 linija 20 kolona), i da li je korisnik putem promenljive okruženja PAICLI_NO_STATUSBAR ručno isključio statusnu traku.
Kako se kontroliše učestalost osvežavanja statusne trake
Osvežavanje statusne trake pokreće pozivatelj, obično se jednom po prijemu tokena ili svakom Agent-ovom iteracijom.
Unutar renderera može se po potrebi primeniti throttling, da bi se izbjeglo treperenje terminala usled visokofrekventnog crtanja.
03, Šta je LSP dijagnostička injekcija? Koja je vrednost za Agent
"Agent je promenio kod, kompajliranje ne uspeva, šta sada?"
PaiCLI-jeva LSP dijagnostička injekcija rešava ovaj problem.
Celi proces je ovakav: nakon što Agent izvrši operaciju pisanja fajla, sistemski edit hook se automatski pokreće.
Dijagnostički modul za izmenjene fajlovi vrši sintaksnu analizu, prikuplja informacije o greškama i upozorenjima, zatim formatira rezultate dijagnostike u struktuirani tekst, pre sledećeg LLM zahteva injektuje se u kontekst kao sintetička poruka. LLM videći preciznu poziciju i opis kompajlacijske greške, u sledećem odgovoru može automatski popraviti.
Trenutna MVP verzija za Java fajlove koristi JavaParser za laku sintaksičnu dijagnostiku. Formatiranje rezultata dijagnostike takođe ima značaj, svaka dijagnostika sadrži nivo greške, putanju fajla, broj linije, broj kolone i detaljne informacije, npr. [error] Foo.java:42:15 nedostaje tačka-zapeta (javaparser). LLM sa ovim formatom može precizno locirati specifičnu liniju koda, direktno popraviti.

Dobra strana ovoga je što Agent ne mora čekati da korisnik ručno kompajlira da bi otkrio kompajlacijsku grešku i automatski popravio, realizovan je automatski krug uređivanje-dijagnostika-popravka.
04, Kako radi Git Side-History snapshot
"Agent je pokvario fajl, kako vratiti unazad?"
Agent-ovo menjanje fajlova je rizično, zato su mehanizmi snapshot-a i rollback-a neophodni.
Korisnik-ov projekat već ima git, Agent svaki put nakon izmene fajla commit-uje, to li to ne radi?
Ne, postoje tri razloga.
Prvi, Agent-ovi automatski snapshot-i će zagađivati korisnički git log, korisnički commit istorija mora biti značajna, ne sme biti smeće.
Drugi, korisnik možda radi rebase ili merge, Agent-ov commit će direktno ometati git stanje mašine.
Treći, snapshot nije značajan commit, mešanje u formalnoj grani samo dodaje šum.
PaiCLI-jevo rešenje je da napravi potpuno nezavisni side-git repozitorijum.
Snapshot podaci se čuvaju u direktorijumu ~/.paicli/snapshots/, organizuju se po heš vrednosti putanje projekta, ne dira korisnički .git direktorijum. Na dnu se koristi JGit za sve operacije, ne zavisi od instaliranog git komanda na mašini.

Momenti snapshot-a su podeljeni u tri tipa.
Prvi je snapshot pre razmišljanja, pre svakog početka Agent-ovog razmišljanja se sinhrono kreira, osigurava se da je bazno stanje već sačuvano.
Drugi je snapshot posle razmišljanja, nakon završetka razmišljanja se asinhrono kreira, beleži konačno stanje izmena ovog kruga.
Treći je snapshot pre povraćaja, pre korisničeve operacije povraćaja se automatski kreira, sprečava da sama operacija povraćaja izgubi trenutno stanje.
Snapshot pre razmišljanja mora biti sinhron, zato što je prethodno stanje pre nego Agent menja fajlove bazna linija za rollback. Snapshot posle razmišljanja može biti asinhron, tako neće blokirati sledeći korisnički unos.
Kada korisnik izvrši komandu /restore <N>, može se vratiti na N-ti snapshot pre razmišljanja, fajlovi se vraćaju u radni direktorijum. Proces povraćaja upisuje sadržaj snapshot-a natrag u radni direktorijum, korisničev .git je potpuno nepromenjen.
Ko je identitet commit-a kod snapshot-a
Svi snapshot-i imaju jedinstven informaciju o autoru commit-a: PaiCLI Snapshot <snapshot@paicli.local>, potpuno izolovano od korisničevog git identiteta.
05, Da li snapshot povraćaj utiče na korisničev .git
"Da li je operacija povraćaja bezbedna? Da li može poremeti korisničev sopstveni git status?"
Neće.
Side-git repozitorijum i korisničev .git su dva potpuno nezavisna sistema. Operacija povraćaja radi samo jednu stvar: upisuje sadržaj fajlova iz snapshot-a natrag u radni direktorijum. Korisničev .git direktorijum, staging area, grančne informacije su svi nepromenjeni.
Nakon povraćaja, git status će prikazati da su fajlovi izmenjeni, ove izmene su potpuno iste kao da ih je korisnik ručno menjao. Korisnik može odabrati commit da zadrži ove izmene, ili discard da ih odbaci, inicijativa je potpuno u korisnikovim rukama.

Ovde je najvažniji dizajn snapshot pre povraćaja.
Korisnik se vraća na stanje pre nekrug razmišljanja, šta ako se povraćaj pogrešno?
Zato što je pre operacije povraćaja automatski napravljen snapshot pre povraćaja, može se ponovno vratiti.
Proces povraćaja takođe vraća rezultat objekat, govori korisniku koji fajlovi su vraćeni, koji fajlovi su obrisani (zato što u snapshot-u ne postoje). Informacije su transparentne, korisnik jasno zna šta je operacija povraćaja promenila.
06, Kako je dizajniran asinhroni pozadinski zadatak
"Agent izvršava veliki zadatak, npr. refakturiše ceo modul, korisnik mora čekati?"
Ne mora.
PaiCLI ima sistem pozadinskih zadataka, korisnik kroz /task add "dodaj hello Autor" šalje zadatak pa može raditi nešto drugo.

Celokupna arhitektura je ovakva:
Zadatak se kroz komandu šalje u SQLite red, u pozadini postoji Worker Pool (podrazumevano 2 workera) koji stalno izvlači zadatke iz reda i izvršava. Svaki worker pokreće nezavisnu Agent nit za obradu zadatka, posle završetka ažurira status.

Životni ciklus zadatka je enqueued → running → completed / failed / canceled.
Worker pri preuzimanju zadatka koristi mehanizam transakcije da garantuje atomičnost.
Prvo se upit jedan zadatak sa statusom enqueued, zatim se optimističnom zaključavanju (proverava da li je status i dalje enqueued) ažurira na running. Ako ažuriranje utiče na 0 redova, znači da ga je drugi worker preuzeo, trenutni worker se vraća i nastavlja da traži sledeći. Sprečava se da više workera izvršava isti zadatak.
Šta ako zadatak ne uspe
Worker nakon hvatanja izuzetka označava status zadatka kao failed, greška se upisuje u bazu podataka.
Korisnik kroz /task log <id> može videti detaljan sažetak izvršenja i detalje greške. Ako je prekid niti (npr. korisnik ručno otkazao), status se označava kao canceled. Bilo koja situacija, worker nastavlja da obrađuje sledeći zadatak u redu, neće se desiti da jedan neuspešni zadatak zaustavi ceo sistem.
07, PaiCLI je samo alat komandne linije? Zašto treba HTTP API
Dodavanjem HTTP API-ja, PaiCLI postaje programabilni Agent motor. CI/CD pipeline može pozvati PaiCLI za automatsku reviziju koda ili generisanje testova, IDE plugin može kroz HTTP integrisati Agent sposobnosti, veb panel može kroz pretraživač zameniti terminal interakciju.
Srce ima tri krajnje tačke:
POST /v1/threadskreira nit razgovora,POST /v1/threads/{id}/turnspokreće jedan krug interakcije,GET /v1/threads/{id}/eventsdobija SSE striming događaje. Nakon kreiranja niti se šalje jedan krug interakcije, zahtev se izvršava asinhrono, klijent kroz SSE krajnju tačku u realnom vremenu prima tok događaja.
Prvi korak, prvo podesi API Key (obavezno)
export PAICLI_RUNTIME_API_KEY=test_key_12345Drugi korak, pokreni Runtime API servis
java -jar target/paicli-1.0-SNAPSHOT.jar serve --http --port 8080
Treći korak, kreira nit razgovora.
curl -X POST http://127.0.0.1:8080/v1/threads \
-H "Authorization: Bearer test_key_12345" \
-H "Content-Type: application/json"
Četvrti korak, šalje jedan krug interakcije.
curl -X POST http://127.0.0.1:8080/v1/threads/<thread_id>/turns \
-H "Authorization: Bearer test_key_12345" \
-H "Content-Type: application/json" \
-d '{"input":"hello world"}'Obrati pažnju na zamenu <thread_id> sa ID-jem koji je vratio prethodni korak.
curl -X POST http://127.0.0.1:8080/v1/threads/thread_0c25b7d80f8f/turns \
-H "Authorization: Bearer test_key_12345" \
-H "Content-Type: application/json" \
-d '{"input":"hello world"}'
Peti korak, pretplata na tok događaja.
curl http://127.0.0.1:8080/v1/threads/<thread_id>/events \
-H "Authorization: Bearer test_key_12345"
curl http://127.0.0.1:8080/v1/threads/thread_0c25b7d80f8f/events \
-H "Authorization: Bearer test_key_12345"
Dizajn sigurnosti ima tri sloja zaštite.
Prvi sloj, samo sluša 127.0.0.1, ne prihvata eksternu konekciju, sa mrežnog nivoa izoluje napadački površinu.
Drugi sloj, mora se podesiti API Key, svaki zahtev mora nositi ključ u Authorization zaglavlju ili X-PaiCLI-API-Key zaglavlju, neuspešna verifikacija direktno vraća 401.
Treći sloj, implementiran na osnovu JDK ugrađenog HttpServer, ne uvodi Netty, ne uvodi Spring Web, nula dodatnih zavisnosti, smanjuje potencijalnu sigurnosnu rupa.
Niti i podaci događaja su takođe perzistentni, čuvaju se u SQLite bazi podataka ~/.paicli/runtime/runtime.db.
Tabela događaja je indeksirana po thread_id i autoincrement id-u, SSE krajnja tačka podržava ?after=<lastId> parametar za inkrementalno dovlačenje, klijent nakon prekida ponovnog povezivanja neće izgubiti događaje.
08, Agent može obrađivati samo tekst? Slike se mogu proslediti
Može.
Korisnik nalepi sliku, PaiCLI može prepoznati sadržaj slike.

Ovo je originalna slika.

Kako PaiCLI implementira
Prvo je adaptacija protokola.
OpenAI kompatibilan protokol polje content treba da proširi iz čisto tekstualnog stringa u listu blokova sadržaja, uključuje dva tipa text i image_base64. Pri čistom tekstu ostaje nepromenjen string format (kompatibilnost sa starim interfejsom), kad ima sliku se prebacuje na niz format.
Drugo je kompresija slike.
Slika se računa po tile-u, jedna slika može potrošiti nekoliko hiljada tokena. PaiCLI-jeva strategija obrade ima nekoliko koraka:
Prvo se proverava da li veličina fajla prelazi 50MB gornju granicu unosa, zatim se proverava da li nakon base64 kodiranja prevazilazi 5MB API ograničenje. Ako ne prelazi i nema providni kanal, koriste se originalni podaci. Ako ima providni kanal, prvo se pozadina uniformno popuni belom pa kodira, zato što različiti modeli ne bi dosledno obrađivali alpha kanal. Ako prelazi ograničenje veličine, prvo se srazmerno smanjuje do 2000x2000, zatim pokušava PNG bezgubitno kodiranje. Ako PNG i dalje prelazi, postepeno smanjuje JPEG kvalitet (od 0.85 do 0.25 ukupno pet stepova) sve dok veličina fajla ne zadovoljava zahtev.
Ako se slika smanji, kako se rešava mapiranje koordinata
U metapodacima nakon kompresije će biti označena proporcionalna relacija između originalne i prikazane veličine, npr. "koordinata množena sa 2.00 se može mapirati nazad na originalnu sliku". Ako Agent treba da anotira ili locira specifičnu poziciju na slici, može na osnovu ove proporcije prevesti nazad u originalne koordinate.
09, Koji je dizajnerski pristup abstrakcije Renderer interfejsa
"Postoji nekoliko rešenja za renderovanje, kako se Agent-ova osnovna logika odvaja od renderovanja?"
Klasičan patern strategije.
PaiCLI definira jedinstven Renderer interfejs, sve operacije vezane za renderovanje se odnose na ovaj interfejs.

Npr.
appendToolCallsznači "ima grupu poziva alata za prikaz", kako se prikazuje, blok sažimanja, punoekranska kolona ili čist tekst, odlukuje konkretna implementacija.appendDiffznači "ima izmenu fajla za poređenje prikaza",updateStatusznači "promenjen status izvršenja",promptApprovalznači "potrebna je potvrda korisnika za operaciju".
Svaki metod odgovara jednoj interakciji nameni, nije vizuelna komponenta.

Kako tri implementacije svako rade?
Inline mod koristi ANSI boje i blokove sažimanja za prikaz poziva alata, koristi inline diff za prikaz poređenja fajlova, dnu statusnu traku za prikaz statusa, terminalni prompt za odobrenje.
Punoekranski TUI izlaz poziva alata u panel zone razgovora, diff se prikazuje kao sistemska poruka, odobrenje koristi modalni iskačući prozor (kroz CountDownLatch vrši sinhronizaciju preko niti).
Čisti tekst mod je samo println, pozivi alata se grupišu po nazivu i prikazuju sažetak, odobrenje koristi petlju unosa komandne linije.
10, Kao što se LSP dijagnostička injekcija razlikuje od crvenog vala u IDE
"Ovo LSP dijagnostičko injektiranje, li nije isto što i crveni talas u IDE?"
U suštini je isto, oba vrše sintaksnu analizu koda i izlaze dijagnostičke informacije. Ali se razlikuje konzument.
Crveni talas u IDE, konzument je čovek. Čovek vidi talas, očima locira grešnu poziciju, čitanjem plutajućeg saveta razume uzrok greške, zatim ručno menja kod.
Agent-ova LSP dijagnostička injekcija, konzument je LLM. Dijagnostički rezultati se formatiraju u struktuirani tekst, ubacuju se u kontekst sledećeg zahteva. LLM nakon prijema u procesu zaključivanja automatski locira i popravlja greške. Trenutak pokretanja je post-edit hook, samo nakon upisa fajla se pokreće jednom. Način prikaza je čist tekst, nosi broj linije, kolonu, nivo greške.

Format svake dijagnostike je [error] Foo.java:42:15 nedostaje tačka-zapeta (javaparser), broj linije, kolona, nivo greške, izvor je odmah jasno.
Uz to postoji i verzija u boji za terminal prikaz, error crvena, warning žuta, info siva, olakšava korisniku da i u terminalu vidi rezultate dijagnostike.
11, Da li Side-Git snapshot veliko utiče na performanse? Kako optimisati
"Snapshot treba da obiđe sve fajlove, računa heš, na velikim projektovima koliko utiče na performanse?"
Kroz četiri strategije smo uticaj držali u prihvatljivom opsegu.
Prvo je isključivanje direktorijuma sa velikim fajlovima. Podrazumevano isključuje .git, node_modules, target, dist, .idea, *.class, *.jar, kao i PaiCLI-jev sopstveni snapshot direktorijum. Korisnik može kroz konfiguraciju dodati dodatna pravila isključenja. Podudaranje isključenja podržava tri načina: tačno podudaranje, prefiks direktorijuma i glob uzorak.
Drugo je razlikovanje sinhronog i asinhronog. Snapshot pre razmišljanja mora biti sinhron, zato što je bazno stanje pre Agent-ove izmene fajlova mora biti sigurno sačuvano. Snapshot posle razmišljanja je asinhron, ne blokira sledeći korisnički unos.
Treće je gornja granica broja snapshot-a. Podrazumevano se čuva najskorijih 50 krugova snapshot-a, preko se automatski čisti. Takođe je pružena komanda za ručno čišćenje.
Četvrto je korišćenje JGit čiste Java implementacije, ne forkira git podproces. Izbjegava se trošak kreiranja i uništavanja procesa, pisanje objekata se dešava u Java heap-u.

12, Zašto Runtime API koristi SSE a ne WebSocket
"Vaš API koristi SSE, zašto ne WebSocket?"
Ovo je klasično pitanje tehničkog izbora.
Prvo pogledajmo zahteve scenarija: korisnik šalje jedan unos, čeka Agent striming rezultat. Ovo je tipičan jednosmeran striming scenario, server strana kontinuirano šalje, klijent samo prima.
U ovom scenariju SSE ima tri prednosti.
Prvi, to je obična HTTP dugačka veza, svi HTTP klijenti i proxy mogu podržati, ne brine se da li enterprise firewall blokira. WebSocket koristi nezavisan ws:// protokol, neki proxy i firewall podrška nije stabilna.
Drugi, SSE implementacija je mnogo jednostavnija, server strana samo treba da kontinuirano piše data: formatirane tekstualne linije u HTTP odgovor. WebSocket treba da radi rukovanje handshake nadogradnje, frame kodiranje i dekodiranje, održavanje heartbeat, itd. dodatnu logiku.
Treći, održava konzistentnost sa OpenAI-jevim striming API-om. OpenAI-jev streaming response je takođe SSE, postojeći klijentski biblioteki mogu se direktno koristiti.

PaiCLI-jeva SSE implementacija takođe radi detaljnu obradu.
Svaki događaj nosi autoincrement id, klijent nakon prekida ponovnog povezivanja kroz ?after=<lastId> parametar radi inkrementalnog dovlačenja, neće izgubiti događaje tokom prekida.
Tipovi događaja su podeljeni u thread.created, turn.started, message.delta, turn.completed četiri tipa, klijent može tačno kontrolisati logiku obrade različitih tipova događaja.
13, Z perspektive proizvoda, u čemu se ogleda "dobroća" Agent CLI
"Poslednje otvoreno pitanje. Kako mislište, koji kvalitet treba imati dobar Agent CLI?"
Predvidivost. Korisnik može predvideti šta će Agent sledeći uraditi. PaiCLI-jev Plan-and-Execute mod pre izvršenja prvo prikazuje plan, HITL odobrenje daje korisniku pravo potvrde za opasne operacije. Agent nije crna kutija, mora biti jasno šta će menjati fajl, koju komandu izvršiti, korisnik mora znati.
Mogućnost povraćaja. Agent je pokvario, može se vratiti unazad. Git Side-History snapshot je upravo ovu svrhu, jedna /restore <N> komanda može se vratiti u stanje pre izmene.
Posmatljivost. Korisnik može videti šta Agent radi. Potrošnja tokena se u realnom vremenu ažurira u statusnoj traci, iskorišćenost kontekstnog prozora se vizuelno prikazuje progres trakom, pozivi alata imaju sažeti dnevnik, operacijska revizija se beleži u JSONL fajl. Ove informacije daju korisniku jasno sagledanje o stanju izvršenja Agent-a.

Progresivnost. Novi korisnici sa ReAct modom mogu obaviti osnovne zadatke, napredni korisnici po potrebi otključavaju Plan mod, Team saradnju, Skill mehanizam, MCP proširenje. PaiCLI-jeva panel komandi (pritisak / pokreće) je takođe ova ideja, česti su stavljani napred.
Otpornost na greške. Mreža je prekinuta, MCP Server pao, LLM timeout, svaka greška ima elegantnu degradaciju, neće se direktno srušiti i izaći.
Kako staviti PaiCLI na životopis
Naziv projekta: PaiCLI -- AI Agent komandna linija
Opis projekta: AI Agent CLI proizvod na osnovu Java 17, uporediv sa Claude Code-om, od ReAct petlje evoluirao do kompletne forme Agent proizvoda, pokriva TUI terminal renderovanje, LSP dijagnostičku injekciju, Git snapshot rollback, asinhrone zadatke, Runtime API i multimodalni unos.
Tehnološki stack: Java 17, JLine (terminal interakcija), Lanterna (punoekranski TUI), JGit (Git operacije), JavaParser (sintaksička dijagnostika), SQLite (perzistencija zadataka), JDK HttpServer (Runtime API), ANSI/VT100 redovi
Ključne odgovornosti:
- Abstrahiran Renderer interfejs, ujedinjuje tri terminalne render forme Inline striming, Lanterna punoekranski, Plain čist tekst, Agent-ova osnovna logika je potpuno odvojena od renderovanja. Inline mod na osnovu DECSTBM implementira dnu stalnu statusnu traku, pozivi alata podržavaju sažimanje/širenje i inline diff poređenje.
- Implementirano LSP dijagnostičko injektiranje, Agent svaki put nakon upisa fajla automatski pokreće JavaParser sintaksičku dijagnostiku, rezultati dijagnostike se formatiraju u struktuirani tekst i injektuju se u sledeći LLM zahtev, realizovan je automatski krug uređivanje-dijagnostika-popravka.
- Dizajniran sistem Git Side-History snapshot-a, na osnovu JGit održava nezavisni side-git repozitorijum, pre i posle svakog kruga razmišljanja automatski snapshot, ne zagađuje korisničevu .git istoriju. Podržava jednostavno vraćanje.
- Implementiran Runtime API i sistem asinhronih pozadinskih zadataka, na osnovu JDK HttpServer + SSE pruža RESTful interfejs, podržava CI/CD i IDE plugin integraciju. Stanje zadatka je perzistentno u SQLite, nakon restarta procesa se automatski vraća, garantuje at-least-once semantiku izvršenja.
