İçeriğe geç
Oleaflyv0.4.7

Oleafly'ın masaüstü uygulamasını frontend çalışma alanı, Rust servisleri ve sabit sürümlü sidecar'lar arasında nasıl böldüğü.

Oleafly’ın frontend’i bir pnpm çalışma alanıdır: uygulama kabuğu depo kökünde (src/), yeniden kullanılabilir frontend kodu ise packages/* altında odaklanmış on iki paket olarak yer alır. Tauri backend’i src-tauri/ içinde, yeniden kullanılabilir AI sağlayıcı ve agent kodu ise crates/oleafly-agent/ içinde bulunur. Frontend/Rust/sidecar genel görünümü için README’deki mimari diyagrama (yeni sekmede açılır), günlük komutlar için Geliştirme sayfasına bakın.

Bu belge şunları ele alır: her paketin ne olduğu, paketleri saf tutan bağımlılık tersine çevirme kuralları, özellikleri kabuğa bağlayan katkı kayıt sistemi, modül çözümlemesinin nasıl çalıştığı ve bir paketin nasıl eklenip çıkarılacağı.

Eskiden her özellik, uygulamanın Zustand store’larına, Tauri IPC istemcisine ve shadcn UI kitine doğrudan erişiyordu. Bu, özellikleri kabuktan ayrılmaz hale getiriyordu: hiçbir şey izole biçimde test edilemiyor, yeniden kullanılamıyor ya da tek başına değerlendirilemiyordu. Çalışma alanı bunu tersine çevirir. Paketler özellik mantığını barındırır ve ihtiyaç duydukları her şey için port adı verilen dar arayüzler tanımlar. Uygulama bu portları kendi store’ları ve Tauri istemcisi üzerinden uygular ve enjekte eder. Uygulama paketlere bağımlıdır, asla tersi değil.

Paketler TypeScript kaynağı olarak tüketilir (main alanları src/index.ts dosyasını gösterir). Derleme adımı yoktur, yayınlama yoktur, sürüm kayması yoktur: Vite, Vitest ve tsc, @oleafly/* paketlerini takma adlar (alias) aracılığıyla doğrudan paket kaynaklarına çözümler (bkz. Modül çözümlemesi).

PaketNe olduğuEnjekte edilen portlarÖnemli bağımlılıklar
@oleafly/latexSaf LaTeX/şekil mantığı: diyagram modeli, TikZ serileştiricisi (modelToTikz, gömülü model gidiş-gelişi), bağımsız belge oluşturucu (buildStandaloneDoc), şekil adı/bayt yardımcılarıyok (saf)yok
@oleafly/ai-coreRust kataloğuyla eşitlik içinde tutulan sağlayıcı görüntüleme metaverisi ve frontend model seçimiyok (saf)yok
@oleafly/latex-intelligenceEditör zekasının kullandığı LaTeX derlemi için doğrulanmış tipler ve veri erişimiyok (saf)yok
@oleafly/registryKatkı kayıt sistemi: ray sekmeleri, palet/omnibar komutları, AI araç takımları (ayrıntılar aşağıda)yok (katkılar kendi davranışlarını taşır)react (tipler)
@oleafly/preflightÖn denetim motoru: belge türü belirleme, kaynak kod/PDF/kaynakça kuralları, ATS ayrıştırma, erişilebilir dışa aktarma hazırlığı, puanlama. pdf-extract, @oleafly/preflight/pdf-extract alt yolu olarak dağıtılır; böylece pdf.js node test grafiklerinin dışında kalıryok (saf)pdfjs-dist (yalnızca alt yol)
@oleafly/pdf-to-latexYerel PDF’den LaTeX’e yeniden yapılandırma işlem hattı: satır gruplama, başlık ve sütun algılama, stil çıkarımı, sembol eşleme, şekil çıkarma, kaçış işleme ve belge birleştirme. pdf.js adaptörü, aynı node-test-grafiği nedeniyle @oleafly/pdf-to-latex/pdf-adapter alt yolu olarak dağıtılıryok (saf)pdfjs-dist (yalnızca alt yol)
@oleafly/wysiwygKısıtlı görsel editör çekirdeği: paylaşılan şema, LaTeX ve Markdown ayrıştırma/serileştirme ve desteklenmeyen kaynağı atmak yerine görünür tutan ham satır içi/blok düğümleryok (saf)yok
@oleafly/editorLaTeX, Typst ve Markdown için CodeMirror çekirdeği: CodeMirrorEditor, editör görünümü denetleyicisi (insertAtCursor, gotoLine, …), diller + tamamlamalar, tema, katlama, yapışkan başlıklar, linter’lar, latex-mask, matematik önizlemesi (LaTeX için KaTeX, Typst için Typst), Typst düzenleme yardımcıları ve LaTeX’ten Typst’a matematik dönüştürmesi, LaTeX ve Typst için yerinde Görsel mod (@oleafly/editor/visual), arama paneli, yazım/dil bilgisi linter’larıEditorHost (belge modeli + ayarlar, hook biçimli), SpellHost (yazım denetleyici/Harper/sözlük), setBibKeysProvider, extraExtensions/extraKeymap@codemirror/*, @replit/codemirror-vim, @replit/codemirror-emacs, katex
@oleafly/previewSanallaştırılmış pdf.js görüntüleyicisi (PdfViewer), SyncTeX sayfa denetleyicisi (gotoRect, pageClickToBp), pdf.js worker’ı ve WebView polyfill’leri (@oleafly/preview/polyfills, main.tsx içinde ilk içe aktarılan)onOpenLink prop’u (sistem tarayıcısı bağlantıları), setPdfLoggerpdfjs-dist
@oleafly/diagramTikZ, Typst (fletcher) ve Mermaid için görsel diyagram oluşturucu: React Flow tuvali, şekil denetçisi, Çiz/Kod sekmeleri, derle-önizle-ekle akışı. src/languages/ içindeki her dilin bir yazıcısı, bir okuyucusu ve kendi ekleme ve dosya biçimleri vardır; tuval ve kod iki yönde de eşzamanlı yürürDiagramHost (LaTeX derleme, Typst ve Mermaid işleme, dosya GÇ’si, editöre ekleme, AI düzeltme), DiagramKit bağlamı (Button/Tooltip/Select/toast/theme)@xyflow/react, @codemirror/*, @oleafly/latex, @oleafly/editor
@oleafly/ai-toolsOnay farkındalı mutasyonlarla proje, araştırma, bellek ve şekil araç tanımlarıAiToolsHost (dosyalar, derleme, sembol dizini, şekil işlem hattı, editör)@oleafly/latex
@oleafly/templatesYeni proje şablon galerisi (iki adımlı sihirbaz, kategoriler, önizlemeler, ilerleme gösteren tek seferlik varlık indirmeleri)TemplatesHost (önizlemeler, varlık indirmeleri, günlükleme), TemplatesKit (Button/Tooltip), prop olarak renk seçenekleriUI yardımcıları dışında yok

Bağımlılık yönü, katı biçimde zorunlu kılınır:

Uygulama kabuğu ve paketler birbirine nasıl bağlıdırsrc/ içindeki uygulama kabuğu Zustand depolarını, UI kitini, Tauri istemcisini ve port bağdaştırıcılarını barındırır. Bağdaştırıcılar, @oleafly özellik paketlerinin bildirdiği EditorHost gibi portları uygular ve uygulama onları enjekte eder. Özellik paketleri latex, ai-core ve registry gibi saf yaprak paketlere bağlı olabilir. Tauri istemcisi Rust arka ucuyla Tauri IPC üzerinden konuşur. Paketler uygulamayı, depolarını veya Tauri API'lerini asla içe aktarmaz.Uygulama kabuğu, src/@oleafly/* paketleriDepolarZustandBağdaştırıcılarPortları uygularUI kitishadcnTauri istemcisisrc/lib/tauri.tsÖzellik paketleriEditorHost gibi portları bildirirYaprak paketlerlatex, ai-core, registryRust arka ucusrc-tauri, crates/oleafly-agentEnjekte ederTauri IPCPaketler uygulamayı, depolarını veya Tauri API'lerini asla içe aktarmaz.Uygulama kabuğu ve paketler birbirine nasıl bağlıdırsrc/ içindeki uygulama kabuğu Zustand depolarını, UI kitini, Tauri istemcisini ve port bağdaştırıcılarını barındırır. Bağdaştırıcılar, @oleafly özellik paketlerinin bildirdiği EditorHost gibi portları uygular ve uygulama onları enjekte eder. Özellik paketleri latex, ai-core ve registry gibi saf yaprak paketlere bağlı olabilir. Tauri istemcisi Rust arka ucuyla Tauri IPC üzerinden konuşur. Paketler uygulamayı, depolarını veya Tauri API'lerini asla içe aktarmaz.Uygulama kabuğu, src/@oleafly/* paketleriDepolarUI kitiTauri istemcisiBağdaştırıcılarRust arka ucusrc-tauri, cratesÖzellik paketleriPortları bildirirYaprak paketlerlatex, ai-core, registryTauri IPCEnjekte ederPaketler uygulamayı, depolarınıveya Tauri API'lerini asla içe aktarmaz.
Uygulama paketlere bağlıdır ve bildirdikleri portlar için bağdaştırıcıları enjekte eder. Paketler uygulamayı asla içe aktarmaz.

Bir paket asla src/ konumundan (@/…), bir Zustand store’undan, @tauri-apps/* paketlerinden veya uygulamanın UI bileşenlerinden içe aktarma yapmamalıdır. Saflık denetimi, çıkarma temizliğinin bir parçasıdır:

Terminal penceresi
grep -rn 'from "@/\|@tauri\|zustand' packages/*/src # must return nothing

