GitHub Copilot Runtime’ın Rust Portu Neyi Değiştirdi

GitHub, Copilot agent runtime katmanını TypeScript/Node.js’ten Rust’a taşıdı. Runtime artık ayrı bir Node.js süreci başlatmadan uygulamanın içine gömülebiliyor ve port sürecinde yüz binlerce satırlık kod üretildi.

GitHub, Copilot CLI, Copilot uygulaması ve Copilot SDK’nın altında çalışan Copilot agent runtime katmanını TypeScript/Node.js yığınından Rust’a taşıdı. Ortaya 800.000 satırı aşan üretim Rust kodu çıktı; çalışma zamanı artık ayrı bir Node.js süreci başlatmadan doğrudan uygulamanın içine gömülebiliyor. Aşağıda portun gerekçesi, izlenen strateji ve süreç boyunca ortaya çıkan sayılar var.

Neden taşıma ihtiyacı doğdu

Copilot agent runtime yalnızca Copilot CLI’nin motoru değil. Microsoft, GitHub ve ekosistem tarafındaki giderek büyüyen bir çözüm kümesinin ortak altyapısı: Copilot CLI ve Copilot uygulamasının yanı sıra VS Code ve Visual Studio’nun güncel sürümleri, Copilot cloud agent (CCA), Copilot Code Review, Copilot Cowork, Copilot Studio ve Excel, Outlook, PowerPoint, Word gibi ürünler bu runtime’ı kullanıyor. Bu ürünlerin çoğu başlangıçta kendi agent döngüsünü yazmıştı, sonra hepsi runtime’ın giriş noktası olan GitHub Copilot SDK’ya geçti. Bir yerde yapılan düzeltme böylece hepsinde birden geçerli oluyor.

Sıkıntı paylaşımın kendisinden değil, paylaşılan şeyin doğasından geliyordu. CLI, mantıksal olarak bir agent döngüsünün üzerine oturan terminal arayüzüydü (TUI); tüm yığın TypeScript ile, Node.js çatısı, V8 motoru, arayüzde ise Ink ve React kullanılarak yazılmıştı. Bir konsol uygulaması için makul bir tercih, çünkü başlatma süresi, tepkisellik ve bellek tüketimi kabul edilebilir sınırlarda kalıyor. Aynı uygulama farklı ortamlarda, hızlı başlatma ve düşük bellek yüküyle yüksek sunucu yoğunluğu gerektiren senaryolarda kullanıldığında tablo değişiyor.

Süreç sınırının maliyeti

Mimari de sorunu büyütüyordu. CLI hızla yazılıp yayına alındığı için TUI ile runtime ayrı katmanlara bölünmek yerine iç içe geçmişti. Programatik erişim için bir SDK gerektiğinde, katmanlar net ayrılmadığından pragmatik bir karar verildi ve SDK, CLI’nin üzerine kondu. Mantıken tersi beklenirdi. CLI’ye stdin’den komut okuyup stdout’a yanıt yazan başsız (headless) bir mod eklendi, dışarıdaki süreçle işlev çağrıları JSON-RPC üzerinden taşınmaya başladı.

Pratikte bu, SDK’dan yeni bir istemci oluşturmanın yeni bir süreç başlatması demekti.

const client = new CopilotClient();
await client.start(); // spawns the CLI as a subprocess
const session = await client.createSession({
/*... */
});

Bu sürecin Node ve V8’i barındırması, TypeScript’ten üretilen hatırı sayılır miktarda JavaScript’i ayrıştırması, bytecode üretmesi ve sıcak kodu sonraki JIT katmanlarında optimize etmesi gerekiyordu. V8’in bellek yükü, Node’un varsayılan olarak CPU yoğun işleri seri hale getiren iş parçacığı modeli ve yalnızca fonksiyon çağrısı yapmak için zorunlu süreçler arası iletişim de cabası. C#, Python, Go, Java ve Rust SDK’larının her biri, uygulamanın başka hiçbir amaçla ihtiyaç duymadığı ikinci bir dil çalışma zamanının bedelini ödüyordu, yani istemci başına en az 100 MB civarı çalışma kümesi. Her olay, her mesaj, soyutlanmış oturum dosya sistemi üzerindeki her okuma ve yazma süreç sınırından geçiyordu. Node tarafındaki bir çökme oturumu da beraberinde götürüyor, dağıtımı yapan herkes en az iki süreci izlemek, gözlemlemek ve hata ayıklamak zorunda kalıyordu.