Paketler arayüzleri tanımlar. Uygulama bunları genellikle kendi store’larını sarmalayan modül düzeyinde bir adaptör nesnesi olarak bir kez uygular. Sık görülen dört biçim:

Host portları: her paket için, ihtiyaç duyduğu servisleri kapsayan tek bir interface XHost. Uygulama, adaptörü store’lara ilişkin imperatif okumalarla kurar:

// src/lib/ai-tools.ts (app adapter, abridged)
const HOST: AiToolsHost = {
getProjectId: () => useFilesStore.getState().projectId,
readFileContent, // Tauri client passthrough
recompile: () => useCompileStore.getState().recompile(),
insertAtCursor, // editor controller
// ...
};
export const createOleaflyTools = (opts?) => createOleaflyToolsCore(HOST, opts);

Yalnızca uygulamaya ait kaygıları adaptörün içinde tutmak, bağımlılıkların paketlere sızmasını da önler. Sağlayıcı kimlik bilgileri ve istekleri Rust tarafında kalır; böylece frontend paketleri yalnızca arayüzlerinin gerektirdiği durumu ve sonuçları alır.

UI kitleri: yapısal tipli bileşenlerden oluşan bir React bağlamı (veya prop): Button: ComponentType<{ variant?: …; onClick?: () => void }>. Uygulama, shadcn bileşenlerini değiştirmeden geçirir, çünkü daha küçük yapısal tip uyumludur. Kitler ayrıca toast ve bir useThemeMode() hook’u taşır.

Hook biçimli portlar: uygulama durumuna abone olması gereken paketler için. Editörün EditorHost’u, olay dinleyicileri için hook üyeleri (useActivePath(), useSettings()) ve bunların imperatif eşlerini (getActivePath()) içerir. Kurallar: host nesnesi modül düzeyinde olmalıdır (kararlı kimlik) ve use* üyeleri hook’ları koşulsuz çağırmalıdır.

Modül tekil örnekleri: yatay kesen yapıştırıcı kod için setPdfLogger(fn), setSpellHost(host), setBibKeysProvider(fn) hiçbir şey yapmayan varsayılanlara sahiptir ve uygulama shim’i tarafından bir içe aktarma yan etkisi olarak kurulur.

Her çıkarma işlemi, paketi yeniden dışa aktaran (veya sarmalayan) eski @/… yolunda ince bir dosya bıraktı; böylece tüketiciler ve mevcut vi.mock(...) yolları hiç değişmedi. Örnekler: src/components/editor/cm/controller.ts (yeniden dışa aktarma), src/components/pdf/PdfViewer.tsx (kabuk eklentisinin bağlantı açıcısını enjekte eden sarmalayıcı), src/lib/ai-tools.ts (adaptör + özgün fabrika imzaları). Yeni kod @oleafly/* paketlerini doğrudan içe aktarabilir. Shim’ler uyumluluk için vardır, tercih edilen yol olarak değil.

@oleafly/registry, özelliklerin kabuğun onları tanımasına gerek kalmadan uygulama kabuğuna takılmasını sağlar. Üç katkı türü vardır:

  • Ray sekmeleri (registerRailTab): simge, bölüm (explore / review / assist, boş olmayan bölümler arasına ayraç çizilir), isteğe bağlı when(ctx) görünürlüğü, isteğe bağlı useBadge() hook’u (ör. Git değişiklik sayısı) ve kenar çubuğu panel bileşeni.
  • Komutlar (registerCommand): komut paletine (Cmd+K, group ile gruplanır) ve/veya surfaces aracılığıyla omnibara (Cmd+P) sunulur. Etiketler ve simgeler bağlamın işlevleri olabilir (ör. “Açık temaya geç”).
  • AI araç takımları (registerAiToolset): bir sohbet modu ("chat", "figure") bir araç takımı fabrikasına eşlenir. Sohbet paneli, sabit kodlanmış bir takım yerine etkin modun araç takımını arar.

AppContext ({ projectId, projectKind, theme }), her işleme yüzeyi tarafından kendi aboneliklerinden oluşturulur; böylece when/label koşulları tepkisel kalır.

Kayıt statiktir: src/contributions/ tüm yerleşikleri (sekmeler, komutlar, araç takımları) kaydeder ve main.tsx, kabuk bağlanmadan önce registerContributions() işlevini bir kez çağırır. Rail, Sidebar, CommandPalette, SearchOmnibar ve ChatPanel yalnızca kayıtlı olanı işler.

Bir özelliğin sekmesini veya komutunu eklemek için onu kaydedin. Kabukta değişiklik gerekmez:

// src/contributions/my-feature.tsx (called from src/contributions/index.ts)
registerRailTab({
id: "review", label: "Review", icon: MessageSquare,
section: "review", order: 55,
when: (ctx) => ctx.projectKind !== "image",
panel: ReviewPanel,
});
registerCommand({
id: "omnibar.review", surfaces: ["omnibar"], order: 45,
label: "Open review", keywords: "review comments",
run: () => useSettingsStore.getState().setRailTab("review"),
});

Bu dahili bir API’dir, eklenti SDK’sı değildir: biçimler serbestçe değişebilir ve hiçbir şey dinamik olarak yüklenmez. Gerçek bir tüketici ortaya çıkana dek ertelenenler: dışa aktarma menüsü biçimleri, ayar şemaları ve proje türü davranışlarının katkı olarak sunulması.

Paketler kaynak olarak tüketildiği için aynı takma ad üç yerde bildirilir ve bir paket eklendiğinde üçünün de eşitlemiş olması gerekir:

  1. tsconfig.json → compilerOptions.paths. @oleafly/preflight/pdf-extract gibi alt yolların kendi açık girdisi olmalıdır.
  2. vite.config.ts → resolve.alias. Dize takma adları önek olarak eşleşir; bu sayede alt yollar ek bir girdi olmadan çözümlenir.
  3. vitest.config.ts → aynı resolve.alias, ayrıca test.include yolu packages/**/*.test.ts dosyalarını kapsamalıdır. Aksi takdirde taşınan testler sessizce çalışmanın dışında kalır.