Neden Rust seçildi

Hedeflenen runtime için konulan kriterler şunlardı:

  • TUI içermeyen, arayüzlerin ve servislerin üzerine düzgün biçimde katmanlanabileceği bağımsız bir kütüphane olması
  • Bağımlılığı ve ek yükü minimum bir dille yazılması
  • Süreç dışına zorlanmak yerine süreç içine temiz biçimde gömülebilmesi
  • Performans, ölçeklenebilirlik ve güvenilirlik açısından üst düzey özelliklere sahip bir dil kullanılması
  • Altı Copilot SDK dilinin (C#, TypeScript, Python, Rust, Go, Java) kendi FFI mekanizmasıyla sorunsuz kullanabileceği kadar iyi birlikte çalışabilirlik sunması
  • Daha modern bir güvenlik duruşu, daha az tedarik zinciri riski ve tasarımı gereği doğru kod yazımına daha fazla destek veren bir araç zinciri sağlaması

Ekip deneyimi ve sektörün yönü gibi daha yumuşak gerekçelerle birlikte tercih Rust’tan yana kullanıldı. GitHub bunun “her büyük TypeScript programı Rust olmalı” anlamına gelmediğini açıkça belirtiyor; gereksinimler C ABI üzerinden gömülebilirliği, düşük başlatma ve kararlı durum yükünü, öngörülebilir kaynak kullanımını öne çıkardığı için Rust uygun oldu. Bedeli de yaşam süreleri (lifetime) ve paylaşılan durumun açıkça ifade edilmesi gibi ek karmaşıklıklar oldu.

Çalışma iki ilişkili başlıkta yürüdü: TUI’ye özgü kodu runtime’dan ayırıp SDK’nın genel yüzeyi üzerine katmanlamak ve runtime katmanını %100 Rust’a taşımak. İkincisi tamamlandı. CLI bugün hala birkaç noktada doğrudan runtime iç yapılarını çağırıyor, tamamen SDK yüzeyine taşınması devam eden bir iş.

Yerinde (in-place) port stratejisi

Mayıs 2026 başındaki ilk port planı runtime’ı yaklaşık 130.000 satır TypeScript olarak tahmin ediyordu. Kapsam belirleme açısından makul olsa da bu ölçüm iki nedenle yanıltıcı çıktı: TUI katmanında sıkışmış parçalar port sırasında runtime katmanına indirildi, bu arada onlarca agent destekli geliştirici haftada yüzlerce PR birleştirerek depodaki TypeScript miktarını sürekli artırdı. Her şey hesaba katıldığında portun içinden yaklaşık 430.000 satır üretim TypeScript’i geçtiği tahmin ediliyor. Süreç boyunca runtime’a ~300.000 satır üretim TypeScript’i girdi, ~430.000 satır çıktı; ~1.200.000 satır üretim Rust’ı girdi, ~365.000 satır çıktı. TypeScript satır sayısının görece sabit görünmesi, aslında ciddi bir çalkantıyı gizliyordu.

Bu ölçekte bir yeniden yazım için iki ana yaklaşım var: büyük patlama (ya herkesin durup main üzerinde yazması ya da uzun ömürlü bir dalda paralel geliştirme) ve yerinde bileşen bazlı port (ya atomik değişim ya da TypeScript ve Rust sürümlerinin sıcak takas edilebilir tutulduğu A/B yöntemi). GitHub atomik değişimli yerinde portu seçti. Gerekçeler:

  • Kimse çalışmayı durdurmuyor; main aktif kalıyor. Yalnızca uzun süredir açık kalan ve eş zamanlı port edilen kodlara dokunan PR’lar rebase gerektiriyor.
  • Her PR mevcut TypeScript uygulamasını Rust’ı çağıran ince bir shim ile değiştirip eski kodu aynı atomik değişiklikte siliyor; yeni kod anında gerçek ortamda çalışıyor ve main her an sevk edilebilir kalıyor.
  • Her PR tek bir bileşeni ya da dilimi taşıdığı için diff’ler insan veya agent incelemesine daha uygun.
  • Portların çoğu görece küçük ve kendi içinde kapalı; fazla büyük TypeScript bileşenleri önce daha kolay taşınabilir parçalara refaktör edilebiliyor.
  • CLI ve SDK genelindeki tüm uçtan uca testler her adımda yeni Rust kodu üzerinde koşuyor; zorunlu bir test başarısız olduğunda PR birleşmiyor.

A/B varyantı pratik bir nedenle elendi. İki dilde, iki bağımlılık kümesiyle aynı bileşenin iki sürümünü yaşatmak ciddi karmaşıklık ekliyor. Üstelik dikkatli paralel geçişten en çok fayda görecek alt sistemler, paralelleştirmesi en zor olanlar. Oturum orkestrasyonu bunun tipik örneği. Bir bayrağa bakıp iki farklı sürümü çağırabileceğiniz saf bir fonksiyon değil; değişebilir durumu sahipleniyor, iki yönde geri çağrımlar tetikliyor, neredeyse tüm alt sistemlerin içinden geçiyor. Bir bileşeni taşımayı zorlaştıran bağlaşım, onu gölgelemeyi de neredeyse imkansız kılıyor.

Kademeli yayınla doğrulama

Doğrulamanın son halkası kademeli dağıtımdı. Büyük patlamada tüm port uzun ömürlü bir dalda beklerdi ve tüketiciler gözden kaçan tüm regresyonlarla aynı anda karşılaşırdı. Bunun yerine her sürüm küçük ve bilinen bir port kümesi taşıdı. Yaklaşık on dört buçuk haftalık port penceresinde main üzerinden 135 sürüm yayınlandı: 100 ön sürüm ve 35 kararlı sürüm, günde ortalama 1,3 sürüm. Açılan port PR sayısı da günde yaklaşık 1,3 oldu. Yedi günlük bir npm örneklemesinde ön sürümler indirmelerin yalnızca %10,5’ini oluşturdu, yani ilk maruziyet sınırlı tutulmuştu; bu sırada geri bildirim kanalları izlenip düzeltmeler bir sonraki ön sürüme yetiştirildi. Bildirilen sorunlar yakın tarihli değişikliklerle daha kolay ilişkilendirilebildiği için kök neden analizi de hızlandı. Portun uzun bir süreye yayılması burada dezavantaj değil, işleyişin lehine çalışan bir tercih oldu.

21 Ağustos itibarıyla runtime %100 üretim Rust’ıydı: 832.378 satır üretim Rust kodu, 468.689 satır Rust birim testi ve ek olarak 174.675 satır uçtan uca TypeScript testi. Ayrı GitHub Copilot SDK deposu ise Node.js, Python, Go, C#, Rust ve Java tarafında ~130.000 satır daha uçtan uca test kodu ekliyor.

İşe nereden başlandı

Tam gaz başlamadan önce mekanizma uçtan uca denendi. İlk iki PR Rust çalışma alanını, araç zincirini, lint kurallarını, CI’ı, derleme hattını ve kodlama talimatlarını kurdu; ardından runtime crate’i, kod üretimi ve interop kalıpları, I/O ile paylaşılan durumu olmayan ve zaten güçlü testlere sahip saf mantık ilkelleri taşınarak tanıtıldı. Bunlar birleştikten sonra ilk asıl port PR’ı, yan etkisiz üç yardımcı fonksiyonu tüm süreçten geçirdi. Bu adımlar depo yerleşimi, FFI, paketleme, test ve inceleme konusundaki varsayımları, sonraki çok daha büyük portların yeniden kullanacağı sözleşmelere dönüştürdü.

Plan yapraklardan içeriye doğru ilerledi. Saf yardımcılar, içerik dışlama (content exclusion), shell yardımcıları ve oturum dosya sistemi işlemleri çeviri ile test kalıbını oluşturdu; ardından durumlu alt sistemler geldi, sonra araçlar, hook’lar, model istemcileri ve MCP bu parçaların üzerine bindi. Runtime’ın en bağlaşık ve en az paralelleşebilir kısmı olan oturum orkestrasyonu sona bırakıldı.

Dönem Pull request Medyan değişen satır
1–15 Mayıs 8 3.250
16–31 Mayıs 2 9.421
1–15 Haziran 40 5.073
16–30 Haziran 31 8.253
1–15 Temmuz 10 9.514
16–31 Temmuz 14 28.159
1–15 Ağustos 19 13.861
16–30 Ağustos 4 99.445

Küçük yaprak bileşenlerden oluşan erken portlar hızlı ilerledi, büyük alt sistemler ise tek adımda taşınmadı. MCP desteği yedi ayrı PR üzerinden ilerledi, araçlar altı parçalık bir seride taşındı, ardından orkestrasyonun taşınması ve kalan TypeScript’in emekliye ayrılması için ek çalışma gerekti. Hook’lar, kimlik doğrulama, telemetri, eklentiler, ayarlar ve kalıcılık da benzer yollardan geçti.

Öne çıkan sonuç

GitHub’ın aktardığına göre kodun büyük bölümünü AI agent’ları yazdı, main‘e inen 128 pull request tek bir büyük geçişi beklemek yerine kademeli olarak sevk edildi. Kaçınılmaz birkaç regresyon yol boyunca hızla bulunup düzeltildi, runtime’ın performansı ise kat kat iyileşti. Agent’lardan önce bütün bir geliştirici ekibinin bir ila iki yılını alacak bir proje, ekibin geri kalanı runtime’ın yeteneklerini genişletmeyi sürdürürken ağırlıklı olarak tek bir geliştirici tarafından birkaç ayda tamamlandı.

Kaynaklar ve İleri Okuma

Bu yazı yapay zeka (büyük dil modelleri) ile hazırlanmış, insan editör tarafından incelenmiştir. İçerik üretim sürecimiz.
Aşkın KILIÇ

20+ yıl deneyimli Azure Solutions Architect. Microsoft sertifikalı bulut mimari ve DevOps danışmanı. Azure, yapay zekâ ve bulut teknolojileri üzerine Türkçe teknik içerikler üretiyor.

AZ-305AZ-104AZ-500AZ-400DP-203AI-102

Bu içerik işinize yaradı mı?

Benzer içerikleri kaçırmamak için YouTube ve GitHub hesaplarımı takip edin.

Haftalık Bülten

Her pazar özenle seçilmiş teknoloji yazıları doğrudan e-postanıza gelsin.

4 Yorum

  1. Rust’a geçiş kararı mantıklı ama yüz binlerce satırlık kodun portlanması nasıl yönetildi asıl merak ettiğim o. Otomatik araçlar mı kullandılar yoksa elle mi yazdılar acaba? Node.js sürecinden kurtulmak özellikle editör entegrasyonları için ciddi fark yaratır bence.

  2. Node.js sürecinden kurtulup embed edilebilir hale gelmesi bence en büyük kazanım, özellikle editör entegrasyonları için ciddi fark yaratır. Merak ettiğim şu: yüz binlerce satırlık portu elle mi yaptılar yoksa Copilot’un kendisine mi yazdırdılar?

  3. Rust’a geçişle ayrı Node.js süreci derdinin kalkması bence en büyük kazanım, özellikle editör entegrasyonlarında fark hissedilir. Merak ettiğim şu, yüz binlerce satırı porta ederken davranış farkları nasıl test edildi acaba? Bu arada şu yazınız da işime yaramıştı: Microsoft Graph PowerShell 5.1 Desteği Ne Değişti? — https://www.ask

  4. Rust’a geçiş furyası Copilot’a da sıçramış demek. Ayrı Node.js süreci başlatmadan gömülebilmesi bence en büyük kazanım, özellikle editör eklentilerinde başlangıç süresi baya fark eder. Yüz binlerce satırı porta ederken davranış farklılıklarını nasıl test etmişler acaba, o kısım merak konusu.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

✉

Haftalık Bülten

Azure, DevOps ve Yapay Zeka dünyasındaki en güncel içerikleri her hafta doğrudan e-postanıza alın.

Spam yok. İstediğiniz zaman iptal edebilirsiniz.
📱
Uygulamayı Yükle Ana ekrana ekle, çevrimdışı oku
Kategoriler
Ara
Paylaş
WhatsApp
İçindekiler
← Microsoft Agent Framework Harn...
Ubuntu 26.04 Runner GA: ubuntu... →
📩

Gitmeden önce!

Her pazar özenle seçilmiş teknoloji yazıları ve AI haberleri doğrudan e-postanıza gelsin. Ücretsiz, spam yok.

🔒 Bilgileriniz güvende. İstediğiniz zaman ayrılabilirsiniz.

📬 Haftalık bülten: Teknoloji + AI haberleri
Beni Takip Et Yeni Azure / AI / DevOps yazılarını GitHub ve RSS üzerinden takip edin.