Ayrıca: kök package.json, her pakete "workspace:*" üzerinden bağımlıdır ve src/styles/globals.css içinde @source "../../packages" bulunduğundan Tailwind v4 sınıf adları için paket kaynaklarını tarar.

Yalnızca Vite’e özgü içe aktarımlar (?worker&url worker’ları, CSS içe aktarımları), takma adlar kaynağı gösterdiği için paket kaynaklarından değişmeden çalışır. pdf.js’yi peşine takan her şeyi, node ortamındaki testlerin içe aktardığı barrel dosyalarının dışında tutun: pdf-extract ile önizleme paketinin görüntüleyicisinin yalnızca DOM’un var olduğu yerden erişilebilir olmasının nedeni budur.

  • Testler kaynağın yanında yer alır (packages/*/src/*.test.ts) ve uygulama testleriyle aynı pnpm test komutunda çalışır. Dosya taşırken test sayısını izleyin.
  • Bağımlılıklar gevşek bildirilir ("react": "*"). pnpm, gerçek sürüm tabanlarının bulunduğu köke göre tekilleştirme yapar. Paketin içe aktarmadığı bağımlılıkları bildirmeyin.
  • Bir pakette yapılan her değişiklik için geçitler: pnpm exec tsc --noEmit, pnpm build, pnpm test (değişmeyen test sayısı) ve yukarıdaki saflık grep’i.
  • Yeni bir şey çıkarmak: dosyaları git mv ile taşıyın (geçmiş izler), portları tanımlayın, eski yollarda shim’ler bırakın, üç takma adı bağlayın, ardından geçitleri çalıştırın. Üzerinde etkin olarak iterasyon yaptığınız bir özelliği o sırada çıkarmayın.
  • Lisanslama: her paket, uygulama gibi AGPL-3.0-or-later lisanslıdır.

src/, gerçekten frontend uygulaması olan her şeyi barındırır: Zustand store’ları, Tauri IPC istemcisi (src/lib/tauri.ts), shadcn UI kiti, düzen/kabuk bileşenleri, port adaptörleri ve shim’ler, src/contributions/ ve doğası gereği store’a bağlı özellik yapıştırıcıları (ön denetim paneli arayüzü, satır içi AI düzenleme eklentisi ve editöre extraExtensions olarak enjekte edilen kod ya da üzerine gelme zekası). Tauri komutları ve işletim sistemi entegrasyonu src-tauri/ içinde kalır. Sağlayıcı istemcileri, akış ve agent orkestrasyonu crates/oleafly-agent/ içinde yer almalıdır; böylece gizli bilgiler ve sağlayıcı istekleri webview dışında kalır.

Görsel önizlemesi

Yapay zekâ yanıtları yüklenemedi

Yeniden deneyin ya da dokümanlarda arama yapın.