{"locale":"tr","source":{"rawBase":"https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/docs","githubBase":"https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs","editBase":"https://github.com/earendil-works/pi/edit/main/packages/coding-agent/docs"},"redirects":[{"from":"/docs/latest/session","to":"/docs/latest/session-format"},{"from":"/docs/latest/tree","to":"/docs/latest/sessions"}],"fileToSlug":{"compaction.md":"compaction","containerization.md":"containerization","custom-provider.md":"custom-provider","development.md":"development","environment-variables.md":"environment-variables","extensions.md":"extensions","index.md":"index","json.md":"json","keybindings.md":"keybindings","llama-cpp.md":"llama-cpp","models.md":"models","packages.md":"packages","prompt-templates.md":"prompt-templates","providers.md":"providers","quickstart.md":"quickstart","rpc.md":"rpc","sdk.md":"sdk","security.md":"security","session-format.md":"session-format","sessions.md":"sessions","settings.md":"settings","shell-aliases.md":"shell-aliases","skills.md":"skills","terminal-setup.md":"terminal-setup","termux.md":"termux","themes.md":"themes","tmux.md":"tmux","tui.md":"tui","usage.md":"usage","windows.md":"windows"},"pages":{"tr":{"compaction":{"title":"Sıkıştırma ve Dal Özetleme","markdown":"Yüksek Lisans'ların sınırlı bağlam pencereleri vardır. Konuşmalar çok uzadığında, Pi yeni çalışmaları korurken eski içeriği özetlemek için sıkıştırmayı kullanır. Bu sayfa hem otomatik sıkıştırmayı hem de branch summarization'yi kapsar.\n\n**Kaynak dosyalar** ([pi-mono](https://github.com/earendil-works/pi-mono)):\n- [`packages/coding-agent/src/core/compaction/compaction.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) - Otomatik sıkıştırma mantığı\n- [`packages/coding-agent/src/core/compaction/branch-summarization.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) - Şube özeti\n- [`packages/coding-agent/src/core/compaction/utils.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/compaction/utils.ts) - Paylaşılan yardımcı programlar (dosya izleme, serileştirme)\n- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/session-manager.ts) - Giriş türleri (`CompactionEntry`, `BranchSummaryEntry`)\n- [`packages/coding-agent/src/core/extensions/types.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/extensions/types.ts) - Uzantı etkinlik türleri\n\nProjenizdeki TypeScript tanımları için `node_modules/@earendil-works/pi-coding-agent/dist/`'yi inceleyin.\n\n## Genel Bakış\n\nPi'nin iki özetleme mekanizması vardır:\n\n| Mekanizma | Tetiklemek | Amaç |\n|-----------|---------|---------|\n| Sıkıştırma | Bağlam eşiği aşıyor veya `/compact` | Bağlamı boşaltmak için eski mesajları özetleyin |\n| Şube özeti | `/tree` navigasyon | Dalları değiştirirken bağlamı koruyun |\n\nHer ikisi de aynı yapılandırılmış özet formatını kullanır ve dosya işlemlerini kümülatif olarak izler. Sıkıştırma ve dal özeti istekleri, yeni yönlendirme oturumu kimliklerini kullanır ve sağlayıcı tarafından desteklendiğinde, bu tek seferlik istemlerin yeniden kullanılma olasılığı düşük olduğundan bilgi istemi önbelleğine yazma işlemlerini devre dışı bırakır.\n\n## Sıkıştırma\n\n### Tetiklendiğinde\n\nOtomatik sıkıştırma şu durumlarda tetiklenir:\n\n```\ncontextTokens > contextWindow - reserveTokens\n```\n\nVarsayılan olarak `reserveTokens` 16384 jetondur (`~/.pi/agent/settings.json` veya `<project-dir>/.pi/settings.json` olarak yapılandırılabilir). Bu, LLM'nin yanıtına yer bırakıyor.\n\nİsteğe bağlı talimatların özete odaklandığı `/compact [instructions]` ile manuel olarak da tetikleyebilirsiniz.\n\n### Nasıl Çalışır?\n\n1. **Kesme noktasını bul**: `keepRecentTokens`'ye (varsayılan 20k, `~/.pi/agent/settings.json` veya `<project-dir>/.pi/settings.json`'de yapılandırılabilir) ulaşılana kadar jeton tahminlerini toplayarak en yeni mesajdan geriye doğru yürüyün\n2. **Mesajları çıkar**: Önceki tutulan sınırdan (veya oturum başlangıcından) kesme noktasına kadar olan mesajları toplayın\n3. **Özet oluştur**: Yapılandırılmış biçimde özetlemek için LLM'yi arayın ve önceki özeti mevcut olduğunda yinelenen bağlam olarak iletin\n4. **Girişi ekle**: `CompactionEntry`'yi özet ve `firstKeptEntryId` ile kaydedin\n5. **Yeniden yükle**: `firstKeptEntryId` tarihinden itibaren özet ve mesajlar kullanılarak oturum yeniden yüklenir\n\n```\nBefore compaction:\n\n  entry:  0     1     2     3      4     5     6      7      8     9\n        ┌─────┬─────┬─────┬─────┬──────┬─────┬──── ─┬──────┬─────┬─────┐\n        │ hdr │ usr │ ass │ tool │ usr │ ass │ tool │ tool │ ass │ tool│\n        └─────┴─────┴─────┴──────┴─────┴─────┴──────┴──────┴─────┴─────┘\n                └────────┬───────┘ └──────────────┬──────────────┘\n               messagesToSummarize            kept messages\n                                   ↑\n                          firstKeptEntryId (entry 4)\n\nAfter compaction (new entry appended):\n\n  entry:  0     1     2     3      4     5     6      7      8     9     10\n        ┌─────┬─────┬─────┬─────┬──────┬─────┬──── ─┬──────┬─────┬─────┬─────┐\n        │ hdr │ usr │ ass │ tool │ usr │ ass │ tool │ tool │ ass │ tool│ cmp │\n        └─────┴─────┴─────┴──────┴─────┴─────┴──────┴──────┴─────┴─────┴─────┘\n               └──────────┬──────┘ └──────────────────────┬───────────────────┘\n                 not sent to LLM                    sent to LLM\n                                                         ↑\n                                              starts from firstKeptEntryId\n\nWhat the LLM sees:\n\n  ┌────────┬─────────┬─────┬─────┬──────┬──────┬─────┬──────┐\n  │ system │ summary │ usr │ ass │ tool │ tool │ ass │ tool │\n  └────────┴─────────┴─────┴─────┴──────┴──────┴─────┴──────┘\n       ↑         ↑      └─────────────────┬────────────────┘\n    prompt   from cmp          messages from firstKeptEntryId\n```\n\nTekrarlanan sıkıştırmalarda özetlenen aralık, sıkıştırma girişinde değil, önceki sıkıştırmanın korunan sınırında (`firstKeptEntryId`) başlar ve tutulan giriş yolda bulunamazsa önceki sıkıştırmadan sonraki girişe geri döner. Bu, önceki sıkıştırmadan sağ çıkan mesajları bir sonraki özetleme geçişine de dahil ederek korur. Pi ayrıca yeni `CompactionEntry`'yi yazmadan önce yeniden oluşturulan oturum bağlamından `tokensBefore`'yi yeniden hesaplar, böylece simge sayısı değiştirilmekte olan gerçek sıkıştırma öncesi bağlamı yansıtır.\n\n### Bölünmüş Dönüşler\n\nBir \"dönüş\", bir kullanıcı mesajıyla başlar ve bir sonraki kullanıcı mesajına kadar tüm asistan yanıtlarını ve araç çağrılarını içerir. Normalde sıkıştırma dönüş sınırlarında kesilir.\n\nTek bir dönüş `keepRecentTokens` değerini aştığında, kesme noktası dönüşün ortasında bir asistan mesajına ulaşır. Bu bir \"bölünmüş dönüş\"tür:\n\n```\nSplit turn (one huge turn exceeds budget):\n\n  entry:  0     1     2      3     4      5      6     7      8\n        ┌─────┬─────┬─────┬──────┬─────┬──────┬──────┬─────┬──────┐\n        │ hdr │ usr │ ass │ tool │ ass │ tool │ tool │ ass │ tool │\n        └─────┴─────┴─────┴──────┴─────┴──────┴──────┴─────┴──────┘\n                ↑                                     ↑\n         turnStartIndex = 1                  firstKeptEntryId = 7\n                │                                     │\n                └──── turnPrefixMessages (1-6) ───────┘\n                                                      └── kept (7-8)\n\n  isSplitTurn = true\n  messagesToSummarize = []  (no complete turns before)\n  turnPrefixMessages = [usr, ass, tool, ass, tool, tool]\n```\n\nBölünmüş dönüşler için Pi iki özet oluşturur ve bunları birleştirir:\n1. **Geçmiş özeti**: Önceki bağlam (varsa)\n2. **Dönüş öneki özeti**: Ayrık dönüşün ilk kısmı\n\n### Kesim Noktası Kuralları\n\nGeçerli kesme noktaları şunlardır:\n- Kullanıcı mesajları\n- Asistan mesajları\n- Bash Yürütme mesajları\n- Özel mesajlar (custom_message, Branch_summary)\n\nHiçbir zaman takım sonuçlarında kesme yapmayın (takım çağrılarıyla kalmaları gerekir).\n\n### Sıkıştırma Giriş Yapısı\n\n[`session-manager.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/session-manager.ts)'de tanımlanmış:\n\n```typescript\ninterface CompactionEntry<T = unknown> {\n  type: \"compaction\";\n  id: string;\n  parentId: string;\n  timestamp: number;\n  summary: string;\n  firstKeptEntryId: string;\n  tokensBefore: number;\n  usage?: Usage;       // LLM usage that generated the summary\n  fromHook?: boolean;  // true if provided by extension (legacy field name)\n  details?: T;         // implementation-specific data\n}\n\n// Default compaction uses this for details (from compaction.ts):\ninterface CompactionDetails {\n  readFiles: string[];\n  modifiedFiles: string[];\n}\n```\n\nExtensions herhangi bir JSON serileştirilebilir veriyi `details`'de saklayabilir. Varsayılan sıkıştırma dosya işlemlerini izler ancak özel uzantı uygulamaları kendi yapılarını kullanabilir. Oluşturulan ve uzantı tarafından sağlanan özetler, mümkün olduğunda LLM'lerini `usage` saklar, böylece oturum toplamları özetleme çalışmasını içerir.\n\nUygulama için [`prepareCompaction()`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) ve [`compact()`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts)'ye bakın. Doğrudan programlı özetleme için, `generateSummary()` özet metnini döndürür ve `generateSummaryWithUsage()`, `{ text, usage }` değerini döndürür.\n\n## Şube Özetleme\n\n### Tetiklendiğinde\n\nFarklı bir şubeye gitmek için `/tree` kullandığınızda, Pi bıraktığınız işi özetleme olanağı sunar. Bu, sol daldan yeni dalın içine bağlam enjekte eder.\n\n### Nasıl Çalışır?\n\n1. **Ortak atayı bul**: Eski ve yeni konumların paylaştığı en derin düğüm\n2. **Girişleri toplayın**: Eski yapraktan ortak ataya doğru yürüyün\n3. **Bütçeyle hazırlanın**: Belirteç bütçesine kadar olan mesajları dahil edin (önce en yenisi)\n4. **Özet oluştur**: Yapılandırılmış formatla LLM'yi arayın\n5. **Girişi ekle**: Gezinme noktasında `BranchSummaryEntry` kaydet\n\n```\nTree before navigation:\n\n         ┌─ B ─ C ─ D (old leaf, being abandoned)\n    A ───┤\n         └─ E ─ F (target)\n\nCommon ancestor: A\nEntries to summarize: B, C, D\n\nAfter navigation with summary:\n\n         ┌─ B ─ C ─ D\n    A ───┤\n         └─ E ─ F ─ [summary of B,C,D] (new leaf)\n```\n\n### Kümülatif Dosya Takibi\n\nHem sıkıştırma hem de branch summarization dosyaları kümülatif olarak izler. Bir özet oluştururken pi, dosya işlemlerini aşağıdakilerden çıkarır:\n- Özetlenen mesajlardaki araç çağrıları\n- Önceki sıkıştırma veya dallanma özeti `details` (varsa)\n\nBu, dosya izlemenin birden çok sıkıştırmada veya iç içe geçmiş dal özetlerinde toplanarak okunan ve değiştirilen dosyaların tam geçmişini koruduğu anlamına gelir.\n\n### ŞubeÖzetGiriş Yapısı\n\n[`session-manager.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/session-manager.ts)'de tanımlanmış:\n\n```typescript\ninterface BranchSummaryEntry<T = unknown> {\n  type: \"branch_summary\";\n  id: string;\n  parentId: string;\n  timestamp: number;\n  summary: string;\n  fromId: string;      // Entry we navigated from\n  usage?: Usage;       // LLM usage that generated the summary\n  fromHook?: boolean;  // true if provided by extension (legacy field name)\n  details?: T;         // implementation-specific data\n}\n\n// Default branch summarization uses this for details (from branch-summarization.ts):\ninterface BranchSummaryDetails {\n  readFiles: string[];\n  modifiedFiles: string[];\n}\n```\n\nSıkıştırmayla aynı şekilde, uzantılar özel verileri `details`'de depolayabilir.\n\nUygulama için [`collectEntriesForBranchSummary()`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts), [`prepareBranchEntries()`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) ve [`generateBranchSummary()`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts)'ye bakın.\n\n## Özet Formatı\n\nHem sıkıştırma hem de branch summarization aynı yapılandırılmış formatı kullanır:\n\n```markdown\n## Goal\n[What the user is trying to accomplish]\n\n## Constraints & Preferences\n- [Requirements mentioned by user]\n\n## Progress\n### Done\n- [x] [Completed tasks]\n\n### In Progress\n- [ ] [Current work]\n\n### Blocked\n- [Issues, if any]\n\n## Key Decisions\n- **[Decision]**: [Rationale]\n\n## Next Steps\n1. [What should happen next]\n\n## Critical Context\n- [Data needed to continue]\n\n<read-files>\npath/to/file1.ts\npath/to/file2.ts\n</read-files>\n\n<modified-files>\npath/to/changed.ts\n</modified-files>\n```\n\n### Mesaj Serileştirme\n\nÖzetlemeden önce mesajlar [`serializeConversation()`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/compaction/utils.ts) aracılığıyla metne serileştirilir:\n\n```\n[User]: What they said\n[Assistant thinking]: Internal reasoning\n[Assistant]: Response text\n[Assistant tool calls]: read(path=\"foo.ts\"); edit(path=\"bar.ts\", ...)\n[Tool result]: Output from tool\n```\n\nBu, modelin bunu devam edecek bir konuşma olarak ele almasını engeller.\n\nAraç sonuçları serileştirme sırasında 2000 karaktere kısaltılır. Bu sınırı aşan içerik, kaç karakterin kesildiğini gösteren bir işaretle değiştirilir. Araç sonuçları (özellikle `read` ve `bash`'den) genellikle bağlam boyutuna en büyük katkıyı sağladığından, bu, özetleme isteklerini makul belirteç bütçeleri dahilinde tutar.\n\n## Extensions aracılığıyla Özel Özetleme\n\nExtensions hem sıkıştırmayı hem de branch summarization'yi engelleyebilir ve özelleştirebilir. Etkinlik türü tanımları için [`extensions/types.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/extensions/types.ts)'e bakın.\n\n### session_before_compact\n\nOtomatik sıkıştırmadan önce tetiklendi veya `/compact`. İptal edebilir veya özel özet sağlayabilir. Türler dosyasında `SessionBeforeCompactEvent` ve `CompactionPreparation`'ye bakın.\n\n```typescript\npi.on(\"session_before_compact\", async (event, ctx) => {\n  const { preparation, branchEntries, customInstructions, reason, willRetry, signal } = event;\n\n  // preparation.messagesToSummarize - messages to summarize\n  // preparation.turnPrefixMessages - split turn prefix (if isSplitTurn)\n  // preparation.previousSummary - previous compaction summary\n  // preparation.fileOps - extracted file operations\n  // preparation.tokensBefore - context tokens before compaction\n  // preparation.firstKeptEntryId - where kept messages start\n  // preparation.settings - compaction settings\n\n  // branchEntries - all entries on current branch (for custom state)\n  // reason - \"manual\" (/compact), \"threshold\", or \"overflow\"\n  // willRetry - whether the aborted turn is retried after compaction (overflow recovery)\n  // signal - AbortSignal (pass to LLM calls)\n\n  // Cancel:\n  return { cancel: true };\n\n  // Custom summary:\n  return {\n    compaction: {\n      summary: \"Your summary...\",\n      firstKeptEntryId: preparation.firstKeptEntryId,\n      tokensBefore: preparation.tokensBefore,\n      // usage: summaryResponse.usage, // Optional; included in session totals\n      details: { /* custom data */ },\n    }\n  };\n});\n```\n\n#### Mesajları Metne Dönüştürme\n\nKendi modelinizle bir özet oluşturmak için `serializeConversation` kullanarak mesajları metne dönüştürün:\n\n```typescript\nimport { convertToLlm, serializeConversation } from \"@earendil-works/pi-coding-agent\";\n\npi.on(\"session_before_compact\", async (event, ctx) => {\n  const { preparation } = event;\n  \n  // Convert AgentMessage[] to Message[], then serialize to text\n  const conversationText = serializeConversation(\n    convertToLlm(preparation.messagesToSummarize)\n  );\n  // Returns:\n  // [User]: message text\n  // [Assistant thinking]: thinking content\n  // [Assistant]: response text\n  // [Assistant tool calls]: read(path=\"...\"); bash(command=\"...\")\n  // [Tool result]: output text\n\n  // Now send to your model for summarization\n  const { summary, usage } = await myModel.summarize(conversationText);\n  \n  return {\n    compaction: {\n      summary,\n      firstKeptEntryId: preparation.firstKeptEntryId,\n      tokensBefore: preparation.tokensBefore,\n      usage,\n    }\n  };\n});\n```\n\nFarklı bir modelin kullanıldığı tam bir örnek için [custom-compaction.ts](../examples/extensions/custom-compaction.ts)'e bakın.\n\n### session_before_tree\n\n`/tree` navigasyondan önce tetiklendi. Kullanıcının özetlemeyi seçip seçmemesine bakılmaksızın her zaman tetiklenir. Gezinmeyi iptal edebilir veya özel özet sağlayabilir.\n\n```typescript\npi.on(\"session_before_tree\", async (event, ctx) => {\n  const { preparation, signal } = event;\n\n  // preparation.targetId - where we're navigating to\n  // preparation.oldLeafId - current position (being abandoned)\n  // preparation.commonAncestorId - shared ancestor\n  // preparation.entriesToSummarize - entries that would be summarized\n  // preparation.userWantsSummary - whether user chose to summarize\n\n  // Cancel navigation entirely:\n  return { cancel: true };\n\n  // Provide custom summary (only used if userWantsSummary is true):\n  if (preparation.userWantsSummary) {\n    return {\n      summary: {\n        summary: \"Your summary...\",\n        // usage: summaryResponse.usage, // Optional; included in session totals\n        details: { /* custom data */ },\n      }\n    };\n  }\n});\n```\n\nTürler dosyasında `SessionBeforeTreeEvent` ve `TreePreparation`'ye bakın.\n\n## Ayarlar\n\nSıkıştırmayı `~/.pi/agent/settings.json` veya `<project-dir>/.pi/settings.json` olarak yapılandırın:\n\n```json\n{\n  \"compaction\": {\n    \"enabled\": true,\n    \"reserveTokens\": 16384,\n    \"keepRecentTokens\": 20000\n  }\n}\n```\n\n| Ayar | Varsayılan | Tanım |\n|---------|---------|-------------|\n| `enabled` | `true` | Otomatik sıkıştırmayı etkinleştir |\n| `reserveTokens` | `16384` | LLM yanıtı için rezerve edilecek jetonlar |\n| `keepRecentTokens` | `20000` | Saklanacak en son belirteçler (özetlenmemiş) |\n\n`\"enabled\": false` ile otomatik sıkıştırmayı devre dışı bırakın. `/compact` ile manuel olarak sıkıştırmaya devam edebilirsiniz.","sourceFile":"compaction.md"},"containerization":{"title":"Konteynerizasyon","markdown":"Pi varsayılan olarak tüm izinlerle çalışır, ancak bazı durumlarda Pi'nin hangi dizinlere yazabileceği ve hangi erişimlere sahip olduğu konusunda daha fazla kontrole sahip olmak isteyebilirsiniz.\n\nİki genel seçenek vardır. Sen de yapabilirsin\n1. `pi` sürecinin tamamını yalıtılmış bir ortamda çalıştırın veya\n2. Ana bilgisayarda `pi` komutunu çalıştırın ve araç yürütmesini yalıtılmış bir ortama yönlendirin.\n\n## Bir desen seçin\n\n| Model | İzole edilen şey | Şunun için en iyisi: | Notlar |\n| --- | --- | --- | --- |\n| Gondolin uzantı | Yerleşik araçlar ve `!` komutları | Ana bilgisayarda kimlik doğrulamayı korurken yerel mikro sanal makine yalıtımı | Bakınız [`examples/extensions/gondolin/`](../examples/extensions/gondolin/). |\n| Sade Docker | Yerel bir kapta tüm `pi` süreci | Basit yerel izolasyon | Sağlayıcı API key'lar konteynere girer. |\n| OpenShell | Politika kontrollü bir sandbox'deki tüm `pi` süreci | Yerel veya uzaktan yönetilen sandbox | OpenShell ağ geçidi gerektirir |\n\nExtensions, `pi` işleminin çalıştığı yerde çalıştırın. `pi` ana bilgisayarını bir araç yönlendirme uzantısıyla çalıştırırsanız, diğer özel uzantı araçları da kendi işlemlerini devretmedikleri sürece ana bilgisayarda çalışmaya devam eder.\n\n## Gondolin\n\n[Gondolin](https://github.com/earendil-works/gondolin) yerel bir Linux mikro VM'sidir.\nAna makinede `pi` istiyorsanız ancak tüm yerleşik araçların VM'ye yönlendirilmesini istiyorsanız [example extension](../examples/extensions/gondolin)'yi kullanın.\n\nKurmak:\n\n```bash\ncp -R packages/coding-agent/examples/extensions/gondolin ~/.pi/agent/extensions/gondolin\ncd ~/.pi/agent/extensions/gondolin\nnpm install --ignore-scripts\n```\n\nMonte edilmesini istediğiniz projeden çalıştırın:\n\n```bash\ncd /path/to/project\npi -e ~/.pi/agent/extensions/gondolin\n```\n\nUzantı, ana bilgisayar cwd'sini VM'de `/workspace` konumuna bağlar ve `read`, `write`, `edit`, `bash`, `grep`, `find` ve `ls`'yi geçersiz kılar.\nKullanıcı `!` komutları da VM'ye yönlendirilir.\n`/workspace` altındaki dosya değişiklikleri ana bilgisayara aktarılır.\n\nGereksinimler: `@earendil-works/gondolin` için Node.js >= 23.6.0, artı QEMU (paket yöneticiniz aracılığıyla kurulum gerektirir).\n\n## Sade Docker\n\nEn basit yerel konteyner sınırını istediğinizde `pi` işleminin tamamını Docker'de çalıştırın.\n\n`Dockerfile.pi`:\n\n```dockerfile\nFROM node:24-bookworm-slim\n\nRUN apt-get update \\\n  && apt-get install -y --no-install-recommends bash ca-certificates git ripgrep \\\n  && rm -rf /var/lib/apt/lists/*\nRUN npm install -g --ignore-scripts @earendil-works/pi-coding-agent\n\nWORKDIR /workspace\nENTRYPOINT [\"pi\"]\n```\n\nOluşturun ve çalıştırın:\n\n```bash\ndocker build -t pi-sandbox -f Dockerfile.pi .\n\ndocker run --rm -it \\\n  -e ANTHROPIC_API_KEY \\\n  -v \"$PWD:/workspace\" \\\n  -v pi-agent-home:/root/.pi/agent \\\n  pi-sandbox\n```\n\n`-v \"$PWD:/workspace\"`, geçerli dizininizi /workspace'teki kapsayıcıya bağlar; böylece Gondolin örneğinde olduğu gibi, Docker içindeki `/workspace`'deki okuma ve yazmalar ana bilgisayar dosyalarınızı doğrudan etkiler.\n\nKapsayıcı yerel ayarlar ve oturumlar istiyorsanız `/root/.pi/agent` için adlandırılmış bir birim kullanın. Ana makinenizi `~/.pi/agent` monte ettiğinizde, ana makine kimlik doğrulaması ve oturum dosyaları kapsayıcıya sunulur.\n\n## OpenShell\n\nDosya sistemi, süreç, ağ, kimlik bilgisi ve çıkarım kontrolleriyle politika kontrollü bir sandbox istiyorsanız [NVIDIA OpenShell](https://docs.nvidia.com/openshell/about/overview) kullanın.\nOpenShell, sandboxes'i Docker, Podman veya VM çalışma zamanı tarafından desteklenen yerel bir ağ geçidi veya uzak bir Kubernetes ağ geçidi aracılığıyla çalıştırabilir.\n\nHer sandbox aktif bir ağ geçidi gerektirir.\nsandbox oluşturmadan önce kaydolun ve birini seçin:\n\n```bash\nopenshell gateway add <gateway-url> --name <name>\nopenshell gateway select <name>\n```\n\nOpenShell sandbox içinde `pi`'yi başlatın:\n\n```bash\nopenshell sandbox create --name pi-sandbox --from pi -- pi\n```\n\nBu modelde, `pi` sürecinin tamamı sandbox'nin içinde çalışır.\nYerleşik araçlar, `!` komutları ve uzantı araçları OpenShell sınırı içinde yürütülür.\n\nAğ geçidi uzaksa, proje dosyaları ana bilgisayardan bağlamayla bağlanmaz; bu, sandbox'deki yazma işlemlerinin makinenize yansıtılmadığı anlamına gelir.\nDepoyu sandbox içine kopyalayın veya OpenShell dosya aktarım komutlarını kullanın:\n\n```bash\nopenshell sandbox upload pi-sandbox ./repo /workspace\nopenshell sandbox download pi-sandbox /workspace/repo ./repo-out\n```\n\nOpenShell sağlayıcılar ham model API key'leri sandbox'nin dışında tutabilir.\nÇıkarım yönlendirmesi yapılandırıldığında, sandbox içindeki kod `https://inference.local`'yi arayabilir ve ağ geçidi, yapılandırılmış sağlayıcı kimlik bilgilerini yukarı akışa enjekte eder.\nModel trafiğinin bu rotayı kullanmasını istiyorsanız, ilgili OpenAI uyumlu veya Antropik uyumlu uç noktayı kullanmak için Pi öğesini yapılandırın.","sourceFile":"containerization.md"},"custom-provider":{"title":"Özel Providers","markdown":"Extensions özel model sağlayıcılarını `pi.registerProvider()` aracılığıyla kaydedebilir. Bu şunları sağlar:\n\n- **Proxy'ler** - İstekleri kurumsal proxy'ler veya API ağ geçitleri aracılığıyla yönlendirin\n- **Özel uç noktalar** - Şirket içinde barındırılan veya özel model dağıtımlarını kullanın\n- **OAuth/SSO** - Kurumsal sağlayıcılar için kimlik doğrulama akışları ekleyin\n- **Özel API'ler** - Standart olmayan LLM API'ler için akış uygulayın\n\n## Örnek Extensions\n\nBu eksiksiz sağlayıcı örneklerine bakın:\n\n- [`examples/extensions/custom-provider-anthropic/`](../examples/extensions/custom-provider-anthropic/)\n- [`examples/extensions/custom-provider-gitlab-duo/`](../examples/extensions/custom-provider-gitlab-duo/)\n\n## İçindekiler\n\n- [Example Extensions](#example-extensions)\n- [Quick Reference](#quick-reference)\n- [Override Existing Provider](#override-existing-provider)\n- [Register New Provider](#register-new-provider)\n- [Unregister Provider](#unregister-provider)\n- [OAuth Support](#oauth-support)\n- [Custom Streaming API](#custom-streaming-api)\n- [Context Overflow Errors](#context-overflow-errors)\n- [Testing Your Implementation](#testing-your-implementation)\n- [Config Reference](#config-reference)\n- [Model Definition Reference](#model-definition-reference)\n\n## Hızlı Referans\n\nExtensions tam bir pi-ai `Provider` kaydedebilir veya eski sağlayıcı yapılandırma formunu kullanabilir. Özel kimlik doğrulama, filtreleme, yenileme veya akış davranışı gerektiğinde eksiksiz bir sağlayıcıyı tercih edin. Pi, kayıtlı yerel sağlayıcıların üzerindeki `models.json` geçersiz kılmaları oluşturur.\n\n```typescript\nimport { createProvider, openAICompletionsApi } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\n\nexport default function (pi: ExtensionAPI) {\n  pi.registerProvider(createProvider({\n    id: \"native-local\",\n    name: \"Native Local\",\n    baseUrl: \"http://localhost:8080/v1\",\n    auth: {\n      apiKey: {\n        name: \"Local server API key\",\n        async login(interaction) {\n          return {\n            type: \"api_key\",\n            key: await interaction.prompt({ type: \"secret\", message: \"API key\" })\n          };\n        },\n        async resolve({ credential }) {\n          return credential?.key\n            ? { auth: { apiKey: credential.key }, source: \"stored API key\" }\n            : undefined;\n        }\n      }\n    },\n    models: [],\n    api: openAICompletionsApi()\n  }));\n\n  // Legacy provider-config form:\n  // Override baseUrl for existing provider\n  pi.registerProvider(\"anthropic\", {\n    baseUrl: \"https://proxy.example.com\"\n  });\n\n  // Register new provider with models\n  pi.registerProvider(\"my-provider\", {\n    name: \"My Provider\",\n    baseUrl: \"https://api.example.com\",\n    apiKey: \"$MY_API_KEY\",\n    api: \"openai-completions\",\n    models: [\n      {\n        id: \"my-model\",\n        name: \"My Model\",\n        reasoning: false,\n        input: [\"text\", \"image\"],\n        cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n        contextWindow: 128000,\n        maxTokens: 4096\n      }\n    ]\n  });\n}\n```\n\nUzantı fabrikası da `async` olabilir. Dinamik model keşfi için, modelleri `session_start` yerine fabrikaya getirin ve kaydedin. pi, başlatma devam etmeden önce fabrikayı bekler, böylece sağlayıcı etkileşimli başlatma sırasında ve `pi --list-models`'ye hazır olur.\n\n## Mevcut Sağlayıcıyı Geçersiz Kıl\n\nEn basit kullanım durumu: Mevcut bir sağlayıcıyı bir proxy aracılığıyla yeniden yönlendirmek.\n\n```typescript\n// All Anthropic requests now go through your proxy\npi.registerProvider(\"anthropic\", {\n  baseUrl: \"https://proxy.example.com\"\n});\n\n// Add custom headers to OpenAI requests\npi.registerProvider(\"openai\", {\n  headers: {\n    \"X-Custom-Header\": \"value\"\n  }\n});\n\n// Both baseUrl and headers\npi.registerProvider(\"google\", {\n  baseUrl: \"https://ai-gateway.corp.com/google\",\n  headers: {\n    \"X-Corp-Auth\": \"$CORP_AUTH_TOKEN\"  // env var or literal\n  }\n});\n```\n\nYalnızca `baseUrl` ve/veya `headers` sağlandığında (`models` yok), o sağlayıcı için mevcut tüm modeller yeni uç noktayla korunur.\n\n## Yeni Sağlayıcıyı Kaydedin\n\nTamamen yeni bir sağlayıcı eklemek için gerekli yapılandırmayla birlikte `models` belirtin.\n\nModel listesi uzak bir uç noktadan geliyorsa eşzamansız bir uzantı fabrikası kullanın:\n\n```typescript\nimport type { ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\n\nexport default async function (pi: ExtensionAPI) {\n  const response = await fetch(\"http://localhost:1234/v1/models\");\n  const payload = (await response.json()) as {\n    data: Array<{\n      id: string;\n      name?: string;\n      context_window?: number;\n      max_tokens?: number;\n    }>;\n  };\n\n  pi.registerProvider(\"local-openai\", {\n    baseUrl: \"http://localhost:1234/v1\",\n    apiKey: \"$LOCAL_OPENAI_API_KEY\",\n    api: \"openai-completions\",\n    models: payload.data.map((model) => ({\n      id: model.id,\n      name: model.name ?? model.id,\n      reasoning: false,\n      input: [\"text\"],\n      cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n      contextWindow: model.context_window ?? 128000,\n      maxTokens: model.max_tokens ?? 4096,\n    })),\n  });\n}\n```\n\nBu, getirilen modelleri başlatma tamamlanmadan önce kaydeder.\n\n```typescript\npi.registerProvider(\"my-llm\", {\n  baseUrl: \"https://api.my-llm.com/v1\",\n  apiKey: \"$MY_LLM_API_KEY\",  // env var reference\n  api: \"openai-completions\",  // which streaming API to use\n  models: [\n    {\n      id: \"my-llm-large\",\n      name: \"My LLM Large\",\n      reasoning: true,        // supports extended thinking\n      input: [\"text\", \"image\"],\n      cost: {\n        input: 3.0,           // $/million tokens\n        output: 15.0,\n        cacheRead: 0.3,\n        cacheWrite: 3.75\n      },\n      contextWindow: 200000,\n      maxTokens: 16384\n    }\n  ]\n});\n```\n\n`models` sağlandığında, o sağlayıcı için mevcut tüm modellerin **yerini alır**.\n\n`apiKey` ve özel başlık değerleri, `models.json` ile aynı yapılandırma değeri sözdizimini kullanır: `!command` başlangıçta tüm değer için bir komut yürütür, `$ENV_VAR` ve `${ENV_VAR}` ortam değişkenlerini enterpolasyona tabi tutar, `$` bir değişmez değer ``apiKey` ve özel başlık değerleri, `models.json` ile aynı yapılandırma değeri sözdizimini kullanır: `!command` başlangıçta tüm değer için bir komut yürütür, `$ENV_VAR` ve `${ENV_VAR}` ortam değişkenlerini enterpolasyona tabi tutar, `$` bir değişmez değer  ve `$!` bir değişmez değer yayar `!`.\n\n## Sağlayıcının Kaydını İptal Et\n\nDaha önce `pi.registerProvider(name,...)` aracılığıyla kaydedilen bir sağlayıcıyı kaldırmak için `pi.unregisterProvider(name)` tuşunu kullanın:\n\n```typescript\n// Register\npi.registerProvider(\"my-llm\", {\n  baseUrl: \"https://api.my-llm.com/v1\",\n  apiKey: \"$MY_LLM_API_KEY\",\n  api: \"openai-completions\",\n  models: [\n    {\n      id: \"my-llm-large\",\n      name: \"My LLM Large\",\n      reasoning: true,\n      input: [\"text\", \"image\"],\n      cost: { input: 3.0, output: 15.0, cacheRead: 0.3, cacheWrite: 3.75 },\n      contextWindow: 200000,\n      maxTokens: 16384\n    }\n  ]\n});\n\n// Later, remove it\npi.unregisterProvider(\"my-llm\");\n```\n\nKayıt silme işlemi, sağlayıcının dinamik modellerini, API key geri dönüşünü, OAuth sağlayıcı kaydını ve özel akış işleyicisi kayıtlarını kaldırır. Geçersiz kılınan tüm yerleşik modeller veya sağlayıcı davranışları geri yüklenir.\n\nİlk dahili yükleme aşamasından sonra yapılan çağrılar hemen uygulanır, dolayısıyla `/reload` gerekli değildir.\n\n### API Türler\n\n`api` alanı hangi akış uygulamasının kullanılacağını belirler:\n\n| API | Şunun için kullanın: |\n|-----|---------|\n| `anthropic-messages` | Antropik Claude API ve uyumlular |\n| `openai-completions` | OpenAI Sohbet Tamamlamaları API ve uyumlular |\n| `openai-responses` | OpenAI Yanıtları API |\n| `azure-openai-responses` | Azure OpenAI Yanıtları API |\n| `openai-codex-responses` | OpenAI Kodeksi Yanıtları API |\n| `mistral-conversations` | Yerel Mistral Sohbet Tamamlamaları akışı |\n| `google-generative-ai` | Google Üretken Yapay Zeka API |\n| `google-vertex` | Google Vertex AI API |\n| `bedrock-converse-stream` | Amazon Bedrock Converse API |\n\nÇoğu OpenAI uyumlu sağlayıcı `openai-completions` ile çalışır. Modele özgü düşünme düzeyleri için model düzeyi `thinkingLevelMap`'yi ve sağlayıcı tuhaflıkları için `compat`'yi kullanın. `xhigh` ve `max` düzeyleri isteğe bağlıdır, boş olmayan harita girişleri gerektirir ve desteklenmeyen deliklerle ayrılabilir:\n\n```typescript\nmodels: [{\n  id: \"custom-model\",\n  // ...\n  reasoning: true,\n  thinkingLevelMap: {              // map pi levels to provider values; null hides unsupported levels\n    minimal: null,\n    low: null,\n    medium: null,\n    high: \"default\",\n    xhigh: null,\n    max: \"max\"\n  },\n  compat: {\n    supportsDeveloperRole: false,   // use \"system\" instead of \"developer\"\n    supportsReasoningEffort: true,\n    maxTokensField: \"max_tokens\",   // instead of \"max_completion_tokens\"\n    requiresToolResultName: true,   // tool results need name field\n    thinkingFormat: \"qwen\",        // top-level enable_thinking: true\n    cacheControlFormat: \"anthropic\" // Anthropic-style cache_control markers\n  }\n}]\n```\n\nOpenRouter tarzı `reasoning: { effort }` kontrolleri için `openrouter` kullanın. Birlikte tarzı `reasoning: { enabled }` kontrolleri için `together` kullanın; `supportsReasoningEffort` ile `reasoning_effort`'yi de gönderir. `chat_template_kwargs.enable_thinking` okuyan ve `preserve_thinking`'ye ihtiyaç duyan yerel Qwen uyumlu sunucular için `qwen-chat-template` kullanın.\nSistem isteminde, son araç tanımında ve son kullanıcı, asistan veya araç sonucu metin içeriğinde `cache_control` aracılığıyla Antropik tarzda bilgi istemi önbelleğe almayı ortaya çıkaran OpenAI uyumlu sağlayıcılar için `cacheControlFormat: \"anthropic\"` kullanın.\n\n`api: \"anthropic-messages\"` kullanan Antropik uyumlu sağlayıcılar için, yukarı akış modeli uyarlamalı düşünme gerektiren modellere veya sağlayıcılara (`thinking.type: \"adaptive\"` artı `output_config.effort`) `compat.forceAdaptiveThinking: true` değerini ayarlayın. Yerleşik uyarlanabilir Claude modelleri bunu otomatik olarak ayarlar. `compat.allowEmptySignature: true`'yi yalnızca boş düşünme imzaları yayan ve tekrar oynatıldığında `signature: \"\"` bekleyen sağlayıcılar için ayarlayın.\n\n> Geçiş notu: Mistral `openai-completions`'den `mistral-conversations`'ye taşındı.\n> Yerel Mistral modelleri için `mistral-conversations` kullanın.\n> Mistral uyumlu/özel uç noktaları kasıtlı olarak `openai-completions` üzerinden yönlendiriyorsanız, `compat` işaretlerini gerektiği gibi açıkça ayarlayın.\n\n### Kimlik Doğrulama Başlığı\n\nSağlayıcınız `Authorization: Bearer <key>` bekliyor ancak standart API kullanmıyorsa `authHeader: true` değerini ayarlayın:\n\n```typescript\npi.registerProvider(\"custom-api\", {\n  baseUrl: \"https://api.example.com\",\n  apiKey: \"$MY_API_KEY\",\n  authHeader: true,  // adds Authorization: Bearer header\n  api: \"openai-completions\",\n  models: [...]\n});\n```\n\nAnahtar her istek için çözümlenir. Açık bir istek `Authorization` başlığı, oluşturulan değere göre önceliklidir.\n\n## OAuth Destek\n\n`/login` ile entegre olan OAuth/SSO kimlik doğrulamasını ekleyin:\n\n```typescript\nimport type { OAuthCredentials, OAuthLoginCallbacks } from \"@earendil-works/pi-ai\";\n\npi.registerProvider(\"corporate-ai\", {\n  baseUrl: \"https://ai.corp.com/v1\",\n  api: \"openai-responses\",\n  models: [...],\n  oauth: {\n    name: \"Corporate AI (SSO)\",\n\n    async login(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials> {\n      const method = await callbacks.onSelect({\n        message: \"Select login method:\",\n        options: [\n          { id: \"browser\", label: \"Browser OAuth\" },\n          { id: \"device\", label: \"Device code\" }\n        ]\n      });\n      if (!method) throw new Error(\"Login cancelled\");\n\n      let code: string;\n      if (method === \"device\") {\n        callbacks.onDeviceCode({\n          userCode: \"ABCD-1234\",\n          verificationUri: \"https://sso.corp.com/device\",\n          intervalSeconds: 5,\n          expiresInSeconds: 900\n        });\n        code = await pollDeviceCodeUntilComplete();\n      } else {\n        callbacks.onAuth({ url: \"https://sso.corp.com/authorize?...\" });\n        code = await callbacks.onPrompt({ message: \"Enter SSO code:\" });\n      }\n\n      // Exchange for tokens (your implementation)\n      const tokens = await exchangeCodeForTokens(code);\n\n      return {\n        refresh: tokens.refreshToken,\n        access: tokens.accessToken,\n        expires: Date.now() + tokens.expiresIn * 1000\n      };\n    },\n\n    async refreshToken(credentials: OAuthCredentials, signal: AbortSignal): Promise<OAuthCredentials> {\n      const tokens = await refreshAccessToken(credentials.refresh, signal);\n      return {\n        refresh: tokens.refreshToken ?? credentials.refresh,\n        access: tokens.accessToken,\n        expires: Date.now() + tokens.expiresIn * 1000\n      };\n    },\n\n    getApiKey(credentials: OAuthCredentials): string {\n      return credentials.access;\n    }\n  }\n});\n```\n\nKayıt olduktan sonra kullanıcılar `/login corporate-ai` aracılığıyla kimlik doğrulaması yapabilir.\n\n### OAuthOturum AçmaGeri Aramalar\n\n`callbacks` nesnesi, sağlayıcının sahip olduğu akış için kullanıcı arayüzünden bağımsız etkileşimler sağlar:\n\n```typescript\ninterface OAuthLoginCallbacks {\n  // Open URL in browser (for OAuth redirects)\n  onAuth(params: { url: string }): void;\n\n  // Show device code (for device authorization flow)\n  onDeviceCode(params: {\n    userCode: string;\n    verificationUri: string;\n    intervalSeconds?: number;\n    expiresInSeconds?: number;\n  }): void;\n\n  // Show transient progress\n  onProgress?(message: string): void;\n\n  // Prompt user for input (for manual token entry)\n  onPrompt(params: { message: string }): Promise<string>;\n\n  // Show an interactive selector, e.g. to choose browser OAuth vs device code\n  onSelect(params: {\n    message: string;\n    options: { id: string; label: string }[];\n  }): Promise<string | undefined>;\n}\n```\n\n### OAuthKimlik Bilgileri\n\nKimlik bilgileri `~/.pi/agent/auth.json`'de kalıcıdır:\n\n```typescript\ninterface OAuthCredentials {\n  refresh: string;   // Refresh token (for refreshToken())\n  access: string;    // Access token (returned by getApiKey())\n  expires: number;   // Expiration timestamp in milliseconds\n}\n```\n\n## Özel Yayın API\n\nStandart olmayan API'lere sahip sağlayıcılar için `streamSimple`'yi uygulayın. Kendi uygulamanızı yazmadan önce mevcut sağlayıcı uygulamalarını inceleyin:\n\n**Referans uygulamalar:**\n- [anthropic.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/providers/anthropic.ts) - Antropik Mesajlar API\n- [mistral.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/providers/mistral.ts) - Mistral Konuşmalar API\n- [openai-completions.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/providers/openai-completions.ts) - OpenAI Sohbet Tamamlamaları\n- [openai-responses.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/providers/openai-responses.ts) - OpenAI Yanıtları API\n- [google.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/providers/google.ts) - Google Üretken Yapay Zeka\n- [amazon-bedrock.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/providers/amazon-bedrock.ts) - AWS Ana Kayası\n\n### Akış Deseni\n\nTüm sağlayıcılar aynı modeli izler:\n\n```typescript\nimport {\n  type AssistantMessage,\n  type AssistantMessageEventStream,\n  type Context,\n  type Model,\n  type SimpleStreamOptions,\n  calculateCost,\n  createAssistantMessageEventStream,\n} from \"@earendil-works/pi-ai\";\n\nfunction streamMyProvider(\n  model: Model<any>,\n  context: Context,\n  options?: SimpleStreamOptions\n): AssistantMessageEventStream {\n  const stream = createAssistantMessageEventStream();\n\n  (async () => {\n    // Initialize output message\n    const output: AssistantMessage = {\n      role: \"assistant\",\n      content: [],\n      api: model.api,\n      provider: model.provider,\n      model: model.id,\n      usage: {\n        input: 0,\n        output: 0,\n        cacheRead: 0,\n        cacheWrite: 0,\n        totalTokens: 0,\n        cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n      },\n      stopReason: \"pending\",\n      timestamp: Date.now(),\n    };\n\n    try {\n      // Push start event\n      stream.push({ type: \"start\", partial: output });\n\n      // Make API request and process response...\n      // Push content events as they arrive and set stopReason from the terminal event.\n      if (output.stopReason === \"pending\") {\n        throw new Error(\"Provider stream ended without a stop reason\");\n      }\n      if (output.stopReason === \"error\" || output.stopReason === \"aborted\") {\n        throw new Error(output.errorMessage || \"An unknown error occurred\");\n      }\n\n      // Push done event\n      stream.push({\n        type: \"done\",\n        reason: output.stopReason,\n        message: output\n      });\n      stream.end();\n    } catch (error) {\n      output.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n      output.errorMessage = error instanceof Error ? error.message : String(error);\n      stream.push({ type: \"error\", reason: output.stopReason, error: output });\n      stream.end();\n    }\n  })();\n\n  return stream;\n}\n```\n\n### Etkinlik Türleri\n\nOlayları `stream.push()` aracılığıyla şu sırayla aktarın:\n\n1. `{ type: \"start\", partial: output }` - Yayın başladı\n\n2. İçerik etkinlikleri (tekrarlanabilir, her blok için `contentIndex` parça):\n   - `{ type: \"text_start\", contentIndex, partial }` - Metin bloğu başlatıldı\n   - `{ type: \"text_delta\", contentIndex, delta, partial }` - Metin öbeği\n   - `{ type: \"text_end\", contentIndex, content, partial }` - Metin bloğu sona erdi\n   - `{ type: \"thinking_start\", contentIndex, partial }` - Düşünmeye başlandı\n   - `{ type: \"thinking_delta\", contentIndex, delta, partial }` - Düşünme öbeği\n   - `{ type: \"thinking_end\", contentIndex, content, partial }` - Düşünme sona erdi\n   - `{ type: \"toolcall_start\", contentIndex, partial }` - Araç çağrısı başlatıldı\n   - `{ type: \"toolcall_delta\", contentIndex, delta, partial }` - Araç çağrısı JSON öbeği\n   - `{ type: \"toolcall_end\", contentIndex, toolCall, partial }` - Araç çağrısı sona erdi\n\n3. `{ type: \"done\", reason, message }` veya `{ type: \"error\", reason, error }` - Yayın sona erdi\n\nHer etkinlikteki `partial` alanı mevcut `AssistantMessage` durumunu içerir. Verileri aldıkça `output.content`'yi güncelleyin, ardından `partial` olarak `output`'yi ekleyin.\n\n### İçerik Blokları\n\n`output.content`'ye ulaştıkça içerik blokları ekleyin:\n\n```typescript\n// Text block\noutput.content.push({ type: \"text\", text: \"\" });\nstream.push({ type: \"text_start\", contentIndex: output.content.length - 1, partial: output });\n\n// As text arrives\nconst block = output.content[contentIndex];\nif (block.type === \"text\") {\n  block.text += delta;\n  stream.push({ type: \"text_delta\", contentIndex, delta, partial: output });\n}\n\n// When block completes\nstream.push({ type: \"text_end\", contentIndex, content: block.text, partial: output });\n```\n\n### Araç Çağrıları\n\nAraç çağrıları JSON biriktirmeyi ve ayrıştırmayı gerektirir:\n\n```typescript\n// Start tool call\noutput.content.push({\n  type: \"toolCall\",\n  id: toolCallId,\n  name: toolName,\n  arguments: {}\n});\nstream.push({ type: \"toolcall_start\", contentIndex: output.content.length - 1, partial: output });\n\n// Accumulate JSON\nlet partialJson = \"\";\npartialJson += jsonDelta;\ntry {\n  block.arguments = JSON.parse(partialJson);\n} catch {}\nstream.push({ type: \"toolcall_delta\", contentIndex, delta: jsonDelta, partial: output });\n\n// Complete\nstream.push({\n  type: \"toolcall_end\",\n  contentIndex,\n  toolCall: { type: \"toolCall\", id, name, arguments: block.arguments },\n  partial: output\n});\n```\n\n### Kullanım ve Maliyet\n\nAPI yanıtından kullanımı güncelleyin ve maliyeti hesaplayın:\n\n```typescript\noutput.usage.input = response.usage.input_tokens;\noutput.usage.output = response.usage.output_tokens;\noutput.usage.cacheRead = response.usage.cache_read_tokens ?? 0;\noutput.usage.cacheWrite = response.usage.cache_write_tokens ?? 0;\noutput.usage.totalTokens = output.usage.input + output.usage.output +\n                           output.usage.cacheRead + output.usage.cacheWrite;\ncalculateCost(model, output.usage);\n```\n\n### Bağlam Taşması Hataları\n\nBir istek modelin bağlam penceresini aştığında pi, konuşmayı sıkıştırıp yeniden deneyerek otomatik olarak kurtarılabilir. Bu kurtarma yalnızca Pi'nin arızayı bir taşma olarak algılaması durumunda devreye girer.\n\nAlgılama, sonlandırılan asistan mesajı üzerinde çalışır:\n\n- `stopReason === \"error\"`\n- `errorMessage` pi'nin bilinen taşma modellerinden biriyle eşleşir (bkz. [`packages/ai/src/utils/overflow.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/utils/overflow.ts))\n\nSağlayıcınız pi'nin tanımadığı bir mesajla taşma hataları döndürürse, sağlayıcıyı kaydeden aynı uzantıdan hatayı normalleştirin. Asistan mesajını, `errorMessage` pi'nin tanıdığı bir ifadeyle başlayacak şekilde yeniden yazmak için bir `message_end` işleyicisi kullanın. Genel geri dönüş `context_length_exceeded` en güvenli seçimdir.\n\n```typescript\nconst MY_PROVIDER_OVERFLOW_PATTERN = /your provider's overflow phrase/i;\n\nexport default function (pi: ExtensionAPI) {\n  pi.registerProvider(\"my-provider\", { /* ... */ });\n\n  pi.on(\"message_end\", (event, ctx) => {\n    const message = event.message;\n    if (message.role !== \"assistant\") return;\n    if (message.stopReason !== \"error\") return;\n    if (\n      message.provider !== \"my-provider\" &&\n      ctx.model?.provider !== \"my-provider\"\n    )\n      return;\n\n    const errorMessage = message.errorMessage ?? \"\";\n    if (errorMessage.includes(\"context_length_exceeded\")) return;\n    if (!MY_PROVIDER_OVERFLOW_PATTERN.test(errorMessage)) return;\n\n    return {\n      message: {\n        ...message,\n        errorMessage: `context_length_exceeded: ${errorMessage}`,\n      },\n    };\n  });\n}\n```\n\n`message_end`, pi'nin otomatik sıkıştırma için asistan mesajını izlemesinden önce çalışır, dolayısıyla yeniden yazılan `errorMessage`, pi'nin kontrol ettiği şeydir. Bunu yerine getirdiğimizde pi şunları yapacaktır:\n\n1. `errorMessage`'den taşmayı tespit edin.\n2. Başarısız olan asistan mesajını canlı bağlamdan bırakın.\n3. Sıkıştırmayı çalıştırın.\n4. İsteği bir kez yeniden deneyin.\n\nYeniden yazmayı dikkatli bir şekilde koruyun:\n\n- Bunu sağlayıcınızın kapsamına alın (`message.provider` ve `ctx.model?.provider`), böylece diğer sağlayıcılardan gelen ilgisiz hatalara dokunulmaz.\n- Pi'nin genel taşma modellerini değil, sağlayıcıya özel bir modeli eşleştirin. Hız sınırı veya azaltma hatalarının (`rate limit`, `too many requests`) yeniden yazılması, pi'nin normal geri çekme ile yeniden deneme yolu yerine yanlışlıkla sıkıştırmayı tetikler.\n- `errorMessage` zaten `context_length_exceeded` içerdiğinde, işleyicinin önemsiz olması durumunda atlayın.\n\n### Kayıt\n\nAkış işlevinizi kaydedin:\n\n```typescript\npi.registerProvider(\"my-provider\", {\n  baseUrl: \"https://api.example.com\",\n  apiKey: \"$MY_API_KEY\",\n  api: \"my-custom-api\",\n  models: [...],\n  streamSimple: streamMyProvider\n});\n```\n\n## Uygulamanızı Test Etme\n\nSağlayıcınızı, yerleşik sağlayıcılar tarafından kullanılan aynı test paketleriyle karşılaştırarak test edin. Bu test dosyalarını [packages/ai/test/](https://github.com/earendil-works/pi-mono/tree/main/packages/ai/test) adresinden kopyalayıp uyarlayın:\n\n| Test | Amaç |\n|------|---------|\n| `stream.test.ts` | Temel akış, metin çıkışı |\n| `tokens.test.ts` | Jeton sayımı ve kullanımı |\n| `abort.test.ts` | AbortSinyal yönetimi |\n| `empty.test.ts` | Boş/minimum yanıtlar |\n| `context-overflow.test.ts` | Bağlam penceresi sınırları |\n| `image-limits.test.ts` | Görüntü girişi yönetimi |\n| `unicode-surrogate.test.ts` | Unicode uç durumları |\n| `tool-call-without-result.test.ts` | Araç çağrısı uç durumları |\n| `image-tool-result.test.ts` | Araç sonuçlarındaki resimler |\n| `total-tokens.test.ts` | Toplam jeton hesaplaması |\n| `cross-provider-handoff.test.ts` | Sağlayıcılar arasında bağlam aktarımı |\n\nUyumluluğu doğrulamak için sağlayıcınız/model çiftlerinizle testler yapın.\n\n## Yapılandırma Referansı\n\n```typescript\ninterface ProviderConfig {\n  /** Display name for the provider in UI such as /login. */\n  name?: string;\n\n  /** API endpoint URL. Required when defining models. */\n  baseUrl?: string;\n\n  /** API key literal, env interpolation ($ENV_VAR or ${ENV_VAR}), or !command. Required when defining models (unless oauth). */\n  apiKey?: string;\n\n  /** API type for streaming. Required at provider or model level when defining models. */\n  api?: Api;\n\n  /** Custom streaming implementation for non-standard APIs. */\n  streamSimple?: (\n    model: Model<Api>,\n    context: Context,\n    options?: SimpleStreamOptions\n  ) => AssistantMessageEventStream;\n\n  /** Custom headers to include in requests. Values use the same resolution syntax as apiKey. */\n  headers?: Record<string, string>;\n\n  /** If true, adds Authorization: Bearer header with the resolved API key. */\n  authHeader?: boolean;\n\n  /** Models to register. If provided, replaces all existing models for this provider. */\n  models?: ProviderModelConfig[];\n\n  /** OAuth provider for /login support. */\n  oauth?: {\n    name: string;\n    login(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;\n    refreshToken(credentials: OAuthCredentials, signal: AbortSignal): Promise<OAuthCredentials>;\n    getApiKey(credentials: OAuthCredentials): string;\n  };\n}\n```\n\n## Model Tanımı Referansı\n\n```typescript\ninterface ProviderModelConfig {\n  /** Model ID (e.g., \"claude-sonnet-4-20250514\"). */\n  id: string;\n\n  /** Display name (e.g., \"Claude 4 Sonnet\"). */\n  name: string;\n\n  /** API type override for this specific model. */\n  api?: Api;\n\n  /** API endpoint URL override for this specific model. */\n  baseUrl?: string;\n\n  /** Whether the model supports extended thinking. */\n  reasoning: boolean;\n\n  /** Maps pi thinking levels to provider/model-specific values; null marks a level unsupported. */\n  thinkingLevelMap?: Partial<Record<\"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\", string | null>>;\n\n  /** Supported input types. */\n  input: (\"text\" | \"image\")[];\n\n  /** Cost per million tokens (for usage tracking). */\n  cost: {\n    input: number;\n    output: number;\n    cacheRead: number;\n    cacheWrite: number;\n  };\n\n  /** Maximum context window size in tokens. */\n  contextWindow: number;\n\n  /** Maximum output tokens. */\n  maxTokens: number;\n\n  /** Custom headers for this specific model. */\n  headers?: Record<string, string>;\n\n  /** Compatibility settings for the selected API. */\n  compat?: {\n    // openai-completions\n    supportsStore?: boolean;\n    supportsDeveloperRole?: boolean;\n    supportsReasoningEffort?: boolean;\n    supportsUsageInStreaming?: boolean;\n    supportsFinishReason?: boolean;\n    supportsStrictMode?: boolean;\n    supportsOpenAIGrammarTools?: boolean; // openai-completions/openai-responses; false falls back to normal function tools\n    maxTokensField?: \"max_completion_tokens\" | \"max_tokens\";\n    requiresToolResultName?: boolean;\n    requiresAssistantAfterToolResult?: boolean;\n    requiresThinkingAsText?: boolean;\n    requiresReasoningContentOnAssistantMessages?: boolean;\n    thinkingFormat?: \"openai\" | \"openrouter\" | \"deepseek\" | \"together\" | \"baseten\" | \"zai\" | \"qwen\" | \"chat-template\" | \"qwen-chat-template\" | \"string-thinking\" | \"ant-ling\";\n    chatTemplateKwargs?: Record<string, string | number | boolean | null | { \"$var\": \"thinking.enabled\" | \"thinking.effort\"; omitWhenOff?: boolean }>;\n    chatTemplateArgs?: Record<string, string | number | boolean | null | { \"$var\": \"thinking.enabled\" | \"thinking.effort\"; omitWhenOff?: boolean }>;\n    cacheControlFormat?: \"anthropic\";\n    sessionAffinityFormat?: \"openai\" | \"openai-nosession\" | \"openrouter\";\n    sendSessionAffinityHeaders?: boolean;\n\n    // anthropic-messages\n    supportsEagerToolInputStreaming?: boolean;\n    supportsLongCacheRetention?: boolean;\n    sendSessionAffinityHeaders?: boolean;\n    supportsCacheControlOnTools?: boolean;\n    forceAdaptiveThinking?: boolean;\n    allowEmptySignature?: boolean;\n    supportsStrictTools?: boolean;\n  };\n}\n```\n\n`openrouter` `reasoning: { effort }` gönderir. `deepseek` etkinleştirildiğinde `thinking: { type: \"enabled\" | \"disabled\" }` ve `reasoning_effort` gönderir. `together`, `reasoning: { enabled }`'yi ve ayrıca `supportsReasoningEffort` etkinleştirildiğinde `reasoning_effort`'yi gönderir. `qwen` DashScope tarzı üst düzey `enable_thinking` içindir. `chat_template_kwargs.enable_thinking` okuyan ve `preserve_thinking`'ye ihtiyaç duyan yerel Qwen uyumlu sunucular için `qwen-chat-template` kullanın. Yapılandırılabilir `chat_template_kwargs` için `chat-template` kullanın, örneğin `chatTemplateKwargs: { \"thinking\": { \"$var\": \"thinking.enabled\" } }` ile vLLM'nin arkasında DeepSeek V3.x. Sağlayıcı `chat_template_args`'nin altında geçiş değerleri beklediğinde ve isteğe bağlı olarak üst düzey `reasoning_effort`'yi desteklediğinde `thinkingFormat: \"baseten\"`'yi `chatTemplateArgs` ile birlikte kullanın.\n`cacheControlFormat: \"anthropic\"` sistem istemine, son araç tanımına ve son kullanıcı, asistan veya araç sonucu metin içeriğine Antropik stil `cache_control` işaretleyicileri uygular.","sourceFile":"custom-provider.md"},"development":{"title":"Gelişim","markdown":"Ek yönergeler için [AGENTS.md](https://github.com/earendil-works/pi-mono/blob/main/AGENTS.md)'e bakın.\n\n## Kurmak\n\n```bash\ngit clone https://github.com/earendil-works/pi-mono\ncd pi-mono\nnpm install\nnpm run build\n```\n\nKaynaktan çalıştır:\n\n```bash\n/path/to/pi-mono/pi-test.sh\n```\n\nKomut dosyası herhangi bir dizinden çalıştırılabilir. Pi arayanın mevcut çalışma dizinini tutar.\n\n## Çatallanma / Yeniden Markalama\n\n`package.json` aracılığıyla yapılandırın:\n\n```json\n{\n  \"piConfig\": {\n    \"name\": \"pi\",\n    \"configDir\": \".pi\"\n  }\n}\n```\n\nÇatalınızın `name`, `configDir` ve `bin` alanını değiştirin. CLI banner'ı, yapılandırma yollarını ve ortam değişkeni adlarını etkiler.\n\n## Yol Çözünürlüğü\n\nÜç yürütme modu: npm kurulum, bağımsız ikili, kaynaktan tsx.\n\n**Paket varlıkları için her zaman `src/config.ts`** kullanın:\n\n```typescript\nimport { getPackageDir, getThemeDir } from \"./config.js\";\n```\n\nPaket varlıkları için hiçbir zaman doğrudan `__dirname` kullanmayın.\n\n## Hata Ayıklama Komutu\n\n`/debug` (gizli) `~/.pi/agent/pi-debug.log`'ye yazar:\n- ANSI kodlarıyla işlenen TUI satırlar\n- LLM'ye gönderilen son mesajlar\n\n## Test\n\n```bash\n./test.sh                         # Run non-LLM tests (no API keys needed)\nnpm test                          # Run all tests\nnpm test -- test/specific.test.ts # Run specific test\n```\n\n## Proje Yapısı\n\n```\npackages/\n  ai/           # LLM provider abstraction\n  agent/        # Agent loop and message types  \n  tui/          # Terminal UI components\n  coding-agent/ # CLI and interactive mode\n```","sourceFile":"development.md"},"environment-variables":{"title":"Ortam Değişkenleri","markdown":"Pi ortam değişkenlerini üç şekilde kullanır:\n\n- `PI_OFFLINE` gibi değişkenler Pi sürecini yapılandırır.\n- Pi `PI_CODING_AGENT`'yi ayarlar, böylece alt süreçler Pi içinde çalıştıklarını tespit edebilir.\n- LLM tarafından çağrılabilir bash aracı tarafından çalıştırılan komutlar, mevcut oturumu tanımlayan `PI_*` değişkenleri alır.\n\nSağlayıcı API-anahtar değişkenleri [Providers](providers.md#environment-variables-or-auth-file)'de ayrı olarak belgelenmiştir.\n\n## Süreç İşaretleyicisi\n\nCLI ve RPC giriş noktaları `PI_CODING_AGENT=true` olarak ayarlanır. Alt süreçler onu devralır ve içeride çalıştıklarını tespit etmek için bunu kullanabilir Pi. Oturuma özel değildir ve Pi, SDK'ye yerleştirildiğinde otomatik olarak ayarlanmaz.\n\n## Bash Aracı Oturum Ortamı\n\nbash aracı tarafından çalıştırılan komutlar mevcut Pi oturum durumunu alır:\n\n| Değişken | Tanım |\n|----------|-------------|\n| `PI_SESSION_ID` | Geçerli oturum kimliği |\n| `PI_SESSION_FILE` | Geçerli oturum JSONL dosyasının mutlak yolu; geçici oturumlar için ayarlanmamış |\n| `PI_PROVIDER` | Şu anda seçili model sağlayıcı |\n| `PI_MODEL` | Şu anda seçili model kimliği |\n| `PI_REASONING_LEVEL` | Mevcut etkili akıl yürütme düzeyi: `off`, `minimal`, `low`, `medium`, `high`, `xhigh` veya `max` |\n\nHer komut başlatıldığında değerler çözümlenir. Bu nedenle modelleri değiştirmek veya mantık düzeyini değiştirmek, Pi'yi yeniden başlatmadan sonraki bash komutunu etkiler. `PI_PROVIDER` ve `PI_MODEL`, bir yönlendiricinin dahili olarak seçebileceği farklı bir yukarı akış modeli değil, seçilen Pi modelini tanımlar.\n\nHangi modelin veya sağlayıcının çalıştığı sorulduğunda, cevabı sistem isteminden çıkarmak yerine bu değişkenleri inceleyin:\n\n```bash\nprintf '%s/%s\\n' \"$PI_PROVIDER\" \"$PI_MODEL\"\nprintf 'reasoning=%s session=%s\\n' \"$PI_REASONING_LEVEL\" \"$PI_SESSION_ID\"\n```\n\nOturum kalıcı olduğunda oturum dosyası doğrudan incelenebilir:\n\n```bash\nif [ -n \"$PI_SESSION_FILE\" ]; then\n  tail -n 1 \"$PI_SESSION_FILE\"\nfi\n```\n\nBu değişkenler LLM tarafından çağrılabilen bash aracına enjekte edilir. Kullanıcı tarafından girilen `!` veya `!!` komutlarına eklenmezler.\n\n### Özel Bash Araçları\n\n`createBashTool()` ile oluşturulan Bash araçları, Pi ile kaydedildiğinde varsayılan olarak oturum ortamını ortaya çıkarır. Enjeksiyon `spawnHook`'den önce gerçekleşir, dolayısıyla bir kanca `ctx.env`'deki değişkenleri alır:\n\n```typescript\nconst bashTool = createBashTool(cwd, {\n  spawnHook: (ctx) => ({\n    ...ctx,\n    env: { ...ctx.env, CI: \"1\" },\n  }),\n});\n```\n\nOturum meta verilerini, ortaya çıkma kancasından bağımsız olarak devre dışı bırakın:\n\n```typescript\nconst bashTool = createBashTool(cwd, {\n  exposeSessionEnvironment: false,\n  spawnHook: (ctx) => ctx,\n});\n```\n\nDevre dışı bırakıldığında, Pi bu değişkenler için devralınan değerleri kaldırır, böylece iç içe geçmiş Pi süreçleri eski üst oturum meta verilerini açığa çıkarmaz.\n\n## Pi Süreç Yapılandırması\n\nBu değişkenler Pi'nin kendisi tarafından okunur:\n\n| Değişken | Tanım |\n|----------|-------------|\n| `PI_CODING_AGENT_DIR` | Yapılandırma dizinini geçersiz kılın; varsayılan `~/.pi/agent` |\n| `PI_CODING_AGENT_SESSION_DIR` | Oturum depolamayı geçersiz kıl; `--session-dir` tarafından geçersiz kılındı |\n| `PI_PACKAGE_DIR` | Nix/Guix mağaza yolları için yararlı olan paket dizinini geçersiz kılın |\n| `PI_OFFLINE` | Güncelleme kontrolleri, paket güncellemeleri ve kurulum/güncelleme telemetrisi dahil başlangıç ​​ağ işlemlerini devre dışı bırakın |\n| `PI_SKIP_VERSION_CHECK` | `pi.dev` son sürüm isteğini devre dışı bırakın |\n| `PI_TELEMETRY` | Yükleme/güncelleme telemetrisini ve sağlayıcı ilişkilendirme başlıklarını geçersiz kıl: `1`/`true`/`yes` veya `0`/`false`/`no` |\n| `PI_CACHE_RETENTION` | Desteklendiği yerlerde genişletilmiş sağlayıcı istemi önbelleğe alma işlemi için `long` olarak ayarlayın |\n| `PI_SHARE_VIEWER_URL` | `/share` tarafından kullanılan temel URL'yi geçersiz kılın |\n| `PI_HARDWARE_CURSOR` | Donanım imlecini göstermek için `1` olarak ayarlayın; bkz. [Terminal setup](terminal-setup.md) |\n| `VISUAL`, `EDITOR` | `externalEditor` ayarlanmadığında harici düzenleyici geri dönüşü |\n| `HTTP_PROXY`, `HTTPS_PROXY` | Proxy giden HTTP istekleri |\n\n`ANTHROPIC_API_KEY`, `OPENAI_API_KEY` gibi sağlayıcı kimlik bilgileri ve bulut sağlayıcı yapılandırması [Providers](providers.md#environment-variables-or-auth-file)'de listelenmiştir.","sourceFile":"environment-variables.md"},"extensions":{"title":"Extensions","markdown":"> pi uzantılar oluşturabilir. Kullanım durumunuz için bir tane oluşturmasını isteyin.\n\n\nExtensions pi'nin davranışını genişleten TypeScript modüllerdir. Yaşam döngüsü olaylarına abone olabilirler, LLM tarafından çağrılabilen özel araçları kaydedebilirler, komutlar ekleyebilirler ve daha fazlasını yapabilirler.\n\n> **/reload için yerleştirme:** Otomatik keşif için uzantıları `~/.pi/agent/extensions/` (genel) veya `.pi/extensions/` (proje-yerel) içine yerleştirin. `pi -e./path.ts`'yi yalnızca hızlı testler için kullanın. Otomatik keşfedilen konumlardaki Extensions, `/reload` ile çalışırken yeniden yüklenebilir.\n\n**Temel yetenekler:**\n- **Özel araçlar** - LLM'nin `pi.registerTool()` aracılığıyla arayabileceği araçları kaydedin\n- **Olay müdahalesi** - Araç çağrılarını engelleyin veya değiştirin, bağlam ekleyin, sıkıştırmayı özelleştirin\n- **Kullanıcı etkileşimi** - Kullanıcılara `ctx.ui` aracılığıyla bilgi verin (seç, onayla, gir, bildir)\n- **Özel kullanıcı arayüzü bileşenleri** - Karmaşık etkileşimler için `ctx.ui.custom()` aracılığıyla klavye girişine sahip tam TUI bileşenler\n- **Özel komutlar** - `/mycommand` gibi komutları `pi.registerCommand()` aracılığıyla kaydedin\n- **Oturum kalıcılığı** - `pi.appendEntry()` aracılığıyla yeniden başlatıldıktan sonra hayatta kalan mağaza durumu\n- **Özel oluşturma** - Araç çağrılarının/sonuçlarının ve mesajlarının TUI'de nasıl görüneceğini kontrol edin\n\n**Örnek kullanım durumları:**\n- İzin kapıları (`rm -rf`, `sudo` vb.'den önce onaylayın)\n- Git kontrol noktası oluşturma (her fırsatta saklama, dalda geri yükleme)\n- Yol koruması (blok `.env`, `node_modules/`'ye yazar)\n- Özel sıkıştırma (konuşmayı kendi tarzınızda özetleyin)\n- Konuşma özetleri (bkz. `summarize.ts` örneği)\n- Etkileşimli araçlar (sorular, sihirbazlar, özel diyaloglar)\n- Durum bilgisi olan araçlar (yapılacaklar listeleri, bağlantı havuzları)\n- Harici entegrasyonlar (dosya izleyicileri, web kancaları, CI tetikleyicileri)\n- Beklerken oynanan oyunlar (bkz. `snake.ts` örneği)\n\nÇalışan uygulamalar için [examples/extensions/](../examples/extensions/)'e bakın.\n\n## İçindekiler\n\n- [Quick Start](#quick-start)\n- [Extension Locations](#extension-locations)\n- [Available Imports](#available-imports)\n- [Writing an Extension](#writing-an-extension)\n  - [Extension Styles](#extension-styles)\n- [Events](#events)\n  - [Lifecycle Overview](#lifecycle-overview)\n  - [Resource Events](#resource-events)\n  - [Session Events](#session-events)\n  - [Agent Events](#agent-events)\n  - [Model Events](#model-events)\n  - [Tool Events](#tool-events)\n- [ExtensionContext](#extensioncontext)\n- [ExtensionCommandContext](#extensioncommandcontext)\n- [ExtensionAPI Methods](#extensionapi-methods)\n- [State Management](#state-management)\n- [Custom Tools](#custom-tools)\n  - [Dynamic Tool Loading](#dynamic-tool-loading)\n- [Custom UI](#custom-ui)\n- [Error Handling](#error-handling)\n- [Mode Behavior](#mode-behavior)\n- [Examples Reference](#examples-reference)\n\n## Hızlı Başlangıç\n\n`~/.pi/agent/extensions/my-extension.ts` oluştur:\n\n```typescript\nimport type { ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\nimport { Type } from \"typebox\";\n\nexport default function (pi: ExtensionAPI) {\n  // React to events\n  pi.on(\"session_start\", async (_event, ctx) => {\n    ctx.ui.notify(\"Extension loaded!\", \"info\");\n  });\n\n  pi.on(\"tool_call\", async (event, ctx) => {\n    if (event.toolName === \"bash\" && event.input.command?.includes(\"rm -rf\")) {\n      const ok = await ctx.ui.confirm(\"Dangerous!\", \"Allow rm -rf?\");\n      if (!ok) return { block: true, reason: \"Blocked by user\" };\n    }\n  });\n\n  // Register a custom tool\n  pi.registerTool({\n    name: \"greet\",\n    label: \"Greet\",\n    description: \"Greet someone by name\",\n    parameters: Type.Object({\n      name: Type.String({ description: \"Name to greet\" }),\n    }),\n    async execute(toolCallId, params, signal, onUpdate, ctx) {\n      return {\n        content: [{ type: \"text\", text: `Hello, ${params.name}!` }],\n        details: {},\n      };\n    },\n  });\n\n  // Register a command\n  pi.registerCommand(\"hello\", {\n    description: \"Say hello\",\n    handler: async (args, ctx) => {\n      ctx.ui.notify(`Hello ${args || \"world\"}!`, \"info\");\n    },\n  });\n}\n```\n\n`--extension` (veya `-e`) bayrağıyla test edin:\n\n```bash\npi -e ./my-extension.ts\n```\n\n## Uzantı Konumları\n\n> **Güvenlik:** Extensions tüm sistem izinlerinizle çalıştırın ve isteğe bağlı kod çalıştırabilir. Yalnızca güvendiğiniz kaynaklardan yükleyin.\n\nExtensions güvenilir konumlardan otomatik olarak keşfedilir. Proje yerel `.pi/extensions` girişleri yalnızca projeye güvenildikten sonra yüklenir.\n\n| Konum | Kapsam |\n|----------|-------|\n| `~/.pi/agent/extensions/*.ts` | Küresel (tüm projeler) |\n| `~/.pi/agent/extensions/*/index.ts` | Genel (alt dizin) |\n| `.pi/extensions/*.ts` | Proje-yerel |\n| `.pi/extensions/*/index.ts` | Proje-yerel (alt dizin) |\n\n`settings.json` aracılığıyla ek yollar:\n\n```json\n{\n  \"packages\": [\n    \"npm:@foo/bar@1.0.0\",\n    \"git:github.com/user/repo@v1\"\n  ],\n  \"extensions\": [\n    \"/path/to/local/extension.ts\",\n    \"/path/to/local/extension/dir\"\n  ]\n}\n```\n\nUzantıları npm veya git aracılığıyla pi paketleri olarak paylaşmak için, bkz. [packages.md](packages.md).\n\n## Mevcut İçe Aktarmalar\n\n| Paket | Amaç |\n|---------|---------|\n| `@earendil-works/pi-coding-agent` | Uzantı türleri (`ExtensionAPI`, `ExtensionContext`, etkinlikler) |\n| `typebox` | Takım parametreleri için şema tanımları |\n| `@earendil-works/pi-ai` | Yapay zeka yardımcı programları (Google uyumlu numaralandırmalar için `StringEnum`) |\n| `@earendil-works/pi-tui` | TUI özel işleme için bileşenler |\n\nnpm bağımlılıklar da işe yarar. Uzantınızın yanına (veya bir ana dizine) `package.json` ekleyin, `npm install` komutunu çalıştırın; `node_modules/`'den yapılan içe aktarmalar otomatik olarak çözümlenir.\n\n`pi install` (npm veya git) ile kurulan dağıtılmış pi paketleri için çalışma zamanı depoları `dependencies`'de olmalıdır. Paket kurulumunda varsayılan olarak üretim kurulumları (`npm install --omit=dev`) kullanılır, dolayısıyla `devDependencies` çalışma zamanında kullanılamaz; `npmCommand` yapılandırıldığında git paketleri sarmalayıcılarla uyumluluk için düz `install` kullanır.\n\nNode.js yerleşikler (`node:fs`, `node:path`, vb.) de mevcuttur.\n\n## Uzantı Yazma\n\nBir uzantı, `ExtensionAPI` alan bir varsayılan fabrika işlevini dışa aktarır. Fabrika senkron veya asenkron olabilir:\n\n```typescript\nimport type { ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\n\nexport default function (pi: ExtensionAPI) {\n  // Subscribe to events\n  pi.on(\"event_name\", async (event, ctx) => {\n    // ctx.ui for user interaction\n    const ok = await ctx.ui.confirm(\"Title\", \"Are you sure?\");\n    ctx.ui.notify(\"Done!\", \"info\");\n    ctx.ui.setStatus(\"my-ext\", \"Processing...\");  // Footer status\n    ctx.ui.setWidget(\"my-ext\", [\"Line 1\", \"Line 2\"]);  // Widget above editor (default)\n  });\n\n  // Register tools, commands, shortcuts, flags\n  pi.registerTool({ ... });\n  pi.registerCommand(\"name\", { ... });\n  pi.registerShortcut(\"ctrl+x\", { ... });\n  pi.registerFlag(\"my-flag\", { ... });\n}\n```\n\nExtensions [jiti](https://github.com/unjs/jiti) aracılığıyla yüklenir, dolayısıyla TypeScript derleme olmadan çalışır.\n\nFabrika `Promise` değerini döndürürse pi, başlatmaya devam etmeden önce bunu bekler. Bu, eşzamansız başlatmanın `session_start`'den önce, `resources_discover`'den önce ve `pi.registerProvider()` aracılığıyla kuyruğa alınan sağlayıcı kayıtları temizlenmeden önce tamamlandığı anlamına gelir.\n\n### Eşzamansız fabrika işlevleri\n\nUzaktan yapılandırmayı getirme veya kullanılabilir modelleri dinamik olarak keşfetme gibi tek seferlik başlatma işleri için eşzamansız fabrika kullanın.\n\n```typescript\nimport type { ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\n\nexport default async function (pi: ExtensionAPI) {\n  const response = await fetch(\"http://localhost:1234/v1/models\");\n  const payload = (await response.json()) as {\n    data: Array<{\n      id: string;\n      name?: string;\n      context_window?: number;\n      max_tokens?: number;\n    }>;\n  };\n\n  pi.registerProvider(\"local-openai\", {\n    baseUrl: \"http://localhost:1234/v1\",\n    apiKey: \"$LOCAL_OPENAI_API_KEY\",\n    api: \"openai-completions\",\n    models: payload.data.map((model) => ({\n      id: model.id,\n      name: model.name ?? model.id,\n      reasoning: false,\n      input: [\"text\"],\n      cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n      contextWindow: model.context_window ?? 128000,\n      maxTokens: model.max_tokens ?? 4096,\n    })),\n  });\n}\n```\n\nBu model, getirilen modellerin normal başlatma sırasında ve `pi --list-models`'ye kadar kullanılabilir olmasını sağlar.\n\n### Uzun ömürlü kaynaklar ve kapatma\n\nUzantı fabrikaları hiçbir zaman oturum başlatmayan çağrılarda çalışabilir. İşlemler, yuvalar, dosya izleyiciler veya zamanlayıcılar gibi arka plan kaynaklarını fabrikadan başlatmayın.\n\nArka plan kaynağının başlatılmasını `session_start` tarihine veya kaynağa ihtiyaç duyan komut/araç/olayına kadar erteleyin. Başlattığınız oturum kapsamlı kaynakları kapatmak için idempotent bir `session_shutdown` işleyici kaydedin.\n\n### Uzatma Stilleri\n\n**Tek dosya** - küçük uzantılar için en basiti:\n\n```\n~/.pi/agent/extensions/\n└── my-extension.ts\n```\n\n**index.ts içeren dizin** - çoklu dosya uzantıları için:\n\n```\n~/.pi/agent/extensions/\n└── my-extension/\n    ├── index.ts        # Entry point (exports default function)\n    ├── tools.ts        # Helper module\n    └── utils.ts        # Helper module\n```\n\n**Bağımlılık içeren paket** - npm paketlere ihtiyaç duyan uzantılar için:\n\n```\n~/.pi/agent/extensions/\n└── my-extension/\n    ├── package.json    # Declares dependencies and entry points\n    ├── package-lock.json\n    ├── node_modules/   # After npm install\n    └── src/\n        └── index.ts\n```\n\n```json\n// package.json\n{\n  \"name\": \"my-extension\",\n  \"dependencies\": {\n    \"zod\": \"^3.0.0\",\n    \"chalk\": \"^5.0.0\"\n  },\n  \"pi\": {\n    \"extensions\": [\"./src/index.ts\"]\n  }\n}\n```\n\nUzantı dizininde `npm install` komutunu çalıştırın, ardından `node_modules/`'den içe aktarmalar otomatik olarak çalışır.\n\n## Olaylar\n\n### Yaşam Döngüsüne Genel Bakış\n\n```\npi starts\n  │\n  ├─► project_trust (user/global and CLI extensions only, before project resources load)\n  ├─► session_start { reason: \"startup\" }\n  └─► resources_discover { reason: \"startup\" }\n      │\n      ▼\nuser sends prompt ─────────────────────────────────────────┐\n  │                                                        │\n  ├─► (extension commands checked first, bypass if found)  │\n  ├─► input (can intercept, transform, or handle)          │\n  ├─► (skill/template expansion if not handled)            │\n  ├─► before_agent_start (can inject message, modify system prompt)\n  ├─► agent_start                                          │\n  ├─► message_start / message_update / message_end         │\n  │                                                        │\n  │   ┌─── turn (repeats while LLM calls tools) ───┐       │\n  │   │                                            │       │\n  │   ├─► turn_start                               │       │\n  │   ├─► context (can modify messages)            │       │\n  │   ├─► before_provider_headers (can mutate headers)     |\n  │   ├─► before_provider_request (can inspect or replace payload)\n  │   ├─► after_provider_response (status + headers, before stream consume)\n  │   │                                            │       │\n  │   │   LLM responds, may call tools:            │       │\n  │   │     ├─► tool_execution_start               │       │\n  │   │     ├─► tool_call (can block)              │       │\n  │   │     ├─► tool_execution_update              │       │\n  │   │     ├─► tool_result (can modify)           │       │\n  │   │     └─► tool_execution_end                 │       │\n  │   │                                            │       │\n  │   └─► turn_end                                 │       │\n  │                                                        │\n  ├─► agent_end                                            │\n  └─► agent_settled (no retry/compaction/follow-up left)   │\n                                                           │\nuser sends another prompt ◄────────────────────────────────┘\n\n/new (new session) or /resume (switch session)\n  ├─► session_before_switch (can cancel)\n  ├─► session_shutdown\n  ├─► session_start { reason: \"new\" | \"resume\", previousSessionFile? }\n  └─► resources_discover { reason: \"startup\" }\n\n/fork or /clone\n  ├─► session_before_fork (can cancel)\n  ├─► session_shutdown\n  ├─► session_start { reason: \"fork\", previousSessionFile }\n  └─► resources_discover { reason: \"startup\" }\n\n/name or pi.setSessionName()\n  └─► session_info_changed\n\n/compact or auto-compaction\n  ├─► session_before_compact (can cancel or customize)\n  └─► session_compact\n\n/tree navigation\n  ├─► session_before_tree (can cancel or customize)\n  └─► session_tree\n\n/model or Ctrl+P (model selection/cycling)\n  ├─► thinking_level_select (if model change changes/clamps thinking level)\n  └─► model_select\n\nthinking level changes (settings, keybinding, pi.setThinkingLevel())\n  └─► thinking_level_select\n\nexit (Ctrl+C, Ctrl+D, SIGHUP, SIGTERM)\n  └─► session_shutdown\n```\n\n### Başlangıç ​​Etkinlikleri\n\n#### proje_güveni\n\nPi, dinamik yapılandırmalara (`.pi` veya `.agents/skills`) sahip bir projeye güvenilip güvenilmeyeceğine karar vermeden önce tetiklenir. Başlangıç ​​sırasında ve oturum değişimi (örneğin `/resume`) mevcut süreçte güveni çözülmemiş bir cwd'ye girdiğinde çalışır. Yalnızca kullanıcı/global uzantılar ve CLI `-e` uzantılar katılır; proje yerel uzantıları, güven çözümlenene kadar yüklenmez.\n\n```typescript\npi.on(\"project_trust\", async (event, ctx) => {\n  // event.cwd - current working directory\n  // ctx has a limited trust context: cwd, mode, hasUI, and select/confirm/input/notify UI helpers\n  if (await ctx.ui.confirm(\"Trust project?\", event.cwd)) {\n    return { trusted: \"yes\", remember: true };\n  }\n  return { trusted: \"undecided\" };\n});\n```\n\nBir `project_trust` işleyicisi `{ trusted: \"yes\" | \"no\" | \"undecided\" }` döndürmelidir. Kararın sahibi, `\"yes\"` veya `\"no\"` döndüren kullanıcı/global veya CLI uzantısıdır; ilk evet/hayır kararı kazanır ve yerleşik güven istemini bastırır. Evet/hayır kararına devam etmek için `remember: true` tuşlarını kullanın; aksi takdirde yalnızca mevcut süreç için geçerlidir. Daha sonraki işleyicilerin veya yerleşik güven akışının karar vermesine izin vermek için `\"undecided\"` değerini döndürün. İstemden önce `ctx.hasUI` seçeneğini işaretleyin. Hiçbir işleyici evet/hayır döndürmezse normal güven çözümlemesi devam eder: kaydedilen `trust.json` kararlar önce uygulanır, ardından `defaultProjectTrust` pi'nin varsayılan olarak sorup sormadığını, güvendiğini veya reddedip reddetmediğini kontrol eder.\n\n### Kaynak Etkinlikleri\n\n#### kaynaklar_keşfet\n\nUzantıların ek beceri, bilgi istemi ve tema yollarına katkıda bulunabilmesi için `session_start` tarihinden sonra tetiklenir.\nBaşlangıç ​​yolu `reason: \"startup\"` kullanır. Yeniden yükleme `reason: \"reload\"` kullanır.\n\n```typescript\npi.on(\"resources_discover\", async (event, _ctx) => {\n  // event.cwd - current working directory\n  // event.reason - \"startup\" | \"reload\"\n  return {\n    skillPaths: [\"/path/to/skills\"],\n    promptPaths: [\"/path/to/prompts\"],\n    themePaths: [\"/path/to/themes\"],\n  };\n});\n```\n\n### Oturum Etkinlikleri\n\nOturum depolama dahili bilgileri için [Session Format](session-format.md) ve SessionManager API'e bakın.\n\n#### oturum_başlangıcı\n\nBir oturum başlatıldığında, yüklendiğinde veya yeniden yüklendiğinde tetiklenir.\n\n```typescript\npi.on(\"session_start\", async (event, ctx) => {\n  // event.reason - \"startup\" | \"reload\" | \"new\" | \"resume\" | \"fork\"\n  // event.previousSessionFile - present for \"new\", \"resume\", and \"fork\"\n  ctx.ui.notify(`Session: ${ctx.sessionManager.getSessionFile() ?? \"ephemeral\"}`, \"info\");\n});\n```\n\n#### session_info_changed\n\nGeçerli oturumun görünen adı `/name`, RPC veya `pi.setSessionName()` aracılığıyla ayarlandığında tetiklenir.\n\n```typescript\npi.on(\"session_info_changed\", async (event, ctx) => {\n  // event.name - current normalized name, or undefined if cleared\n  ctx.ui.notify(`Session renamed: ${event.name ?? \"(none)\"}`, \"info\");\n});\n```\n\n#### session_before_switch\n\nYeni bir oturum başlatmadan (`/new`) veya oturum değiştirmeden (`/resume`) önce tetiklendi.\n\n```typescript\npi.on(\"session_before_switch\", async (event, ctx) => {\n  // event.reason - \"new\" or \"resume\"\n  // event.targetSessionFile - session we're switching to (only for \"resume\")\n\n  if (event.reason === \"new\") {\n    const ok = await ctx.ui.confirm(\"Clear?\", \"Delete all messages?\");\n    if (!ok) return { cancel: true };\n  }\n});\n```\n\nBaşarılı bir geçiş veya yeni oturum eyleminden sonra pi, eski uzantı örneği için `session_shutdown` yayar, yeni oturum için uzantıları yeniden yükler ve yeniden bağlar, ardından `reason: \"new\" | \"resume\"` ve `previousSessionFile` ile `session_start` yayar.\n`session_shutdown`'de temizleme çalışması yapın, ardından `session_start`'de herhangi bir bellek içi durumu yeniden kurun.\n\n#### session_before_fork\n\n`/fork` ile çatallanırken veya `/clone` ile klonlanırken ateşlenir.\n\n```typescript\npi.on(\"session_before_fork\", async (event, ctx) => {\n  // event.entryId - ID of the selected entry\n  // event.position - \"before\" for /fork, \"at\" for /clone\n  return { cancel: true }; // Cancel fork/clone\n  // OR\n  return { skipConversationRestore: true }; // Reserved for future conversation restore control\n});\n```\n\nBaşarılı bir çatallanma veya klonlamanın ardından pi, eski uzantı örneği için `session_shutdown` yayar, yeni oturum için uzantıları yeniden yükler ve yeniden bağlar, ardından `reason: \"fork\"` ve `previousSessionFile` ile `session_start` yayar.\n`session_shutdown`'de temizleme çalışması yapın, ardından `session_start`'de herhangi bir bellek içi durumu yeniden kurun.\n\n#### session_before_compact / session_compact\n\nSıkıştırma sırasında ateşlendi. Ayrıntılar için [compaction.md](compaction.md)'e bakın.\n\n```typescript\npi.on(\"session_before_compact\", async (event, ctx) => {\n  const { preparation, branchEntries, customInstructions, reason, willRetry, signal } = event;\n\n  // reason - \"manual\" (/compact), \"threshold\", or \"overflow\"\n  // willRetry - whether the aborted turn is retried after compaction (overflow recovery)\n\n  // Cancel:\n  return { cancel: true };\n\n  // Custom summary:\n  return {\n    compaction: {\n      summary: \"...\",\n      firstKeptEntryId: preparation.firstKeptEntryId,\n      tokensBefore: preparation.tokensBefore,\n      // usage: summaryResponse.usage, // Optional; included in session totals\n    }\n  };\n});\n\npi.on(\"session_compact\", async (event, ctx) => {\n  // event.compactionEntry - the saved compaction\n  // event.fromExtension - whether extension provided it\n  // event.reason - \"manual\" (/compact), \"threshold\", or \"overflow\"\n  // event.willRetry - whether the aborted turn is retried after compaction (overflow recovery)\n});\n```\n\n#### oturum_önceki_ağaç / oturum_ağaç\n\n`/tree` navigasyonda tetiklendi. Ağaç gezinme kavramları için [Sessions](sessions.md)'ye bakın.\n\n```typescript\npi.on(\"session_before_tree\", async (event, ctx) => {\n  const { preparation, signal } = event;\n  return { cancel: true };\n  // OR provide custom summary:\n  return {\n    summary: {\n      summary: \"...\",\n      // usage: summaryResponse.usage, // Optional; included in session totals\n      details: {},\n    },\n  };\n});\n\npi.on(\"session_tree\", async (event, ctx) => {\n  // event.newLeafId, oldLeafId, summaryEntry, fromExtension\n});\n```\n\n#### session_shutdown\n\nBaşlatılmış bir oturum çalışma zamanı kesilmeden önce tetiklenir. `session_start` veya diğer oturum kapsamlı kancalardan açılan kaynakları temizlemek için bunu kullanın.\n\n```typescript\npi.on(\"session_shutdown\", async (event, ctx) => {\n  // event.reason - \"quit\" | \"reload\" | \"new\" | \"resume\" | \"fork\"\n  // event.targetSessionFile - destination session for session replacement flows\n  // Cleanup, save state, etc.\n});\n```\n\n### Temsilci Etkinlikleri\n\n#### before_agent_start\n\nKullanıcı istemi gönderdikten sonra, aracı döngüsünden önce tetiklenir. Bir mesaj enjekte edebilir ve/veya sistem istemini değiştirebilir.\n\n```typescript\npi.on(\"before_agent_start\", async (event, ctx) => {\n  // event.prompt - user's prompt text\n  // event.images - attached images (if any)\n  // event.systemPrompt - current chained system prompt for this handler\n  //   (includes changes from earlier before_agent_start handlers)\n  // event.systemPromptOptions - structured options used to build the system prompt\n  //   .customPrompt - any custom system prompt (from --system-prompt, SYSTEM.md, or custom templates)\n  //   .selectedTools - tools currently active in the prompt\n  //   .toolSnippets - one-line descriptions for each tool\n  //   .promptGuidelines - custom guideline bullets\n  //   .appendSystemPrompt - text from --append-system-prompt flags\n  //   .cwd - working directory\n  //   .contextFiles - AGENTS.md files and other loaded context files\n  //   .skills - loaded skills\n\n  return {\n    // Inject a persistent message (stored in session, sent to LLM)\n    message: {\n      customType: \"my-extension\",\n      content: \"Additional context for the LLM\",\n      display: true,\n    },\n    // Replace the system prompt for this turn (chained across extensions)\n    systemPrompt: event.systemPrompt + \"\\n\\nExtra instructions for this turn...\",\n  };\n});\n```\n\n`systemPromptOptions` alanı, uzantılara, Pi'nin sistem istemini oluşturmak için kullandığı aynı yapılandırılmış verilere erişim sağlar. Bu, kaynakları yeniden keşfetmeden veya bayrakları yeniden ayrıştırmadan Pi'nin yüklediklerini (özel istemler, yönergeler, araç parçacıkları, context files, beceriler) incelemenizi sağlar. Uzantınızın, kullanıcı tarafından sağlanan yapılandırmayı korurken sistem isteminde derin ve bilinçli değişiklikler yapması gerektiğinde bunu kullanın.\n\nİçerideki `before_agent_start`, `event.systemPrompt` ve `ctx.getSystemPrompt()`'nin her ikisi de mevcut işleyiciden itibaren zincirleme sistem istemini yansıtır. Daha sonra `before_agent_start` işleyiciler yine de onu yeniden değiştirebilir.\n\n#### Agent_start / Agent_end / Agent_settled\n\n`agent_start` düşük seviyeli bir ajan çalıştırması başladığında tetiklenir. `agent_end` bu çalıştırma sona erdiğinde tetiklenir, ancak Pi yine de otomatik olarak yeniden deneyebilir, otomatik olarak sıkıştırabilir ve yeniden deneyebilir veya sıradaki takip mesajlarıyla devam edebilir. Pi'nin otomatik olarak çalışmaya devam etmeyeceğini bilmesi gereken durum entegrasyonları için `agent_settled` kullanın.\n\n```typescript\npi.on(\"agent_start\", async (_event, ctx) => {});\n\npi.on(\"agent_end\", async (event, ctx) => {\n  // event.messages - messages from this low-level run\n});\n\npi.on(\"agent_settled\", async (_event, ctx) => {\n  // ctx.isIdle() is true here unless another extension started a new run.\n});\n```\n\n#### dönüş_başlangıç ​​/ dönüş_son\n\nHer turda ateşlenir (bir LLM yanıtı + araç çağrıları).\n\n```typescript\npi.on(\"turn_start\", async (event, ctx) => {\n  // event.turnIndex, event.timestamp\n});\n\npi.on(\"turn_end\", async (event, ctx) => {\n  // event.turnIndex, event.message, event.toolResults\n});\n```\n\n#### message_start / message_update / message_end\n\nİleti yaşam döngüsü güncellemeleri nedeniyle tetiklendi.\n\n- `message_start` ve `message_end` kullanıcı, asistan ve araçSonuç mesajları için tetiklenir.\n- `message_update` asistan akış güncellemeleri için etkinleşir.\n- `message_end` işleyiciler, sonlandırılmış mesajı değiştirmek için `{ message }` değerini döndürebilir. Değiştirme aynı `role` tutmalıdır.\n\n```typescript\npi.on(\"message_start\", async (event, ctx) => {\n  // event.message\n});\n\npi.on(\"message_update\", async (event, ctx) => {\n  // event.message\n  // event.assistantMessageEvent (token-by-token stream event)\n});\n\npi.on(\"message_end\", async (event, ctx) => {\n  if (event.message.role !== \"assistant\") return;\n\n  return {\n    message: {\n      ...event.message,\n      usage: {\n        ...event.message.usage,\n        cost: {\n          ...event.message.usage.cost,\n          total: 0.123,\n        },\n      },\n    },\n  };\n});\n```\n\n#### tool_execution_start / tool_execution_update / tool_execution_end\n\nAraç yürütme yaşam döngüsü güncellemeleri nedeniyle tetiklendi.\n\nParalel takım modunda:\n- `tool_execution_start` ön kontrol aşamasında yardımcı kaynak sırasına göre yayılır\n- `tool_execution_update` olaylar araçlara karışabilir\n- `tool_execution_end` her takım sonlandırıldıktan sonra takım tamamlama sırasına göre yayınlanır\n- son `toolResult` mesaj etkinlikleri daha sonra yardımcı kaynak sırasına göre yayınlanmaya devam eder\n\n```typescript\npi.on(\"tool_execution_start\", async (event, ctx) => {\n  // event.toolCallId, event.toolName, event.args\n});\n\npi.on(\"tool_execution_update\", async (event, ctx) => {\n  // event.toolCallId, event.toolName, event.args, event.partialResult\n});\n\npi.on(\"tool_execution_end\", async (event, ctx) => {\n  // event.toolCallId, event.toolName, event.result, event.isError\n});\n```\n\n#### bağlam\n\nHer LLM çağrısından önce kovuldu. Mesajları tahribatsız olarak değiştirin. Mesaj türleri için [Session Format](session-format.md)'e bakın.\n\n```typescript\npi.on(\"context\", async (event, ctx) => {\n  // event.messages - deep copy, safe to modify\n  const filtered = event.messages.filter(m => !shouldPrune(m));\n  return { messages: filtered };\n});\n```\n\n#### before_provider_headers\n\nGiden HTTP üstbilgileri birleştirildikten sonra tetiklenir. İstek başlıklarını eklemek, geçersiz kılmak veya kaldırmak için bunu kullanın.\n\nİşleyiciler yerinde `event.headers` mutasyona uğrar. Eklemek veya geçersiz kılmak için bir dizeye veya silmek için `null`'ye bir tuş ayarlayın.\n\n```typescript\npi.on(\"before_provider_headers\", (event, ctx) => {\n  // Add or override — e.g. a session id for gateway tracing/attribution\n  event.headers[\"x-session-id\"] = ctx.sessionManager.getSessionId();\n\n  // Drop a tracking header pi adds for this call\n  event.headers[\"X-OpenRouter-Title\"] = null;\n});\n```\n\nSağlayıcı isteği başına bir kez çalıştırılır; Kancayı yeniden ateşlemek yerine aynı başlıkları yeniden kullanmayı dener.\n\n#### before_provider_request\n\nSağlayıcıya özel veri oluşturulduktan sonra, istek gönderilmeden hemen önce tetiklenir. İşleyiciler uzantı yükleme sırasına göre çalışır. `undefined` değerini döndürmek yükün değişmemesini sağlar. Başka herhangi bir değerin döndürülmesi, daha sonraki işleyicilerin ve gerçek isteğin yükünün yerini alır.\n\nBu kanca, sağlayıcı düzeyindeki sistem talimatlarını yeniden yazabilir veya bunları tamamen kaldırabilir. Bu yük düzeyi değişiklikleri, son serileştirilmiş sağlayıcı yükü yerine Pi'nin sistem istem dizesini bildiren `ctx.getSystemPrompt()` tarafından yansıtılmaz.\n\n```typescript\npi.on(\"before_provider_request\", (event, ctx) => {\n  console.log(JSON.stringify(event.payload, null, 2));\n\n  // Optional: replace payload\n  // return { ...event.payload, temperature: 0 };\n});\n```\n\nBu esas olarak sağlayıcı serileştirmesinde ve önbellek davranışında hata ayıklamak için kullanışlıdır.\n\n#### after_provider_response\n\nBir HTTP yanıtı alındıktan sonra ve akış gövdesi tüketilmeden önce tetiklenir. İşleyiciler uzantı yükleme sırasına göre çalışır.\n\n```typescript\npi.on(\"after_provider_response\", (event, ctx) => {\n  // event.status - HTTP status code\n  // event.headers - normalized response headers\n  if (event.status === 429) {\n    console.log(\"rate limited\", event.headers[\"retry-after\"]);\n  }\n});\n```\n\nÜstbilginin kullanılabilirliği sağlayıcıya ve aktarıma bağlıdır. Providers soyut HTTP yanıtlarının başlıkları açığa çıkarmaması.\n\n### Modeli Etkinlikleri\n\n#### model_select\n\nModel `/model` komutu, model döngüsü (`Ctrl+P`) veya oturum geri yükleme yoluyla değiştiğinde tetiklenir.\n\n```typescript\npi.on(\"model_select\", async (event, ctx) => {\n  // event.model - newly selected model\n  // event.previousModel - previous model (undefined if first selection)\n  // event.source - \"set\" | \"cycle\" | \"restore\"\n\n  const prev = event.previousModel\n    ? `${event.previousModel.provider}/${event.previousModel.id}`\n    : \"none\";\n  const next = `${event.model.provider}/${event.model.id}`;\n\n  ctx.ui.notify(`Model changed (${event.source}): ${prev} -> ${next}`, \"info\");\n});\n```\n\nKullanıcı arayüzü öğelerini (durum çubukları, alt bilgiler) güncellemek veya etkin model değiştiğinde modele özel başlatma gerçekleştirmek için bunu kullanın.\n\n#### think_level_select\n\nDüşünme düzeyi değiştiğinde kovulur. Bu yalnızca bildirim amaçlıdır; işleyici dönüş değerleri göz ardı edilir.\n\n```typescript\npi.on(\"thinking_level_select\", async (event, ctx) => {\n  // event.level - newly selected thinking level\n  // event.previousLevel - previous thinking level\n\n  ctx.ui.setStatus(\"thinking\", `thinking: ${event.level}`);\n});\n```\n\n`pi.setThinkingLevel()`, model değişiklikleri veya yerleşik düşünme düzeyi kontrolleri aktif düşünme düzeyini değiştirdiğinde uzantı kullanıcı arayüzünü güncellemek için bunu kullanın.\n\n### Araç Olayları\n\n#### tool_call\n\n`tool_execution_start` sonrasında, araç çalıştırılmadan önce tetiklendi. **Engelleyebilir.** Yazılı girişleri daraltmak ve almak için `isToolCallEventType` tuşunu kullanın.\n\n`tool_call` çalıştırılmadan önce pi, önceden yayılan Ajan olaylarının `AgentSession` boyunca boşaltılmasını bitirmesini bekler. Bu, `ctx.sessionManager`'nin mevcut yardımcı araç çağırma mesajı aracılığıyla güncel olduğu anlamına gelir.\n\nVarsayılan paralel takım yürütme modunda, aynı asistan mesajından gelen kardeş takım çağrılarının sırasıyla ön kontrolü yapılır ve ardından eş zamanlı olarak yürütülür. `tool_call`, `ctx.sessionManager`'deki aynı asistan mesajından kardeş aracı sonuçlarını göreceğiniz garanti edilmez.\n\n`event.input` değiştirilebilir. Yürütmeden önce araç bağımsız değişkenlerini yamamak için onu yerinde değiştirin.\n\nDavranış garantileri:\n- `event.input`'deki mutasyonlar gerçek takım uygulamasını etkiler\n- Daha sonra `tool_call` işleyiciler daha önceki işleyiciler tarafından yapılan mutasyonları görür\n- Mutasyonunuzdan sonra yeniden doğrulama yapılmaz\n- `{ block: true, reason?: string, terminate?: boolean }` aracılığıyla `tool_call` kontrol engellemesinden değerleri döndür\n- `terminate` yalnızca engellenen çağrı için geçerlidir; aracı yalnızca gruptaki her kesin sonuç sona erdiğinde erken durur\n\n```typescript\nimport { isToolCallEventType } from \"@earendil-works/pi-coding-agent\";\n\npi.on(\"tool_call\", async (event, ctx) => {\n  // event.toolName - \"bash\", \"read\", \"write\", \"edit\", etc.\n  // event.toolCallId\n  // event.input - tool parameters (mutable)\n\n  // Built-in tools: no type params needed\n  if (isToolCallEventType(\"bash\", event)) {\n    // event.input is { command: string; timeout?: number }\n    event.input.command = `source ~/.profile\\n${event.input.command}`;\n\n    if (event.input.command.includes(\"rm -rf\")) {\n      return { block: true, reason: \"Dangerous command\", terminate: true };\n    }\n  }\n\n  if (isToolCallEventType(\"read\", event)) {\n    // event.input is { path: string; offset?: number; limit?: number }\n    console.log(`Reading: ${event.input.path}`);\n  }\n});\n```\n\n#### Özel araç girişi yazma\n\nÖzel araçlar giriş türlerini dışa aktarmalıdır:\n\n```typescript\n// my-extension.ts\nexport type MyToolInput = Static<typeof myToolSchema>;\n```\n\nAçık tür parametreleriyle `isToolCallEventType` kullanın:\n\n```typescript\nimport { isToolCallEventType } from \"@earendil-works/pi-coding-agent\";\nimport type { MyToolInput } from \"my-extension\";\n\npi.on(\"tool_call\", (event) => {\n  if (isToolCallEventType<\"my_tool\", MyToolInput>(\"my_tool\", event)) {\n    event.input.action;  // typed\n  }\n});\n```\n\n#### tool_result\n\nAracın yürütülmesi tamamlandıktan sonra ve `tool_execution_end` artı son araç sonuç mesajı olayları yayınlanmadan önce tetiklenir. **Sonucu değiştirebilir.**\n\nParalel takım modunda, `tool_result` ve `tool_execution_end` takım tamamlama sırasına göre karışabilir, son `toolResult` mesaj olayları ise daha sonra yardımcı kaynak sırasına göre yayınlanmaya devam eder.\n\n`tool_result` ara katman yazılımı gibi işleyiciler zinciri:\n- İşleyiciler uzantı yükleme sırasına göre çalışır\n- Her işleyici, önceki işleyici değişikliklerinden sonraki en son sonucu görür\n- İşleyiciler kısmi yamaları döndürebilir (`content`, `details`, `isError` veya `usage`); atlanan alanlar mevcut değerlerini korur\n\nİşleyicinin içindeki iç içe eşzamansız çalışma için `ctx.signal` kullanın. Bu, Esc'nin model çağrılarını, `fetch()` ve uzantı tarafından başlatılan diğer iptal etmeye duyarlı işlemleri iptal etmesine olanak tanır.\n\n```typescript\nimport { isBashToolResult } from \"@earendil-works/pi-coding-agent\";\n\npi.on(\"tool_result\", async (event, ctx) => {\n  // event.toolName, event.toolCallId, event.input\n  // event.content, event.details, event.isError, event.usage\n\n  if (isBashToolResult(event)) {\n    // event.details is typed as BashToolDetails\n  }\n\n  const response = await fetch(\"https://example.com/summarize\", {\n    method: \"POST\",\n    body: JSON.stringify({ content: event.content }),\n    signal: ctx.signal,\n  });\n\n  // Modify result:\n  return { content: [...], details: {...}, isError: false, usage: nestedModelUsage };\n});\n```\n\n### Kullanıcı Bash Etkinlikleri\n\n#### kullanıcı_bash\n\nKullanıcı `!` veya `!!` komutlarını çalıştırdığında tetiklenir. **Araya girebilir.**\n\n```typescript\nimport { createLocalBashOperations } from \"@earendil-works/pi-coding-agent\";\n\npi.on(\"user_bash\", (event, ctx) => {\n  // event.command - the bash command\n  // event.excludeFromContext - true if !! prefix\n  // event.cwd - working directory\n\n  // Option 1: Provide custom operations (e.g., SSH)\n  return { operations: remoteBashOps };\n\n  // Option 2: Wrap pi's built-in local bash backend\n  const local = createLocalBashOperations();\n  return {\n    operations: {\n      exec(command, cwd, options) {\n        return local.exec(`source ~/.profile\\n${command}`, cwd, options);\n      }\n    }\n  };\n\n  // Option 3: Full replacement - return result directly\n  return { result: { output: \"...\", exitCode: 0, cancelled: false, truncated: false } };\n});\n```\n\n### Giriş Olayları\n\n#### giriş\n\nKullanıcı girişi alındığında, uzantı komutları kontrol edildikten sonra ancak beceri ve şablon genişletmeden önce tetiklenir. Etkinlik ham giriş metnini gördüğünden `/skill:foo` ve `/template` henüz genişletilmedi.\n\n**İşleme sırası:**\n1. Önce uzantı komutları (`/cmd`) kontrol edilir - bulunursa işleyici çalışır ve giriş olayı atlanır\n2. `input` olay tetiklenir - müdahale edebilir, dönüştürebilir veya işleyebilir\n3. Eğer işlenmezse: beceri komutları (`/skill:name`) beceri içeriğine genişletildi\n4. İşlenmezse: prompt templates (`/template`) şablon içeriğine genişletildi\n5. Aracı işleme başlar (`before_agent_start` vb.)\n\n```typescript\npi.on(\"input\", async (event, ctx) => {\n  // event.text - raw input (before skill/template expansion)\n  // event.images - attached images, if any\n  // event.source - \"interactive\" (typed), \"rpc\" (API), or \"extension\" (via sendUserMessage)\n  // event.streamingBehavior - \"steer\" | \"followUp\" | undefined\n  //   undefined when idle, \"steer\" for mid-stream interrupts,\n  //   \"followUp\" for messages queued until the agent finishes\n\n  // Transform: rewrite input before expansion\n  if (event.text.startsWith(\"?quick \"))\n    return { action: \"transform\", text: `Respond briefly: ${event.text.slice(7)}` };\n\n  // Handle: respond without LLM (extension shows its own feedback)\n  if (event.text === \"ping\") {\n    ctx.ui.notify(\"pong\", \"info\");\n    return { action: \"handled\" };\n  }\n\n  // Route by source: skip processing for extension-injected messages\n  if (event.source === \"extension\") return { action: \"continue\" };\n\n  // Intercept skill commands before expansion\n  if (event.text.startsWith(\"/skill:\")) {\n    // Could transform, block, or let pass through\n  }\n\n  return { action: \"continue\" };  // Default: pass through to expansion\n});\n```\n\n**Sonuçlar:**\n- `continue` - değişmeden geçiş (işleyici hiçbir şey döndürmezse varsayılan)\n- `transform` - metni/resimleri değiştirin, ardından genişletmeye devam edin\n- `handled` - temsilciyi tamamen atla (bunu geri veren ilk işleyici kazanır)\n\nZinciri işleyiciler arasında dönüştürür. `streamingBehavior` bilinçli yönlendirme için [input-transform.ts](../examples/extensions/input-transform.ts) ve [input-transform-streaming.ts](../examples/extensions/input-transform-streaming.ts)'ye bakın.\n\n## Uzantı Bağlamı\n\nTüm işleyiciler `ctx: ExtensionContext` alır.\n\n### ctx.ui\n\nKullanıcı etkileşimi için kullanıcı arayüzü yöntemleri. Tüm ayrıntılar için [Custom UI](#custom-ui)'e bakın.\n\n### ctx.mode\n\nGeçerli çalışma modu: `\"tui\"`, `\"rpc\"`, `\"json\"` veya `\"print\"`. `custom()`, bileşen fabrikaları, terminal girişi ve doğrudan TUI oluşturma gibi yalnızca terminal özelliklerini korumak için `ctx.mode === \"tui\"` kullanın.\n\n### ctx.hasUI\n\nTUI ve RPC modlarında `true`. `false` baskı modunda (`-p`) ve JSON modunda. Hem TUI hem de çalışan diyalog yöntemlerini (`select`, `confirm`, `input`, `editor`) ve ateşle ve unut yöntemlerini (`notify`, `setStatus`, `setWidget`, `setTitle`, `setEditorText`) korumak için bunu kullanın. RPC modları. RPC modunda, TUI'ye özgü bazı yöntemler işlem gerektirmez veya varsayılanları döndürür (bkz. [rpc.md](rpc.md#extension-ui-protocol)).\n\n### ctx.cwd\n\nGeçerli çalışma dizini.\n\nProje yerel yapılandırma yollarını oluştururken `.pi` sabit kodlama yerine `CONFIG_DIR_NAME` kullanın. Yeniden markalanan dağıtımlar farklı bir yapılandırma dizini adı kullanabilir.\n\n```typescript\nimport { CONFIG_DIR_NAME, type ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\nimport { join } from \"node:path\";\n\nexport default function (pi: ExtensionAPI) {\n  pi.on(\"session_start\", (_event, ctx) => {\n    const projectConfigPath = join(ctx.cwd, CONFIG_DIR_NAME, \"my-extension.json\");\n    // ...\n  });\n}\n```\n\n### ctx.isProjectTrusted()\n\nGeçerli oturum bağlamı için proje yerel güveninin etkin olup olmadığını döndürür. Bu, yalnızca küresel güven deposunda kaydedilen kararları değil, geçici güven kararlarını ve CLI güven geçersiz kılmalarını da içerir.\n\nYalnızca güvenilir projeler için dikkate alınması gereken proje yerel uzantı yapılandırmasını okumadan önce bunu kullanın.\n\n### ctx.sessionManager'ı\n\nOturum durumuna salt okunur erişim. Tam SessionManager API ve giriş türleri için [Session Format](session-format.md)'ye bakın.\n\n`tool_call` için bu durum, işleyiciler çalıştırılmadan önce mevcut asistan mesajı aracılığıyla senkronize edilir. Paralel takım yürütme modunda, aynı asistan mesajından kardeş takım sonuçlarının dahil edilmesi hala garanti edilmez.\n\n```typescript\nctx.sessionManager.getEntries()             // All entries\nctx.sessionManager.getBranch()              // Current branch\nctx.sessionManager.buildContextEntries()    // Active branch entries with compaction applied\nctx.sessionManager.getLeafId()              // Current leaf entry ID\n```\n\n### ctx.modelRegistry / ctx.model / ctx.thinkingLevel / ctx.scopedModels\n\nModellere, sağlayıcılara ve çözümlenmiş kimlik doğrulamaya erişim. `ctx.modelRegistry.getProvider(id)` etkili pi-ai sağlayıcısını döndürürken `getProviderAuth(id)`, yüklü bir model gerektirmeden mevcut API key, başlıklarını, temel URL'sini ve sağlayıcı kapsamlı ortamını çözer. `ctx.model` aktif model, `ctx.thinkingLevel` ise mevcut etkili düşünme düzeyidir.\n\n`ctx.scopedModels` geçerli oturumun kapsamındaki modellerin salt okunur listesidir — `/scoped-models` komutunun gösterdiği kümenin aynısıdır. Oturum başlangıcında `--models` CLI bayrağı ve `enabledModels` ayarından çözümlenir (`provider/modelId` veya çıplak `modelId`'de mini eşleşme ile mevcut katalogla eşleştirilir). Kapsam belirleme yapılandırılmadığında boştur; bu, mevcut her modelin kullanılabileceği anlamına gelir. Her giriş `{ model, thinkingLevel? }`'dir; burada `thinkingLevel` yalnızca bir desen sabitlendiğinde ayarlanır (örn. `anthropic/*:high`). Kataloğun tamamını `ctx.modelRegistry.getAvailable()` aracılığıyla numaralandırmak yerine yerleşik modeli yansıtan bir model seçiciyi doldurmak için bunu kullanın.\n\n### ctx.sinyali\n\nGeçerli temsilci iptal sinyali veya hiçbir temsilci dönüşü etkin olmadığında `undefined`.\n\nUzantı işleyicileri tarafından başlatılan, iptal etme özelliğine sahip iç içe geçmiş işler için bunu kullanın, örneğin:\n- `fetch(..., { signal: ctx.signal })`\n- kabul edilen model çağrıları `signal`\n- `AbortSignal` kabul eden dosya veya işlem yardımcıları\n\n`ctx.signal` genellikle `tool_call`, `tool_result`, `message_update` ve `turn_end` gibi aktif dönüş etkinlikleri sırasında tanımlanır.\nOturum olayları, uzantı komutları ve pi boştayken başlatılan kısayollar gibi boşta veya dönüşsüz bağlamlarda genellikle `undefined` olur.\n\n```typescript\npi.on(\"tool_result\", async (event, ctx) => {\n  const response = await fetch(\"https://example.com/api\", {\n    method: \"POST\",\n    body: JSON.stringify(event),\n    signal: ctx.signal,\n  });\n\n  const data = await response.json();\n  return { details: data };\n});\n```\n\n### ctx.isIdle() / ctx.abort() / ctx.hasPendingMessages()\n\nAkış yardımcılarını kontrol edin. Pi bir aracı çalıştırmayı, otomatik yeniden denemeyi, otomatik sıkıştırma yeniden denemesini veya sıraya alınmış devamı işlerken `ctx.isIdle()` yanlıştır.\n\n### ctx.shutdown()\n\nPi'nin zarif bir şekilde kapatılmasını talep edin.\n\n- **Etkileşimli mod:** Temsilci boşta kalana kadar ertelenir (sıradaki tüm yönlendirme ve takip mesajlarını işledikten sonra).\n- **RPC modu:** Bir sonraki boşta durumuna kadar ertelenir (mevcut komut yanıtını tamamladıktan sonra, sonraki komutu beklerken).\n- **Baskı modu:** İşlem yok. Tüm istemler işlendiğinde işlemden otomatik olarak çıkılır.\n\nÇıkmadan önce tüm uzantılara `session_shutdown` olayını yayar. Tüm bağlamlarda kullanılabilir (olay işleyicileri, araçlar, komutlar, kısayollar).\n\n```typescript\npi.on(\"tool_call\", (event, ctx) => {\n  if (isFatal(event.input)) {\n    ctx.shutdown();\n  }\n});\n```\n\n### ctx.getContextUsage()\n\nEtkin model için geçerli bağlam kullanımını döndürür. Mümkün olduğunda son yardımcı kullanımını kullanır ve ardından takip eden mesajlar için belirteçleri tahmin eder.\n\n```typescript\nconst usage = ctx.getContextUsage();\nif (usage && usage.tokens > 100_000) {\n  // ...\n}\n```\n\n### ctx.compact()\n\nTamamlanmayı beklemeden sıkıştırmayı tetikleyin. Takip işlemleri için `onComplete` ve `onError` tuşlarını kullanın.\n\n```typescript\nctx.compact({\n  customInstructions: \"Focus on recent changes\",\n  onComplete: (result) => {\n    ctx.ui.notify(\"Compaction completed\", \"info\");\n  },\n  onError: (error) => {\n    ctx.ui.notify(`Compaction failed: ${error.message}`, \"error\");\n  },\n});\n```\n\n### ctx.getSystemPrompt()\n\nPi'nin geçerli sistem istem dizesini döndürür.\n\n- `before_agent_start` sırasında bu, mevcut tur için şu ana kadar yapılan zincirleme sistem istemi değişikliklerini yansıtır.\n- Daha sonraki `context` mesaj mutasyonlarını içermez.\n- `before_provider_request` yük yeniden yazma işlemlerini içermez.\n- Daha sonra yüklenen uzantılar sizinkinden sonra çalışırsa, sonuçta gönderilenleri yine de değiştirebilirler.\n\n```typescript\npi.on(\"before_agent_start\", (event, ctx) => {\n  const prompt = ctx.getSystemPrompt();\n  console.log(`System prompt length: ${prompt.length}`);\n});\n```\n\n## ExtensionCommandContext\n\nKomut işleyicileri, oturum kontrol yöntemleriyle `ExtensionContext`'yi genişleten `ExtensionCommandContext`'yi alır. Bunlar yalnızca komutlarda mevcuttur çünkü olay işleyicilerinden çağrıldıklarında kilitlenebilirler.\n\n### ctx.getSystemPromptOptions()\n\nPi'nin şu anda sistem istemini oluşturmak için kullandığı temel girişleri döndürür.\n\n```typescript\nconst options = ctx.getSystemPromptOptions();\nconst contextPaths = options.contextFiles?.map((file) => file.path) ?? [];\n```\n\nBu, `before_agent_start` `event.systemPromptOptions` ile aynı şekle ve değiştirilebilirliğe sahiptir: özel bilgi istemi, aktif araçlar, araç parçacıkları, bilgi istemi yönergeleri, eklenen sistem bilgi istemi metni, cwd, yüklü context files ve yüklü beceriler. Tam bağlam dosyası içeriği içerebilir; bu nedenle, onu hassas uzantı yerel verileri olarak değerlendirin ve komut listeleri, günlükler veya otomatik tamamlama meta verileri aracılığıyla açığa çıkarmaktan kaçının.\n\nBu, geçerli temel bilgi istemi girişlerini rapor eder. Tur başına `before_agent_start` zincirleme sistem istemi değişikliklerini, daha sonra `context` olay mesajı mutasyonlarını veya `before_provider_request` yük yeniden yazma işlemlerini içermez.\n\n### ctx.waitForIdle()\n\nOtomatik yeniden denemeler, otomatik sıkıştırma yeniden denemeleri ve sıraya alınmış devamlar da dahil olmak üzere aracının tamamen yerleşmesini bekleyin:\n\n```typescript\npi.registerCommand(\"my-cmd\", {\n  handler: async (args, ctx) => {\n    await ctx.waitForIdle();\n    // Agent is now idle, safe to modify session\n  },\n});\n```\n\n### ctx.newSession(seçenekler?)\n\nYeni bir oturum oluşturun:\n\n```typescript\nconst parentSession = ctx.sessionManager.getSessionFile();\nconst kickoff = \"Continue in the replacement session\";\n\nconst result = await ctx.newSession({\n  parentSession,\n  setup: async (sm) => {\n    sm.appendMessage({\n      role: \"user\",\n      content: [{ type: \"text\", text: \"Context from previous session...\" }],\n      timestamp: Date.now(),\n    });\n  },\n  withSession: async (ctx) => {\n    // Use only the replacement-session ctx here.\n    await ctx.sendUserMessage(kickoff);\n  },\n});\n\nif (result.cancelled) {\n  // An extension cancelled the new session\n}\n```\n\nSeçenekler:\n- `parentSession`: yeni oturum başlığına kaydedilecek ana oturum dosyası\n- `setup`: `withSession` çalıştırılmadan önce yeni oturumun `SessionManager`'sini değiştirin\n- `withSession`: geçiş sonrası çalışmayı yeni bir değişim oturumu bağlamına göre çalıştırın. Yakalanan eski `pi` / komut `ctx`'yi kullanmayın; bkz. [Session replacement lifecycle and footguns](#session-replacement-lifecycle-and-footguns).\n\n### ctx.fork(giriş kimliği, seçenekler?)\n\nBelirli bir girişten çatallanarak yeni bir oturum dosyası oluşturulur:\n\n```typescript\nconst result = await ctx.fork(\"entry-id-123\", {\n  withSession: async (ctx) => {\n    // Use only the replacement-session ctx here.\n    ctx.ui.notify(\"Now in the forked session\", \"info\");\n  },\n});\nif (result.cancelled) {\n  // An extension cancelled the fork\n}\n\nconst cloneResult = await ctx.fork(\"entry-id-456\", { position: \"at\" });\nif (cloneResult.cancelled) {\n  // An extension cancelled the clone\n}\n```\n\nSeçenekler:\n- `position`: `\"before\"` (varsayılan) seçili kullanıcı mesajından önce çatallar, bu istemi düzenleyiciye geri yükler\n- `position`: `\"at\"` düzenleyici metnini geri yüklemeden seçilen girişteki etkin yolu kopyalar\n- `withSession`: geçiş sonrası çalışmayı yeni bir değişim oturumu bağlamına göre çalıştırın. Yakalanan eski `pi` / komut `ctx`'yi kullanmayın; bkz. [Session replacement lifecycle and footguns](#session-replacement-lifecycle-and-footguns).\n\n### ctx.navigateTree(hedefId, seçenekler?)\n\nsession tree'de farklı bir noktaya gidin:\n\n```typescript\nconst result = await ctx.navigateTree(\"entry-id-456\", {\n  summarize: true,\n  customInstructions: \"Focus on error handling changes\",\n  replaceInstructions: false, // true = replace default prompt entirely\n  label: \"review-checkpoint\",\n});\n```\n\nSeçenekler:\n- `summarize`: Terk edilen dalın özetinin oluşturulup oluşturulmayacağı\n- `customInstructions`: Özetleyici için özel talimatlar\n- `replaceInstructions`: Doğruysa, `customInstructions`, eklenmek yerine varsayılan istemin yerine geçer\n- `label`: Şube özet girişine eklenecek etiket (veya özetlemiyorsa hedef giriş)\n\n### ctx.switchSession(sessionPath, seçenekler?)\n\nFarklı bir oturum dosyasına geçin:\n\n```typescript\nconst result = await ctx.switchSession(\"/path/to/session.jsonl\", {\n  withSession: async (ctx) => {\n    await ctx.sendUserMessage(\"Resume work in the replacement session\");\n  },\n});\nif (result.cancelled) {\n  // An extension cancelled the switch via session_before_switch\n}\n```\n\nSeçenekler:\n- `withSession`: geçiş sonrası çalışmayı yeni bir değişim oturumu bağlamına göre çalıştırın. Yakalanan eski `pi` / komut `ctx`'yi kullanmayın; bkz. [Session replacement lifecycle and footguns](#session-replacement-lifecycle-and-footguns).\n\nKullanılabilir oturumları keşfetmek için statik `SessionManager.list()` veya `SessionManager.listAll()` yöntemlerini kullanın:\n\n```typescript\nimport { SessionManager } from \"@earendil-works/pi-coding-agent\";\n\npi.registerCommand(\"switch\", {\n  description: \"Switch to another session\",\n  handler: async (args, ctx) => {\n    const sessions = await SessionManager.list(ctx.cwd);\n    if (sessions.length === 0) return;\n    const choice = await ctx.ui.select(\n      \"Pick session:\",\n      sessions.map(s => s.file),\n    );\n    if (choice) {\n      await ctx.switchSession(choice, {\n        withSession: async (ctx) => {\n          ctx.ui.notify(\"Switched session\", \"info\");\n        },\n      });\n    }\n  },\n});\n```\n\n### Oturum değiştirme yaşam döngüsü ve temelleri\n\n`withSession` yeni bir `ReplacedSessionContext` alır ve bu, değiştirme oturumuna bağlı async `sendMessage()` ve `sendUserMessage()` yardımcılarıyla `ExtensionCommandContext`'yi genişletir.\n\nYaşam döngüsü ve tüfekler:\n- `withSession` yalnızca eski oturum `session_shutdown` yayınlandıktan, eski çalışma zamanı bozulduktan, değiştirme oturumu geri döndükten ve yeni uzantı örneği zaten `session_start` aldıktan sonra çalışır.\n- Geri çağırma, yeni uzantı örneğinin içinde değil, orijinal kapanışta yürütülmeye devam eder. Bu, eski uzantı örneğinizin `withSession` başlamadan önce kapatma temizleme işlemini zaten çalıştırmış olabileceği anlamına gelir.\n- Yakalanan eski `pi` / eski komut `ctx` oturuma bağlı nesneler değiştirildikten sonra eskidir ve kullanılırsa atılır. Oturuma bağlı çalışma için yalnızca `withSession`'ye iletilen `ctx`'yi kullanın.\n- Daha önce çıkarılan ham nesneler hâlâ sizin sorumluluğunuzdadır. Örneğin, değiştirmeden önce `const sm = ctx.sessionManager` yakalarsanız, `sm` hâlâ eski `SessionManager` nesnesidir. Değiştirdikten sonra tekrar kullanmayın.\n- `withSession`'deki kod, `session_shutdown` işleyiciniz tarafından geçersiz kılınan herhangi bir durumun zaten kaybolduğunu varsaymalıdır. Dizeler, kimlikler ve serileştirilmiş yapılandırma gibi yalnızca kapanmadan temiz bir şekilde kurtulabilen düz verileri yakalayın.\n\nGüvenli desen:\n\n```typescript\npi.registerCommand(\"handoff\", {\n  handler: async (_args, ctx) => {\n    const kickoff = \"Continue from the replacement session\";\n    await ctx.newSession({\n      withSession: async (ctx) => {\n        await ctx.sendUserMessage(kickoff);\n      },\n    });\n  },\n});\n```\n\nGüvenli olmayan model:\n\n```typescript\npi.registerCommand(\"handoff\", {\n  handler: async (_args, ctx) => {\n    const oldSessionManager = ctx.sessionManager;\n    await ctx.newSession({\n      withSession: async (_ctx) => {\n        // stale old objects: do not do this\n        oldSessionManager.getSessionFile();\n        pi.sendUserMessage(\"wrong\");\n      },\n    });\n  },\n});\n```\n\n### ctx.reload()\n\n`/reload` ile aynı yeniden yükleme akışını çalıştırın.\n\n```typescript\npi.registerCommand(\"reload-runtime\", {\n  description: \"Reload extensions, skills, prompts, themes, and context files\",\n  handler: async (_args, ctx) => {\n    await ctx.reload();\n    return;\n  },\n});\n```\n\nÖnemli davranış:\n- `await ctx.reload()` geçerli uzatma çalışma zamanı için `session_shutdown` yayar\n- Daha sonra kaynakları yeniden yükler ve `reason: \"reload\"` ile `session_start` ve `\"reload\"` nedeni ile `resources_discover` yayar\n- Şu anda çalışan komut işleyicisi hala eski çağrı çerçevesinde devam ediyor\n- `await ctx.reload()`'den sonraki kod, yeniden yükleme öncesi sürümden itibaren hala çalışıyor\n- `await ctx.reload()` sonrasındaki kod, eski bellek içi uzantı durumunun hala geçerli olduğunu varsaymamalıdır\n- İşleyici geri döndükten sonra gelecekteki komutlar/olaylar/araç çağrıları yeni uzantı sürümünü kullanır\n\nTahmin edilebilir davranış için, yeniden yüklemeyi söz konusu işleyicinin terminali olarak değerlendirin (`await ctx.reload(); return;`).\n\nAraçlar `ExtensionContext` ile çalışır, dolayısıyla `ctx.reload()`'yi doğrudan çağıramazlar. Yeniden yükleme giriş noktası olarak bir komut kullanın, ardından bu komutu takip eden kullanıcı mesajı olarak sıraya koyan bir aracı kullanıma açın.\n\nLLM'nin yeniden yüklemeyi tetiklemek için çağırabileceği örnek araç:\n\n```typescript\nimport type { ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\nimport { Type } from \"typebox\";\n\nexport default function (pi: ExtensionAPI) {\n  pi.registerCommand(\"reload-runtime\", {\n    description: \"Reload extensions, skills, prompts, themes, and context files\",\n    handler: async (_args, ctx) => {\n      await ctx.reload();\n      return;\n    },\n  });\n\n  pi.registerTool({\n    name: \"reload_runtime\",\n    label: \"Reload Runtime\",\n    description: \"Reload extensions, skills, prompts, themes, and context files\",\n    parameters: Type.Object({}),\n    async execute() {\n      pi.sendUserMessage(\"/reload-runtime\", { deliverAs: \"followUp\" });\n      return {\n        content: [{ type: \"text\", text: \"Queued /reload-runtime as a follow-up command.\" }],\n      };\n    },\n  });\n}\n```\n\n## UzantıAPI Yöntemler\n\n### pi.on(olay, işleyici)\n\nEtkinliklere abone olun. Etkinlik türleri ve dönüş değerleri için [Events](#events)'ye bakın.\n\n### pi.registerTool(tanım)\n\nYüksek Lisans tarafından çağrılabilen özel bir aracı kaydedin. Tüm ayrıntılar için [Custom Tools](#custom-tools)'e bakın.\n\n`pi.registerTool()` hem uzatma yüklemesi sırasında hem de başlatma sonrasında çalışır. Bunu `session_start`, komut işleyicileri veya diğer olay işleyicileri içinden çağırabilirsiniz. Yeni araçlar aynı oturumda hemen yenilenir, böylece `pi.getAllTools()`'de görünürler ve LLM tarafından `/reload` olmadan çağrılabilirler.\n\nÇalışma zamanında araçları (dinamik olarak eklenen araçlar dahil) etkinleştirmek veya devre dışı bırakmak için `pi.setActiveTools()` tuşunu kullanın.\n\n`Available tools`'de özel bir aracı tek satırlık bir girişe dahil etmek için `promptSnippet` tuşunu, araç etkinken varsayılan `Guidelines` bölümüne araca özel madde işaretleri eklemek için `promptGuidelines` tuşunu kullanın.\n\n**Önemli:** `promptGuidelines` madde işaretleri, araç adı öneki olmadan `Guidelines` bölümüne düz olarak eklenir. Her kılavuz, atıfta bulunduğu araca bir isim vermelidir; \"Bu aracı şu durumlarda kullan...\" kaçının çünkü Yüksek Lisans \"bu\"nun hangi araç anlamına geldiğini söyleyemez. Bunun yerine \"My_tool'u şu durumlarda kullan...\" yazın.\n\nTam bir örnek için [dynamic-tools.ts](../examples/extensions/dynamic-tools.ts)'e bakın.\n\n```typescript\nimport { Type } from \"typebox\";\nimport { StringEnum } from \"@earendil-works/pi-ai\";\n\npi.registerTool({\n  name: \"my_tool\",\n  label: \"My Tool\",\n  description: \"What this tool does\",\n  promptSnippet: \"Summarize or transform text according to action\",\n  promptGuidelines: [\"Use my_tool when the user asks to summarize previously generated text.\"],\n  parameters: Type.Object({\n    action: StringEnum([\"list\", \"add\"] as const),\n    text: Type.Optional(Type.String()),\n  }),\n  prepareArguments(args) {\n    // Optional compatibility shim. Runs before schema validation.\n    // Return the current schema shape, for example to fold legacy fields\n    // into the modern parameter object.\n    return args;\n  },\n\n  async execute(toolCallId, params, signal, onUpdate, ctx) {\n    // Stream progress\n    onUpdate?.({ content: [{ type: \"text\", text: \"Working...\" }] });\n\n    return {\n      content: [{ type: \"text\", text: \"Done\" }],\n      details: { result: \"...\" },\n    };\n  },\n\n  // Optional: Custom rendering\n  renderCall(args, theme, context) { ... },\n  renderResult(result, options, theme, context) { ... },\n});\n```\n\n### pi.sendMessage(mesaj, seçenekler?)\n\nOturuma özel bir mesaj enjekte edin. Özel mesajlar LLM bağlamına katılır. LLM'ye gönderilmemesi gereken yalnızca TUI kalıcı içerik için, [`pi.registerEntryRenderer()`](#piregisterentryrenderercustomtype-renderer) ile [`pi.appendEntry()`](#piappendentrycustomtype-data) kullanın.\n\n```typescript\npi.sendMessage({\n  customType: \"my-extension\",\n  content: \"Message text\",\n  display: true,\n  details: { ... },\n}, {\n  triggerTurn: true,\n  deliverAs: \"steer\",\n});\n```\n\n**Seçenekler:**\n- `deliverAs` - Teslimat modu:\n  - `\"steer\"` (varsayılan) - Akış sırasında mesajı sıraya koyar. Mevcut asistan sırası, bir sonraki LLM çağrısından önce, araç çağrılarını yürütmeyi tamamladıktan sonra teslim edilir.\n  - `\"followUp\"` - Temsilcinin bitirmesini bekler. Yalnızca temsilcinin başka araç çağrısı kalmadığında teslim edilir.\n  - `\"nextTurn\"` - Bir sonraki kullanıcı istemi için sıraya alındı. Hiçbir şeyi kesintiye uğratmaz veya tetiklemez.\n- `triggerTurn: true` - Temsilci boştaysa hemen bir LLM yanıtını tetikleyin. Yalnızca `\"steer\"` ve `\"followUp\"` modları için geçerlidir (`\"nextTurn\"` için dikkate alınmaz).\n\n### pi.sendUserMessage(içerik, seçenekler?)\n\nTemsilciye bir kullanıcı mesajı gönderin. Özel mesajlar gönderen `sendMessage()`'den farklı olarak bu, sanki kullanıcı tarafından yazılmış gibi görünen gerçek bir kullanıcı mesajı gönderir. Her zaman bir dönüşü tetikler.\n\n```typescript\n// Simple text message\npi.sendUserMessage(\"What is 2+2?\");\n\n// With content array (text + images)\npi.sendUserMessage([\n  { type: \"text\", text: \"Describe this image:\" },\n  { type: \"image\", source: { type: \"base64\", mediaType: \"image/png\", data: \"...\" } },\n]);\n\n// During streaming - must specify delivery mode\npi.sendUserMessage(\"Focus on error handling\", { deliverAs: \"steer\" });\npi.sendUserMessage(\"And then summarize\", { deliverAs: \"followUp\" });\n```\n\n**Seçenekler:**\n- `deliverAs` - Aracı akış halindeyken gereklidir:\n  - `\"steer\"` - Geçerli asistan sırasının araç çağrılarını yürütmesi tamamlandıktan sonra mesajı teslim edilmek üzere sıraya koyar\n  - `\"followUp\"` - Temsilcinin tüm araçları bitirmesini bekler\n\nAkış yapılmadığında mesaj hemen gönderilir ve yeni bir dönüşü tetikler. `deliverAs` olmadan yayın yaparken hata verir.\n\nTam bir örnek için [send-user-message.ts](../examples/extensions/send-user-message.ts)'e bakın.\n\n### pi.appendEntry(customType, veri?)\n\nUzantı verilerini kalıcı hale getirin. Özel girişler LLM bağlamına katılmaz. Etkileşimli modda, `pi.registerEntryRenderer()` ile eşleştirildiğinde sohbet metninin içinde de görüntü oluşturabilirler.\n\n```typescript\npi.appendEntry(\"my-state\", { count: 42 });\npi.appendEntry(\"status-card\", { title: \"Indexed files\", count: 17 });\n\n// Restore on reload\npi.on(\"session_start\", async (_event, ctx) => {\n  for (const entry of ctx.sessionManager.getEntries()) {\n    if (entry.type === \"custom\" && entry.customType === \"my-state\") {\n      // Reconstruct from entry.data\n    }\n  }\n});\n```\n\n### pi.setSessionName(ad)\n\nOturumun görünen adını ayarlayın (ilk mesaj yerine oturum seçicide gösterilir).\n\n```typescript\npi.setSessionName(\"Refactor auth module\");\n```\n\n### pi.getSessionName()\n\nAyarlanmışsa geçerli oturum adını alın.\n\n```typescript\nconst name = pi.getSessionName();\nif (name) {\n  console.log(`Session: ${name}`);\n}\n```\n\n### pi.setLabel(girişKimliği, etiket)\n\nGirişteki etiketi ayarlayın veya temizleyin. Etiketler, yer işareti koyma ve gezinme için kullanıcı tanımlı işaretçilerdir (`/tree` seçicide gösterilir).\n\n```typescript\n// Set a label\npi.setLabel(entryId, \"checkpoint-before-refactor\");\n\n// Clear a label\npi.setLabel(entryId, undefined);\n\n// Read labels via sessionManager\nconst label = ctx.sessionManager.getLabel(entryId);\n```\n\nEtiketler oturumda kalır ve yeniden başlatmalarda hayatta kalır. Konuşma ağacındaki önemli noktaları (dönüşler, kontrol noktaları) işaretlemek için bunları kullanın.\n\n### pi.registerCommand(ad, seçenekler)\n\nBir komutu kaydedin.\n\nBirden fazla uzantı aynı komut adını kaydederse, pi bunların hepsini tutar ve yükleme sırasına göre sayısal çağırma soneklerini atar, örneğin `/review:1` ve `/review:2`.\n\n```typescript\npi.registerCommand(\"stats\", {\n  description: \"Show session statistics\",\n  handler: async (args, ctx) => {\n    const count = ctx.sessionManager.getEntries().length;\n    ctx.ui.notify(`${count} entries`, \"info\");\n  }\n});\n```\n\nİsteğe bağlı: `/command...` için bağımsız değişkenin otomatik tamamlanmasını ekleyin:\n\n```typescript\nimport type { AutocompleteItem } from \"@earendil-works/pi-tui\";\n\npi.registerCommand(\"deploy\", {\n  description: \"Deploy to an environment\",\n  getArgumentCompletions: (prefix: string): AutocompleteItem[] | null => {\n    const envs = [\"dev\", \"staging\", \"prod\"];\n    const items = envs.map((e) => ({ value: e, label: e }));\n    const filtered = items.filter((i) => i.value.startsWith(prefix));\n    return filtered.length > 0 ? filtered : null;\n  },\n  handler: async (args, ctx) => {\n    ctx.ui.notify(`Deploying: ${args}`, \"info\");\n  },\n});\n```\n\n### pi.getCommands()\n\nGeçerli oturumda slash commands'yi `prompt` aracılığıyla çağırmaya uygun hale getirin. Uzatma komutlarını, prompt templates ve beceri komutlarını içerir.\nListe RPC `get_commands` sıralamasıyla eşleşiyor: önce uzantılar, sonra şablonlar, ardından beceriler.\n\n```typescript\nconst commands = pi.getCommands();\nconst bySource = commands.filter((command) => command.source === \"extension\");\nconst userScoped = commands.filter((command) => command.sourceInfo.scope === \"user\");\n```\n\nHer giriş şu şekle sahiptir:\n\n```typescript\n{\n  name: string; // Invokable command name without the leading slash. May be suffixed like \"review:1\"\n  description?: string;\n  source: \"extension\" | \"prompt\" | \"skill\";\n  sourceInfo: {\n    path: string;\n    source: string;\n    scope: \"user\" | \"project\" | \"temporary\";\n    origin: \"package\" | \"top-level\";\n    baseDir?: string;\n  };\n}\n```\n\nKurallı kaynak alanı olarak `sourceInfo` kullanın. Komut adlarından veya özel yol ayrıştırmasından sahiplik sonucunu çıkarmayın.\n\nYerleşik etkileşimli komutlar (`/model` ve `/settings` gibi) buraya dahil edilmemiştir. Yalnızca etkileşimli olarak ele alınırlar\nmodundadır ve `prompt` aracılığıyla gönderilirse yürütülmez.\n\n### pi.registerMessageRenderer(customType, oluşturucu)\n\n`customType`'nizle özel mesajlar için özel bir TUI oluşturucu kaydedin. Özel mesajlar `pi.sendMessage()` ile oluşturulur ve LLM bağlamına katılır. Bakınız [Custom UI](#custom-ui).\n\n### pi.registerMarkdownTransformer(transformer)\n\nNormal kullanıcı metninde, yardımcı metinde ve düşünme bloklarında Markdown için bir dönüştürücü kaydedin. Transformatörler uzatma yükü sırasına göre çalışır ve her transformatör, önceki transformatörün döndürdüğü Markdown'yi alır. Zincir tamamlandıktan sonra Pi dönüştürülen içeriği yerleşik oluşturucuyla işler.\n\nTransformatör Markdown dizesini ve aşağıdakileri içeren bir bağlamı alır:\n\n- `messageType` — `\"user\"`, `\"assistant\"` veya `\"assistant-thinking\"`\n- `isStreaming` — `true` kısmi asistan güncellemeleri için; `false` kullanıcı, sonlandırılan asistan ve geri yüklenen mesajlar için\n- `availableWidth` — dönüştürülmüş Markdown içeriği için tam terminal sütunları mevcuttur\n\nDönüştürülen Markdown'yi döndür:\n\n```typescript\npi.registerMarkdownTransformer((markdown, { messageType, isStreaming }) => {\n  if (isStreaming || messageType === \"assistant-thinking\") return markdown;\n  return markdown.replaceAll(\"-->\", \"→\");\n});\n```\n\nBir transformatör atarsa ​​Pi o ana kadar üretilen Markdown'yi korur ve bir sonraki transformatörle devam eder. Kanca yalnızca görüntülenir: orijinal mesaj, oturum ve model bağlamında değişmeden kalır. Yeni kullanıcı mesajları, asistan akış güncellemeleri, geri yüklenen oturum mesajları ve terminal genişliği değişiklikleri için çalışır, dolayısıyla transformatörlerin senkronize ve ucuz kalması gerekir.\n\n### pi.registerEntryRenderer(customType, oluşturucu)\n\n`customType`'ınızla özel girişler için özel bir TUI oluşturucu kaydedin. Özel girişler `pi.appendEntry()` ile oluşturulur ve LLM bağlamına katılmaz.\n\n```typescript\nimport { Box, Text } from \"@earendil-works/pi-tui\";\n\npi.registerEntryRenderer(\"status-card\", (entry, { expanded }, theme) => {\n  const data = entry.data as { title: string; count: number };\n  const box = new Box(1, 1, (text) => theme.bg(\"customMessageBg\", text));\n  box.addChild(new Text(`${theme.bold(data.title)}: ${data.count}`));\n  if (expanded) {\n    box.addChild(new Text(theme.fg(\"dim\", JSON.stringify(data, null, 2))));\n  }\n  return box;\n});\n\npi.appendEntry(\"status-card\", { title: \"Indexed files\", count: 17 });\n```\n\n### pi.registerShortcut(kısayol, seçenekler)\n\nBir klavye kısayolu kaydedin. Kısayol formatı ve yerleşik tuş atamaları için [keybindings.md](keybindings.md)'ye bakın.\n\n```typescript\npi.registerShortcut(\"ctrl+shift+p\", {\n  description: \"Toggle plan mode\",\n  handler: async (ctx) => {\n    ctx.ui.notify(\"Toggled!\");\n  },\n});\n```\n\n### pi.registerFlag(ad, seçenekler)\n\nBir CLI bayrağı kaydedin.\n\n```typescript\npi.registerFlag(\"plan\", {\n  description: \"Start in plan mode\",\n  type: \"boolean\",\n  default: false,\n});\n\n// Check value\nif (pi.getFlag(\"plan\")) {\n  // Plan mode enabled\n}\n```\n\n### pi.exec(komut, bağımsız değişkenler, seçenekler?)\n\nBir kabuk komutunu yürütün.\n\n```typescript\nconst result = await pi.exec(\"git\", [\"status\"], { signal, timeout: 5000 });\n// result.stdout, result.stderr, result.code, result.killed\n```\n\n### pi.getActiveTools() / pi.getAllTools() / pi.setActiveTools(isimler)\n\nEtkin araçları yönetin. Bu, hem yerleşik araçlar hem de dinamik olarak kayıtlı araçlar için işe yarar. `pi.getActiveTools()` etkin araç adlarını `string[]` olarak döndürür; `pi.getAllTools()` yapılandırılmış tüm araçlar için meta verileri döndürür.\n\n```typescript\nconst active = pi.getActiveTools(); // [\"read\", \"bash\", ...]\nconst all = pi.getAllTools();\n// all = [{\n//   name: \"read\",\n//   description: \"Read file contents...\",\n//   parameters: ...,\n//   promptGuidelines: [\"Use read to examine files instead of cat or sed.\"],\n//   sourceInfo: { path: \"<builtin:read>\", source: \"builtin\", scope: \"temporary\", origin: \"top-level\" }\n// }, ...]\nconst builtinTools = all.filter((t) => t.sourceInfo.source === \"builtin\");\nconst extensionTools = all.filter((t) => t.sourceInfo.source !== \"builtin\" && t.sourceInfo.source !== \"sdk\");\npi.setActiveTools([...new Set([...active, \"my_custom_tool\"])]); // Keep current tools and enable my_custom_tool\npi.setActiveTools([\"read\", \"bash\"]); // Switch to read-only\n```\n\n`pi.getAllTools()`, `name`, `description`, `parameters`, `promptGuidelines` ve `sourceInfo`'yi döndürür.\n\nTipik `sourceInfo.source` değerleri:\n- `builtin` yerleşik araçlar için\n- `sdk` `createAgentSession({ customTools })` üzerinden geçirilen takımlar için\n- Uzantılar tarafından kaydedilen araçlar için uzantı kaynağı meta verileri\n\n### pi.setModel(model)\n\nGeçerli modeli ayarlayın. Model için API key mevcut değilse `false` değerini döndürür. Özel modelleri yapılandırmak için [models.md](models.md)'e bakın.\n\n```typescript\nconst model = ctx.modelRegistry.find(\"anthropic\", \"claude-sonnet-4-5\");\nif (model) {\n  const success = await pi.setModel(model);\n  if (!success) {\n    ctx.ui.notify(\"No API key for this model\", \"error\");\n  }\n}\n```\n\n### pi.getThinkingLevel() / pi.setThinkingLevel(seviye)\n\nDüşünme seviyesini alın veya ayarlayın. Düzey, model yeteneklerine bağlıdır (akıl yürütmeyen modeller her zaman \"kapalı\"yı kullanır). Değişiklikler `thinking_level_select` yayar.\n\n```typescript\nconst current = pi.getThinkingLevel();  // \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\"\npi.setThinkingLevel(\"high\");\n```\n\n### pi.events\n\nUzantılar arasındaki iletişim için paylaşılan olay veri yolu:\n\n```typescript\npi.events.on(\"my:event\", (data) => { ... });\npi.events.emit(\"my:event\", { ... });\n```\n\n### pi.registerProvider(ad, yapılandırma)\n\nBir model sağlayıcıyı dinamik olarak kaydedin veya geçersiz kılın. Proxy'ler, özel uç noktalar veya ekip çapında model yapılandırmaları için kullanışlıdır.\n\nUzatma fabrikası işlevi sırasında yapılan çağrılar kuyruğa alınır ve çalıştırıcı başlatıldıktan sonra uygulanır. Bundan sonra yapılan çağrılar (örneğin, kullanıcı kurulum akışını izleyen bir komut işleyicisinden) `/reload` gerektirmeden hemen etkili olur.\n\nDinamik sağlayıcılar `refreshModels` uygulayabilir. Pi model yenileme sırasında bunu çağırır, döndürülen listeyi sağlayıcı aracılığıyla eşzamanlı olarak yayınlar ve kanonik kimlik bilgisi/depolanan katalog/ağ/sinyal bağlamını iletir. Uzantı, katalog meta verilerinin üretim kontrollü `context.publish({ persist: entry })` aracılığıyla sürdürülüp sürdürülmeyeceğine karar verir; llama.cpp gibi canlı sunucular, modelleri ısrar etmeden döndürebilir.\n\n`context.signal` her zaman somut bir sinyaldir ve sağlayıcı geri aramalarının bunu G/Ç engellemeye iletmesi gerekir. Genel `ModelRuntime.refresh()` ve `ModelRegistry.refresh()` çağrıları isteğe bağlı bir sinyali kabul eder ve atlandığında sınırsızdır; Uzatmalar ve başvurular kendi son tarihlerini seçer. İptal, sağlayıcı sinyali görmezden gelse bile arayanın beklemesini durdurur, ancak temeldeki işi durdurmak için yine de işbirliği gereklidir.\n\nYerel sağlayıcı kimlik doğrulaması, filtreleme, yenileme veya akış davranışına ihtiyaç duyan Extensions, `@earendil-works/pi-ai`'den tam bir `Provider` kaydedebilir. Sağlayıcı kompozisyon tabanı haline gelir ve `models.json` geçersiz kılmalar hâlâ bunun üzerinde geçerlidir.\n\n```typescript\nimport { createProvider, openAICompletionsApi } from \"@earendil-works/pi-ai\";\n\nconst provider = createProvider({\n  id: \"local-server\",\n  name: \"Local Server\",\n  baseUrl: \"http://localhost:8080/v1\",\n  auth: {\n    apiKey: {\n      name: \"Local server setup\",\n      async login(interaction) {\n        return {\n          type: \"api_key\",\n          key: await interaction.prompt({ type: \"secret\", message: \"API key\" }),\n        };\n      },\n      async resolve({ credential }) {\n        return credential?.key\n          ? { auth: { apiKey: credential.key }, source: \"stored API key\" }\n          : undefined;\n      },\n    },\n  },\n  models: [],\n  api: openAICompletionsApi(),\n});\n\npi.registerProvider(provider);\n\n// Register a new provider with custom models\npi.registerProvider(\"my-proxy\", {\n  name: \"My Proxy\",\n  baseUrl: \"https://proxy.example.com\",\n  apiKey: \"$PROXY_API_KEY\",  // env var reference\n  api: \"anthropic-messages\",\n  models: [\n    {\n      id: \"claude-sonnet-4-20250514\",\n      name: \"Claude 4 Sonnet (proxy)\",\n      reasoning: false,\n      input: [\"text\", \"image\"],\n      cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n      contextWindow: 200000,\n      maxTokens: 16384\n    }\n  ]\n});\n\n// Register a live llama.cpp catalog without persisting discovered models\npi.registerProvider(\"llama.cpp\", {\n  baseUrl: \"http://localhost:8080/v1\",\n  apiKey: \"local\",\n  api: \"openai-completions\",\n  async refreshModels({ signal }) {\n    const response = await fetch(\"http://localhost:8080/v1/models\", { signal });\n    const { data } = await response.json();\n    return data.map(({ id }) => ({\n      id,\n      name: id,\n      reasoning: false,\n      input: [\"text\"],\n      cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n      contextWindow: 128000,\n      maxTokens: 16384\n    }));\n  }\n});\n\n// Override baseUrl for an existing provider (keeps all models)\npi.registerProvider(\"anthropic\", {\n  baseUrl: \"https://proxy.example.com\"\n});\n\n// Register provider with OAuth support for /login\npi.registerProvider(\"corporate-ai\", {\n  baseUrl: \"https://ai.corp.com\",\n  api: \"openai-responses\",\n  models: [...],\n  oauth: {\n    name: \"Corporate AI (SSO)\",\n    async login(callbacks) {\n      // Custom OAuth flow\n      callbacks.onAuth({ url: \"https://sso.corp.com/...\" });\n      const code = await callbacks.onPrompt({ message: \"Enter code:\" });\n      return { refresh: code, access: code, expires: Date.now() + 3600000 };\n    },\n    async refreshToken(credentials, signal) {\n      signal.throwIfAborted();\n      // Refresh logic\n      return credentials;\n    },\n    getApiKey(credentials) {\n      return credentials.access;\n    }\n  }\n});\n```\n\nNesne formu, yerel `auth`, `getModels`, `refreshModels`, `filterModels`, `stream` ve `streamSimple` davranışı da dahil olmak üzere tam bir pi-ai `Provider`'yi kabul eder.\n\n**Eski yapılandırma seçenekleri:**\n- `name` - Sağlayıcının kullanıcı arayüzünde `/login` gibi görünen adı.\n- `baseUrl` - API uç nokta URL'si. Modelleri tanımlarken gereklidir.\n- `apiKey` - API key değişmez, ortam enterpolasyonu (`$ENV_VAR` veya `${ENV_VAR}`) veya baştaki `!command`. Modelleri tanımlarken gereklidir (`oauth` sağlanmadığı sürece). `$`, ``apiKey` - API key değişmez, ortam enterpolasyonu (`$ENV_VAR` veya `${ENV_VAR}`) veya baştaki `!command`. Modelleri tanımlarken gereklidir (`oauth` sağlanmadığı sürece). `$`, 'den kaçar ve `$!`, komut yürütmeyi tetiklemeden değişmez bir `!`'den kaçar.\n- `api` - API yazın: `\"anthropic-messages\"`, `\"openai-completions\"`, `\"openai-responses\"`, vb.\n- `headers` - İsteklere eklenecek özel başlıklar.\n- `authHeader` - Doğruysa, otomatik olarak `Authorization: Bearer` başlığını ekler.\n- `models` - Model tanımları dizisi. Sağlanırsa, bu sağlayıcı için mevcut tüm modellerin yerine geçer. Model tanımları, söz konusu model için sağlayıcı uç noktasını geçersiz kılmak üzere `baseUrl` ayarını yapabilir.\n- `refreshModels` - Eşzamansız dinamik keşif geri araması. İade edilen modelleri, genişletme tarafından sağlanan modellerin yerini alır. `context.stored` kalıcı sağlayıcı anlık görüntüsünü içerir; nesil kontrollü `context.publish({ persist: entry })`'yi yalnızca güncellenmiş katalog verilerinin devam etmesi gerektiğinde kullanın. Bu anlık görüntüyü silmek için `persist: null` tuşlarını kullanın.\n- `/login` desteği için `oauth` - OAuth sağlayıcı yapılandırması. Sağlandığında, sağlayıcı oturum açma menüsünde görünür.\n- `streamSimple` - Standart olmayan API'ler için özel akış uygulaması.\n\nGelişmiş konular için [custom-provider.md](custom-provider.md)'e bakın: özel akış API'ler, OAuth ayrıntıları, model tanımı referansı.\n\n### pi.unregisterProvider(isim)\n\nDaha önce kayıtlı bir sağlayıcıyı ve modellerini kaldırın. Sağlayıcı tarafından geçersiz kılınan yerleşik modeller geri yüklenir. Sağlayıcı kayıtlı değilse hiçbir etkisi yoktur.\n\n`registerProvider` gibi, bu da ilk yükleme aşamasından sonra çağrıldığında hemen etkili olur, dolayısıyla `/reload` gerekli değildir.\n\n```typescript\npi.registerCommand(\"my-setup-teardown\", {\n  description: \"Remove the custom proxy provider\",\n  handler: async (_args, _ctx) => {\n    pi.unregisterProvider(\"my-proxy\");\n  },\n});\n```\n\n## Devlet Yönetimi\n\nExtensions durumla birlikte, uygun dallanma desteği için bunu araç sonucu `details`'da saklamalıdır:\n\n```typescript\nexport default function (pi: ExtensionAPI) {\n  let items: string[] = [];\n\n  // Reconstruct state from session\n  pi.on(\"session_start\", async (_event, ctx) => {\n    items = [];\n    for (const entry of ctx.sessionManager.getBranch()) {\n      if (entry.type === \"message\" && entry.message.role === \"toolResult\") {\n        if (entry.message.toolName === \"my_tool\") {\n          items = entry.message.details?.items ?? [];\n        }\n      }\n    }\n  });\n\n  pi.registerTool({\n    name: \"my_tool\",\n    // ...\n    async execute(toolCallId, params, signal, onUpdate, ctx) {\n      items.push(\"new item\");\n      return {\n        content: [{ type: \"text\", text: \"Added\" }],\n        details: { items: [...items] },  // Store for reconstruction\n      };\n    },\n  });\n}\n```\n\n## Özel Araçlar\n\nLLM'nin `pi.registerTool()` aracılığıyla arayabileceği araçları kaydedin. Araçlar sistem isteminde görünür ve özel işleme sahip olabilir.\n\nVarsayılan sistem istemindeki `Available tools` bölümünde kısa bir tek satırlık giriş için `promptSnippet` tuşunu kullanın. Atlanırsa özel araçlar bu bölümün dışında bırakılır.\n\nVarsayılan sistem istemi `Guidelines` bölümüne araca özel madde işaretleri eklemek için `promptGuidelines` tuşunu kullanın. Bu madde işaretleri yalnızca araç etkinken dahil edilir (örneğin, `pi.setActiveTools([...])`'den sonra).\n\n**Önemli:** `promptGuidelines` madde işaretleri, araç adı öneki veya gruplaması olmaksızın `Guidelines` bölümüne düz olarak eklenir. Her kılavuz, atıfta bulunduğu araca bir isim vermelidir; \"Bu aracı şu durumlarda kullan...\" kaçının çünkü Yüksek Lisans \"bu\"nun hangi araç anlamına geldiğini söyleyemez. Bunun yerine \"My_tool'u şu durumlarda kullan...\" yazın.\n\nNot: Bazı modeller aptaldır ve takım yolu argümanlarında @ önekini içerir. Yerleşik araçlar, yolları çözümlemeden önce baştaki @ karakterini çıkarır. Özel aracınız bir yolu kabul ediyorsa baştaki @ karakterini de normalleştirin.\n\nÖzel aracınız dosyaları değiştiriyorsa, yerleşik `edit` ve `write` ile aynı dosya başına kuyruğa katılması için `withFileMutationQueue()` kullanın. Bu önemlidir çünkü araç çağrıları varsayılan olarak paralel olarak çalışır. Sıra olmadan, iki araç aynı eski dosya içeriğini okuyabilir, farklı güncellemeleri hesaplayabilir ve ardından hangisi en son yazılırsa diğerinin üzerine yazılabilir.\n\nÖrnek başarısızlık durumu: özel aracınız `foo.ts`'yi düzenlerken yerleşik `edit` aynı asistan turunda `foo.ts`'yi de değiştirir. Aracınız kuyruğa katılmıyorsa, her ikisi de orijinal `foo.ts`'yi okuyabilir, ayrı değişiklikler uygulayabilir ve bu değişikliklerden biri kaybolur.\n\nHam kullanıcı bağımsız değişkenini değil, gerçek hedef dosya yolunu `withFileMutationQueue()`'ye iletin. Bunu önce `ctx.cwd`'ye veya aracınızın çalışma dizinine göre mutlak bir yola çözümleyin. Mevcut dosyalar için yardımcı, `realpath()` aracılığıyla kanonikleştirir, böylece aynı dosya için sembolik bağlantı takma adları bir kuyruğu paylaşır. Yeni dosyalar için çözümlenen mutlak yola geri döner çünkü henüz `realpath()` için hiçbir şey yoktur.\n\nTüm mutasyon penceresini o hedef yol üzerinde sıraya alın. Bu, yalnızca son yazmayı değil, okuma-değiştirme-yazma mantığını da içerir.\n\n```typescript\nimport { withFileMutationQueue } from \"@earendil-works/pi-coding-agent\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\n\nasync execute(_toolCallId, params, _signal, _onUpdate, ctx) {\n  const absolutePath = resolve(ctx.cwd, params.path);\n\n  return withFileMutationQueue(absolutePath, async () => {\n    await mkdir(dirname(absolutePath), { recursive: true });\n    const current = await readFile(absolutePath, \"utf8\");\n    const next = current.replace(params.oldText, params.newText);\n    await writeFile(absolutePath, next, \"utf8\");\n\n    return {\n      content: [{ type: \"text\", text: `Updated ${params.path}` }],\n      details: {},\n    };\n  });\n}\n```\n\n### Araç Tanımı\n\n```typescript\nimport { Type } from \"typebox\";\nimport { StringEnum } from \"@earendil-works/pi-ai\";\nimport { Text } from \"@earendil-works/pi-tui\";\n\npi.registerTool({\n  name: \"my_tool\",\n  label: \"My Tool\",\n  description: \"What this tool does (shown to LLM)\",\n  promptSnippet: \"List or add items in the project todo list\",\n  promptGuidelines: [\n    \"Use my_tool for todo planning instead of direct file edits when the user asks for a task list.\"\n  ],\n  parameters: Type.Object({\n    action: StringEnum([\"list\", \"add\"] as const),  // Use StringEnum for Google compatibility\n    text: Type.Optional(Type.String()),\n  }),\n  prepareArguments(args) {\n    if (!args || typeof args !== \"object\") return args;\n    const input = args as { action?: string; oldAction?: string };\n    if (typeof input.oldAction === \"string\" && input.action === undefined) {\n      return { ...input, action: input.oldAction };\n    }\n    return args;\n  },\n\n  async execute(toolCallId, params, signal, onUpdate, ctx) {\n    // Check for cancellation\n    if (signal?.aborted) {\n      return { content: [{ type: \"text\", text: \"Cancelled\" }] };\n    }\n\n    // Stream progress updates\n    onUpdate?.({\n      content: [{ type: \"text\", text: \"Working...\" }],\n      details: { progress: 50 },\n    });\n\n    // Run commands via pi.exec (captured from extension closure)\n    const result = await pi.exec(\"some-command\", [], { signal });\n\n    // Return result\n    return {\n      content: [{ type: \"text\", text: \"Done\" }],  // Sent to LLM\n      details: { data: result },                   // For rendering & state\n      // usage: nestedModelResponse.usage,          // Optional nested LLM usage\n      // Optional: stop after this tool batch when every finalized tool result\n      // in the batch also returns terminate: true.\n      terminate: true,\n    };\n  },\n\n  // Optional: Custom rendering\n  renderCall(args, theme, context) { ... },\n  renderResult(result, options, theme, context) { ... },\n});\n```\n\n**Kullanım hesaplaması:** Bir araç iç içe geçmiş LLM çağrıları yapıyorsa, bunların birleştirilmiş `Usage` değerini `usage` olarak döndürün. Pi bunu araç sonucunda sürdürür ve altbilgiye, `/session` ve RPC oturum toplamlarına ekler. `tool_result` işleyiciler bu değeri inceleyebilir veya değiştirebilir.\n\n**Sinyalleme hataları:** Bir aracın yürütülmesini başarısız olarak işaretlemek için (sonuçta `isError: true` ayarlar ve bunu LLM'ye bildirir), `execute`'den bir hata atın. Bir değerin döndürülmesi, dönüş nesnesine hangi özellikleri dahil ettiğinize bakılmaksızın hiçbir zaman hata bayrağını ayarlamaz.\n\n**Erken sonlandırma:** Geçerli araç grubundan sonra otomatik takip LLM çağrısının atlanması gerektiğini belirtmek için `execute()`'den `terminate: true`'ye dönün. Bu yalnızca o gruptaki her sonlandırılmış araç sonucu sona erdiğinde etkili olur. Aracının son yapılandırılmış çıktı aracı çağrısıyla sona erdiği minimal bir örnek için [examples/extensions/structured-output.ts](../examples/extensions/structured-output.ts)'e bakın.\n\n```typescript\n// Correct: throw to signal an error\nasync execute(toolCallId, params) {\n  if (!isValid(params.input)) {\n    throw new Error(`Invalid input: ${params.input}`);\n  }\n  return { content: [{ type: \"text\", text: \"OK\" }], details: {} };\n}\n```\n\n**Önemli:** Dize numaralandırmaları için `@earendil-works/pi-ai`'den `StringEnum`'ı kullanın. `Type.Union`/`Type.Literal` Google'ın API'si ile çalışmaz.\n\n**Argüman hazırlığı:** `prepareArguments(args)` isteğe bağlıdır. Tanımlanmışsa şema doğrulamasından önce ve `execute()`'den önce çalışır. Pi, saklanan araç çağrısı argümanları artık geçerli şemayla eşleşmeyen eski bir oturumu sürdürdüğünde, kabul edilen eski bir giriş şeklini taklit etmek için bunu kullanın. `parameters` ile doğrulanmasını istediğiniz nesneyi döndürün. Genel şemayı sıkı tutun. Sırf eski sürdürülen oturumların çalışmaya devam etmesi için `parameters`'e kullanım dışı uyumluluk alanları eklemeyin.\n\nÖrnek: eski bir oturum, üst düzey `oldText` ve `newText` içeren bir `edit` araç çağrısı içerebilir, mevcut şema ise yalnızca `edits: [{ oldText, newText }]`'yi kabul eder.\n\n```typescript\npi.registerTool({\n  name: \"edit\",\n  label: \"Edit\",\n  description: \"Edit a single file using exact text replacement\",\n  parameters: Type.Object({\n    path: Type.String(),\n    edits: Type.Array(\n      Type.Object({\n        oldText: Type.String(),\n        newText: Type.String(),\n      }),\n    ),\n  }),\n  prepareArguments(args) {\n    if (!args || typeof args !== \"object\") return args;\n\n    const input = args as {\n      path?: string;\n      edits?: Array<{ oldText: string; newText: string }>;\n      oldText?: unknown;\n      newText?: unknown;\n    };\n\n    if (typeof input.oldText !== \"string\" || typeof input.newText !== \"string\") {\n      return args;\n    }\n\n    return {\n      ...input,\n      edits: [...(input.edits ?? []), { oldText: input.oldText, newText: input.newText }],\n    };\n  },\n  async execute(toolCallId, params, signal, onUpdate, ctx) {\n    // params now matches the current schema\n    return {\n      content: [{ type: \"text\", text: `Applying ${params.edits.length} edit block(s)` }],\n      details: {},\n    };\n  },\n});\n```\n\n### Yerleşik Araçları Geçersiz Kılma\n\nExtensions aynı ada sahip bir aracı kaydederek yerleşik araçları (`read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`) geçersiz kılabilir. Etkileşimli mod bu durumda bir uyarı görüntüler.\n\n```bash\n# Extension's read tool replaces built-in read\npi -e ./tool-override.ts\n```\n\nAlternatif olarak, uzatma araçlarını etkin durumda tutarken herhangi bir yerleşik araç olmadan başlamak için `--no-builtin-tools` tuşunu kullanın:\n```bash\n# No built-in tools, only extension tools\npi --no-builtin-tools -e ./my-extension.ts\n```\n\nGünlüğe kaydetme ve erişim kontrolü ile `read`'yi geçersiz kılan tam bir örnek için [examples/extensions/tool-override.ts](../examples/extensions/tool-override.ts)'ye bakın.\n\n**Oluşturma:** Yerleşik oluşturucunun devralınması yuva başına çözümlenir. Yürütme geçersiz kılma ve oluşturma geçersiz kılma bağımsızdır. Geçersiz kılma işleminizde `renderCall` atlanırsa yerleşik `renderCall` kullanılır. Geçersiz kılma işleminizde `renderResult` atlanırsa yerleşik `renderResult` kullanılır. Geçersiz kılma işleminizde her ikisi de atlanırsa yerleşik oluşturucu otomatik olarak kullanılır (sözdizimi vurgulama, farklar vb.). Bu, kullanıcı arayüzünü yeniden uygulamaya gerek kalmadan günlüğe kaydetme veya erişim kontrolü için yerleşik araçları sarmanıza olanak tanır.\n\n**Bilgi meta verileri:** `promptSnippet` ve `promptGuidelines` yerleşik araçtan devralınmaz. Geçersiz kılma işleminizin bu istem talimatlarını tutması gerekiyorsa bunları geçersiz kılmada açıkça tanımlayın.\n\n**Uygulamanız, `details` türü de dahil olmak üzere sonuç şekliyle tam olarak eşleşmelidir**. Kullanıcı arayüzü ve oturum mantığı, oluşturma ve durum takibi için bu şekillere bağlıdır.\n\nYerleşik araç uygulamaları:\n- [read.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/tools/read.ts) - `ReadToolDetails`\n- [bash.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/tools/bash.ts) - `BashToolDetails`\n- [edit.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/tools/edit.ts)\n- [write.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/tools/write.ts)\n- [grep.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/tools/grep.ts) - `GrepToolDetails`\n- [find.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/tools/find.ts) - `FindToolDetails`\n- [ls.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/tools/ls.ts) - `LsToolDetails`\n\n### Uzaktan Yürütme\n\nYerleşik araçlar, uzak sistemlere (SSH, kapsayıcılar vb.) yetki vermek için takılabilir işlemleri destekler:\n\n```typescript\nimport { createReadTool, createBashTool, type ReadOperations } from \"@earendil-works/pi-coding-agent\";\n\n// Create tool with custom operations\nconst remoteRead = createReadTool(cwd, {\n  operations: {\n    readFile: (path) => sshExec(remote, `cat ${path}`),\n    access: (path) => sshExec(remote, `test -r ${path}`).then(() => {}),\n  }\n});\n\n// Register, checking flag at execution time\npi.registerTool({\n  ...remoteRead,\n  async execute(id, params, signal, onUpdate, _ctx) {\n    const ssh = getSshConfig();\n    if (ssh) {\n      const tool = createReadTool(cwd, { operations: createRemoteOps(ssh) });\n      return tool.execute(id, params, signal, onUpdate);\n    }\n    return localRead.execute(id, params, signal, onUpdate);\n  },\n});\n```\n\n**İşlem arayüzleri:** `ReadOperations`, `WriteOperations`, `EditOperations`, `BashOperations`, `LsOperations`, `GrepOperations`, `FindOperations`\n\n`user_bash` için uzantılar, yerel süreç oluşturmayı, kabuk çözümlemesini ve süreç ağacı sonlandırmayı yeniden uygulamak yerine pi'nin yerel kabuk arka ucunu `createLocalBashOperations()` aracılığıyla yeniden kullanabilir.\n\nbash aracı aynı zamanda yürütmeden önce komutu, cwd veya env'yi ayarlamak için bir ortaya çıkma kancasını da destekler:\n\n```typescript\nimport { createBashTool } from \"@earendil-works/pi-coding-agent\";\n\nconst bashTool = createBashTool(cwd, {\n  spawnHook: ({ command, cwd, env }) => ({\n    command: `source ~/.profile\\n${command}`,\n    cwd: `/mnt/sandbox${cwd}`,\n    env: { ...env, CI: \"1\" },\n  }),\n});\n```\n\n`createBashTool()` mevcut oturumu `PI_SESSION_ID`, `PI_SESSION_FILE`, `PI_PROVIDER`, `PI_MODEL` ve `PI_REASONING_LEVEL` aracılığıyla komutlara maruz bırakır. Enjeksiyon `spawnHook`'dan önce gerçekleşir, dolayısıyla kancalar bu değerleri `env`'de alır ve yukarıdaki gibi mevcut ortama yayıldıklarında bunları korurlar. Bunları devre dışı bırakmak için `exposeSessionEnvironment: false` öğesini ayarlayın:\n\n```typescript\nconst bashTool = createBashTool(cwd, {\n  exposeSessionEnvironment: false,\n});\n```\n\nDeğişken semantiği için [Bash tool session environment](environment-variables.md#bash-tool-session-environment)'ye bakın. `--ssh` bayrağıyla tam bir SSH örneği için [examples/extensions/ssh.ts](../examples/extensions/ssh.ts)'ye bakın.\n\n### Çıkış Kesilmesi\n\n**LLM bağlamının aşırı yüklenmesini önlemek için araçların çıktılarını kesmesi GEREKİR**. Büyük çıktılar şunlara neden olabilir:\n- Bağlam taşması hataları (istemin çok uzun olması)\n- Sıkıştırma hataları\n- Düşük model performansı\n\nDahili sınır **50 KB** (~10 bin jeton) ve **2000 satır**'dır (hangisi önce gerçekleşirse). Dışa aktarılan kesme yardımcı programlarını kullanın:\n\n```typescript\nimport {\n  truncateHead,      // Keep first N lines/bytes (good for file reads, search results)\n  truncateTail,      // Keep last N lines/bytes (good for logs, command output)\n  truncateLine,      // Truncate a single line to maxBytes with ellipsis\n  formatSize,        // Human-readable size (e.g., \"50KB\", \"1.5MB\")\n  DEFAULT_MAX_BYTES, // 50KB\n  DEFAULT_MAX_LINES, // 2000\n} from \"@earendil-works/pi-coding-agent\";\n\nasync execute(toolCallId, params, signal, onUpdate, ctx) {\n  const output = await runCommand();\n\n  // Apply truncation\n  const truncation = truncateHead(output, {\n    maxLines: DEFAULT_MAX_LINES,\n    maxBytes: DEFAULT_MAX_BYTES,\n  });\n\n  let result = truncation.content;\n\n  if (truncation.truncated) {\n    // Write full output to temp file\n    const tempFile = writeTempFile(output);\n\n    // Inform the LLM where to find complete output\n    result += `\\n\\n[Output truncated: ${truncation.outputLines} of ${truncation.totalLines} lines`;\n    result += ` (${formatSize(truncation.outputBytes)} of ${formatSize(truncation.totalBytes)}).`;\n    result += ` Full output saved to: ${tempFile}]`;\n  }\n\n  return { content: [{ type: \"text\", text: result }] };\n}\n```\n\n**Önemli noktalar:**\n- Başlangıcın önemli olduğu içerik için `truncateHead` kullanın (arama sonuçları, dosya okumaları)\n- Sonunun önemli olduğu içerik için `truncateTail` kullanın (günlükler, komut çıkışı)\n- Çıktı kesildiğinde ve tam sürümün nerede bulunacağı konusunda daima LLM'yi bilgilendirin\n- Aracınızın açıklamasında kesme sınırlarını belgeleyin\n\n`rg` (ripgrep) öğesinin uygun kesmeyle sarmalanmasının tam bir örneği için [examples/extensions/truncated-tool.ts](../examples/extensions/truncated-tool.ts) öğesine bakın.\n\n### Çoklu Araçlar\n\nBir uzantı birden fazla aracı paylaşılan duruma kaydedebilir:\n\n```typescript\nexport default function (pi: ExtensionAPI) {\n  let connection = null;\n\n  pi.registerTool({ name: \"db_connect\", ... });\n  pi.registerTool({ name: \"db_query\", ... });\n  pi.registerTool({ name: \"db_close\", ... });\n\n  pi.on(\"session_shutdown\", async () => {\n    connection?.close();\n  });\n}\n```\n\n### Özel İşleme\n\nAraçlar, özel TUI ekranı için `renderCall` ve `renderResult` sağlayabilir. Bileşenin tamamı için [tui.md](tui.md)'ye bakın API ve araç satırlarının nasıl oluşturulduğu için [tool-execution.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/modes/interactive/components/tool-execution.ts)'ye bakın.\n\nVarsayılan olarak araç çıktısı, dolguyu ve arka planı işleyen bir `Box` içine sarılır. Tanımlanmış bir `renderCall` veya `renderResult`, `Component` döndürmelidir. Bir yuva oluşturucu tanımlanmamışsa `tool-execution.ts` o yuva için geri dönüş oluşturmayı kullanır.\n\nVarsayılan `Box` kullanmak yerine aracın ne zaman kendi kabuğunu oluşturması gerektiğini `renderShell: \"self\"` olarak ayarlayın. Bu, çerçeveleme veya arka plan davranışı üzerinde tam kontrole ihtiyaç duyan araçlar için kullanışlıdır; örneğin, araç yerleştikten sonra görsel olarak sabit kalması gereken büyük önizlemeler.\n\n```typescript\npi.registerTool({\n  name: \"my_tool\",\n  label: \"My Tool\",\n  description: \"Custom shell example\",\n  parameters: Type.Object({}),\n  renderShell: \"self\",\n  async execute() {\n    return { content: [{ type: \"text\", text: \"ok\" }], details: undefined };\n  },\n  renderCall(args, theme, context) {\n    return new Text(theme.fg(\"accent\", \"my custom shell\"), 0, 0);\n  },\n});\n```\n\n`renderCall` ve `renderResult`'nin her biri aşağıdaki özelliklere sahip bir `context` nesnesi alır:\n- `args` - mevcut araç çağrısı argümanları\n- `state` - `renderCall` ve `renderResult` genelinde paylaşılan satır yerel durumu\n- `lastComponent` - varsa o yuva için önceden döndürülen bileşen\n- `invalidate()` - bu araç satırının yeniden oluşturulmasını talep edin\n- `toolCallId`, `cwd`, `executionStarted`, `argsComplete`, `isPartial`, `expanded`, `showImages`, `isError`\n\nYuvalar arası paylaşım durumu için `context.state` kullanın. Aynı bileşeni işlemeler arasında yeniden kullanmak ve değiştirmek istediğinizde, döndürülen bileşen örneğinde yuva yerel önbelleklerini tutun.\n\n#### renderÇağrı\n\nAraç çağrısını veya başlığını işler:\n\n```typescript\nimport { Text } from \"@earendil-works/pi-tui\";\n\nrenderCall(args, theme, context) {\n  const text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n  let content = theme.fg(\"toolTitle\", theme.bold(\"my_tool \"));\n  content += theme.fg(\"muted\", args.action);\n  if (args.text) {\n    content += \" \" + theme.fg(\"dim\", `\"${args.text}\"`);\n  }\n  text.setText(content);\n  return text;\n}\n```\n\n#### renderSonucu\n\nAraç sonucunu veya çıktısını işler:\n\n```typescript\nrenderResult(result, { expanded, isPartial }, theme, context) {\n  if (isPartial) {\n    return new Text(theme.fg(\"warning\", \"Processing...\"), 0, 0);\n  }\n\n  if (result.details?.error) {\n    return new Text(theme.fg(\"error\", `Error: ${result.details.error}`), 0, 0);\n  }\n\n  let text = theme.fg(\"success\", \"✓ Done\");\n  if (expanded && result.details?.items) {\n    for (const item of result.details.items) {\n      text += \"\\n  \" + theme.fg(\"dim\", item);\n    }\n  }\n  return new Text(text, 0, 0);\n}\n```\n\nBir yuvanın kasıtlı olarak görünür içeriği yoksa, boş bir `Container` gibi boş bir `Component` döndürün.\n\n#### Tuş Bağlama İpuçları\n\nEtkin tuş bağlama yapılandırmasına uygun tuş bağlama ipuçlarını görüntülemek için `keyHint()` tuşunu kullanın:\n\n```typescript\nimport { keyHint } from \"@earendil-works/pi-coding-agent\";\n\nrenderResult(result, { expanded }, theme, context) {\n  let text = theme.fg(\"success\", \"✓ Done\");\n  if (!expanded) {\n    text += ` (${keyHint(\"app.tools.expand\", \"to expand\")})`;\n  }\n  return new Text(text, 0, 0);\n}\n```\n\nMevcut işlevler:\n- `keyHint(keybinding, description)` - `\"app.tools.expand\"` veya `\"tui.select.confirm\"` gibi yapılandırılmış bir tuş bağlama kimliğini biçimlendirir\n- `keyText(keybinding)` - Bir tuş bağlama kimliği için ham yapılandırılmış anahtar metnini döndürür\n- `rawKeyHint(key, description)` - Ham anahtar dizesini biçimlendirin\n\nAd alanlı tuş bağlama kimliklerini kullanın:\n- Kodlama aracısı kimlikleri `app.*` ad alanını kullanır; örneğin `app.tools.expand`, `app.editor.external`, `app.session.rename`\n- Paylaşılan TUI kimlikleri `tui.*` ad alanını kullanır; örneğin `tui.select.confirm`, `tui.select.cancel`, `tui.input.tab`\n\nTuş bağlama kimlikleri ve varsayılanlarının kapsamlı listesi için bkz. [keybindings.md](keybindings.md). `keybindings.json` aynı ad alanı kimliklerini kullanır.\n\nÖzel düzenleyiciler ve `ctx.ui.custom()` bileşenleri, eklenen argüman olarak `keybindings: KeybindingsManager`'yi alır. `getKeybindings()` veya `setKeybindings()`'ı çağırmak yerine, enjekte edilen yöneticiyi doğrudan kullanmaları gerekir.\n\n#### En İyi Uygulamalar\n\n- `(0, 0)` dolgusu ile `Text` kullanın. Varsayılan Kutu dolguyu işler.\n- Çok satırlı içerik için `\\n` kullanın.\n- Akış ilerlemesi için `isPartial` tutamacını kullanın.\n- Talep üzerine ayrıntılar için `expanded` desteği.\n- Varsayılan görünümü kompakt tutun.\n- Bağımsız değişkenleri `context.state`'ye kopyalamak yerine `renderResult`'deki `context.args`'yi okuyun.\n- `context.state` işaretini yalnızca çağrı ve sonuç alanları arasında paylaşılması gereken veriler için kullanın.\n- Aynı bileşen örneği yerinde güncellenebildiğinde `context.lastComponent`'yi yeniden kullanın.\n- `renderShell: \"self\"` tuşunu yalnızca varsayılan kutulu kabuk engel teşkil ettiğinde kullanın. Kendi kendine kabuk modunda araç kendi çerçevelemesinden, dolgusundan ve arka planından sorumludur.\n\n#### Geri çekilmek\n\nBir slot oluşturucu tanımlanmamışsa veya şunu atarsa:\n- `renderCall`: Araç adını gösterir\n- `renderResult`: `content`'den ham metni gösterir\n\n### Dinamik Takım Yükleme\n\nExtensions yalnızca küçük bir başlangıç ​​ayarını aktif tutarken birçok aracı kaydedebilir. Bir araç daha sonra yürütme sırasında `pi.setActiveTools()` ile daha fazla araç ekleyebilir. Pi tamamen eklemeli değişiklikleri algılar, yeni mevcut takım adlarını o takım sonucuna kaydeder ve güncellenmiş aktif seti bir sonraki model talebinden önce uygular.\n\nBu her modelde işe yarar. Models yerel ertelenmiş yükleme desteği ile kararlı bilgi istemi önekini koruyun ve yeni tanımları araç sonuç konumuna yükleyin. Diğer modeller aşağıda açıklanan geri dönüşü kullanır.\n\nYaşam döngüsü:\n\n1. Her aracı `pi.registerTool()` ile kaydedin, böylece `pi.getAllTools()`'de görünecektir.\n2. `search_tools` gibi yükleyici araçlarını etkin tutun ve aranabilir araçları devre dışı bırakın.\n3. Yükleyicinin yürütülmesi sırasında `pi.setActiveTools([...currentTools,...matchingTools])`'ı arayın. Değişiklik ek nitelikte olmalıdır: aynı çağrıda halihazırda etkin olan araçları kaldırmayın.\n4. Pi yükleyicinin takım sonucuna hangi araçların eklendiğini kaydeder.\n5. Bir sonraki model yanıtından önce, Pi desteklendiğinde yerel ertelenmiş yüklemeyi veya aksi takdirde normal aktif araç listesini kullanarak eklenen tanımları ortaya çıkarır.\n\nSağlayıcıya özel araç referanslarını döndürmenize veya yükleyiciyi özel bir arama aracı olarak işaretlemenize gerek yoktur. Aktif takım değişimi sinyaldir. `pi.setActiveTools()`'ye aktarılan adların zaten kayıtlı olması gerekir; bilinmeyen isimler dikkate alınmaz.\n\n#### Models yerel ertelenmiş yüklemeyle\n\n- **Antropik**\n  - **Models:** Sonnet, Opus, Fable sürüm 4.5 veya daha yenisi (Haiku olmadan)\n  - **Yerel gösterim:** Ertelenmiş tanımlarda `defer_loading` kullanılır; yükleme noktası `tool_reference` içeriğini kullanır.\n- **Açık AI**\n  - **Models:** `gpt-5.4` ve daha yeni aile\n  - **Yerel gösterim:** Pi, yükleme noktasında tamamlanmış istemci `tool_search_call` ve `tool_search_output` öğelerini ekler.\n\nDoğrulanmış bir özel model veya proxy için yerel işleme, `anthropic-messages` için `compat.supportsToolReferences: true` veya `openai-responses` ve `openai-codex-responses` için `compat.supportsToolSearch: true` ile etkinleştirilebilir. Uç nokta ve model ilgili yerel protokolü kabul etmediği sürece bunları devre dışı bırakın.\n\n#### Geri çekilme davranışı\n\nDiğer tüm modeller ve sağlayıcılar için dinamik aktivasyon hala çalışıyor: Pi bir sonraki istekte normal olarak mevcut aktif takım listesinin tamamını gönderir. Model, yeni etkinleştirilen araçları çağırabilir ancak bunların tanımlarını eklemek, sağlayıcının önbelleğe alınmış bilgi istemi önekini geçersiz kılabilir.\n\nPi aynı zamanda bu güvenli geri dönüşü, bir araç grubunu diğeriyle değiştirmek gibi, aktif küme tamamen eklemeli olmadığında da kullanır. Bu nedenle takım çıkarma işlemleri işe yarar, ancak ertelenmiş yüklemeyi kullanmazlar.\n\nEn iyi önbellek davranışı için, yükleyici aracını tüm oturum boyunca etkin tutun ve etkin kümeyi değiştirmek yerine araçlar ekleyin. Ayrıca bir aracı `promptSnippet` veya `promptGuidelines` ile etkinleştirmenin sistem istemini yeniden oluşturduğunu unutmayın; Bu sistem istemi değişikliği, sağlayıcı ertelenmiş şemaları desteklediğinde bile öneki geçersiz kılabilir. Geç yüklenen araçlar genellikle `description` araçlarına güvenmeli ve yalnızca etkin bilgi istemi meta verilerini çıkarmalıdır.\n\n#### Arama aracı örneği\n\nAşağıdaki uzantı, aranabilir iki aracı kaydeder, bunları başlangıçtaki etkin kümeden kaldırır ve yükleyici olarak yalnızca `search_tools`'yi tutar. Örnek basit anahtar kelime eşlemeyi kullanıyor ancak arama uygulaması BM25'i, yerleştirmeleri, uzak kataloğu veya projeye özel yönlendirmeyi kullanabilir.\n\n```typescript\nimport type { ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\nimport { Type } from \"typebox\";\n\nconst SEARCHABLE_TOOL_NAMES = new Set([\"lookup_weather\", \"search_issues\"]);\n\nexport default function (pi: ExtensionAPI) {\n  pi.registerTool({\n    name: \"lookup_weather\",\n    label: \"Lookup Weather\",\n    description: \"Look up the current weather for a city\",\n    parameters: Type.Object({ city: Type.String() }),\n    async execute(_toolCallId, params) {\n      return {\n        content: [{ type: \"text\", text: `Weather for ${params.city}: sunny` }],\n        details: {},\n      };\n    },\n  });\n\n  pi.registerTool({\n    name: \"search_issues\",\n    label: \"Search Issues\",\n    description: \"Search project issues by keyword\",\n    parameters: Type.Object({ query: Type.String() }),\n    async execute(_toolCallId, params) {\n      return {\n        content: [{ type: \"text\", text: `No open issues matching ${params.query}` }],\n        details: {},\n      };\n    },\n  });\n\n  pi.registerTool({\n    name: \"search_tools\",\n    label: \"Search Tools\",\n    description: \"Search for and enable tools relevant to a task\",\n    promptSnippet: \"Search for additional tools when the active tools cannot perform the task\",\n    promptGuidelines: [\n      \"Use search_tools when a task requires a capability that is not currently available.\",\n    ],\n    parameters: Type.Object({\n      query: Type.String({ description: \"Capability or task to search for\" }),\n      limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 10 })),\n    }),\n    async execute(_toolCallId, params) {\n      const terms = params.query.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);\n      const matches = pi.getAllTools()\n        .filter((tool) => SEARCHABLE_TOOL_NAMES.has(tool.name))\n        .map((tool) => ({\n          tool,\n          score: terms.reduce(\n            (score, term) =>\n              score + (`${tool.name} ${tool.description}`.toLowerCase().includes(term) ? 1 : 0),\n            0,\n          ),\n        }))\n        .filter((match) => match.score > 0)\n        .sort((a, b) => b.score - a.score)\n        .slice(0, params.limit ?? 3)\n        .map((match) => match.tool.name);\n\n      if (matches.length === 0) {\n        return {\n          content: [{ type: \"text\", text: `No tools found for: ${params.query}` }],\n          details: { matches: [] },\n        };\n      }\n\n      const active = pi.getActiveTools();\n      const added = matches.filter((name) => !active.includes(name));\n      pi.setActiveTools([...new Set([...active, ...added])]);\n\n      return {\n        content: [{\n          type: \"text\",\n          text: added.length > 0\n            ? `Loaded tools: ${added.join(\", \")}`\n            : `Matching tools already active: ${matches.join(\", \")}`,\n        }],\n        details: { matches, added },\n      };\n    },\n  });\n\n  pi.on(\"session_start\", () => {\n    // Keep searchable tools registered but initially inactive. Preserve built-ins\n    // and tools owned by other extensions, and keep the loader itself active.\n    const initialTools = pi.getActiveTools().filter(\n      (name) => !SEARCHABLE_TOOL_NAMES.has(name),\n    );\n    pi.setActiveTools([...new Set([...initialTools, \"search_tools\"])]);\n  });\n}\n```\n\n`search_tools` bir eşleşme eklediğinde model, hemen ardından gelen istek üzerine bu tanımı alır. Yerel özellikli bir modelde tanım, başlangıçtaki araç şeması öneki değiştirilmeden arama sonucundan sonra sabitlenir. Diğer modellerde aynı istek üzerine normal takım listesinde görünür.\n\n## Özel kullanıcı arayüzü\n\nExtensions kullanıcılarla `ctx.ui` yöntemleri aracılığıyla etkileşim kurabilir ve mesajların/araçların nasıl oluşturulduğunu özelleştirebilir.\n\n**Özel bileşenler için, aşağıdakiler için kopyala-yapıştır kalıplarına sahip [tui.md](tui.md)**'e bakın:\n- Seçim diyalogları (SelectList)\n- İptal ile eşzamansız işlemler (BorderedLoader)\n- Ayarlar arasında geçiş yapar (AyarlarList)\n- Durum göstergeleri (setStatus)\n- Akış sırasında çalışma mesajı, görünürlük ve gösterge (`setWorkingMessage`, `setWorkingVisible`, `setWorkingIndicator`)\n- Düzenleyicinin üstünde/altında widget'lar (setWidget)\n- Yerleşik eğik çizgi/yol tamamlamanın üstüne yerleştirilmiş otomatik tamamlama sağlayıcıları (addAutocompleteProvider)\n- Özel altbilgiler (setFooter)\n\n### Diyaloglar\n\n```typescript\n// Select from options\nconst choice = await ctx.ui.select(\"Pick one:\", [\"A\", \"B\", \"C\"]);\n\n// Confirm dialog\nconst ok = await ctx.ui.confirm(\"Delete?\", \"This cannot be undone\");\n\n// Text input\nconst name = await ctx.ui.input(\"Name:\", \"placeholder\");\n\n// Multi-line editor\nconst text = await ctx.ui.editor(\"Edit:\", \"prefilled text\");\n\n// Notification (non-blocking)\nctx.ui.notify(\"Done!\", \"info\");  // \"info\" | \"warning\" | \"error\"\n```\n\n#### Geri Sayımlı Zamanlanmış Diyaloglar\n\nİletişim kutuları, canlı geri sayım ekranıyla otomatik olarak kapatılan `timeout` seçeneğini destekler:\n\n```typescript\n// Dialog shows \"Title (5s)\" → \"Title (4s)\" → ... → auto-dismisses at 0\nconst confirmed = await ctx.ui.confirm(\n  \"Timed Confirmation\",\n  \"This dialog will auto-cancel in 5 seconds. Confirm?\",\n  { timeout: 5000 }\n);\n\nif (confirmed) {\n  // User confirmed\n} else {\n  // User cancelled or timed out\n}\n```\n\n**Zaman aşımında döndürülen değerler:**\n- `select()` `undefined` değerini döndürür\n- `confirm()` `false` değerini döndürür\n- `input()` `undefined` değerini döndürür\n\n#### AbortSignal ile Manuel İşten Çıkarma\n\nDaha fazla kontrol için (örneğin, zaman aşımını kullanıcı iptalinden ayırt etmek için) `AbortSignal` kullanın:\n\n```typescript\nconst controller = new AbortController();\nconst timeoutId = setTimeout(() => controller.abort(), 5000);\n\nconst confirmed = await ctx.ui.confirm(\n  \"Timed Confirmation\",\n  \"This dialog will auto-cancel in 5 seconds. Confirm?\",\n  { signal: controller.signal }\n);\n\nclearTimeout(timeoutId);\n\nif (confirmed) {\n  // User confirmed\n} else if (controller.signal.aborted) {\n  // Dialog timed out\n} else {\n  // User cancelled (pressed Escape or selected \"No\")\n}\n```\n\nTam örnekler için [examples/extensions/timed-confirm.ts](../examples/extensions/timed-confirm.ts)'e bakın.\n\n### Widget'lar, Durum ve Altbilgi\n\n```typescript\n// Status in footer (persistent until cleared)\nctx.ui.setStatus(\"my-ext\", \"Processing...\");\nctx.ui.setStatus(\"my-ext\", undefined);  // Clear\n\n// Working loader (shown during streaming)\nctx.ui.setWorkingMessage(\"Thinking deeply...\");\nctx.ui.setWorkingMessage();  // Restore default\nctx.ui.setWorkingVisible(false);  // Hide the built-in working loader row entirely\nctx.ui.setWorkingVisible(true);   // Show the built-in working loader row\n\n// Working indicator (shown during streaming)\nctx.ui.setWorkingIndicator({ frames: [ctx.ui.theme.fg(\"accent\", \"●\")] });  // Static dot\nctx.ui.setWorkingIndicator({\n  frames: [\n    ctx.ui.theme.fg(\"dim\", \"·\"),\n    ctx.ui.theme.fg(\"muted\", \"•\"),\n    ctx.ui.theme.fg(\"accent\", \"●\"),\n    ctx.ui.theme.fg(\"muted\", \"•\"),\n  ],\n  intervalMs: 120,\n});\nctx.ui.setWorkingIndicator({ frames: [] });  // Hide indicator\nctx.ui.setWorkingIndicator();  // Restore default spinner\n\n// Widget above editor (default)\nctx.ui.setWidget(\"my-widget\", [\"Line 1\", \"Line 2\"]);\n// Widget below editor\nctx.ui.setWidget(\"my-widget\", [\"Line 1\", \"Line 2\"], { placement: \"belowEditor\" });\nctx.ui.setWidget(\"my-widget\", (tui, theme) => new Text(theme.fg(\"accent\", \"Custom\"), 0, 0));\nctx.ui.setWidget(\"my-widget\", undefined);  // Clear\n\n// Custom footer (replaces built-in footer entirely)\nctx.ui.setFooter((tui, theme) => ({\n  render(width) { return [theme.fg(\"dim\", \"Custom footer\")]; },\n  invalidate() {},\n}));\nctx.ui.setFooter(undefined);  // Restore built-in footer\n\n// Terminal title\nctx.ui.setTitle(\"pi - my-project\");\n\n// Editor text\nctx.ui.setEditorText(\"Prefill text\");\nconst current = ctx.ui.getEditorText();\n\n// Paste into editor (triggers paste handling, including collapse for large content)\nctx.ui.pasteToEditor(\"pasted content\");\n\n// Stack custom autocomplete behavior on top of the built-in provider\nctx.ui.addAutocompleteProvider((current) => ({\n  triggerCharacters: [\"#\"],\n  async getSuggestions(lines, line, col, options) {\n    const beforeCursor = (lines[line] ?? \"\").slice(0, col);\n    const match = beforeCursor.match(/(?:^|[ \\t])#([^\\s#]*)$/);\n    if (!match) {\n      return current.getSuggestions(lines, line, col, options);\n    }\n\n    return {\n      prefix: `#${match[1] ?? \"\"}`,\n      items: [{ value: \"#2983\", label: \"#2983\", description: \"Extension API for autocomplete\" }],\n    };\n  },\n  applyCompletion(lines, line, col, item, prefix) {\n    return current.applyCompletion(lines, line, col, item, prefix);\n  },\n  shouldTriggerFileCompletion(lines, line, col) {\n    return current.shouldTriggerFileCompletion?.(lines, line, col) ?? true;\n  },\n}));\n\n// Tool output expansion\nconst wasExpanded = ctx.ui.getToolsExpanded();\nctx.ui.setToolsExpanded(true);\nctx.ui.setToolsExpanded(wasExpanded);\n\n// Custom editor (vim mode, emacs mode, etc.)\nctx.ui.setEditorComponent((tui, theme, keybindings) => new VimEditor(tui, theme, keybindings));\nconst currentEditor = ctx.ui.getEditorComponent();\nctx.ui.setEditorComponent((tui, theme, keybindings) =>\n  new WrappedEditor(tui, theme, keybindings, currentEditor?.(tui, theme, keybindings))\n);\nctx.ui.setEditorComponent(undefined);  // Restore default editor\n\n// Theme management (see themes.md for creating themes)\nconst themes = ctx.ui.getAllThemes();  // [{ name: \"dark\", path: \"/...\" | undefined }, ...]\nconst lightTheme = ctx.ui.getTheme(\"light\");  // Load without switching\nconst result = ctx.ui.setTheme(\"light\");  // Switch by name\nif (!result.success) {\n  ctx.ui.notify(`Failed: ${result.error}`, \"error\");\n}\nctx.ui.setTheme(lightTheme!);  // Or switch by Theme object\nctx.ui.theme.fg(\"accent\", \"styled text\");  // Access current theme\n```\n\nÖzel çalışma göstergesi çerçeveleri kelimesi kelimesine işlenir. Renkleri istiyorsanız bunları çerçeve dizelerine kendiniz ekleyin, örneğin `ctx.ui.theme.fg(...)` ile.\n\n### Otomatik tamamlama Providers\n\nÖzel otomatik tamamlama mantığını yerleşik eğik çizgi komutu ve yol sağlayıcının üstüne yığmak için `ctx.ui.addAutocompleteProvider()` tuşunu kullanın. `Özel otomatik tamamlama mantığını yerleşik eğik çizgi komutu ve yol sağlayıcının üstüne yığmak için `ctx.ui.addAutocompleteProvider()` tuşunu kullanın.  gibi özel doğal tetikleyiciler için `triggerCharacters`'yi ayarlayın.\n\nTipik desen:\n\n- imleçten önceki metni inceleyin\n- Uzantıya özel söz diziminiz eşleştiğinde kendi önerilerinizi döndürün\n- aksi takdirde `current.getSuggestions(...)`'ye yetki verin\n- Özel ekleme davranışına ihtiyacınız olmadığı sürece `applyCompletion(...)` delegesini verin\n\n```typescript\npi.on(\"session_start\", (_event, ctx) => {\n  ctx.ui.addAutocompleteProvider((current) => ({\n    triggerCharacters: [\"#\"],\n    async getSuggestions(lines, cursorLine, cursorCol, options) {\n      const line = lines[cursorLine] ?? \"\";\n      const beforeCursor = line.slice(0, cursorCol);\n      const match = beforeCursor.match(/(?:^|[ \\t])#([^\\s#]*)$/);\n      if (!match) {\n        return current.getSuggestions(lines, cursorLine, cursorCol, options);\n      }\n\n      return {\n        prefix: `#${match[1] ?? \"\"}`,\n        items: [\n          { value: \"#2983\", label: \"#2983\", description: \"Extension API for registering custom @ autocomplete providers\" },\n          { value: \"#2753\", label: \"#2753\", description: \"Reload stale resource settings\" },\n        ],\n      };\n    },\n\n    applyCompletion(lines, cursorLine, cursorCol, item, prefix) {\n      return current.applyCompletion(lines, cursorLine, cursorCol, item, prefix);\n    },\n\n    shouldTriggerFileCompletion(lines, cursorLine, cursorCol) {\n      return current.shouldTriggerFileCompletion?.(lines, cursorLine, cursorCol) ?? true;\n    },\n  }));\n});\n```\n\n`gh issue list` ile en son açık GitHub sayılarını önceden yükleyen ve hızlı `#...` tamamlama için bunları yerel olarak filtreleyen eksiksiz bir örnek için [github-issue-autocomplete.ts](../examples/extensions/github-issue-autocomplete.ts)'ye bakın. GitHub CLI (`gh`) ve GitHub depo kontrolü gerektirir.\n\n### Özel Bileşenler\n\nKarmaşık kullanıcı arayüzü için `ctx.ui.custom()` kullanın. Bu, `done()` çağrılana kadar düzenleyiciyi geçici olarak bileşeninizle değiştirir:\n\n```typescript\nimport { Text, Component } from \"@earendil-works/pi-tui\";\n\nconst result = await ctx.ui.custom<boolean>((tui, theme, keybindings, done) => {\n  const text = new Text(\"Press Enter to confirm, Escape to cancel\", 1, 1);\n\n  text.onKey = (key) => {\n    if (key === \"return\") done(true);\n    if (key === \"escape\") done(false);\n    return true;\n  };\n\n  return text;\n});\n\nif (result) {\n  // User pressed Enter\n}\n```\n\nGeri arama şunları alır:\n- `tui` - TUI örneği (ekran boyutları, odak yönetimi için)\n- `theme` - Stil için güncel tema\n- `keybindings` - Uygulama tuş bağlama yöneticisi (kısayolları kontrol etmek için)\n- `done(value)` - Bileşeni kapatmak ve değeri döndürmek için çağrı\n\nAPI bileşeninin tamamı için [tui.md](tui.md)'ye bakın.\n\n#### Yer Paylaşımı Modu (Deneysel)\n\nEkranı temizlemeden bileşeni mevcut içeriğin üzerinde kayan bir model olarak oluşturmak için `{ overlay: true }` iletin:\n\n```typescript\nconst result = await ctx.ui.custom<string | null>(\n  (tui, theme, keybindings, done) => new MyOverlayComponent({ onClose: done }),\n  { overlay: true }\n);\n```\n\nGelişmiş konumlandırma için (sabitlemeler, kenar boşlukları, yüzdeler, duyarlı görünürlük), `overlayOptions`'yi geçin. Odağı veya görünürlüğü programlı olarak kontrol etmek için `onHandle` tuşunu kullanın:\n\n```typescript\nconst result = await ctx.ui.custom<string | null>(\n  (tui, theme, keybindings, done) => new MyOverlayComponent({ onClose: done }),\n  {\n    overlay: true,\n    overlayOptions: { anchor: \"top-right\", width: \"50%\", margin: 2 },\n    onHandle: (handle) => {\n      handle.focus(); // focus this overlay and bring it to the visual front\n      // handle.unfocus({ target: editorComponent }); // release input to a specific component\n      // handle.setHidden(true/false); // toggle visibility\n      // handle.hide(); // permanently remove\n    }\n  }\n);\n```\n\nOdaklanmış görünür bir yer paylaşımı, geçici olarak yer paylaşımsız özel kullanıcı arayüzü kapatıldıktan sonra girişi geri alabilir. Kaplama görünür kalırken kasıtlı olarak başka bir bileşenin girişi tutmasını istiyorsanız `handle.unfocus({ target })`'ı arayın. `{ target: null }` geçişi, başka bir bileşene odaklanmadan kaplamayı serbest bırakır.\n\n`OverlayOptions`'nin tamamı için [tui.md](tui.md) ve örnekler için `OverlayHandle` API ve [overlay-qa-tests.ts](../examples/extensions/overlay-qa-tests.ts)'ye bakın.\n\n### Özel Düzenleyici\n\nAna giriş düzenleyicisini özel bir uygulamayla (vim modu, emacs modu vb.) değiştirin:\n\n```typescript\nimport { CustomEditor, type ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\nimport { matchesKey } from \"@earendil-works/pi-tui\";\n\nclass VimEditor extends CustomEditor {\n  private mode: \"normal\" | \"insert\" = \"insert\";\n\n  handleInput(data: string): void {\n    if (matchesKey(data, \"escape\") && this.mode === \"insert\") {\n      this.mode = \"normal\";\n      return;\n    }\n    if (this.mode === \"normal\" && data === \"i\") {\n      this.mode = \"insert\";\n      return;\n    }\n    super.handleInput(data);  // App keybindings + text editing\n  }\n}\n\nexport default function (pi: ExtensionAPI) {\n  pi.on(\"session_start\", (_event, ctx) => {\n    ctx.ui.setEditorComponent((tui, theme, keybindings) =>\n      new VimEditor(tui, theme, keybindings)\n    );\n  });\n}\n```\n\n**Önemli noktalar:**\n- Uygulama tuş atamalarını almak için `CustomEditor` (temel `Editor` değil) öğesini genişletin (iptal etmek için kaçış, ctrl+d, model değiştirme)\n- Kullanmadığınız anahtarlar için `super.handleInput(data)`'ı arayın\n- Fabrika uygulamadan `tui`, `theme` ve `keybindings` alır\n- Önceden yapılandırılmış özel düzenleyiciyi kaydırmak için `setEditorComponent()`'den önce `ctx.ui.getEditorComponent()` kullanın\n- Varsayılanı geri yüklemek için `undefined` iletin: `ctx.ui.setEditorComponent(undefined)`\n\nDüzenleyicinin yerini almış olan başka bir uzantıyla kompozisyon oluşturmak için, kendi fabrikanızı ayarlamadan önce önceki fabrikayı yakalayın:\n\n```typescript\nconst previous = ctx.ui.getEditorComponent();\nctx.ui.setEditorComponent((tui, theme, keybindings) =>\n  new MyEditor(tui, theme, keybindings, { base: previous?.(tui, theme, keybindings) })\n);\n```\n\nMod göstergeli tam bir örnek için [tui.md](tui.md) Desen 7'ye bakın.\n\n### Mesaj ve Giriş Oluşturma\n\n`customType`'ınızla mesajlar için özel bir oluşturucu kaydedin. Yüksek Lisans bağlamına katılması gereken içerik için mesaj oluşturucuları kullanın:\n\n```typescript\nimport { Text } from \"@earendil-works/pi-tui\";\n\npi.registerMessageRenderer(\"my-extension\", (message, options, theme) => {\n  const { expanded, outputPad } = options;\n  let text = theme.fg(\"accent\", `[${message.customType}] `);\n  text += message.content;\n\n  if (expanded && message.details) {\n    text += \"\\n\" + theme.fg(\"dim\", JSON.stringify(message.details, null, 2));\n  }\n\n  return new Text(text, outputPad, 0);\n});\n```\n\nMesajlar `pi.sendMessage()` aracılığıyla gönderilir:\n\n```typescript\npi.sendMessage({\n  customType: \"my-extension\",  // Matches registerMessageRenderer\n  content: \"Status update\",\n  display: true,               // Show in TUI\n  details: { ... },            // Available in renderer\n});\n```\n\nLLM'ye gönderilmemesi gereken yalnızca TUI içeriği için bunun yerine özel girişler oluşturun:\n\n```typescript\npi.registerEntryRenderer(\"my-card\", (entry, options, theme) => {\n  return new Text(theme.fg(\"accent\", JSON.stringify(entry.data)));\n});\n\npi.appendEntry(\"my-card\", { status: \"done\" });\n```\n\n### Tema Renkleri\n\nTüm oluşturma işlevleri bir `theme` nesnesi alır. Özel temalar ve tam renk paleti oluşturmak için [themes.md](themes.md)'e bakın.\n\n```typescript\n// Foreground colors\ntheme.fg(\"toolTitle\", text)   // Tool names\ntheme.fg(\"accent\", text)      // Highlights\ntheme.fg(\"success\", text)     // Success (green)\ntheme.fg(\"error\", text)       // Errors (red)\ntheme.fg(\"warning\", text)     // Warnings (yellow)\ntheme.fg(\"muted\", text)       // Secondary text\ntheme.fg(\"dim\", text)         // Tertiary text\n\n// Text styles\ntheme.bold(text)\ntheme.italic(text)\ntheme.strikethrough(text)\n```\n\nÖzel araç oluşturucularda sözdizimi vurgulaması için:\n\n```typescript\nimport { highlightCode, getLanguageFromPath } from \"@earendil-works/pi-coding-agent\";\n\n// Highlight code with explicit language\nconst highlighted = highlightCode(\"const x = 1;\", \"typescript\", theme);\n\n// Auto-detect language from file path\nconst lang = getLanguageFromPath(\"/path/to/file.rs\");  // \"rust\"\nconst highlighted = highlightCode(code, lang, theme);\n```\n\n## Hata İşleme\n\n- Uzantı hataları günlüğe kaydedilir, temsilci devam eder\n- `tool_call` hatalar aracı engeller (arızaya karşı korumalı)\n- Araç `execute` hataları atılarak bildirilmelidir; atılan hata yakalanır, LLM'ye `isError: true` ile bildirilir ve yürütme devam eder\n\n## Mod Davranışı\n\n| Mod | `ctx.mode` | `ctx.hasUI` | Notlar |\n|------|------------|-------------|-------|\n| İnteraktif | `\"tui\"` | `true` | Terminal oluşturma ile tam TUI |\n| RPC (`--mode rpc`) | `\"rpc\"` | `true` | JSON protokolü aracılığıyla diyaloglar ve bildirimler; `custom()`, `undefined` değerini döndürür. Bkz. [rpc.md](rpc.md) |\n| JSON (`--mode json`) | `\"json\"` | `false` | stdout'e olay akışı; Kullanıcı arayüzü yöntemleri işlem gerektirmez |\n| Yazdır (`-p`) | `\"print\"` | `false` | Extensions çalıştır ama istemde bulunamıyorum |\n\nTUI'ye özgü özelliklerden (`custom()`, bileşen fabrikaları, terminal girişi) önce `ctx.mode === \"tui\"` kullanın. Hem TUI hem de RPC modlarında çalışan diyalog ve bildirim yöntemlerinden önce `ctx.hasUI`'yi kullanın.\n\n## Örnekler Referans\n\nTüm örnekler [examples/extensions/](../examples/extensions/)'dedir.\n\n| Örnek | Tanım | Tuş APIs |\n|---------|-------------|----------|\n| **Aletler** |  |  |\n| `hello.ts` | Minimum takım kaydı | `registerTool` |\n| `question.ts` | Kullanıcı etkileşimli araç | `registerTool`, `ui.select` |\n| `questionnaire.ts` | Çok adımlı sihirbaz aracı | `registerTool`, `ui.custom` |\n| `todo.ts` | Kalıcılığa sahip durum bilgisi olan araç | `registerTool`, `appendEntry`, `renderResult`, oturum etkinlikleri |\n| `dynamic-tools.ts` | Araçları başlatma sonrasında ve komutlar sırasında kaydedin | `registerTool`, `session_start`, `registerCommand` |\n| `structured-output.ts` | `terminate: true` ile son yapılandırılmış çıktı aracı | `registerTool`, araç sonuçlarının sonlandırılması |\n| `truncated-tool.ts` | Çıkış kesme örneği | `registerTool`, `truncateHead` |\n| `tool-override.ts` | Yerleşik okuma aracını geçersiz kıl | `registerTool` (yerleşik ile aynı ad) |\n| **Komutlar** |  |  |\n| `pirate.ts` | Her turda sistem istemini değiştirin | `registerCommand`, `before_agent_start` |\n| `summarize.ts` | Konuşma özeti komutu | `registerCommand`, `ui.custom` |\n| `handoff.ts` | Sağlayıcılar arası model aktarımı | `registerCommand`, `ui.editor`, `ui.custom` |\n| `qna.ts` | Özel kullanıcı arayüzü ile Soru-Cevap | `registerCommand`, `ui.custom`, `setEditorText` |\n| `send-user-message.ts` | Kullanıcı mesajlarını enjekte etme | `registerCommand`, `sendUserMessage` |\n| `reload-runtime.ts` | Yeniden yükleme komutu ve LLM aracı aktarımı | `registerCommand`, `ctx.reload()`, `sendUserMessage` |\n| `shutdown-command.ts` | Zarif kapatma komutu | `registerCommand`, `shutdown()` |\n| **Etkinlikler ve Kapılar** |  |  |\n| `permission-gate.ts` | Tehlikeli komutları engelle | `on(\"tool_call\")`, `ui.confirm` |\n| `project-trust.ts` | Bir kullanıcı/global veya CLI uzantısından proje güvenine karar verin veya bu güveni erteleyin | `on(\"project_trust\")`, güven kullanıcı arayüzü, gerekli güven sonucu |\n| `protected-paths.ts` | Belirli yollara yazmayı engelle | `on(\"tool_call\")` |\n| `confirm-destructive.ts` | Oturum değişikliklerini onaylayın | `on(\"session_before_switch\")`, `on(\"session_before_fork\")` |\n| `dirty-repo-guard.ts` | Kirli git deposu hakkında uyar | `on(\"session_before_*\")`, `exec` |\n| `input-transform.ts` | Kullanıcı girişini dönüştürün | `on(\"input\")` |\n| `input-transform-streaming.ts` | Akış uyumlu giriş dönüşümü | `on(\"input\")`, `streamingBehavior` |\n| `model-status.ts` | React model değişikliklerine | `on(\"model_select\")`, `setStatus` |\n| `provider-payload.ts` | Yükleri ve sağlayıcı yanıt başlıklarını inceleyin | `on(\"before_provider_request\")`, `on(\"after_provider_response\")` |\n| `system-prompt-header.ts` | Sistem istemi bilgilerini görüntüle | `on(\"agent_start\")`, `getSystemPrompt` |\n| `claude-rules.ts` | Dosyalardan kuralları yükle | `on(\"session_start\")`, `on(\"before_agent_start\")` |\n| `prompt-customizer.ts` | `systemPromptOptions` kullanarak bağlama duyarlı araç rehberliği ekleyin | `on(\"before_agent_start\")`, `BuildSystemPromptOptions` |\n| `file-trigger.ts` | Dosya izleyici mesajları tetikler | `sendMessage` |\n| **Sıkıştırma ve Oturumlar** |  |  |\n| `custom-compaction.ts` | Özel sıkıştırma özeti | `on(\"session_before_compact\")` |\n| `trigger-compact.ts` | Sıkıştırmayı manuel olarak tetikleyin | `compact()` |\n| `git-checkpoint.ts` | Git dönüşlerde saklanma | `on(\"turn_start\")`, `on(\"session_before_fork\")`, `exec` |\n| `git-merge-and-resolve.ts` | Çakışmaları getirme, birleştirme ve çözme | `on(\"agent_end\")`, `exec`, `sendUserMessage` |\n| `auto-commit-on-exit.ts` | Kapatmayı taahhüt et | `on(\"session_shutdown\")`, `exec` |\n| **Kullanıcı Arayüzü Bileşenleri** |  |  |\n| `status-line.ts` | Altbilgi durum göstergesi | `setStatus`, oturum etkinlikleri |\n| `working-indicator.ts` | Akış çalışma göstergesini özelleştirin | `setWorkingIndicator`, `registerCommand` |\n| `github-issue-autocomplete.ts` | `gh issue list`'den en son açık sayıları önceden yükleyerek yerleşik otomatik tamamlamanın üstüne `#1234` sayı tamamlamaları ekleyin | `addAutocompleteProvider`, `on(\"session_start\")`, `exec` |\n| `custom-footer.ts` | Alt bilgiyi tamamen değiştir | `registerCommand`, `setFooter` |\n| `custom-header.ts` | Başlangıç ​​başlığını değiştir | `on(\"session_start\")`, `setHeader` |\n| `modal-editor.ts` | Vim tarzı modal düzenleyici | `setEditorComponent`, `CustomEditor` |\n| `rainbow-editor.ts` | Özel düzenleyici stili | `setEditorComponent` |\n| `widget-placement.ts` | Widget düzenleyicinin üstünde/altında | `setWidget` |\n| `overlay-test.ts` | Kaplama bileşenleri | `ui.custom` kaplama seçenekleriyle |\n| `overlay-qa-tests.ts` | Kapsamlı kaplama testleri | `ui.custom`, tüm kaplama seçenekleri |\n| `notify.ts` | Basit bildirimler | `ui.notify` |\n| `timed-confirm.ts` | Zaman aşımı olan diyaloglar | `ui.confirm` zaman aşımı/sinyalli |\n| `mac-system-theme.ts` | Temayı otomatik değiştir | `setTheme`, `exec` |\n| **Karmaşık Extensions** |  |  |\n| `plan-mode/` | Tam plan modu uygulaması | Tüm etkinlik türleri, `registerCommand`, `registerShortcut`, `registerFlag`, `setStatus`, `setWidget`, `sendMessage`, `setActiveTools` |\n| `preset.ts` | Kaydedilebilir ön ayarlar (model, araçlar, düşünme) | `registerCommand`, `registerShortcut`, `registerFlag`, `setModel`, `setActiveTools`, `setThinkingLevel`, `appendEntry` |\n| `tools.ts` | Araçların kullanıcı arayüzünü açma/kapatma | `registerCommand`, `setActiveTools`, `SettingsList`, oturum etkinlikleri |\n| **Uzaktan Kumanda ve Korumalı Alan** |  |  |\n| `ssh.ts` | SSH uzaktan yürütme | `registerFlag`, `on(\"user_bash\")`, `on(\"before_agent_start\")`, araç işlemleri |\n| `interactive-shell.ts` | Kalıcı kabuk oturumu | `on(\"user_bash\")` |\n| `sandbox/` | Korumalı alanda araç yürütme | Takım işlemleri |\n| `gondolin/` | Yerleşik araçları ve `!` komutlarını Gondolin mikro sanal makineye yönlendirin | Araç işlemleri, yerleşik araç geçersiz kılmaları, `on(\"user_bash\")` |\n| `subagent/` | Alt ajanları doğur | `registerTool`, `exec` |\n| **Oyunlar** |  |  |\n| `snake.ts` | Yılan oyunu | `registerCommand`, `ui.custom`, klavye kullanımı |\n| `space-invaders.ts` | Uzay İstilacıları oyunu | `registerCommand`, `ui.custom` |\n| `doom-overlay/` | Yer paylaşımında kıyamet | `ui.custom` kaplamalı |\n| **Providers** |  |  |\n| `custom-provider-anthropic/` | Özel Antropik proxy | `registerProvider` |\n| `custom-provider-gitlab-duo/` | GitLab Duo entegrasyonu | `registerProvider` ile OAuth |\n| **Mesajlar ve İletişim** |  |  |\n| `message-renderer.ts` | Özel mesaj oluşturma | `registerMessageRenderer`, `sendMessage` |\n| `entry-renderer.ts` | TUI-yalnızca özel giriş oluşturma | `registerEntryRenderer`, `appendEntry` |\n| `event-bus.ts` | Uzantılar arası olaylar | `pi.events` |\n| **Oturum Meta Verileri** |  |  |\n| `session-name.ts` | Seçici için oturumları adlandırın | `setSessionName`, `getSessionName` |\n| `bookmark.ts` | /tree için yer imi girişleri | `setLabel` |\n| **Çeşitli** |  |  |\n| `inline-bash.ts` | Araç çağrılarında satır içi bash | `on(\"tool_call\")` |\n| `bash-spawn-hook.ts` | Yürütmeden önce bash komutunu, cwd'yi ve env'yi ayarlayın | `createBashTool`, `spawnHook` |\n| `with-deps/` | npm bağımlılıklara sahip uzantı | `package.json` ile paket yapısı |","sourceFile":"extensions.md"},"index":{"title":"Pi Belgeler","markdown":"Pi minimum terminal kodlama donanımıdır. TypeScript uzantılar, beceriler, prompt templates, temalar ve pi paketleri aracılığıyla genişletilirken özünde küçük kalacak şekilde tasarlanmıştır.\n\n## Hızlı başlangıç\n\nPi'yi npm ile yükleyin:\n\n```bash\nnpm install -g --ignore-scripts @earendil-works/pi-coding-agent\n```\n\n`--ignore-scripts` yükleme sırasında bağımlılık yaşam döngüsü komut dosyalarını devre dışı bırakır. Pi normal npm kurulumları için kurulum komut dosyalarına ihtiyaç duymaz.\n\nLinux veya macOS'ta yükleyiciyi de kullanabilirsiniz:\n\n```bash\ncurl -fsSL https://pi.dev/install.sh | sh\n```\n\nPi'nin kendisini kaldırmak için curl ve npm kurulumları için npm kullanın:\n\n```bash\nnpm uninstall -g @earendil-works/pi-coding-agent\n```\n\npnpm, Yarn veya Bun yüklemeleri için eşleşen genel kaldırma komutunu kullanın: `pnpm remove -g @earendil-works/pi-coding-agent`, `yarn global remove @earendil-works/pi-coding-agent` veya `bun uninstall -g @earendil-works/pi-coding-agent`.\n\nDaha sonra bunu bir proje dizininde çalıştırın:\n\n```bash\npi\n```\n\nsubscription providers için `/login` ile kimlik doğrulaması yapın veya pi'yi başlatmadan önce `ANTHROPIC_API_KEY` gibi bir API key ayarlayın.\n\nİlk çalıştırma akışının tamamı için bkz. [Quickstart](quickstart.md).\n\n## Buradan başlayın\n\n- [Quickstart](quickstart.md) - ilk oturumu yükleyin, doğrulayın ve çalıştırın.\n- [Using Pi](usage.md) - etkileşimli mod, slash commands, context files ve CLI referansı.\n- [Providers](providers.md) - yerleşik sağlayıcılar için abonelik ve API tuş kurulumu.\n- [llama.cpp](llama-cpp.md) - yerel bir yönlendirici çalıştırın ve modelleri `/llama` ile yönetin.\n- [Security](security.md) - proje güveni, sandbox sınırlar ve güvenlik açığı raporlaması.\n- [Containerization](containerization.md) - sandbox pi ile Gondolin, Docker veya OpenShell.\n- [Settings](settings.md) - genel ve proje ayarları.\n- [Keybindings](keybindings.md) - varsayılan kısayollar ve özel tuş atamaları.\n- [Sessions](sessions.md) - oturum yönetimi, dallanma ve ağaçta gezinme.\n- [Compaction](compaction.md) - context compaction ve branch summarization.\n\n## Özelleştirme\n\n- [Extensions](extensions.md) - TypeScript araçlar, komutlar, etkinlikler ve özel kullanıcı arayüzü için modüller.\n- [Skills](skills.md) - Yeniden kullanılabilir isteğe bağlı özellikler için Aracı Skills.\n- [Prompt templates](prompt-templates.md) - slash commands'den genişleyen yeniden kullanılabilir istemler.\n- [Themes](themes.md) - yerleşik ve özel terminal themes.\n- [Pi packages](packages.md) - Uzantıları, becerileri, istemleri ve temaları paketleyin ve paylaşın.\n- [Custom models](models.md) - desteklenen sağlayıcı API'ler için model girişleri ekleyin.\n- [Custom providers](custom-provider.md) - özel API ve OAuth akışlarını uygulayın.\n\n## Programatik kullanım\n\n- [SDK](sdk.md) - Pi'yi Node.js uygulamalarına yerleştirin.\n- [RPC mode](rpc.md) - stdin/stdout JSONL üzerinden integral alın.\n- [JSON event stream mode](json.md) - yapılandırılmış olaylarla yazdırma modu.\n- [TUI components](tui.md) - uzantılar için özel terminal kullanıcı arayüzü oluşturun.\n\n## Referans\n\n- [Environment variables](environment-variables.md) - Pi süreç yapılandırması ve oturum meta verileri bash araçları tarafından kullanılabilir.\n- [Session format](session-format.md) - JSONL oturum dosyası formatı, giriş türleri ve SessionManager API.\n\n## Platform kurulumu\n\n- [Windows](windows.md)\n- [Termux on Android](termux.md)\n- [tmux](tmux.md)\n- [Terminal setup](terminal-setup.md)\n- [Shell aliases](shell-aliases.md)\n\n## Gelişim\n\n- [Development](development.md) - yerel kurulum, proje yapısı ve hata ayıklama.","sourceFile":"index.md"},"json":{"title":"JSON Etkinlik Akışı Modu","markdown":"```bash\npi --mode json \"Your prompt\"\n```\n\nTüm oturum olaylarını JSON satırlardan stdout'ye çıkarır. Pi'yi diğer araçlara veya özel kullanıcı arayüzlerine entegre etmek için kullanışlıdır.\n\n## Etkinlik Türleri\n\nWire olayları `JsonAgentSessionEvent` kullanır. Eşleşiyor\n[`AgentSessionEvent`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/agent-session.ts)\nakış mesajı güncellemelerinin kümülatif anlık görüntüleri hariç tutması dışında:\n\n```typescript\ntype WithoutPartial<T> = T extends { partial: unknown } ? Omit<T, \"partial\"> : T;\n\ntype JsonAgentSessionEvent =\n  | Exclude<AgentSessionEvent, { type: \"message_update\" }>\n  | {\n      type: \"message_update\";\n      assistantMessageEvent: WithoutPartial<AssistantMessageEvent>;\n    };\n```\n\n`queue_update` değiştiklerinde bekleyen yönlendirme ve takip kuyruklarının tamamını yayınlar. `compaction_start` ve `compaction_end` hem manuel hem de otomatik sıkıştırmayı kapsar.\n\nDiğer temel olaylar\n[`AgentEvent`](https://github.com/earendil-works/pi-mono/blob/main/packages/agent/src/types.ts):\n\n```typescript\ntype AgentEvent =\n  // Agent lifecycle\n  | { type: \"agent_start\" }\n  | { type: \"agent_end\"; messages: AgentMessage[] }\n  // Turn lifecycle\n  | { type: \"turn_start\" }\n  | { type: \"turn_end\"; message: AgentMessage; toolResults: ToolResultMessage[] }\n  // Message lifecycle\n  | { type: \"message_start\"; message: AgentMessage }\n  | { type: \"message_update\"; message: AgentMessage; assistantMessageEvent: AssistantMessageEvent }\n  | { type: \"message_end\"; message: AgentMessage }\n  // Tool execution\n  | { type: \"tool_execution_start\"; toolCallId: string; toolName: string; args: any }\n  | { type: \"tool_execution_update\"; toolCallId: string; toolName: string; args: any; partialResult: any }\n  | { type: \"tool_execution_end\"; toolCallId: string; toolName: string; result: any; isError: boolean };\n```\n\n## Mesaj Türleri\n\n[`packages/ai/src/types.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/types.ts#L134)'den gelen temel mesajlar:\n- `UserMessage` (satır 134)\n- `AssistantMessage` (satır 140)\n- `ToolResultMessage` (satır 152)\n\n[`packages/coding-agent/src/core/messages.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/messages.ts#L29)'den gelen genişletilmiş mesajlar:\n- `BashExecutionMessage` (satır 29)\n- `CustomMessage` (satır 46)\n- `BranchSummaryMessage` (satır 55)\n- `CompactionSummaryMessage` (satır 62)\n\n## Çıkış Formatı\n\nHer satır bir JSON nesnesidir. İlk satır oturum başlığıdır:\n\n```json\n{\"type\":\"session\",\"version\":3,\"id\":\"uuid\",\"timestamp\":\"...\",\"cwd\":\"/path\"}\n```\n\nOlaylar meydana geldikçe takip edilir:\n\n```json\n{\"type\":\"agent_start\"}\n{\"type\":\"turn_start\"}\n{\"type\":\"message_start\",\"message\":{\"role\":\"assistant\",\"content\":[],...}}\n{\"type\":\"message_update\",\"assistantMessageEvent\":{\"type\":\"text_delta\",\"contentIndex\":0,\"delta\":\"Hello\"}}\n{\"type\":\"message_end\",\"message\":{...}}\n{\"type\":\"turn_end\",\"message\":{...},\"toolResults\":[]}\n{\"type\":\"agent_end\",\"messages\":[...]}\n```\n\n`message_update` kayıtlar yalnızca deltadır. Hem kümülatif `message` alanını hem de\n`assistantMessageEvent.partial` akış boyutunu doğrusal tutmak için. `contentIndex` ve `delta` tuşlarını kullanın\nGerekirse canlı metni, düşünmeyi veya araç çağrısı argümanlarını bir araya getirmek. `message_end` içerir\nson yetkili mesaj.\n\n## Örnek\n\n```bash\npi --mode json \"List files\" 2>/dev/null | jq -c 'select(.type == \"message_end\")'\n```","sourceFile":"json.md"},"keybindings":{"title":"Tuş atamaları","markdown":"Tüm klavye kısayolları `~/.pi/agent/keybindings.json` aracılığıyla özelleştirilebilir. Her eylem bir veya daha fazla tuşa bağlanabilir.\n\nYapılandırma dosyası, pi'nin dahili olarak kullandığı ve uzantı yazarlarının `keyHint()` ve enjekte edilen `keybindings` yöneticilerinde kullandığı aynı ad alanlı tuş bağlama kimliklerini kullanır.\n\n`cursorUp` veya `expandTools` gibi önceden ad alanlı kimlikleri kullanan daha eski yapılandırmalar, başlangıçta otomatik olarak ad alanlı kimliklere taşınır.\n\n`keybindings.json`'yi düzenledikten sonra, değişiklikleri oturumu yeniden başlatmadan uygulamak için pi'de `/reload` komutunu çalıştırın.\n\n## Anahtar Formatı\n\n`modifier+key` burada değiştiriciler `ctrl`, `shift`, `alt`, `super` (birleştirilebilir) ve tuşlar şunlardır:\n\n- **Harfler:** `a-z`\n- **Rakamlar:** `0-9`\n- **Özel tuşlar:** `escape`, `esc`, `enter`, `return`, `tab`, `space`, `backspace`, `delete`, `insert`, `clear`, `home`, `end`, `pageUp`, `pageDown`, `up`, `down`, `left`, `right`\n- **Fonksiyon tuşları:** `f1`-`f12`\n- **Semboller:** `` ` ``, `-`, `=`, `[`, `]`, `\\`, `;`, `'`, `,`, `.`, `/`, `!`, `@`, `#`, `$`, `%`, `^`, `&`, `*`, `(`, `)`, `_`, `+`, `|`, `~`, `{`, `}`, `:`, `<`, `>`, `?`\n\nDeğiştirici kombinasyonları: `ctrl+shift+x`, `alt+ctrl+x`, `ctrl+shift+alt+x`, `super+k`, `ctrl+super+k`, `ctrl+1`, vb.\n\n`super` bağlamalar, değiştiriciyi genellikle Kitty klavye protokolü aracılığıyla ayrı olarak rapor eden bir terminal gerektirir. Bu desteğin olmadığı terminallerde çalışmayabilirler.\n\n## Tüm Eylemler\n\n### TUI Düzenleyici İmleç Hareketi\n\n| Tuş bağlama kimliği | Varsayılan | Tanım |\n|--------|---------|-------------|\n| `tui.editor.cursorUp` | `up` | İmleci yukarı hareket ettirerek eski geçmişi en üstte tarayın |\n| `tui.editor.cursorDown` | `down` | İmleci aşağı taşıyın, altta daha yeni geçmişe göz atın |\n| `tui.editor.historyPrevious` | *(hiçbiri)* | Önceki bilgi istemi geçmişi girişini seçin |\n| `tui.editor.historyNext` | *(hiçbiri)* | Sonraki bilgi istemi geçmişi girişini seçin |\n| `tui.editor.cursorLeft` | `left`, `ctrl+b` | İmleci sola taşı |\n| `tui.editor.cursorRight` | `right`, `ctrl+f` | İmleci sağa taşı |\n| `tui.editor.cursorWordLeft` | `alt+left`, `ctrl+left`, `alt+b` | İmleç kelimesini sola taşı |\n| `tui.editor.cursorWordRight` | `alt+right`, `ctrl+right`, `alt+f` | İmleç kelimesini sağa taşı |\n| `tui.editor.cursorLineStart` | `home`, `ctrl+home`, `ctrl+a` | Satır başlangıcına git |\n| `tui.editor.cursorLineEnd` | `end`, `ctrl+end`, `ctrl+e` | Satır sonuna git |\n| `tui.editor.jumpForward` | `ctrl+]` | Karaktere ileri atla |\n| `tui.editor.jumpBackward` | `ctrl+alt+]` | Karaktere geri git |\n| `tui.editor.pageUp` | `pageUp`, `ctrl+pageUp` | Sayfaya göre yukarı kaydır |\n| `tui.editor.pageDown` | `pageDown`, `ctrl+pageDown` | Sayfaya göre aşağı kaydır |\n\nÖzel geçmiş eylemleri, çok satırlı bir istemdeki imleç konumundan bağımsız olarak her zaman geçmiş girişlerini değiştirir. Açık geçmiş bağlamaları, ana düzenleyici odaklandığında uygulama eylemlerine göre önceliklidir, dolayısıyla `tui.editor.historyPrevious`'den `ctrl+p`'ye bağlama, seçicilerdeki `Ctrl+P`'yi değiştirmeden bu bağlamda model döngüsünü geçersiz kılar.\n\n### TUI Düzenleyici Silme\n\n| Tuş bağlama kimliği | Varsayılan | Tanım |\n|--------|---------|-------------|\n| `tui.editor.deleteCharBackward` | `backspace` | Karakteri geriye doğru sil |\n| `tui.editor.deleteCharForward` | `delete`, `ctrl+d` | İleriye doğru karakteri sil |\n| `tui.editor.deleteWordBackward` | `ctrl+w`, `alt+backspace` | Kelimeyi geriye doğru sil |\n| `tui.editor.deleteWordForward` | `alt+d`, `alt+delete` | İleriye doğru kelimeyi sil |\n| `tui.editor.deleteToLineStart` | `ctrl+u` | Satır başına kadar sil |\n| `tui.editor.deleteToLineEnd` | `ctrl+k` | Satır sonuna kadar sil |\n\n### TUI Giriş\n\n| Tuş bağlama kimliği | Varsayılan | Tanım |\n|--------|---------|-------------|\n| `tui.input.newLine` | `shift+enter`, `ctrl+j` | Yeni satır ekle |\n| `tui.input.submit` | `enter` | Girişi gönder |\n| `tui.input.tab` | `tab` | Sekme / otomatik tamamlama |\n\n### TUI Yüzüğü Öldür\n\n| Tuş bağlama kimliği | Varsayılan | Tanım |\n|--------|---------|-------------|\n| `tui.editor.yank` | `ctrl+y` | En son silinen metni yapıştır |\n| `tui.editor.yankPop` | `alt+y` | Çekildikten sonra silinen metin arasında geçiş yap |\n| `tui.editor.undo` | `ctrl+-` | Son düzenlemeyi geri al |\n\n### TUI Pano ve Seçim\n\n| Tuş bağlama kimliği | Varsayılan | Tanım |\n|--------|---------|-------------|\n| `tui.input.copy` | `ctrl+c` | Seçimi kopyala |\n| `tui.select.up` | `up` | Seçimi yukarı taşı |\n| `tui.select.down` | `down` | Seçimi aşağı taşı |\n| `tui.select.pageUp` | `pageUp` | Listede sayfa yukarı |\n| `tui.select.pageDown` | `pageDown` | Listede sayfa aşağı |\n| `tui.select.confirm` | `enter` | Seçimi onayla |\n| `tui.select.cancel` | `escape`, `ctrl+c` | Seçimi iptal et |\n\n### TUI Tam Ekran Görünümü\n\nBu eylemler, etkileşimli mod `--tui-mode fullscreen` kullandığında ve birincil transkript kaydırma bölgesini hedeflediğinde geçerlidir. İki parmakla izleme dörtgeni ve fare tekerleği girişi, işaretçinin altındaki bölgeyi kaydırarak sabit düzenleyici/durum/altbilgi paneli üzerinden metne geri döner. Bir OSC 8 köprüsüne tıklamak onu varsayılan işleyicide açar. Birincil fare düğmesiyle sürüklemek metni seçer ve panoya kopyalar; Transkriptin üst veya alt kenarında tutmak otomatik olarak ekran dışı içeriğe kaydırılır.\n\nTam ekran transkript bağlamaları, düzenleyici bağlamalarına göre önceliklidir. Varsayılan değiştirilmemiş gezinme tuşları bu nedenle transkripti tam ekran modunda kontrol ederken, `ctrl` varyantları düzenleyiciyi kontrol etmeye devam eder. Tam ekran modunun dışında, her iki değişken de düzenleyiciyi kontrol eder.\n\n| Anahtar | Varsayılan mod | Tam ekran modu |\n|-----|--------------|-----------------|\n| `home`, `end` | Editör | Deşifre metni |\n| `ctrl+home`, `ctrl+end` | Editör | Editör |\n| `pageUp`, `pageDown` | Editör | Deşifre metni |\n| `ctrl+pageUp`, `ctrl+pageDown` | Editör | Editör |\n\nBu yönlendirme, sıradan eylem bağlamaları aracılığıyla yapılandırılabilir durumda kalır. Örneğin, `\"tui.altScreen.pageUp\": \"ctrl+pageUp\"`, `pageUp`'nin düzenleyiciyi kontrol etmesini ve `ctrl+pageUp`'nin tam ekran modunda metni kontrol etmesini sağlar. Tam sayfa ciltlemelerini korurken daha küçük transkript adımları için `tui.altScreen.halfPageUp` ve `tui.altScreen.halfPageDown` ciltlemelerini yapın. `\"tui.altScreen.pageUp\": []` ayarı bu transkript kısayolunu tamamen devre dışı bırakır. Kullanıcı bağlamaları bu eyleme ilişkin varsayılanların yerini alır.\n\n| Tuş bağlama kimliği | Varsayılan | Tanım |\n|--------|---------|-------------|\n| `tui.altScreen.pageUp` | `pageUp` | Transkripti bir sayfa yukarı kaydır |\n| `tui.altScreen.pageDown` | `pageDown` | Transkripti bir sayfa aşağı kaydır |\n| `tui.altScreen.halfPageUp` | *(hiçbiri)* | Transkripti yarım sayfa yukarı kaydır |\n| `tui.altScreen.halfPageDown` | *(hiçbiri)* | Transkripti yarım sayfa aşağı kaydır |\n| `tui.altScreen.previousPrompt` | `ctrl+shift+up` | Önceki işaretli mesaja atla |\n| `tui.altScreen.nextPrompt` | `ctrl+shift+down` | Sonraki işaretli mesaja atla |\n| `tui.altScreen.top` | `home` | Transkriptin başlangıcına ilerleyin |\n| `tui.altScreen.bottom` | `end` | Transkriptin sonuna doğru kaydırın ve yeni çıktıyı takip edin |\n\n### Başvuru\n\n| Tuş bağlama kimliği | Varsayılan | Tanım |\n|--------|---------|-------------|\n| `app.interrupt` | `escape` | İptal et / iptal et |\n| `app.clear` | `ctrl+c` | Düzenleyiciyi temizle (birinci) / çıkış (ikinci) |\n| `app.exit` | `ctrl+d` | Çıkış (düzenleyici boş olduğunda) |\n| `app.suspend` | `ctrl+z` (Windows'ta yok) | Arka planda askıya al |\n| `app.editor.external` | `ctrl+g` | Harici düzenleyicide açın (`externalEditor`, `$VISUAL`, `$EDITOR`, Windows'ta Not Defteri veya başka bir yerde `nano`) |\n| `app.clipboard.pasteImage` | `ctrl+v` (Windows'ta `alt+v`) | Panodan resim veya metin yapıştırın |\n\n### Oturumlar\n\n| Tuş bağlama kimliği | Varsayılan | Tanım |\n|--------|---------|-------------|\n| `app.session.new` | *(hiçbiri)* | Yeni bir oturum başlat (`/new`) |\n| `app.session.tree` | *(hiçbiri)* | session tree gezginini aç (`/tree`) |\n| `app.session.fork` | *(hiçbiri)* | Mevcut oturumu çatalla (`/fork`) |\n| `app.session.resume` | *(hiçbiri)* | Açık oturum devam etme seçicisi (`/resume`) |\n| `app.session.togglePath` | `ctrl+p` | Yol görünümünü değiştir |\n| `app.session.toggleSort` | `ctrl+s` | Sıralama modunu değiştir |\n| `app.session.toggleNamedFilter` | `ctrl+n` | Yalnızca adlandırılmış filtreyi aç/kapat |\n| `app.session.rename` | `ctrl+r` | Oturumu yeniden adlandır |\n| `app.session.delete` | `ctrl+d` | Oturumu sil |\n| `app.session.deleteNoninvasive` | `ctrl+backspace` | Sorgu boş olduğunda oturumu sil |\n\n### Models ve Düşünme\n\n| Tuş bağlama kimliği | Varsayılan | Tanım |\n|--------|---------|-------------|\n| `app.model.select` | `ctrl+l` | Model seçiciyi aç |\n| `app.model.cycleForward` | `ctrl+p` | Sonraki modele geç |\n| `app.model.cycleBackward` | `shift+ctrl+p` | Önceki modele geç |\n| `app.thinking.cycle` | `shift+tab` | Döngüsel düşünme düzeyi |\n| `app.thinking.toggle` | `ctrl+t` | Düşünme bloklarını daraltın veya genişletin |\n\n### Görüntüleme ve Mesaj Sırası\n\n| Tuş bağlama kimliği | Varsayılan | Tanım |\n|--------|---------|-------------|\n| `app.tools.expand` | `ctrl+o` | Araç çıktısını daraltın veya genişletin |\n| `app.message.copy` | `ctrl+x` | Son asistan mesajını veya seçilen mesajı `/tree`'ye kopyalayın |\n| `app.message.followUp` | `alt+enter` | Kuyruk takip mesajı |\n| `app.message.dequeue` | `alt+up` | Sıraya alınmış mesajları düzenleyiciye geri yükleyin |\n\n### Ağaçta Gezinme\n\n| Tuş bağlama kimliği | Varsayılan | Tanım |\n|--------|---------|-------------|\n| `app.tree.foldOrUp` | `ctrl+left`, `alt+left` | Geçerli dal bölümünü katla veya önceki bölüm başlangıcına atla |\n| `app.tree.unfoldOrDown` | `ctrl+right`, `alt+right` | Geçerli dal segmentini açın veya sonraki segment başlangıcına veya dal sonuna atlayın |\n| `app.tree.editLabel` | `shift+l` | Seçilen ağaç düğümündeki etiketi düzenleyin |\n| `app.tree.toggleLabelTimestamp` | `shift+t` | Ağaçtaki etiket zaman damgalarını değiştir |\n| `app.tree.filter.default` | `ctrl+d` | Ağaç filtresini varsayılan görünüme ayarla |\n| `app.tree.filter.noTools` | `ctrl+t` | Araç sonuçlarını gizleyen ağaç filtresini açın/kapatın |\n| `app.tree.filter.userOnly` | `ctrl+u` | Yalnızca kullanıcı mesajlarını gösteren ağaç filtresini açın/kapatın |\n| `app.tree.filter.labeledOnly` | `ctrl+l` | Yalnızca etiketli girişleri gösteren ağaç filtresini aç/kapa |\n| `app.tree.filter.all` | `ctrl+a` | Tüm girişleri gösteren ağaç filtresini değiştir |\n| `app.tree.filter.cycleForward` | `ctrl+o` | Ağaç filtresini ileriye doğru döndür |\n| `app.tree.filter.cycleBackward` | `shift+ctrl+o` | Ağaç filtresini geriye doğru döndür |\n\n### Kapsamlı Models Seçici\n\nKapsamlı modeller seçicinin içinde kullanılır (`/scoped-models` ile açılır).\n\n| Tuş bağlama kimliği | Varsayılan | Tanım |\n|--------|---------|-------------|\n| `app.models.save` | `ctrl+s` | Mevcut model seçimini ayarlara kaydet |\n| `app.models.enableAll` | `ctrl+a` | Tüm modelleri (veya mevcut aramayla eşleşen tüm modelleri) etkinleştirin |\n| `app.models.clearAll` | `ctrl+x` | Tüm modelleri (veya mevcut aramayla eşleşen tüm modelleri) temizle |\n| `app.models.toggleProvider` | `ctrl+p` | Mevcut sağlayıcı için tüm modelleri değiştir |\n| `app.models.reorderUp` | `alt+up` | Seçilen modeli döngü sırasında yukarı taşı |\n| `app.models.reorderDown` | `alt+down` | Seçilen modeli döngü sırasında aşağı taşı |\n\n## Özel Yapılandırma\n\n`~/.pi/agent/keybindings.json` oluştur:\n\n```json\n{\n  \"tui.editor.historyPrevious\": \"ctrl+p\",\n  \"tui.editor.historyNext\": \"ctrl+n\",\n  \"tui.editor.deleteWordBackward\": [\"ctrl+w\", \"alt+backspace\"]\n}\n```\n\nHer eylemin tek bir tuşu veya bir dizi tuşu olabilir. Kullanıcı yapılandırması varsayılanları geçersiz kılar.\n\nYerel Windows'ta, Windows terminalleri Unix iş kontrolünü desteklemediğinden `app.suspend`'nin varsayılan bağlaması yoktur. Eğer manuel olarak bağlarsanız pi, askıya almak yerine bir durum mesajı gösterir. WSL'de normal Linux `ctrl+z`/`fg` davranışı hâlâ geçerlidir.\n\n### Emacs Örneği\n\n```json\n{\n  \"tui.editor.historyPrevious\": \"ctrl+p\",\n  \"tui.editor.historyNext\": \"ctrl+n\",\n  \"tui.editor.cursorLeft\": [\"left\", \"ctrl+b\"],\n  \"tui.editor.cursorRight\": [\"right\", \"ctrl+f\"],\n  \"tui.editor.cursorWordLeft\": [\"alt+left\", \"alt+b\"],\n  \"tui.editor.cursorWordRight\": [\"alt+right\", \"alt+f\"],\n  \"tui.editor.deleteCharForward\": [\"delete\", \"ctrl+d\"],\n  \"tui.editor.deleteCharBackward\": [\"backspace\", \"ctrl+h\"],\n  \"tui.input.newLine\": [\"shift+enter\", \"ctrl+j\"]\n}\n```\n\n### Vim Örneği\n\n```json\n{\n  \"tui.editor.cursorUp\": [\"up\", \"alt+k\"],\n  \"tui.editor.cursorDown\": [\"down\", \"alt+j\"],\n  \"tui.editor.cursorLeft\": [\"left\", \"alt+h\"],\n  \"tui.editor.cursorRight\": [\"right\", \"alt+l\"],\n  \"tui.editor.cursorWordLeft\": [\"alt+left\", \"alt+b\"],\n  \"tui.editor.cursorWordRight\": [\"alt+right\", \"alt+w\"]\n}\n```","sourceFile":"keybindings.md"},"llama-cpp":{"title":"llama.cpp","markdown":"Pi, [llama.cpp](https://github.com/ggml-org/llama.cpp) yönlendirici sunucusunu destekler. Yönlendirici birden fazla GGUF modeli keşfeder ve bunları isteğe bağlı olarak yükler veya kaldırır.\n\nYönlendirici desteğine sahip güncel bir llama.cpp yapı kullanın. [build instructions](https://github.com/ggml-org/llama.cpp/blob/master/docs/build.md)'yi takip edin veya platformunuz için bir [prebuilt release](https://github.com/ggml-org/llama.cpp/releases) yükleyin.\n\n## Yönlendiriciyi başlat\n\n`llama-server`'yi `--model` veya `-m` olmadan başlatın. Bir modelin iletilmesi, yönlendirici modu yerine tek model modunu başlatır.\n\n```bash\nllama-server \\\n  --models-dir ~/models \\\n  --no-models-autoload \\\n  --jinja \\\n  --host 127.0.0.1 \\\n  --port 8080 \\\n  -ngl 999 \\\n  -c 32768\n```\n\nÖnemli seçenekler:\n\n- `--models-dir ~/models` yerel GGUF dosyalarını keşfeder.\n- `--no-models-autoload` `/llama` aracılığıyla açık bir şekilde yüklenmeye devam ediyor.\n- `--jinja` uyumlu sohbet şablonlarını ve araç aramayı etkinleştirir.\n- `-ngl 999` GPU'ya mümkün olduğu kadar çok katmanı aktarır.\n- `-c 32768` yüklü her model için bağlam penceresini ayarlar. Önemli ölçüde daha fazla bellek gerektirebilecek modelin yerel bağlamını kullanmak için bunu atlayın.\n\nTek dosyalı bir model doğrudan model dizininde bulunabilir. Çok modlu ve çok parçalı modelleri ayrı alt dizinlere yerleştirin:\n\n```text\n~/models/\n├── llama-3.2-1b-Q4_K_M.gguf\n├── gemma-3-4b-it-Q4_K_M/\n│   ├── gemma-3-4b-it-Q4_K_M.gguf\n│   └── mmproj-F16.gguf\n└── large-model-Q4_K_M/\n    ├── large-model-Q4_K_M-00001-of-00003.gguf\n    ├── large-model-Q4_K_M-00002-of-00003.gguf\n    └── large-model-Q4_K_M-00003-of-00003.gguf\n```\n\nDosyaları manuel olarak ekledikten sonra yönlendiriciyi yeniden başlatın. Model başına bağlam boyutları ve diğer seçenekler için [llama.cpp model presets](https://github.com/ggml-org/llama.cpp/blob/master/tools/server/README.md#model-presets) kullanın.\n\n## Yapılandır Pi\n\nPi uygulamasını başlatın ve sağlayıcıyı yapılandırın:\n\n```text\n/login llama.cpp\n```\n\nYönlendiricinin URL'sini ve isteğe bağlı olarak API key girin. Varsayılan URL `http://127.0.0.1:8080`'dir.\n\nOrtam değişkenleri aynı değerleri `/login` olmadan yapılandırabilir:\n\n```bash\nexport LLAMA_BASE_URL=http://127.0.0.1:8080\nexport LLAMA_API_KEY=optional-secret\npi\n```\n\nSunucu API key kullanıyorsa, `llama-server`'yi eşleşen `--api-key` değeriyle başlatın. Yalnızca yerel erişim için `--host 127.0.0.1`'yi saklayın.\n\n## Modelleri yönet\n\nKoşmak:\n\n```text\n/llama\n```\n\n- Yüklemek için yüklenmemiş bir model seçin.\n- Kaldırmak için yüklü bir modeli seçin.\n- **Modeli indir…**'i seçin, Hugging Face'yi arayın, ardından bir depo ve niceleme seçin. Tam `owner/repository[:quant]` değerleri de işe yarar.\n- İptal işlemini onaylamak için yükleme veya indirme sırasında Escape tuşuna basın.\n\nHugging Face arama, ayarlandığında `HF_TOKEN`'yi kullanır, ardından `$HF_TOKEN_PATH`, `$HF_HOME/token`, `$XDG_CACHE_HOME/huggingface/token` ve `~/.cache/huggingface/token`'yi kontrol eder. Arama, daha düşük hız sınırlarına tabi olarak kimlik doğrulaması olmadan da çalışır. Pi kapılı depoları indirmeden önce uyarır ve erişim sayfalarına bağlantılar verir. İndirmeyi llama.cpp sunucusu gerçekleştirir, bu nedenle seçilen depo erişim gerektirdiğinde işleminde de `HF_TOKEN` bulunmalıdır.\n\nBaşka modeller yüklüyse Pi önce bunları mı boşaltacağınızı yoksa yüklü halde mi tutacağınızı sorar. Pi modelleri sessizce boşaltmaz ve model dosyalarını asla silmez. Yönlendirici diğer istemcilerle paylaşılabilir, dolayısıyla `/llama` her zaman yönlendiricinin mevcut durumunu görüntüler.\n\n`/model`'de yalnızca yüklü modeller görünür. Bir modeli yükledikten sonra, geçerli Pi oturumu için seçmek üzere `/model` komutunu çalıştırın.\n\nYönlendiricinin bağlantısı kesilirse `/llama`, **Yeniden Dene** ve **Kapat**'ı gösterir. Yeniden dene, kesintiye uğrayan işlemi tekrar yürütmeden model durumunu yeniden bağlar ve yeniler.\n\n## Sorun giderme\n\nYönlendiricinin erişilebilir olup olmadığını kontrol edin:\n\n```bash\ncurl http://127.0.0.1:8080/health\ncurl http://127.0.0.1:8080/models\n```\n\n- **`/llama`'da model yok:** `--models-dir` dizin düzenini kontrol edin ve yönlendiriciyi yeniden başlatın.\n- **`/model` modelinde eksik:** Önce `/llama` ile yükleyin.\n- **Yükleme başarısız oluyor veya çok fazla bellek kullanıyor:** `-c` değerini düşürün veya başka bir modeli kaldırın.\n- **Sunucu yönlendirici modunda değil:** `--model`, `-m` veya `-hf` olmadan başlatın.","sourceFile":"llama-cpp.md"},"models":{"title":"Özel Models","markdown":"`~/.pi/agent/models.json` aracılığıyla özel sağlayıcılar ve modeller (Ollama, vLLM, LM Studio, proxy'ler) ekleyin.\n\n## İçindekiler\n\n- [Minimal Example](#minimal-example)\n- [Full Example](#full-example)\n- [Supported APIs](#supported-apis)\n- [Provider Configuration](#provider-configuration)\n- [Model Configuration](#model-configuration)\n- [Overriding Built-in Providers](#overriding-built-in-providers)\n- [Per-model Overrides](#per-model-overrides)\n- [Anthropic Messages Compatibility](#anthropic-messages-compatibility)\n- [OpenAI Compatibility](#openai-compatibility)\n\n## Asgari Örnek\n\nYerel modeller için (Ollama, LM Studio, vLLM), model başına yalnızca `id` gereklidir:\n\n```json\n{\n  \"providers\": {\n    \"ollama\": {\n      \"baseUrl\": \"http://localhost:11434/v1\",\n      \"api\": \"openai-completions\",\n      \"apiKey\": \"ollama\",\n      \"models\": [\n        { \"id\": \"llama3.1:8b\" },\n        { \"id\": \"qwen2.5-coder:7b\" }\n      ]\n    }\n  }\n}\n```\n\n`apiKey` değeri bir yer tutucudur çünkü Ollama onu yok sayar. pi hala modelleri `/model`'de görünmeden önce kimlik doğrulama gerektiriyormuş gibi ele alır, bu nedenle anahtarsız yerel sunucular sahte bir değer tutmalı, `/login` ile o sağlayıcı için bir anahtar kaydetmeli veya modeli seçerken `--api-key`'yi geçmelidir.\n\nBazı OpenAI uyumlu sunucular, muhakeme yeteneğine sahip modeller için kullanılan `developer` rolünü anlamıyor. Bu sağlayıcılar için `compat.supportsDeveloperRole`'yi `false` olarak ayarlayın, böylece pi sistem istemini bunun yerine `system` mesajı olarak gönderir. Sunucu ayrıca `reasoning_effort`'yi desteklemiyorsa, `compat.supportsReasoningEffort`'yi de `false` olarak ayarlayın.\n\nTüm modellere uygulamak için sağlayıcı düzeyinde `compat` ayarını yapabilir veya belirli bir modeli geçersiz kılmak için model düzeyinde ayarlayabilirsiniz. Bu genellikle Ollama, vLLM, SGLang ve benzeri OpenAI uyumlu sunucular için geçerlidir.\n\n```json\n{\n  \"providers\": {\n    \"ollama\": {\n      \"baseUrl\": \"http://localhost:11434/v1\",\n      \"api\": \"openai-completions\",\n      \"apiKey\": \"ollama\",\n      \"compat\": {\n        \"supportsDeveloperRole\": false,\n        \"supportsReasoningEffort\": false\n      },\n      \"models\": [\n        {\n          \"id\": \"gpt-oss:20b\",\n          \"reasoning\": true\n        }\n      ]\n    }\n  }\n}\n```\n\n## Tam Örnek\n\nBelirli değerlere ihtiyaç duyduğunuzda varsayılanları geçersiz kılın:\n\n```json\n{\n  \"providers\": {\n    \"ollama\": {\n      \"baseUrl\": \"http://localhost:11434/v1\",\n      \"api\": \"openai-completions\",\n      \"apiKey\": \"ollama\",\n      \"models\": [\n        {\n          \"id\": \"llama3.1:8b\",\n          \"name\": \"Llama 3.1 8B (Local)\",\n          \"reasoning\": false,\n          \"input\": [\"text\"],\n          \"contextWindow\": 128000,\n          \"maxTokens\": 32000,\n          \"cost\": { \"input\": 0, \"output\": 0, \"cacheRead\": 0, \"cacheWrite\": 0 }\n        }\n      ]\n    }\n  }\n}\n```\n\n`/model` her açtığınızda dosya yeniden yüklenir. Oturum sırasında düzenleme; yeniden başlatmaya gerek yok.\n\n## Google AI Studio Örneği\n\nÖzel Gemma 4 girişleri de dahil olmak üzere Google AI Studio'dan modeller eklemek için `google-generative-ai` ile `baseUrl` kullanın:\n\n```json\n{\n  \"providers\": {\n    \"my-google\": {\n      \"baseUrl\": \"https://generativelanguage.googleapis.com/v1beta\",\n      \"api\": \"google-generative-ai\",\n      \"apiKey\": \"$GEMINI_API_KEY\",\n      \"models\": [\n        {\n          \"id\": \"gemma-4-31b-it\",\n          \"name\": \"Gemma 4 31B\",\n          \"input\": [\"text\", \"image\"],\n          \"contextWindow\": 262144,\n          \"reasoning\": true\n        }\n      ]\n    }\n  }\n}\n```\n\n`google-generative-ai` API türüne özel modeller eklerken `baseUrl` gereklidir.\n\n## Desteklenen APIs\n\n| API | Tanım |\n|-----|-------------|\n| `openai-completions` | OpenAI Sohbet Tamamlamaları (en uyumlu) |\n| `openai-responses` | OpenAI Yanıtları API |\n| `anthropic-messages` | Antropik Mesajlar API |\n| `google-generative-ai` | Google Üretken Yapay Zeka |\n\nSağlayıcı düzeyinde (tüm modeller için varsayılan) veya model düzeyinde (model başına geçersiz kılma) `api` öğesini ayarlayın.\n\n## Sağlayıcı Yapılandırması\n\n| Alan | Tanım |\n|-------|-------------|\n| `baseUrl` | API uç nokta URL'si |\n| `api` | API türü (yukarıya bakın) |\n| `apiKey` | İsteğe bağlı API key yapılandırması (aşağıdaki değer çözünürlüğüne bakın). Kimlik doğrulama `/login`/`auth.json` veya CLI `--api-key` tarafından sağlandığında bunu atlayın. |\n| `oauth` | Dinamik OAuth sağlayıcı türü. Şu anda `\"radius\"`'yi destekliyor; ağ geçidini gerektirir `baseUrl`. |\n| `headers` | Özel başlıklar (aşağıdaki değer çözünürlüğüne bakın) |\n| `authHeader` | `Authorization: Bearer <apiKey>`'yi otomatik olarak eklemek için `true`'yi ayarlayın |\n| `models` | Model konfigürasyonları dizisi |\n| `modelOverrides` | Bu sağlayıcıdaki yerleşik veya uzantıya kayıtlı modeller için model başına geçersiz kılmalar |\n\n`models` değerine sahip sağlayıcılar için, yerleşik olmayan sağlayıcı yapılandırmalarının, sağlayıcı veya model düzeyinde `baseUrl` ve bir `api` değeri olması gerekir. Dosyayı yüklemek için `apiKey` gerekli değildir: kimlik doğrulama `/login`/`auth.json`, CLI `--api-key` veya sağlayıcı `apiKey` aracılığıyla yapılandırıldığında modeller kullanılabilir hale gelir. Hiçbir kimlik doğrulaması yapılandırılmamışsa modeller yüklenir ancak `/model` ve `--list-models`'de kullanılamaz durumda kalır.\n\n### Değer Çözünürlüğü\n\n`apiKey` ve `headers` alanları komut yürütmeyi, ortam enterpolasyonunu ve değişmez değerleri destekler:\n\n- **Kabuk komutu:** `\"!command\"` başlangıçta değerin tamamını komut olarak yürütür ve stdout'yi kullanır\n  ```json\n  \"apiKey\": \"!security find-generic-password -ws 'anthropic'\"\n  \"apiKey\": \"!op read 'op://vault/item/credential'\"\n  ```\n- **Ortam enterpolasyonu:** `\"$ENV_VAR\"` veya `\"${ENV_VAR}\"`, adlandırılmış değişkenin değerini kullanır. Enterpolasyon daha büyük değişmezlerin içinde çalışır.\n  ```json\n  \"apiKey\": \"$MY_API_KEY\"\n  \"apiKey\": \"${KEY_PREFIX}_${KEY_SUFFIX}\"\n  ```\n  `$FOO_BAR`, `FOO_BAR` değişkenidir; `BAR` gerçek metin olduğunda `${FOO}_BAR` kullanın. Eksik ortam değişkenleri değeri çözümsüz hale getirir.\n- **Kaçışlar:** `\"$\"` gerçek bir `\"$\"` yayar; `\"$!\"`, komut yürütmeyi tetiklemeden değişmez bir `\"!\"` yayar.\n  ```json\n  \"apiKey\": \"$$literal-dollar-prefix\"\n  \"apiKey\": \"$!literal-bang-prefix\"\n  ```\n- **Gerçek değer:** Doğrudan kullanılır. `MY_API_KEY` gibi düz büyük harf dizeleri değişmez değerlerdir; ortam değişkenleri için `$MY_API_KEY` kullanın.\n  ```json\n  \"apiKey\": \"sk-...\"\n  ```\n\n`models.json` için kabuk komutları istek zamanında çözümlenir. pi, rastgele komutlar için kasıtlı olarak yerleşik TTL, eski yeniden kullanım veya kurtarma mantığını uygulamaz. Farklı komutlar, farklı önbelleğe alma ve hata stratejilerine ihtiyaç duyar ve pi, doğru olanı çıkaramaz.\n\nKomutunuz yavaşsa, pahalıysa, hız sınırlıysa veya geçici arızalarda önceki bir değeri kullanmaya devam etmesi gerekiyorsa, onu istediğiniz önbelleğe alma veya TTL davranışını uygulayan kendi komut dosyanıza veya komutunuza sarın.\n\n`/model` kullanılabilirlik kontrolleri yapılandırılmış kimlik doğrulama varlığını kullanır ve kabuk komutlarını yürütmez.\n\n### Özel Başlıklar\n\n```json\n{\n  \"providers\": {\n    \"custom-proxy\": {\n      \"baseUrl\": \"https://proxy.example.com/v1\",\n      \"apiKey\": \"$MY_API_KEY\",\n      \"api\": \"anthropic-messages\",\n      \"headers\": {\n        \"x-portkey-api-key\": \"$PORTKEY_API_KEY\",\n        \"x-secret\": \"!op read 'op://vault/item/secret'\"\n      },\n      \"models\": [...]\n    }\n  }\n}\n```\n\n## Model Yapılandırması\n\n| Alan | Gerekli | Varsayılan | Tanım |\n|-------|----------|---------|-------------|\n| `id` | Evet | — | Model tanımlayıcı (API'ye aktarıldı) |\n| `name` | HAYIR | `id` | İnsan tarafından okunabilen model etiketi. (`--model` desenleri) eşleştirmek için kullanılır ve ikincil model detay metni olarak gösterilir. |\n| `api` | HAYIR | sağlayıcının `api` | Bu model için sağlayıcının API değerini geçersiz kıl |\n| `reasoning` | HAYIR | `false` | Genişletilmiş düşünmeyi destekler |\n| `thinkingLevelMap` | HAYIR | atlanmış | Pi düşünme düzeylerini sağlayıcı değerleriyle eşler ve desteklenmeyen düzeyleri işaretler (aşağıya bakın) |\n| `input` | HAYIR | `[\"text\"]` | Giriş türleri: `[\"text\"]` veya `[\"text\", \"image\"]` |\n| `contextWindow` | HAYIR | `128000` | Belirteçlerdeki bağlam penceresi boyutu |\n| `maxTokens` | HAYIR | `16384` | Maksimum çıkış jetonları |\n| `samplingParams` | HAYIR | atlanmış | Örnekleme parametreleri her istek gövdesinde kelimesi kelimesine birleştirildi (aşağıya bakın) |\n| `cost` | HAYIR | hepsi sıfır | İsteğe bağlı istek çapında girdi fiyatlandırma katmanlarıyla milyon başına jeton oranları |\n| `compat` | HAYIR | sağlayıcı `compat` | Sağlayıcı uyumluluğu geçersiz kılınır. Her ikisi de ayarlandığında sağlayıcı düzeyi `compat` ile birleştirilir. |\n\nMaliyet katmanı tam bir alternatif ücret seti sağlar ve toplam girdi kullanımı (`input + cacheRead + cacheWrite`) `inputTokensAbove`'yi aştığında tam isteğe uygulanır. Birden fazla aşama eşleştiğinde en yüksek eşik kazanır.\n\n```json\n{\n  \"cost\": {\n    \"input\": 5,\n    \"output\": 30,\n    \"cacheRead\": 0.5,\n    \"cacheWrite\": 6.25,\n    \"tiers\": [\n      {\n        \"inputTokensAbove\": 272000,\n        \"input\": 10,\n        \"output\": 45,\n        \"cacheRead\": 1,\n        \"cacheWrite\": 12.5\n      }\n    ]\n  }\n}\n```\n\nMevcut davranış:\n- `/model`, `--list-models` ve modele göre etkileşimli altbilgi ekranı girişleri `id`.\n- Yapılandırılmış `name`, model eşleştirme ve ikincil model detay metni için kullanılır. Altbilgi/durum çubuğu model kimliğinin yerini almaz.\n\n### Örnekleme Parametreleri\n\n`samplingParams`, pi alanları kendini ayarladıktan sonra modelin her istek gövdesiyle kelimesi kelimesine birleştirilen serbest biçimli bir nesnedir, böylece anahtarları kazanır. Pi'nin modellemediği örnekleme parametrelerini göndermek için bunu kullanın — llama.cpp'nin `min_p` veya vLLM'nin `top_k`'si gibi sunucuya özgü olanlar dahil:\n\n```json\n{\n  \"id\": \"deepseek-v4-flash\",\n  \"samplingParams\": {\n    \"temperature\": 1.0,\n    \"top_p\": 0.95,\n    \"top_k\": 0,\n    \"min_p\": 0.0\n  }\n}\n```\n\nYalnızca OpenAI uyumlu API'ler bunu uygular (`openai-completions`, `openai-responses`, `azure-openai-responses`); diğer API'ler bunu görmezden gelir. Anahtarlar pi'nin adlandırılmış istek alanlarını geçersiz kılar (örneğin, burada bir `temperature` anahtarı istek seviyesi sıcaklığını geçer), bu nedenle onu bir model için tek örnekleme doğruluğu kaynağı olarak tercih edin. `modelOverrides`'de, `samplingParams` anahtar başına temel modelin değeriyle birleşir.\n\n### Düşünme Seviyesi Haritası\n\nModele özgü düşünme kontrollerini tanımlamak için bir model üzerinde `thinkingLevelMap` kullanın. Anahtarlar pi düşünme seviyeleridir: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`. Haritalar delikler içerebilir; örneğin, bir model `xhigh`'yi göstermeden `high` ve `max`'yi ortaya çıkarabilir.\n\nDeğerler üç durumludur:\n\n| Değer | Anlam |\n|-------|---------|\n| atlanmış | `high` arasındaki standart düzeyler, sağlayıcının varsayılan eşlemesini kullanır; genişletilmiş `xhigh` ve `max` seviyeleri desteklenmez |\n| sicim | Seviye desteklenir ve bu değer sağlayıcıya gönderilir |\n| `null` | Seviye desteklenmiyor ve gizleniyor/atlanıyor/sabitleniyor |\n\nYalnızca kapalı, yüksek ve maksimum akıl yürütmeyi destekleyen bir model örneği:\n\n```json\n{\n  \"id\": \"deepseek-v4-pro\",\n  \"reasoning\": true,\n  \"thinkingLevelMap\": {\n    \"minimal\": null,\n    \"low\": null,\n    \"medium\": null,\n    \"high\": \"high\",\n    \"xhigh\": null,\n    \"max\": \"max\"\n  }\n}\n```\n\nDüşünmenin devre dışı bırakılamayacağı bir model örneği:\n\n```json\n{\n  \"id\": \"always-thinking-model\",\n  \"reasoning\": true,\n  \"thinkingLevelMap\": {\n    \"off\": null\n  }\n}\n```\n\nTaşıma: `compat.reasoningEffortMap` kullanan eski yapılandırmalar, bu eşlemeyi model düzeyi `thinkingLevelMap`'ye taşımalıdır. Kullanıcı arayüzünde görünmemesi gereken seviyeler için `null` tuşunu kullanın.\n\n## Yerleşik Providers Geçersiz Kılma\n\nYerleşik bir sağlayıcıyı, modelleri yeniden tanımlamadan bir proxy aracılığıyla yönlendirin:\n\n```json\n{\n  \"providers\": {\n    \"anthropic\": {\n      \"baseUrl\": \"https://my-proxy.example.com/v1\"\n    }\n  }\n}\n```\n\nTüm yerleşik Antropik modeller mevcut olmaya devam ediyor. Mevcut OAuth veya API key kimlik doğrulaması çalışmaya devam eder.\n\nÖzel modelleri yerleşik bir sağlayıcıda birleştirmek için `models` dizisini ekleyin:\n\n```json\n{\n  \"providers\": {\n    \"anthropic\": {\n      \"baseUrl\": \"https://my-proxy.example.com/v1\",\n      \"apiKey\": \"$ANTHROPIC_API_KEY\",\n      \"api\": \"anthropic-messages\",\n      \"models\": [...]\n    }\n  }\n}\n```\n\nAnlambilimi birleştirme:\n- Yerleşik modeller korunur.\n- Özel modeller sağlayıcı içinde `id` kadar yükseltilir.\n- Özel bir model `id` yerleşik bir modelle `id` eşleşirse, özel model bu yerleşik modelin yerini alır.\n- Özel bir model `id` yeniyse yerleşik modellerin yanına eklenir.\n\n## Model Başına Geçersiz Kılmalar\n\nSağlayıcının tam model listesini değiştirmeden yerleşik modelleri özelleştirmek ve uzantıya kayıtlı modelleri eşleştirmek için `modelOverrides` tuşunu kullanın.\n\n```json\n{\n  \"providers\": {\n    \"openrouter\": {\n      \"modelOverrides\": {\n        \"anthropic/claude-sonnet-4\": {\n          \"name\": \"Claude Sonnet 4 (Bedrock Route)\",\n          \"compat\": {\n            \"openRouterRouting\": {\n              \"only\": [\"amazon-bedrock\"]\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n`modelOverrides` model başına şu alanları destekler: `name`, `reasoning`, `thinkingLevelMap`, `input`, `cost` (kısmi), `contextWindow`, `maxTokens`, `samplingParams` (anahtar başına birleştirilmiş), `headers`, `compat`.\n\nDoğrudan OpenAI GPT-5.6 Sol, Terra ve Luna varsayılan olarak `272000` bağlam penceresine ayarlanır, böylece istekler OpenAI'nin kısa bağlam fiyatlandırma katmanında kalır. OpenAI'nin 1,05M bağlam penceresine dahil olmak için kullandığınız her modelde pencereyi artırın:\n\n```json\n{\n  \"providers\": {\n    \"openai\": {\n      \"modelOverrides\": {\n        \"gpt-5.6-sol\": {\n          \"contextWindow\": 1050000\n        }\n      }\n    }\n  }\n}\n```\n\nGeçersiz kılma, yerleşik fiyatlandırma meta verilerini korur. Toplam 272.000'den fazla giriş jetonu içeren istekler, isteğin tamamı için GPT-5.6'nın uzun bağlam hızlarını kullanır. Gerektiğinde aynı geçersiz kılmayı `gpt-5.6-terra` veya `gpt-5.6-luna`'ye uygulayın.\n\nDavranış notları:\n- `modelOverrides` yerleşik sağlayıcı modellerine ve eşleşen uzantıya kayıtlı sağlayıcı modellerine uygulanır.\n- Bilinmeyen model kimlikleri dikkate alınmaz.\n- Sağlayıcı düzeyindeki `baseUrl`/`headers`'yi `modelOverrides` ile birleştirebilirsiniz.\n- `name` geçersiz kılınması yalnızca model eşleşmesini ve ikincil ayrıntı metnini değiştirir; alt bilgi ve birincil model listeleri modeli `id` göstermeye devam ediyor.\n- Bir sağlayıcı için `models` da tanımlanmışsa özel modeller yerleşik geçersiz kılmalardan sonra birleştirilir. Aynı `id` değerine sahip özel bir model, geçersiz kılınan yerleşik model girişinin yerini alır.\n\n## Antropik Mesaj Uyumluluğu\n\n`api: \"anthropic-messages\"` kullanan sağlayıcılar veya proxy'ler için, Anthropic'e özgü istek uyumluluğunu kontrol etmek için `compat` kullanın.\n\nVarsayılan olarak pi, araç başına `eager_input_streaming: true` gönderir. Proxy veya Antropik uyumlu bir arka uç bu alanı reddederse `supportsEagerToolInputStreaming`'yi `false` olarak ayarlayın. Pi, `tools[].eager_input_streaming`'yi atlayacak ve bunun yerine araç özellikli istekler için eski `fine-grained-tool-streaming-2025-05-14` beta başlığını gönderecektir.\n\nBazı Antropik modeller, eski bütçeye dayalı düşünme yükü yerine uyarlanabilir düşünmeyi (`thinking.type: \"adaptive\"` artı `output_config.effort`) gerektirir. Yerleşik modeller bunu otomatik olarak ayarlar. Bu modellere yönlendiren özel sağlayıcılar veya takma adlar için `forceAdaptiveThinking`'yi `true` olarak ayarlayın.\n\nBazı Antropik uyumlu sağlayıcılar boş imzalara sahip düşünme blokları yayar ve bunların tekrar oynatılmasını bekler. Yalnızca bu sağlayıcılar için `allowEmptySignature`'ı `true` olarak ayarlayın; gerçek Antropik boş düşünce imzalarını reddeder.\n\nYerleşik Antropik modeller, model meta verilerinde `supportsStrictTools` özelliğini etkinleştirir. Özel Antropik uyumlu modeller, uç noktaları katı JSON şema aracı tanımlarını kabul ettiğinde bunu `true` olarak ayarlamalıdır.\n\n```json\n{\n  \"providers\": {\n    \"anthropic-proxy\": {\n      \"baseUrl\": \"https://proxy.example.com\",\n      \"api\": \"anthropic-messages\",\n      \"apiKey\": \"$ANTHROPIC_PROXY_KEY\",\n      \"compat\": {\n        \"supportsEagerToolInputStreaming\": false,\n        \"supportsLongCacheRetention\": true,\n        \"forceAdaptiveThinking\": true,\n        \"allowEmptySignature\": true\n      },\n      \"models\": [\n        {\n          \"id\": \"claude-opus-4-7\",\n          \"reasoning\": true,\n          \"input\": [\"text\", \"image\"]\n        }\n      ]\n    }\n  }\n}\n```\n\n| Alan | Tanım |\n|-------|-------------|\n| `supportsEagerToolInputStreaming` | Sağlayıcının araç başına `eager_input_streaming` kabul edip etmediği. Varsayılan: `true`. Bu alanı atlamak ve aracın etkin olduğu isteklerde eski ayrıntılı araç akışı beta başlığını kullanmak için `false` olarak ayarlayın. |\n| `supportsLongCacheRetention` | Önbellek tutma `long` olduğunda sağlayıcının Antropik uzun önbellek tutmayı (`cache_control.ttl: \"1h\"`) kabul edip etmediği. Varsayılan: `true`. |\n| `sendSessionAffinityHeaders` | Önbelleğe alma etkinleştirildiğinde oturum kimliğinden `x-session-affinity` gönderilip gönderilmeyeceği. Varsayılan: bilinen sağlayıcılar için otomatik olarak algılanır. |\n| `supportsCacheControlOnTools` | Sağlayıcının araç tanımlarında Antropik stil `cache_control` işaretleyicileri kabul edip etmediği. Varsayılan: `true`. |\n| `forceAdaptiveThinking` | Bu model için uyarlanabilir düşünmenin (`thinking.type: \"adaptive\"` artı `output_config.effort`) gönderilip gönderilmeyeceği. Yerleşik uyarlanabilir modeller bunu otomatik olarak ayarlar. Varsayılan: `false`. |\n| `allowEmptySignature` | Düşünceyi metne dönüştürmek yerine boş düşünme imzalarının `signature: \"\"` olarak yeniden oynatılıp oynatılmayacağı. Varsayılan: `false`. |\n| `supportsStrictTools` | Sağlayıcının katı JSON şema aracı tanımlarını kabul edip etmediği. Varsayılan: `false`; yerleşik Antropik modeller, oluşturulan meta verilerde bunu mümkün kılar. |\n\n## OpenAI Uyumluluğu\n\nKısmi OpenAI uyumluluğuna sahip sağlayıcılar için `compat` alanını kullanın.\n\n- Sağlayıcı düzeyi `compat`, varsayılanları o sağlayıcının altındaki tüm modellere uygular.\n- Model düzeyi `compat`, söz konusu model için sağlayıcı düzeyindeki değerleri geçersiz kılar.\n\n```json\n{\n  \"providers\": {\n    \"local-llm\": {\n      \"baseUrl\": \"http://localhost:8080/v1\",\n      \"api\": \"openai-completions\",\n      \"compat\": {\n        \"supportsUsageInStreaming\": false,\n        \"maxTokensField\": \"max_tokens\"\n      },\n      \"models\": [...]\n    }\n  }\n}\n```\n\n| Alan | Tanım |\n|-------|-------------|\n| `supportsStore` | Sağlayıcı `store` alanını destekliyor |\n| `supportsDeveloperRole` | `developer` ve `system` rolünü kullanın |\n| `supportsReasoningEffort` | `reasoning_effort` parametresi desteği |\n| `supportsUsageInStreaming` | `stream_options: { include_usage: true }`'yi destekler (varsayılan: `true`) |\n| `supportsFinishReason` | Akışlı yanıtların `finish_reason` içerip içermediği. `false` olduğunda pi, akış sona erdiğinde `stop` veya `toolUse` sonucunu çıkarır. Varsayılan: `true`. |\n| `maxTokensField` | `max_completion_tokens` veya `max_tokens` kullanın |\n| `requiresToolResultName` | Araç sonuç mesajlarına `name` ekleyin |\n| `requiresAssistantAfterToolResult` | Araç sonuçlarından sonra kullanıcı mesajının önüne bir asistan mesajı ekleyin |\n| `requiresThinkingAsText` | Düşünme bloklarını düz metne dönüştürün |\n| `requiresReasoningContentOnAssistantMessages` | Akıl yürütme etkinleştirildiğinde, tekrarlanan tüm asistan mesajlarına boş `reasoning_content` ekle |\n| `thinkingFormat` | `reasoning_effort`, `openrouter`, `deepseek`, `together`, `baseten`, `zai`, `qwen`, `chat-template` veya `qwen-chat-template` düşünme parametrelerini kullanın |\n| `chatTemplateKwargs` | `thinkingFormat: \"chat-template\"` için `chat_template_kwargs` değerleri; pi kontrollü düşünme değerleri için `{ \"$var\": \"thinking.enabled\" }` veya `{ \"$var\": \"thinking.effort\" }` kullanın |\n| `chatTemplateArgs` | `thinkingFormat: \"baseten\"` için `chat_template_args` değerleri; pi kontrollü düşünme değerleri için `{ \"$var\": \"thinking.enabled\" }` veya `{ \"$var\": \"thinking.effort\" }` kullanın |\n| `cacheControlFormat` | Sistem isteminde, son araç tanımında ve son kullanıcı, asistan veya araç sonucu metin içeriğinde Antropik stil `cache_control` işaretleyicileri kullanın. Şu anda yalnızca `anthropic` desteklenmektedir. |\n| `sendSessionAffinityHeaders` | `openai-completions` için, önbelleğe alma etkinleştirildiğinde oturum kimliğinden oturum benzeşimi başlıklarını gönderin. Varsayılan: `false`. |\n| `sessionAffinityFormat` | `openai-completions` ve `openai-responses` için, oturum benzeşimi başlık formatı: `openai` `session_id`/`x-client-request-id` gönderir (tamamlamalar ayrıca `x-session-affinity`), `openai-nosession` alt çizgi içeren `session_id` başlığını atlar, `openrouter` `x-session-id` gönderir. `prompt_cache_key` vücut parametresini etkilemez. Varsayılan: otomatik olarak algılandı. |\n| `supportsStrictMode` | Sağlayıcının katı JSON-şema işlev aracı tanımlarını kabul edip etmediği. Varsayılanlar API'ye bağlıdır; yerleşik OpenAI modelleri açık yetenek meta verileri taşır. |\n| `supportsOpenAIGrammarTools` | OpenAI uyumlu API'lerin özel Lark/regex dilbilgisi araçları yayınlayıp yayınlamadığı. `false` olduğunda dilbilgisi açısından kısıtlı araçlar normal işlevli araçlara geri döner. Varsayılan: `false`; yerleşik model kataloğu bunu OpenAI, OpenAI Codex, Azure OpenAI, GitHub Copilot, opencode ve Cloudflare AI Gateway'deki GPT-5+ modelleri için etkinleştirir. |\n| `deferredToolsMode` | Sağlayıcıya özel ertelenmiş araç serileştirmesini kullanın. Şu anda Kimi'nin OpenAI uyumlu Sohbet Tamamlama formatı için yalnızca `\"kimi\"` desteklenmektedir. |\n| `supportsLongCacheRetention` | Önbellek tutma `long` olduğunda sağlayıcının uzun önbellek tutmayı kabul edip etmeyeceği: OpenAI istemi önbelleğe alma için `prompt_cache_retention: \"24h\"` veya `cacheControlFormat` `anthropic` olduğunda `cache_control.ttl: \"1h\"`. Varsayılan: `true`. |\n| `openRouterRouting` | OpenRouter sağlayıcısının yönlendirme tercihleri. Bu nesne [OpenRouter API request](https://openrouter.ai/docs/guides/routing/provider-selection)'nin `provider` alanında olduğu gibi gönderilir. |\n| `vercelGatewayRouting` | Sağlayıcı seçimi için Vercel AI Ağ Geçidi yönlendirme yapılandırması (`only`, `order`) |\n\n`openrouter`, `reasoning: { effort }`'yi kullanır. `together`, `reasoning: { enabled }`'yi ve ayrıca `supportsReasoningEffort` etkinleştirildiğinde `reasoning_effort`'yi kullanır. `qwen` üst düzey `enable_thinking`'yi kullanır. `chat_template_kwargs.enable_thinking` ve `preserve_thinking` gerektiren yerel Qwen uyumlu sunucular için `qwen-chat-template` kullanın. Yapılandırılabilir `chat_template_kwargs` gerektiren vLLM/Hugging Face sohbet şablonları için `chat-template` kullanın; örneğin DeepSeek V3.x şablonları için `chatTemplateKwargs: { \"thinking\": { \"$var\": \"thinking.enabled\" } }`. `chat_template_args` aracılığıyla geçiş kontrollerini kullanıma sunan ve isteğe bağlı olarak üst düzey `reasoning_effort`'yi destekleyen sağlayıcılar için `thinkingFormat: \"baseten\"` ile `chatTemplateArgs` kullanın.\n\n`cacheControlFormat: \"anthropic\"`, metin içeriği ve araç tanımlarındaki `cache_control` işaretçileri aracılığıyla Antropik tarzda istem önbelleğe almayı ortaya çıkaran OpenAI uyumlu sağlayıcılar içindir.\n\nÖrnek:\n\n```json\n{\n  \"providers\": {\n    \"openrouter\": {\n      \"baseUrl\": \"https://openrouter.ai/api/v1\",\n      \"apiKey\": \"$OPENROUTER_API_KEY\",\n      \"api\": \"openai-completions\",\n      \"models\": [\n        {\n          \"id\": \"openrouter/anthropic/claude-3.5-sonnet\",\n          \"name\": \"OpenRouter Claude 3.5 Sonnet\",\n          \"compat\": {\n            \"openRouterRouting\": {\n              \"allow_fallbacks\": true,\n              \"require_parameters\": false,\n              \"data_collection\": \"deny\",\n              \"zdr\": true,\n              \"enforce_distillable_text\": false,\n              \"order\": [\"anthropic\", \"amazon-bedrock\", \"google-vertex\"],\n              \"only\": [\"anthropic\", \"amazon-bedrock\"],\n              \"ignore\": [\"gmicloud\", \"friendli\"],\n              \"quantizations\": [\"fp16\", \"bf16\"],\n              \"sort\": {\n                \"by\": \"price\",\n                \"partition\": \"model\"\n              },\n              \"max_price\": {\n                \"prompt\": 10,\n                \"completion\": 20\n              },\n              \"preferred_min_throughput\": {\n                \"p50\": 100,\n                \"p90\": 50\n              },\n              \"preferred_max_latency\": {\n                \"p50\": 1,\n                \"p90\": 3,\n                \"p99\": 5\n              }\n            }\n          }\n        }\n      ]\n    }\n  }\n}\n```\n\nVercel AI Ağ Geçidi örneği:\n\n```json\n{\n  \"providers\": {\n    \"vercel-ai-gateway\": {\n      \"baseUrl\": \"https://ai-gateway.vercel.sh/v1\",\n      \"apiKey\": \"$AI_GATEWAY_API_KEY\",\n      \"api\": \"openai-completions\",\n      \"models\": [\n        {\n          \"id\": \"moonshotai/kimi-k2.5\",\n          \"name\": \"Kimi K2.5 (Fireworks via Vercel)\",\n          \"reasoning\": true,\n          \"input\": [\"text\", \"image\"],\n          \"cost\": { \"input\": 0.6, \"output\": 3, \"cacheRead\": 0, \"cacheWrite\": 0 },\n          \"contextWindow\": 262144,\n          \"maxTokens\": 262144,\n          \"compat\": {\n            \"vercelGatewayRouting\": {\n              \"only\": [\"fireworks\", \"novita\"],\n              \"order\": [\"fireworks\", \"novita\"]\n            }\n          }\n        }\n      ]\n    }\n  }\n}\n```","sourceFile":"models.md"},"packages":{"title":"Pi Packages","markdown":"> pi, pi paketleri oluşturmanıza yardımcı olabilir. Uzantılarınızı, becerilerinizi, prompt templates veya temalarınızı bir araya getirmesini isteyin.\n\n\nPi paketleri; uzantıları, becerileri, prompt templates ve temaları bir araya getirir; böylece bunları npm veya git aracılığıyla paylaşabilirsiniz. Bir paket, `pi` anahtarının altındaki `package.json`'deki kaynakları bildirebilir veya geleneksel dizinleri kullanabilir.\n\n## İçindekiler\n\n- [Install and Manage](#install-and-manage)\n- [Package Sources](#package-sources)\n- [Creating a Pi Package](#creating-a-pi-package)\n- [Package Structure](#package-structure)\n- [Dependencies](#dependencies)\n- [Package Filtering](#package-filtering)\n- [Enable and Disable Resources](#enable-and-disable-resources)\n- [Scope and Deduplication](#scope-and-deduplication)\n\n## Kurulum ve Yönetme\n\n> **Güvenlik:** Pi paketler tam sistem erişimiyle çalışır. Extensions isteğe bağlı kod çalıştırır ve beceriler modele çalıştırılabilir dosyaları çalıştırmak da dahil olmak üzere herhangi bir eylemi gerçekleştirmesi talimatını verebilir. Üçüncü taraf paketleri kurmadan önce kaynak kodunu inceleyin.\n\n```bash\npi install npm:@foo/bar@1.0.0\npi install git:github.com/user/repo@v1\npi install https://github.com/user/repo  # raw URLs work too\npi install /absolute/path/to/package\npi install ./relative/path/to/package\n\npi remove npm:@foo/bar\npi list                     # show installed packages from settings\npi update                   # update pi only\npi update --all             # update pi, update packages, and reconcile pinned git refs\npi update --extensions      # update packages and reconcile pinned git refs only\npi update --models          # refresh model catalogs only\npi update --self            # update pi only\npi update --self --force    # reinstall pi even if current\npi update npm:@foo/bar      # update one package\npi update --extension npm:@foo/bar\n```\n\nBu komutlar pi paketlerini yönetir ve `pi update` pi CLI kurulumunu güncelleyebilir. Pi'nin kendisini kaldırmak için bkz. [Quickstart](quickstart.md#uninstall).\n\nVarsayılan olarak `install` ve `remove` kullanıcı ayarlarına (`~/.pi/agent/settings.json`) yazar. Bunun yerine proje ayarlarına (`.pi/settings.json`) yazmak için `-l` tuşunu kullanın. Proje ayarları ekibinizle paylaşılabilir ve pi, projeye güvenildikten sonra eksik paketleri başlangıçta otomatik olarak yükler.\n\nBir paketi yüklemeden denemek için `--extension` veya `-e` tuşlarını kullanın. Bu, yalnızca geçerli çalıştırma için geçici bir dizine yüklenir:\n\n```bash\npi -e npm:@foo/bar\npi -e git:github.com/user/repo\n```\n\n## Paket Kaynakları\n\nPi ayarlarda üç kaynak türünü kabul eder ve `pi install`.\n\n### npm\n\n```\nnpm:@scope/pkg@1.2.3\nnpm:pkg\n```\n\n- Sürümlü özellikler paket güncellemeleri (`pi update --extensions`, `pi update --all`) tarafından sabitlenir ve atlanır.\n- Kullanıcı yüklemeleri `~/.pi/agent/npm/`'nin altına düşüyor.\n- Proje yüklemeleri `.pi/npm/`'nin altına düşüyor.\n- npm paket aramasını sabitlemek ve işlemleri `mise` veya `asdf` gibi belirli bir sarmalayıcı komutuna yüklemek için `settings.json`'deki `npmCommand`'yi ayarlayın.\n\nÖrnek:\n\n```json\n{\n  \"npmCommand\": [\"mise\", \"exec\", \"node@20\", \"--\", \"npm\"]\n}\n```\n\n### git\n\n```\ngit:github.com/user/repo@v1\ngit:git@github.com:user/repo@v1\nhttps://github.com/user/repo@v1\nssh://git@github.com/user/repo@v1\n```\n\n- `git:` öneki olmadan yalnızca protokol URL'leri kabul edilir (`https://`, `http://`, `ssh://`, `git://`).\n- `git:` önekiyle, `github.com/user/repo` ve `git@github.com:user/repo` dahil olmak üzere kısayol formatları kabul edilir.\n- HTTPS ve SSH URL'lerin her ikisi de desteklenir.\n- SSH URL'ler yapılandırılmış SSH anahtarlarınızı otomatik olarak kullanır (`~/.ssh/config`'ye saygı duyar).\n- Etkileşimli olmayan çalıştırmalarda (örneğin CI), kimlik bilgisi istemlerini devre dışı bırakmak için `GIT_TERMINAL_PROMPT=0` ayarını yapabilir ve hızlı başarısız olmak için `GIT_SSH_COMMAND` (örneğin `ssh -o BatchMode=yes -o ConnectTimeout=5`) ayarını yapabilirsiniz.\n- Referanslar sabitlenmiş etiketler veya taahhütlerdir. `pi update --extensions` ve `pi update --all` onları daha yeni referanslara taşımaz, ancak mevcut bir klonu yapılandırılmış referansla uzlaştırırlar.\n- Ayarları güncellemek ve mevcut bir paketi yeni sabitlenmiş bir referansa taşımak için `pi install git:host/user/repo@new-ref` tuşunu kullanın.\n- `~/.pi/agent/git/<host>/<path>` (global) veya `.pi/git/<host>/<path>` (proje) olarak klonlandı.\n- Mutabakat ödemeyi değiştirdiğinde pi klonu sıfırlar ve temizler, ardından `package.json` mevcutsa `npm install`'yi çalıştırır.\n\n**SSH örnekler:**\n```bash\n# git@host:path shorthand (requires git: prefix)\npi install git:git@github.com:user/repo\n\n# ssh:// protocol format\npi install ssh://git@github.com/user/repo\n\n# With version ref\npi install git:git@github.com:user/repo@v1.0.0\n```\n\n### Yerel Yollar\n\n```\n/absolute/path/to/package\n./relative/path/to/package\n```\n\nYerel yollar diskteki dosyalara veya dizinlere işaret eder ve kopyalanmadan ayarlara eklenir. Göreli yollar, göründükleri ayarlar dosyasına göre çözümlenir. Yol bir dosyaysa tek bir uzantı olarak yüklenir. Eğer bu bir dizin ise pi, kaynakları paket kurallarını kullanarak yükler.\n\n## Pi Paketi Oluşturma\n\n`package.json`'ye bir `pi` bildirimi ekleyin veya geleneksel dizinleri kullanın. Keşfedilebilirlik için `pi-package` anahtar kelimesini ekleyin.\n\n```json\n{\n  \"name\": \"my-package\",\n  \"keywords\": [\"pi-package\"],\n  \"pi\": {\n    \"extensions\": [\"./extensions\"],\n    \"skills\": [\"./skills\"],\n    \"prompts\": [\"./prompts\"],\n    \"themes\": [\"./themes\"]\n  }\n}\n```\n\nYollar paket köküne göredir. Diziler glob desenlerini ve `!exclusions`'yi destekler.\n\n### Galeri Meta Verileri\n\n[package gallery](https://pi.dev/packages), `pi-package` ile etiketlenen paketleri görüntüler. Önizlemeyi göstermek için `video` veya `image` alanlarını ekleyin:\n\n```json\n{\n  \"name\": \"my-package\",\n  \"keywords\": [\"pi-package\"],\n  \"pi\": {\n    \"extensions\": [\"./extensions\"],\n    \"video\": \"https://example.com/demo.mp4\",\n    \"image\": \"https://example.com/screenshot.png\"\n  }\n}\n```\n\n- **video**: yalnızca MP4. Masaüstünde fareyle üzerine gelindiğinde otomatik olarak oynatılır. Tıklandığında tam ekran oynatıcı açılır.\n- **resim**: PNG, JPEG, GIF veya WebP. Statik önizleme olarak görüntülenir.\n\nHer ikisi de ayarlandığında video öncelikli olur.\n\n## Paket Yapısı\n\n### Kongre Dizinleri\n\n`pi` bildirimi mevcut değilse pi, şu dizinlerdeki kaynakları otomatik olarak keşfeder:\n\n- `extensions/` `.ts` ve `.js` dosyalarını yükler\n- `skills/` yinelemeli olarak `SKILL.md` klasörleri bulur ve üst düzey `.md` dosyalarını beceri olarak yükler\n- `prompts/` `.md` dosya yükler\n- `themes/` `.json` dosya yükler\n\n## Bağımlılıklar\n\nÜçüncü taraf çalışma zamanı bağımlılıkları `package.json`'deki `dependencies`'ye aittir. Uzantıları, becerileri, prompt templates veya temaları kaydetmeyen bağımlılıklar da `dependencies`'ye aittir. Pi, npm veya git'ten bir paket kurduğunda `npm install`'yi çalıştırır, böylece bu bağımlılıklar otomatik olarak yüklenir.\n\nPi uzantılar ve beceriler için temel paketleri bir araya getirir. Bunlardan herhangi birini içe aktarırsanız, bunları `\"*\"` aralığıyla `peerDependencies` olarak listeleyin ve bunları gruplandırmayın: `@earendil-works/pi-ai`, `@earendil-works/pi-agent-core`, `@earendil-works/pi-coding-agent`, `@earendil-works/pi-tui`, `typebox`.\n\nDiğer pi paketlerinin tarball'ınızda paketlenmesi gerekir. Bunları `dependencies` ve `bundledDependencies`'ye ekleyin, ardından `node_modules/` yolları aracılığıyla kaynaklarına başvurun. Pi paketleri ayrı modül kökleriyle yükler, böylece ayrı kurulumlar çakışmaz veya modülleri paylaşmaz.\n\nÖrnek:\n\n```json\n{\n  \"dependencies\": {\n    \"shitty-extensions\": \"^1.0.1\"\n  },\n  \"bundledDependencies\": [\"shitty-extensions\"],\n  \"pi\": {\n    \"extensions\": [\"extensions\", \"node_modules/shitty-extensions/extensions\"],\n    \"skills\": [\"skills\", \"node_modules/shitty-extensions/skills\"]\n  }\n}\n```\n\n## Paket Filtreleme\n\nAyarlardaki nesne formunu kullanarak bir paketin yüklediklerini filtreleyin:\n\n```json\n{\n  \"packages\": [\n    \"npm:simple-pkg\",\n    {\n      \"source\": \"npm:my-package\",\n      \"extensions\": [\"extensions/*.ts\", \"!extensions/legacy.ts\"],\n      \"skills\": [],\n      \"prompts\": [\"prompts/review.md\"],\n      \"themes\": [\"+themes/legacy.json\"]\n    }\n  ]\n}\n```\n\n`+path` ve `-path` paket köküne göre tam yollardır.\n\n- Bu türün tamamını yüklemek için bir anahtarı atlayın.\n- Bu türden hiçbirini yüklememek için `[]` tuşunu kullanın.\n- `!pattern` eşleşmeleri hariç tutar.\n- `+path` kuvvet-tam bir yol içerir.\n- `-path` kesin bir yolu zorla hariç tutar.\n- Bildirimin üst kısmındaki filtreler katmanı. Zaten izin verileni daraltıyorlar.\n\n## Kaynakları Etkinleştirme ve Devre Dışı Bırakma\n\nYüklü paketlerdeki ve yerel dizinlerdeki uzantıları, becerileri, prompt templates ve temaları etkinleştirmek veya devre dışı bırakmak için `pi config` tuşunu kullanın. `pi config` genel ayarlarda başlar (`~/.pi/agent/settings.json`); küresel ve proje yerel modları arasında geçiş yapmak için Sekme tuşuna basın. Devralınan global kaynaklar solukken proje geçersiz kılmalarını (`.pi/settings.json`) başlatmak için `pi config -l` tuşunu kullanın.\n\n## Kapsam ve Tekilleştirme\n\nPaketler hem genel hem de proje ayarlarında görünebilir. Her ikisinde de aynı paket görünüyorsa, proje girişi `autoload: false` olmadığı sürece proje girişi kazanır; bu durumda global giriş üzerinde delta olarak uygulanır. Kimlik şu şekilde belirlenir:\n\n- npm: paket adı\n- git: referanssız depo URL'si\n- yerel: çözümlenmiş mutlak yol","sourceFile":"packages.md"},"prompt-templates":{"title":"Bilgi İstemi Şablonları","markdown":"> pi prompt templates oluşturabilir. İş akışınız için bir tane oluşturmasını isteyin.\n\n\nBilgi istemi şablonları, tam istemlere genişleyen Markdown parçacıklardır. Bir şablonu çağırmak için düzenleyiciye `/name` yazın; burada `name`, `.md` olmadan dosya adıdır.\n\n## Konumlar\n\nPi şuradan prompt templates yükler:\n\n- Küresel: `~/.pi/agent/prompts/*.md`\n- Proje: `.pi/prompts/*.md` (yalnızca projeye güvenildikten sonra)\n- Paketler: `prompts/` dizinler veya `package.json` içindeki `pi.prompts` girişler\n- Ayarlar: `prompts` dosya veya dizin içeren dizi\n- CLI: `--prompt-template <path>` (tekrarlanabilir)\n\n`--no-prompt-templates` ile keşfi devre dışı bırakın.\n\n## Biçim\n\n```markdown\n---\ndescription: Review staged git changes\n---\nReview the staged changes (`git diff --cached`). Focus on:\n- Bugs and logic errors\n- Security issues\n- Error handling gaps\n```\n\n- Dosya adı komut adı olur. `review.md`, `/review` olur.\n- `description` isteğe bağlıdır. Eksikse boş olmayan ilk satır kullanılır.\n- `argument-hint` isteğe bağlıdır. Ayarlandığında ipucu, otomatik tamamlama açılır menüsündeki açıklamadan önce görüntülenir.\n\n### Tartışma İpuçları\n\nOtomatik tamamlamada beklenen bağımsız değişkenleri göstermek için ön maddede `argument-hint` kullanın. Gerekli argümanlar için `<angle brackets>` ve isteğe bağlı olanlar için `[square brackets]` kullanın:\n\n```markdown\n---\ndescription: Review PRs from URLs with structured issue and code analysis\nargument-hint: \"<PR-URL>\"\n---\n```\n\nBu, otomatik tamamlama açılır menüsünde şu şekilde görüntülenir:\n\n```\n→ pr   <PR-URL>       — Review PRs from URLs with structured issue and code analysis\n  is   <issue>        — Analyze GitHub issues (bugs or feature requests)\n  wr   [instructions] — Finish the current task end-to-end\n  cl   — Audit changelog entries before release\n```\n\n## Kullanım\n\nDüzenleyicide `/` ve ardından şablon adını yazın. Otomatik tamamlama, mevcut şablonları açıklamalarla birlikte gösterir.\n\n```\n/review                           # Expands review.md\n/component Button                 # Expands with argument\n/component Button \"click handler\" # Multiple arguments\n```\n\n## Argümanlar\n\nŞablonlar konumsal argümanları, varsayılanları ve basit dilimlemeyi destekler:\n\n- `$1`, `$2`,... konumsal argümanlar\n- Birleştirilen tüm bağımsız değişkenler için `$@` veya `$ARGUMENTS`\n- `${1:-default}` mevcut/boş olmadığında argüman 1'i kullanır, aksi halde `default`\n- `${@:-default}` veya `${ARGUMENTS:-default}` mevcut/boş olmadığında tüm argümanları kullanır, aksi takdirde `default`\n- `${@:N}` N'inci konumdan bağımsız değişkenler için (1 dizinli)\n- `${@:N:L}` N'den başlayan `L` argümanlar için\n\nÖrnek:\n\n```markdown\n---\ndescription: Create a component\n---\nCreate a React component named $1 with features: $@\n```\n\nVarsayılan değerler isteğe bağlı bağımsız değişkenler için kullanışlıdır:\n\n```markdown\nSummarize the current state in ${1:-7} bullet points.\n```\n\nKullanım: `/component Button \"onClick handler\" \"disabled support\"`\n\n## Kurallar Yükleniyor\n\n- `prompts/`'deki şablon keşfi yinelemeli değildir.\n- Alt dizinlerde şablonlar istiyorsanız bunları `prompts` ayarları veya paket bildirimi yoluyla açıkça ekleyin.","sourceFile":"prompt-templates.md"},"providers":{"title":"Providers","markdown":"Pi, ortam değişkenleri veya kimlik doğrulama dosyası aracılığıyla OAuth ve API key sağlayıcıları aracılığıyla abonelik tabanlı sağlayıcıları destekler. Yerleşik kataloglar pi ile birlikte gönderilir; yapılandırılmış sağlayıcılar daha yeni katalogları yenileyebilir ve bunları çevrimdışı kullanım için `~/.pi/agent/models-store.json`'de önbelleğe alabilir.\n\n## İçindekiler\n\n- [Subscriptions](#subscriptions)\n- [API Keys](#api-keys)\n- [Auth File](#auth-file)\n- [Cloud Providers](#cloud-providers)\n- [llama.cpp](#llamacpp)\n- [Custom Providers](#custom-providers)\n- [Resolution Order](#resolution-order)\n\n## Abonelikler\n\nEtkileşimli modda `/login` tuşunu kullanın, ardından bir sağlayıcı seçin:\n\n- ChatGPT Plus/Pro (Kodeks)\n- Claude Pro/Max\n- GitHub Yardımcı Pilot\n- xAI (Grok/X aboneliği)\n- OpenRouter (OAuth-basılmış API key OpenRouter kredilerinden faturalandırılır)\n- Yarıçap\n\nKimlik bilgilerini temizlemek için `/logout` tuşunu kullanın. Jetonlar `~/.pi/agent/auth.json`'de saklanır ve süresi dolduğunda otomatik olarak yenilenir. OpenRouter bunun yerine kullanıcı tarafından kontrol edilen ve süresi otomatik olarak dolmayan bir API key basar.\n\n### OpenAI Kodeksi\n\n- ChatGPT Plus veya Pro aboneliği gerektirir\n- OpenAI tarafından resmi olarak onaylanmıştır: [Codex for OSS](https://developers.openai.com/community/codex-for-oss)\n\n### Claude Pro/Max\n\nAntropik abonelik kimlik doğrulaması Claude Pro/Max hesapları için etkindir. Üçüncü taraf kablo demeti kullanımı [extra usage](https://claude.ai/settings/usage)'dan başlar ve Claude planı sınırlarına aykırı değil, jeton başına faturalandırılır.\n\n### GitHub Yardımcı Pilot\n\n- github.com için Enter tuşuna basın veya GitHub Enterprise Server alan adınızı girin\n- \"Model desteklenmiyor\" mesajını alırsanız, bunu VS Kodunda etkinleştirin: Copilot Chat → model seçici → modeli seç → \"Etkinleştir\"\n\n### xAI (Grok/X aboneliği)\n\n- `/login xai` komutunu çalıştırın ve ardından **Abonelik kullan** seçeneğini seçin\n- `XAI_API_KEY`, **API key kullanın** aracılığıyla kullanılabilir olmaya devam eder\n\n### Açık Yönlendirici\n\n- `/login openrouter` komutunu çalıştırın ve ardından OpenRouter PKCE yetkilendirme akışını açmak için **OpenRouter ile oturum aç** seçeneğini seçin\n- Yetkilendirme, OpenRouter kredilerinizden faturalandırılan, kullanıcı kontrollü bir OpenRouter API key oluşturur\n- Uzak/başsız makinelerde (örneğin SSH'nin üzerinde) tarayıcı geri döngü geri çağrısına ulaşamaz; bunun yerine son yönlendirme URL'sini (veya yetkilendirme kodunu) giriş istemine yapıştırın\n- `OPENROUTER_API_KEY`, **API key kullanın** aracılığıyla kullanılabilir olmaya devam eder\n\n### Yarıçap\n\nRadius dinamik bir `pi-messages` ağ geçididir. `/login radius` OAuth token'ı `auth.json`'de saklar; ağ geçidi kataloğu bağımsız olarak yenilenir ve `models-store.json`'de önbelleğe alınır. Özel Yarıçap ağ geçitleri `models.json`'de `\"oauth\": \"radius\"` ve bir ağ geçidi `baseUrl` ile bildirilebilir.\n\n## API Tuşlar\n\n### Ortam Değişkenleri veya Kimlik Doğrulama Dosyası\n\nEtkileşimli modda `/login` kullanın ve API key'yi `auth.json`'de depolamak için bir sağlayıcı seçin veya kimlik bilgilerini ortam değişkeni aracılığıyla ayarlayın:\n\n```bash\nexport ANTHROPIC_API_KEY=sk-ant-...\npi\n```\n\n| sağlayıcı | Ortam Değişkeni | `auth.json` tuşu |\n|----------|----------------------|------------------|\n| Antropik | `ANTHROPIC_API_KEY` | `anthropic` |\n| Karınca Ling | `ANT_LING_API_KEY` | `ant-ling` |\n| Azure OpenAI Yanıtları | `AZURE_OPENAI_API_KEY` | `azure-openai-responses` |\n| OpenAI | `OPENAI_API_KEY` | `openai` |\n| Derin Arama | `DEEPSEEK_API_KEY` | `deepseek` |\n| NVIDIA NIM | `NVIDIA_API_KEY` | `nvidia` |\n| Google İkizler | `GEMINI_API_KEY` | `google` |\n| Amazon Ana Kayası | `AWS_BEARER_TOKEN_BEDROCK` | `amazon-bedrock` |\n| Mistral | `MISTRAL_API_KEY` | `mistral` |\n| Büyük | `GROQ_API_KEY` | `groq` |\n| Beyinler | `CEREBRAS_API_KEY` | `cerebras` |\n| Cloudflare AI Ağ Geçidi | `CLOUDFLARE_API_KEY` (+ `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_GATEWAY_ID`) | `cloudflare-ai-gateway` |\n| Cloudflare Çalışanları Yapay Zekası | `CLOUDFLARE_API_KEY` (+ `CLOUDFLARE_ACCOUNT_ID`) | `cloudflare-workers-ai` |\n| xAI | `XAI_API_KEY` | `xai` |\n| Açık Yönlendirici | `OPENROUTER_API_KEY` | `openrouter` |\n| Vercel AI Ağ Geçidi | `AI_GATEWAY_API_KEY` | `vercel-ai-gateway` |\n| ZAI Kodlama Planı (Küresel) | `ZAI_API_KEY` | `zai` |\n| ZAI Kodlama Planı (Çin) | `ZAI_CODING_CN_API_KEY` | `zai-coding-cn` |\n| OpenCode Zen | `OPENCODE_API_KEY` | `opencode` |\n| OpenCode'a Git | `OPENCODE_API_KEY` | `opencode-go` |\n| Yarıçap | `RADIUS_API_KEY` | `radius` |\n| Hugging Face | `HF_TOKEN` | `huggingface` |\n| havai fişek | `FIREWORKS_API_KEY` | `fireworks` |\n| Birlikte Yapay Zeka | `TOGETHER_API_KEY` | `together` |\n| Baseten | `BASETEN_API_KEY` | `baseten` |\n| Kimi Kodlama İçin | `KIMI_API_KEY` | `kimi-coding` |\n| MiniMaks | `MINIMAX_API_KEY` | `minimax` |\n| MiniMax (Çin) | `MINIMAX_CN_API_KEY` | `minimax-cn` |\n| Qwen Token Planı (mevcut katalog) | `QWEN_TOKEN_PLAN_API_KEY` | `qwen-token-plan` |\n| Qwen Token Planı (Bireysel) | `QWEN_TOKEN_PLAN_API_KEY` | `qwen-token-plan-individual` |\n| Qwen Token Planı (Çin) | `QWEN_TOKEN_PLAN_CN_API_KEY` | `qwen-token-plan-cn` |\n| Xiaomi MiMo | `XIAOMI_API_KEY` | `xiaomi` |\n| Xiaomi MiMo Token Planı (Çin) | `XIAOMI_TOKEN_PLAN_CN_API_KEY` | `xiaomi-token-plan-cn` |\n| Xiaomi MiMo Token Planı (Amsterdam) | `XIAOMI_TOKEN_PLAN_AMS_API_KEY` | `xiaomi-token-plan-ams` |\n| Xiaomi MiMo Token Planı (Singapur) | `XIAOMI_TOKEN_PLAN_SGP_API_KEY` | `xiaomi-token-plan-sgp` |\n\nOrtam değişkenleri ve `auth.json` tuşları için referans: [`packages/ai/src/env-api-keys.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/env-api-keys.ts)'de [`const envMap`](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/env-api-keys.ts).\n\n#### Kimlik Doğrulama Dosyası\n\nKimlik bilgilerini `~/.pi/agent/auth.json` konumunda saklayın:\n\n```json\n{\n  \"anthropic\": { \"type\": \"api_key\", \"key\": \"sk-ant-...\" },\n  \"ant-ling\": { \"type\": \"api_key\", \"key\": \"...\" },\n  \"openai\": { \"type\": \"api_key\", \"key\": \"sk-...\" },\n  \"deepseek\": { \"type\": \"api_key\", \"key\": \"sk-...\" },\n  \"nvidia\": { \"type\": \"api_key\", \"key\": \"nvapi-...\" },\n  \"google\": { \"type\": \"api_key\", \"key\": \"...\" },\n  \"opencode\": { \"type\": \"api_key\", \"key\": \"...\" },\n  \"opencode-go\": { \"type\": \"api_key\", \"key\": \"...\" },\n  \"together\": { \"type\": \"api_key\", \"key\": \"...\" },\n  \"qwen-token-plan\":  { \"type\": \"api_key\", \"key\": \"sk-sp-...\" },\n  \"qwen-token-plan-individual\": { \"type\": \"api_key\", \"key\": \"sk-sp-...\" },\n  \"qwen-token-plan-cn\": { \"type\": \"api_key\", \"key\": \"sk-sp-...\" },\n  \"xiaomi\": { \"type\": \"api_key\", \"key\": \"...\" },\n  \"xiaomi-token-plan-cn\":  { \"type\": \"api_key\", \"key\": \"...\" },\n  \"xiaomi-token-plan-ams\": { \"type\": \"api_key\", \"key\": \"...\" },\n  \"xiaomi-token-plan-sgp\": { \"type\": \"api_key\", \"key\": \"...\" }\n}\n```\n\n`qwen-token-plan-individual` aynı uluslararası uç noktayı kullanır ve `QWEN_TOKEN_PLAN_API_KEY` ile\n`qwen-token-plan`, ancak seçiciyi Bireysel abonelikler için belgelenen modellerle sınırlar. Mevcut\nsağlayıcı geriye dönük uyumluluk için daha geniş kataloğunu korur. `auth.json` kullanırken,\nseçtiğiniz sağlayıcının kimlik bilgileri; bir ortam değişkeni her iki uluslararası sağlayıcı tarafından paylaşılmaktadır.\n\nDosya `0600` izinleriyle oluşturulmuştur (yalnızca kullanıcı okuma/yazma). Kimlik doğrulama dosyası kimlik bilgileri, ortam değişkenlerine göre önceliklidir.\n\nAPI key kimlik bilgileri aynı zamanda sağlayıcı kapsamlı ortam değerlerini de içerebilir. Bu değerler, kimlik bilgisi anahtarı, sağlayıcı/model başlıkları ve Cloudflare hesap kimlikleri, Azure OpenAI ayarları, Vertex projesi/konumu, Bedrock ayarları, `PI_CACHE_RETENTION` ve `HTTP_PROXY`/`HTTPS_PROXY` gibi sağlayıcı yapılandırmaları çözümlenirken işlem ortamı değişkenlerinden önce kullanılır.\n\n```json\n{\n  \"cloudflare-ai-gateway\": {\n    \"type\": \"api_key\",\n    \"key\": \"$CLOUDFLARE_API_KEY\",\n    \"env\": {\n      \"CLOUDFLARE_API_KEY\": \"...\",\n      \"CLOUDFLARE_ACCOUNT_ID\": \"account-id\",\n      \"CLOUDFLARE_GATEWAY_ID\": \"gateway-id\"\n    }\n  }\n}\n```\n\nPi'nin proje kabuk ortamından farklı sağlayıcı ayarları kullanması gerektiğinde bunu kullanın.\n\n### Anahtar Çözünürlüğü\n\n`key` alanı komut yürütmeyi, ortam enterpolasyonunu ve değişmez değerleri destekler:\n\n- **Kabuk komutu:** `\"!command\"` başlangıçta tüm değeri bir komut olarak yürütür ve stdout'yi kullanır (işlem ömrü boyunca önbelleğe alınır)\n  ```json\n  { \"type\": \"api_key\", \"key\": \"!security find-generic-password -ws 'anthropic'\" }\n  { \"type\": \"api_key\", \"key\": \"!op read 'op://vault/item/credential'\" }\n  ```\n- **Ortam enterpolasyonu:** `\"$ENV_VAR\"` veya `\"${ENV_VAR}\"`, adlandırılmış değişkenin değerini kullanır. Enterpolasyon daha büyük değişmezlerin içinde çalışır.\n  ```json\n  { \"type\": \"api_key\", \"key\": \"$MY_ANTHROPIC_KEY\" }\n  { \"type\": \"api_key\", \"key\": \"${KEY_PREFIX}_${KEY_SUFFIX}\" }\n  ```\n  `$FOO_BAR`, `FOO_BAR` değişkenidir; `BAR` gerçek metin olduğunda `${FOO}_BAR` kullanın. Eksik ortam değişkenleri değeri çözümsüz hale getirir.\n- **Kaçışlar:** `\"$\"` gerçek bir `\"$\"` yayar; `\"$!\"`, komut yürütmeyi tetiklemeden değişmez bir `\"!\"` yayar.\n  ```json\n  { \"type\": \"api_key\", \"key\": \"$$literal-dollar-prefix\" }\n  { \"type\": \"api_key\", \"key\": \"$!literal-bang-prefix\" }\n  ```\n- **Gerçek değer:** Doğrudan kullanılır. `MY_API_KEY` gibi düz büyük harf dizeleri değişmez değerlerdir; ortam değişkenleri için `$MY_API_KEY` kullanın.\n  ```json\n  { \"type\": \"api_key\", \"key\": \"sk-ant-...\" }\n  { \"type\": \"api_key\", \"key\": \"public\" }\n  ```\n\nOAuth kimlik bilgileri `/login` sonrasında da burada saklanır ve otomatik olarak yönetilir.\n\n## Bulut Providers\n\n### Azure OpenAI\n\n```bash\nexport AZURE_OPENAI_API_KEY=...\nexport AZURE_OPENAI_BASE_URL=https://your-resource.ai.azure.com\n# also supported: https://your-resource.cognitiveservices.azure.com\n# also supported: https://your-resource.openai.azure.com\n# root endpoints are auto-normalized to /openai/v1\n# or use resource name instead of base URL\nexport AZURE_OPENAI_RESOURCE_NAME=your-resource\n\n# Optional\nexport AZURE_OPENAI_API_VERSION=2024-02-01\nexport AZURE_OPENAI_DEPLOYMENT_NAME_MAP=gpt-4=my-gpt4,gpt-4o=my-gpt4o\n```\n\n### Amazon Ana Kayası\n\nBir Bedrock API key depolamak için `/login amazon-bedrock` kullanın veya aşağıdaki ortam AWS kimlik bilgisi kaynaklarından birini yapılandırın:\n\n```bash\n# Option 1: AWS Profile\nexport AWS_PROFILE=your-profile\n\n# Option 2: IAM Keys\nexport AWS_ACCESS_KEY_ID=AKIA...\nexport AWS_SECRET_ACCESS_KEY=...\n\n# Option 3: Bearer Token\nexport AWS_BEARER_TOKEN_BEDROCK=...\n\n# Optional region (defaults to us-east-1)\nexport AWS_REGION=us-west-2\n```\n\nAyrıca ECS görev rollerini (`AWS_CONTAINER_CREDENTIALS_*`) ve IRSA'yı (`AWS_WEB_IDENTITY_TOKEN_FILE`) destekler.\n\n```bash\npi --provider amazon-bedrock --model us.anthropic.claude-sonnet-4-20250514-v1:0\n```\n\nKimliği tanınabilir bir model adı içeren Claude modelleri (temel modeller ve sistem tanımlı çıkarım profilleri) için istemi önbelleğe alma otomatik olarak etkinleştirilir. Uygulama çıkarım profilleri için (ARN'leri model adını içermeyen), önbellek noktalarını etkinleştirmek için `AWS_BEDROCK_FORCE_CACHE=1` değerini ayarlayın:\n\n```bash\nexport AWS_BEDROCK_FORCE_CACHE=1\npi --provider amazon-bedrock --model arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/abc123\n```\n\nBedrock API proxy'sine bağlanıyorsanız aşağıdaki ortam değişkenleri kullanılabilir:\n\n```bash\n# Set the URL for the Bedrock proxy (standard AWS SDK env var)\nexport AWS_ENDPOINT_URL_BEDROCK_RUNTIME=https://my.corp.proxy/bedrock\n\n# Set if your proxy does not require authentication\nexport AWS_BEDROCK_SKIP_AUTH=1\n\n# Set if your proxy only supports HTTP/1.1\nexport AWS_BEDROCK_FORCE_HTTP1=1\n```\n\n### Cloudflare AI Ağ Geçidi\n\n`CLOUDFLARE_API_KEY` `/login` ile ayarlanabilir. Hesap kimliği ve ağ geçidi bilgisi, ortam değişkenleri olarak veya `auth.json`'deki API key kimlik bilgisinin `env` nesnesinde ayarlanabilir.\n\n```bash\nexport CLOUDFLARE_API_KEY=...           # or use /login\nexport CLOUDFLARE_ACCOUNT_ID=...\nexport CLOUDFLARE_GATEWAY_ID=...        # create at dash.cloudflare.com → AI → AI Gateway\npi --provider cloudflare-ai-gateway --model \"claude-sonnet-4-5\"\n```\n\nCloudflare AI Gateway aracılığıyla OpenAI, Anthropic ve Workers AI'ye giden yollar. Workers AI, Birleşik API (`/compat`) ve ön ekli model kimliklerini (`workers-ai/@cf/...`) kullanır. OpenAI, `gpt-5.1` gibi yerel OpenAI model kimlikleriyle OpenAI geçiş rotasını (`/openai`) kullanır. Anthropic, `claude-sonnet-4-5` gibi yerel Antropik model kimlikleriyle Antropik geçiş rotasını (`/anthropic`) kullanır.\n\nAI Ağ Geçidi kimlik doğrulaması, `CLOUDFLARE_API_KEY`'yi `cf-aig-authorization` olarak kullanır. Yukarı akış kimlik doğrulaması aşağıdakilerden biri olabilir:\n\n| Mod | Kimlik doğrulama isteği | Yukarı akış kimlik doğrulaması |\n|------|--------------|---------------|\n| İşçi Yapay Zekası | Yalnızca Cloudflare jetonu | Cloudflare'de yerel |\n| Birleşik faturalandırma | Yalnızca Cloudflare jetonu | Cloudflare yukarı akış kimlik doğrulamasını yönetir ve kredileri düşürür |\n| BYOK'ta depolandı | Yalnızca Cloudflare jetonu | Cloudflare, AI Gateway kontrol panelinde saklanan sağlayıcı anahtarlarını enjekte ediyor |\n| Satır içi BYOK | Cloudflare belirteci artı yukarı akış `Authorization` başlığı | İstek, yukarı akış sağlayıcı anahtarını sağlar |\n\nNormal pi kullanımı için birleşik faturalandırmayı veya depolanan BYOK'u tercih edin. Satır içi BYOK, Cloudflare AI Ağ Geçidi sağlayıcısı için örneğin `models.json` sağlayıcı/model geçersiz kılma yoluyla ek bir yukarı akış `Authorization` başlığının yapılandırılmasını gerektirir.\n\n### Cloudflare Çalışanları Yapay Zekası\n\n`CLOUDFLARE_API_KEY` `/login` ile ayarlanabilir. `CLOUDFLARE_ACCOUNT_ID` bir ortam değişkeni olarak veya `auth.json`'deki API key kimlik bilgisinin `env` nesnesinde ayarlanabilir.\n\n```bash\nexport CLOUDFLARE_API_KEY=...           # or use /login\nexport CLOUDFLARE_ACCOUNT_ID=...\npi --provider cloudflare-workers-ai --model \"@cf/moonshotai/kimi-k2.6\"\n```\n\nPi, [prefix caching](https://developers.cloudflare.com/workers-ai/features/prompt-caching/) indirimler için otomatik olarak `x-session-affinity`'yi ayarlar.\n\n### Google Vertex AI\n\nUygulama Varsayılan Kimlik Bilgilerini kullanır:\n\n```bash\ngcloud auth application-default login\nexport GOOGLE_CLOUD_PROJECT=your-project\nexport GOOGLE_CLOUD_LOCATION=us-central1\n```\n\nVeya `GOOGLE_APPLICATION_CREDENTIALS`'yi bir hizmet hesabı anahtar dosyasına ayarlayın.\n\n## llama.cpp\n\nPi, llama.cpp yönlendirici sunucusunu destekler. `/login llama.cpp` ile yapılandırın, yüklü modelleri `/llama` ile yönetin ve `/model` ile yüklü bir model seçin.\n\nSunucu kurulumu, model dizini düzeni, ortam değişkenleri ve komut kullanımı için [llama.cpp](llama-cpp.md)'e bakın.\n\n## Özel Providers\n\n**models.json aracılığıyla:** Ollama, LM Studio, vLLM veya desteklenen bir API (OpenAI Tamamlamaları, OpenAI Yanıtları, Antropik Mesajlar, Google Generative AI) konuşan herhangi bir sağlayıcıyı ekleyin. Bakınız [models.md](models.md).\n\n**Uzantılar aracılığıyla:** Özel API uygulamalara veya OAuth akışlara ihtiyaç duyan sağlayıcılar için bir uzantı oluşturun. Bkz. [custom-provider.md](custom-provider.md) ve [examples/extensions/custom-provider-gitlab-duo](../examples/extensions/custom-provider-gitlab-duo/).\n\n## Çözüm Sırası\n\nBir sağlayıcının kimlik bilgilerini çözümlerken:\n\n1. CLI `--api-key` bayrak\n2. `auth.json` girişi (API key veya OAuth jetonu)\n3. Ortam değişkeni\n4. `models.json` tarihinden itibaren özel sağlayıcı anahtarları","sourceFile":"providers.md"},"quickstart":{"title":"Hızlı başlangıç","markdown":"Bu sayfa sizi kurulumdan yararlı bir ilk pi oturumuna götürür.\n\n## Düzenlemek\n\nPi, npm paketi olarak dağıtılır:\n\n```bash\nnpm install -g --ignore-scripts @earendil-works/pi-coding-agent\n```\n\n`--ignore-scripts` yükleme sırasında bağımlılık yaşam döngüsü komut dosyalarını devre dışı bırakır. Pi normal npm kurulumları için kurulum komut dosyalarına ihtiyaç duymaz.\n\n### Kaldır\n\nPi'yi yükleyen paket yöneticisini kullanın. Curl yükleyici genel olarak npm kullanır, dolayısıyla curl ve npm yüklemeleri npm ile kaldırılır:\n\n```bash\n# curl installer or npm install -g\nnpm uninstall -g @earendil-works/pi-coding-agent\n\n# pnpm\npnpm remove -g @earendil-works/pi-coding-agent\n\n# Yarn\nyarn global remove @earendil-works/pi-coding-agent\n\n# Bun\nbun uninstall -g @earendil-works/pi-coding-agent\n```\n\nPi'nin kaldırılması ayarları, kimlik bilgilerini, oturumları ve kurulu pi paketlerini `~/.pi/agent/`'da bırakır.\n\nArdından üzerinde çalışmasını istediğiniz proje dizininde pi'yi başlatın:\n\n```bash\ncd /path/to/project\npi\n```\n\n## Kimlik doğrulama\n\nPi, ortam değişkenleri veya kimlik doğrulama dosyası aracılığıyla subscription providers ila `/login` veya API anahtar sağlayıcılarını kullanabilir.\n\n### Seçenek 1: abonelik girişi\n\nPi'yi başlatın ve çalıştırın:\n\n```text\n/login\n```\n\nDaha sonra bir sağlayıcı seçin. Yerleşik abonelik oturum açma bilgileri arasında Claude Pro/Max, ChatGPT Plus/Pro (Codex) ve GitHub Copilot bulunur.\n\n### Seçenek 2: API key\n\nPi'yi başlatmadan önce bir API key ayarlayın:\n\n```bash\nexport ANTHROPIC_API_KEY=sk-ant-...\npi\n```\n\nAyrıca `/login` komutunu çalıştırabilir ve anahtarı `~/.pi/agent/auth.json`'de saklamak için bir API anahtar sağlayıcısı seçebilirsiniz.\n\nDesteklenen tüm sağlayıcılar, ortam değişkenleri ve bulut sağlayıcı kurulumu için [Providers](providers.md)'ye bakın.\n\n## İlk oturum\n\nPi başladıktan sonra bir istek yazın ve Enter'a basın:\n\n```text\nSummarize this repository and tell me how to run its checks.\n```\n\nPi, varsayılan olarak modele dört araç sağlar:\n\n- `read` - dosyaları oku\n- `write` - dosyalar oluşturun veya üzerine yazın\n- `edit` - yama dosyaları\n- `bash` - kabuk komutlarını çalıştır\n\nEk yerleşik salt okunur araçlar (`grep`, `find`, `ls`) araç seçenekleri aracılığıyla kullanılabilir. Pi mevcut çalışma dizininizde çalışır ve oradaki dosyaları değiştirebilir. Kolay geri alma istiyorsanız git'i veya başka bir kontrol noktası oluşturma iş akışını kullanın.\n\n## Pi projesi talimatlarını verin\n\nPi başlangıçta context files'yi yükler. Bir projede nasıl çalışacağını anlatmak için bir `AGENTS.md` dosyası ekleyin:\n\n```markdown\n# Project Instructions\n\n- Run `npm run check` after code changes.\n- Do not run production migrations locally.\n- Keep responses concise.\n```\n\nPi yükler:\n\n- `~/.pi/agent/AGENTS.md` genel talimatlar için\n- `AGENTS.md` veya `CLAUDE.md` üst dizinlerden ve geçerli dizinden\n\nBir dizin `AGENTS.override.md` içeriyorsa, Pi o dizindeki `AGENTS.md` veya `CLAUDE.md` yerine onu yükler.\n\nPi'yi yeniden başlatın veya context files'yi değiştirdikten sonra `/reload`'yi çalıştırın.\n\n## Denenecek yaygın şeyler\n\n### Referans dosyaları\n\nDosyalarda bulanık arama yapmak için düzenleyiciye `@` yazın veya dosyaları komut satırına iletin:\n\n```bash\npi @README.md \"Summarize this\"\npi @src/app.ts @src/app.test.ts \"Review these together\"\n```\n\nResimler veya metinler Ctrl+V (Windows'ta Alt+V) tuşlarıyla yapıştırılabilir; görüntüler ayrıca desteklenen terminallere de sürüklenebilir.\n\n### Kabuk komutlarını çalıştır\n\nEtkileşimli modda:\n\n```text\n!npm run lint\n```\n\nKomut çıktısı modele gönderilir. Bir komutu, çıktısını model bağlamına eklemeden çalıştırmak için `!!command` tuşunu kullanın.\n\n### Modelleri değiştir\n\nBir model seçmek için `/model` veya Ctrl+L tuşlarını kullanın. Düşünme düzeyini değiştirmek için Shift+Tab tuşlarını kullanın. Kapsamlı modeller arasında geçiş yapmak için Ctrl+P / Shift+Ctrl+P tuşlarını kullanın.\n\n### Daha sonra devam et\n\nOturumlar otomatik olarak kaydedilir:\n\n```bash\npi -c                  # Continue most recent session\npi -r                  # Browse previous sessions\npi --name \"my task\"    # Set session display name at startup\npi --session <path|id> # Open a specific session\n```\n\nOturumları yönetmek için pi'nin içinde `/resume`, `/new`, `/tree`, `/fork` ve `/clone` tuşlarını kullanın.\n\n### Etkileşimsiz mod\n\nTek seferlik istemler için:\n\n```bash\npi -p \"Summarize this codebase\"\ncat README.md | pi -p \"Summarize this text\"\npi -p @screenshot.png \"What's in this image?\"\n```\n\nJSON olay çıkışı için `--mode json` veya süreç entegrasyonu için `--mode rpc` kullanın.\n\n## Sonraki adımlar\n\n- [Using Pi](usage.md) - etkileşimli mod, slash commands, oturumlar, context files ve CLI referansı.\n- [Providers](providers.md) - kimlik doğrulama ve model kurulumu.\n- [Settings](settings.md) - genel ve proje yapılandırması.\n- [Keybindings](keybindings.md) - kısayollar ve özelleştirme.\n- [Pi Packages](packages.md) - paylaşılan uzantıları, becerileri, istemleri ve temaları yükleyin.\n\nPlatform notları: [Windows](windows.md), [Termux](termux.md), [tmux](tmux.md), [Terminal setup](terminal-setup.md), [Shell aliases](shell-aliases.md).","sourceFile":"quickstart.md"},"rpc":{"title":"RPC Modu","markdown":"RPC modu, kodlama aracısının stdin/stdout üzerinden JSON protokolü aracılığıyla başsız çalışmasını sağlar. Bu, aracıyı diğer uygulamalara, IDE'lere veya özel kullanıcı arayüzlerine gömmek için kullanışlıdır.\n\n**Node.js/TypeScript kullanıcıları için not**: Bir Node.js uygulaması oluşturuyorsanız, bir alt süreç oluşturmak yerine doğrudan `@earendil-works/pi-coding-agent`'den `AgentSession` kullanmayı düşünün. API için [`src/core/agent-session.ts`](../src/core/agent-session.ts)'ye bakın. Alt süreç tabanlı bir TypeScript istemcisi için bkz. [`src/modes/rpc/rpc-client.ts`](../src/modes/rpc/rpc-client.ts).\n\n## RPC Modu Başlatılıyor\n\n```bash\npi --mode rpc [options]\n```\n\nOrtak seçenekler:\n- `--provider <name>`: LLM sağlayıcısını ayarlayın (antropik, openai, google vb.)\n- `--model <pattern>`: Model deseni veya kimliği (`provider/id` ve isteğe bağlı `:<thinking>`'yi destekler)\n- `--name <name>` / `-n <name>`: Başlangıçta oturumun görünen adını ayarlayın\n- `--no-session`: Oturum kalıcılığını devre dışı bırak\n- `--session-dir <path>`: Özel oturum depolama dizini\n\n## Protokole Genel Bakış\n\n- **Komutlar**: stdin'ye gönderilen JSON nesneler, her satıra bir tane\n- **Yanıtlar**: JSON komut başarısını/başarısızlığını gösteren `type: \"response\"` içeren nesneler\n- **Olaylar**: Aracı etkinlikleri stdout'ye JSON satır olarak aktarılır\n\nTüm komutlar istek/yanıt korelasyonu için isteğe bağlı bir `id` alanını destekler. Sağlanırsa ilgili yanıt aynı `id`'yi içerecektir. `bash_execution_update` olayları aynı zamanda kaynak `bash` komutunun `id`'sini de içerir.\n\n### Çerçeveleme\n\nRPC modu, tek kayıt sınırlayıcı olarak LF (`\\n`) ile katı JSONL anlambilimini kullanır.\n\nBu müşteriler için önemlidir:\n- Kayıtları yalnızca `\\n`'de bölme\n- Sondaki `\\r` öğesini çıkararak isteğe bağlı `\\r\\n` girişini kabul edin\n- Unicode ayırıcılara yeni satır muamelesi yapan genel satır okuyucuları kullanmayın\n\nÖzellikle, `readline` Düğümü RPC modu için protokolle uyumlu değildir çünkü aynı zamanda JSON dizeleri içinde geçerli olan `U+2028` ve `U+2029` üzerinde de bölünür.\n\n## Komutlar\n\n### İsteme\n\n#### çabuk\n\nTemsilciye bir kullanıcı istemi gönderin. Komut yanıtı, istem kabul edildikten, kuyruğa alındıktan veya işlendikten sonra gönderilir. Etkinlikler kabul edildikten sonra eşzamansız olarak yayınlanmaya devam eder.\n\n```json\n{\"id\": \"req-1\", \"type\": \"prompt\", \"message\": \"Hello, world!\"}\n```\n\nResimlerle:\n```json\n{\"type\": \"prompt\", \"message\": \"What's in this image?\", \"images\": [{\"type\": \"image\", \"data\": \"base64-encoded-data\", \"mimeType\": \"image/png\"}]}\n```\n\n**Akış sırasında**: Aracı zaten akış gerçekleştiriyorsa, mesajı sıraya koymak için `streamingBehavior` belirtmelisiniz:\n\n```json\n{\"type\": \"prompt\", \"message\": \"New instruction\", \"streamingBehavior\": \"steer\"}\n```\n\n- `\"steer\"`: Aracı çalışırken mesajı sıraya alın. Mevcut asistan sırasının takım çağrılarını yürütmeyi bitirmesinden sonra, bir sonraki LLM çağrısından önce teslim edilir.\n- `\"followUp\"`: Temsilcinin işi bitene kadar bekleyin. Mesaj yalnızca aracı durduğunda iletilir.\n\nAracı akış halindeyse ve `streamingBehavior` belirtilmemişse komut bir hata döndürür.\n\n**Uzantı komutları**: Mesaj bir uzantı komutuysa (ör. `/mycommand`), akış sırasında bile hemen yürütülür. Uzantı komutları kendi LLM etkileşimlerini `pi.sendMessage()` aracılığıyla yönetir.\n\n**Giriş genişletme**: Beceri komutları (`/skill:name`) ve prompt templates (`/template`) göndermeden/kuyruğa almadan önce genişletilir.\n\nCevap:\n```json\n{\"id\": \"req-1\", \"type\": \"response\", \"command\": \"prompt\", \"success\": true}\n```\n\n`success: true` istemin hemen kabul edildiği, kuyruğa alındığı veya işlendiği anlamına gelir. `success: false` istemin kabul edilmeden önce reddedildiği anlamına gelir. Kabulden sonraki hatalar, aynı istek kimliği için ikinci bir `response` olarak değil, normal olay ve mesaj akışı aracılığıyla raporlanır.\n\n`images` alanı isteğe bağlıdır. Her resim `ImageContent` biçimini kullanır: `{\"type\": \"image\", \"data\": \"base64-encoded-data\", \"mimeType\": \"image/png\"}`.\n\n#### yönlendirmek\n\nTemsilci çalışırken bir yönlendirme mesajını kuyruğa alın. Mevcut asistan sırasının takım çağrılarını yürütmeyi bitirmesinden sonra, bir sonraki LLM çağrısından önce teslim edilir. Beceri komutları ve prompt templates genişletildi. Uzantı komutlarına izin verilmez (bunun yerine `prompt` kullanın).\n\n```json\n{\"type\": \"steer\", \"message\": \"Stop and do this instead\"}\n```\n\nResimlerle:\n```json\n{\"type\": \"steer\", \"message\": \"Look at this instead\", \"images\": [{\"type\": \"image\", \"data\": \"base64-encoded-data\", \"mimeType\": \"image/png\"}]}\n```\n\n`images` alanı isteğe bağlıdır. Her görsel `ImageContent` formatını kullanır (`prompt` ile aynı).\n\nCevap:\n```json\n{\"type\": \"response\", \"command\": \"steer\", \"success\": true}\n```\n\nYönlendirme mesajlarının nasıl işlendiğini kontrol etmek için [set_steering_mode](#set_steering_mode)'ye bakın.\n\n#### takip etmek\n\nTemsilci işini bitirdikten sonra işlenecek bir takip mesajını sıraya koyun. Yalnızca temsilcinin artık araç çağrısı veya yönlendirme mesajı kalmadığında teslim edilir. Beceri komutları ve prompt templates genişletildi. Uzantı komutlarına izin verilmez (bunun yerine `prompt` kullanın).\n\n```json\n{\"type\": \"follow_up\", \"message\": \"After you're done, also do this\"}\n```\n\nResimlerle:\n```json\n{\"type\": \"follow_up\", \"message\": \"Also check this image\", \"images\": [{\"type\": \"image\", \"data\": \"base64-encoded-data\", \"mimeType\": \"image/png\"}]}\n```\n\n`images` alanı isteğe bağlıdır. Her görsel `ImageContent` formatını kullanır (`prompt` ile aynı).\n\nCevap:\n```json\n{\"type\": \"response\", \"command\": \"follow_up\", \"success\": true}\n```\n\nTakip mesajlarının nasıl işlendiğini kontrol etmek için [set_follow_up_mode](#set_follow_up_mode)'ye bakın.\n\n#### iptal etmek\n\nGeçerli aracı işlemini iptal edin.\n\n```json\n{\"type\": \"abort\"}\n```\n\nCevap:\n```json\n{\"type\": \"response\", \"command\": \"abort\", \"success\": true}\n```\n\n#### yeni_session\n\nYeni bir oturum başlatın. `session_before_switch` eklenti olay işleyicisi tarafından iptal edilebilir.\n\n```json\n{\"type\": \"new_session\"}\n```\n\nİsteğe bağlı ebeveyn oturumu takibiyle:\n```json\n{\"type\": \"new_session\", \"parentSession\": \"/path/to/parent-session.jsonl\"}\n```\n\nCevap:\n```json\n{\"type\": \"response\", \"command\": \"new_session\", \"success\": true, \"data\": {\"cancelled\": false}}\n```\n\nBir uzatma iptal edilirse:\n```json\n{\"type\": \"response\", \"command\": \"new_session\", \"success\": true, \"data\": {\"cancelled\": true}}\n```\n\n### Durum\n\n#### get_state\n\nGeçerli oturum durumunu alın.\n\n```json\n{\"type\": \"get_state\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"get_state\",\n  \"success\": true,\n  \"data\": {\n    \"model\": {...},\n    \"thinkingLevel\": \"medium\",\n    \"isStreaming\": false,\n    \"isCompacting\": false,\n    \"steeringMode\": \"all\",\n    \"followUpMode\": \"one-at-a-time\",\n    \"sessionFile\": \"/path/to/session.jsonl\",\n    \"sessionId\": \"abc123\",\n    \"sessionName\": \"my-feature-work\",\n    \"autoCompactionEnabled\": true,\n    \"messageCount\": 5,\n    \"pendingMessageCount\": 0\n  }\n}\n```\n\n`model` alanı tam bir [Model](#model) nesnesi veya `null`'dir. `sessionName` alanı, `set_session_name` aracılığıyla ayarlanan görünen addır veya ayarlanmadıysa atlanır.\n\n#### get_messages\n\nKonuşmadaki tüm mesajları alın.\n\n```json\n{\"type\": \"get_messages\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"get_messages\",\n  \"success\": true,\n  \"data\": {\"messages\": [...]}\n}\n```\n\nMesajlar `AgentMessage` nesnelerdir (bkz. [Message Types](#message-types)).\n\n### Modeli\n\n#### set_model\n\nBelirli bir modele geçin.\n\n```json\n{\"type\": \"set_model\", \"provider\": \"anthropic\", \"modelId\": \"claude-sonnet-4-20250514\"}\n```\n\nYanıt tam [Model](#model) nesnesini içeriyor:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"set_model\",\n  \"success\": true,\n  \"data\": {...}\n}\n```\n\n#### döngü_modeli\n\nBir sonraki mevcut modele geçin. Yalnızca bir model mevcutsa `null` verisini döndürür.\n\n```json\n{\"type\": \"cycle_model\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"cycle_model\",\n  \"success\": true,\n  \"data\": {\n    \"model\": {...},\n    \"thinkingLevel\": \"medium\",\n    \"isScoped\": false\n  }\n}\n```\n\n`model` alanı tam bir [Model](#model) nesnesidir.\n\n#### get_available_models\n\nYapılandırılmış tüm modelleri listeleyin.\n\n```json\n{\"type\": \"get_available_models\"}\n```\n\nYanıt, tam [Model](#model) nesnelerden oluşan bir dizi içerir:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"get_available_models\",\n  \"success\": true,\n  \"data\": {\n    \"models\": [...]\n  }\n}\n```\n\n### Düşünme\n\n#### set_thinking_level\n\nOnu destekleyen modeller için akıl yürütme/düşünme düzeyini ayarlayın.\n\n```json\n{\"type\": \"set_thinking_level\", \"level\": \"high\"}\n```\n\nSeviyeler: `\"off\"`, `\"minimal\"`, `\"low\"`, `\"medium\"`, `\"high\"`, `\"xhigh\"`, `\"max\"`\n\n`\"xhigh\"` ve `\"max\"` yalnızca seçilen model tarafından desteklendiğinde gösterilir. GPT-5.6 dahil bazı modeller her ikisini de gösterir.\n\nCevap:\n```json\n{\"type\": \"response\", \"command\": \"set_thinking_level\", \"success\": true}\n```\n\n#### cycle_thinking_level\n\nMevcut düşünme seviyeleri arasında geçiş yapın. Model düşünmeyi desteklemiyorsa `null` veriyi döndürür.\n\n```json\n{\"type\": \"cycle_thinking_level\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"cycle_thinking_level\",\n  \"success\": true,\n  \"data\": {\"level\": \"high\"}\n}\n```\n\n#### get_available_thinking_levels\n\nMevcut modelin desteklediği düşünme düzeylerini listeleyiniz. Akıl yürütme desteği olmayan bir model için `[\"off\"]` değerini döndürür.\n\n```json\n{\"type\": \"get_available_thinking_levels\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"get_available_thinking_levels\",\n  \"success\": true,\n  \"data\": {\n    \"levels\": [\"off\", \"minimal\", \"low\", \"medium\", \"high\"]\n  }\n}\n```\n\n### Kuyruk Modları\n\n#### set_steering_mode\n\nYönlendirme mesajlarının (`steer`'den itibaren) nasıl iletildiğini kontrol edin.\n\n```json\n{\"type\": \"set_steering_mode\", \"mode\": \"one-at-a-time\"}\n```\n\nModlar:\n- `\"all\"`: Mevcut asistan dönüşü araç çağrılarını yürütmeyi tamamladıktan sonra tüm direksiyon mesajlarını iletin\n- `\"one-at-a-time\"`: Tamamlanan asistan turu başına bir direksiyon mesajı gönderin (varsayılan)\n\nCevap:\n```json\n{\"type\": \"response\", \"command\": \"set_steering_mode\", \"success\": true}\n```\n\n#### set_follow_up_mode\n\nTakip mesajlarının (`follow_up`'den itibaren) nasıl teslim edildiğini kontrol edin.\n\n```json\n{\"type\": \"set_follow_up_mode\", \"mode\": \"one-at-a-time\"}\n```\n\nModlar:\n- `\"all\"`: Temsilci işini bitirdiğinde tüm takip mesajlarını ilet\n- `\"one-at-a-time\"`: Temsilci tamamlandığında bir takip mesajı gönderin (varsayılan)\n\nCevap:\n```json\n{\"type\": \"response\", \"command\": \"set_follow_up_mode\", \"success\": true}\n```\n\n### Sıkıştırma\n\n#### kompakt\n\nBelirteç kullanımını azaltmak için konuşma içeriğini manuel olarak sıkıştırın.\n\n```json\n{\"type\": \"compact\"}\n```\n\nÖzel talimatlarla:\n```json\n{\"type\": \"compact\", \"customInstructions\": \"Focus on code changes\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"compact\",\n  \"success\": true,\n  \"data\": {\n    \"summary\": \"Summary of conversation...\",\n    \"firstKeptEntryId\": \"abc123\",\n    \"tokensBefore\": 150000,\n    \"estimatedTokensAfter\": 32000,\n    \"usage\": {\n      \"input\": 32000,\n      \"output\": 1200,\n      \"cacheRead\": 0,\n      \"cacheWrite\": 0,\n      \"totalTokens\": 33200,\n      \"cost\": {\"input\": 0.01, \"output\": 0.02, \"cacheRead\": 0, \"cacheWrite\": 0, \"total\": 0.03}\n    },\n    \"details\": {}\n  }\n}\n```\n\n`estimatedTokensAfter`, sağlayıcının tam belirteç sayısı değil, sıkıştırmanın hemen ardından yeniden oluşturulan mesaj bağlamı üzerinden yapılan buluşsal bir tahmindir. `usage` LLM çağrısını veya özeti oluşturan çağrıları bildirir ve özel sıkıştırma işleyicileri tarafından göz ardı edilebilir.\n\n#### set_auto_compaction\n\nBağlam dolmaya yaklaştığında otomatik sıkıştırmayı etkinleştirin veya devre dışı bırakın.\n\n```json\n{\"type\": \"set_auto_compaction\", \"enabled\": true}\n```\n\nCevap:\n```json\n{\"type\": \"response\", \"command\": \"set_auto_compaction\", \"success\": true}\n```\n\n### Yeniden dene\n\n#### set_auto_retry\n\nGeçici hatalarda (aşırı yük, hız sınırı, 5xx) otomatik yeniden denemeyi etkinleştirin veya devre dışı bırakın.\n\n```json\n{\"type\": \"set_auto_retry\", \"enabled\": true}\n```\n\nCevap:\n```json\n{\"type\": \"response\", \"command\": \"set_auto_retry\", \"success\": true}\n```\n\n#### iptal_yeniden dene\n\nDevam eden bir yeniden denemeyi iptal edin (gecikmeyi iptal edin ve yeniden denemeyi durdurun).\n\n```json\n{\"type\": \"abort_retry\"}\n```\n\nCevap:\n```json\n{\"type\": \"response\", \"command\": \"abort_retry\", \"success\": true}\n```\n\n### Bash\n\n#### bash\n\nBir kabuk komutunu yürütün ve çıktıyı konuşma bağlamına ekleyin. Komut çalışırken akışların çıktısını `bash_execution_update` olaylar olarak alın; yanıt nihai sonucu içerir.\n\n```json\n{\"id\": \"req-1\", \"type\": \"bash\", \"command\": \"ls -la\"}\n```\n\nAkışlı `bash_execution_update` olaylarını bu komutla ilişkilendirmek için bir `id` ekleyin.\n\nCevap:\n```json\n{\n  \"id\": \"req-1\",\n  \"type\": \"response\",\n  \"command\": \"bash\",\n  \"success\": true,\n  \"data\": {\n    \"output\": \"total 48\\ndrwxr-xr-x ...\",\n    \"exitCode\": 0,\n    \"cancelled\": false,\n    \"truncated\": false\n  }\n}\n```\n\nÇıktı kesilmişse `fullOutputPath` şunları içerir:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"bash\",\n  \"success\": true,\n  \"data\": {\n    \"output\": \"truncated output...\",\n    \"exitCode\": 0,\n    \"cancelled\": false,\n    \"truncated\": true,\n    \"fullOutputPath\": \"/tmp/pi-bash-abc123.log\"\n  }\n}\n```\n\n**bash sonuçları LLM'ye nasıl ulaşır:**\n\n`bash` komutu hemen yürütülür ve `BashResult` değerini döndürür. Dahili olarak, aracının mesaj durumunda bir `BashExecutionMessage` oluşturulur ve saklanır.\n\nBir sonraki `prompt` komutu gönderildiğinde, tüm mesajlar (`BashExecutionMessage` dahil) LLM'ye gönderilmeden önce dönüştürülür. `BashExecutionMessage` şu formatla `UserMessage`'ye dönüştürülür:\n\n````\nRan `ls -la`\n```\ntoplam 48\ndrwxr-xr-x...\n```\n````\n\nBu şu anlama gelir:\n1. Bash çıktısı LLM bağlamına hemen değil, **sonraki komut isteminde** dahil edilir\n2. Bir istemden önce birden fazla bash komutu yürütülebilir; tüm çıktılar dahil edilecek\n\n#### iptal_bash\n\nÇalışan bir bash komutunu iptal edin.\n\n```json\n{\"type\": \"abort_bash\"}\n```\n\nCevap:\n```json\n{\"type\": \"response\", \"command\": \"abort_bash\", \"success\": true}\n```\n\n### Oturum\n\n#### get_session_stats\n\nBelirteç kullanımını, maliyet istatistiklerini ve mevcut bağlam penceresi kullanımını alın.\n\n```json\n{\"type\": \"get_session_stats\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"get_session_stats\",\n  \"success\": true,\n  \"data\": {\n    \"sessionFile\": \"/path/to/session.jsonl\",\n    \"sessionId\": \"abc123\",\n    \"userMessages\": 5,\n    \"assistantMessages\": 5,\n    \"toolCalls\": 12,\n    \"toolResults\": 12,\n    \"totalMessages\": 22,\n    \"tokens\": {\n      \"input\": 50000,\n      \"output\": 10000,\n      \"cacheRead\": 40000,\n      \"cacheWrite\": 5000,\n      \"total\": 105000\n    },\n    \"cost\": 0.45,\n    \"contextUsage\": {\n      \"tokens\": 60000,\n      \"contextWindow\": 200000,\n      \"percent\": 30\n    }\n  }\n}\n```\n\n`tokens` ve `cost` tüm oturum boyunca asistan mesajlarını, araçlar tarafından bildirilen kullanımı ve sıkıştırma/dal özeti oluşturmayı içerir. `contextUsage` sıkıştırma ve alt bilgi ekranı için kullanılan gerçek geçerli bağlam penceresi tahminini içerir.\n\nHiçbir model veya bağlam penceresi mevcut olmadığında `contextUsage` atlanır. `contextUsage.tokens` ve `contextUsage.percent`, yeni bir sıkıştırma sonrası asistanının yanıtı geçerli kullanım verileri sağlayana kadar sıkıştırmadan hemen sonra `null`'dir.\n\n#### ihracat_html\n\nOturumu bir HTML dosyasına aktarın.\n\n```json\n{\"type\": \"export_html\"}\n```\n\nÖzel yol ile:\n```json\n{\"type\": \"export_html\", \"outputPath\": \"/tmp/session.html\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"export_html\",\n  \"success\": true,\n  \"data\": {\"path\": \"/tmp/session.html\"}\n}\n```\n\n#### switch_session\n\nFarklı bir oturum dosyası yükleyin. `session_before_switch` eklenti olay işleyicisi tarafından iptal edilebilir.\n\n```json\n{\"type\": \"switch_session\", \"sessionPath\": \"/path/to/session.jsonl\"}\n```\n\nCevap:\n```json\n{\"type\": \"response\", \"command\": \"switch_session\", \"success\": true, \"data\": {\"cancelled\": false}}\n```\n\nBir uzantının geçişi iptal etmesi durumunda:\n```json\n{\"type\": \"response\", \"command\": \"switch_session\", \"success\": true, \"data\": {\"cancelled\": true}}\n```\n\n#### çatal\n\nAktif daldaki önceki kullanıcı mesajından yeni bir çatal oluşturun. `session_before_fork` eklenti olay işleyicisi tarafından iptal edilebilir. Çatallanan mesajın metnini döndürür.\n\n```json\n{\"type\": \"fork\", \"entryId\": \"abc123\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"fork\",\n  \"success\": true,\n  \"data\": {\"text\": \"The original prompt text...\", \"cancelled\": false}\n}\n```\n\nBir uzantı çatalı iptal ederse:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"fork\",\n  \"success\": true,\n  \"data\": {\"text\": \"The original prompt text...\", \"cancelled\": true}\n}\n```\n\n#### klon\n\nGeçerli aktif dalı geçerli konumdaki yeni bir oturuma kopyalayın. `session_before_fork` eklenti olay işleyicisi tarafından iptal edilebilir.\n\n```json\n{\"type\": \"clone\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"clone\",\n  \"success\": true,\n  \"data\": {\"cancelled\": false}\n}\n```\n\nBir uzantı klonu iptal ederse:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"clone\",\n  \"success\": true,\n  \"data\": {\"cancelled\": true}\n}\n```\n\n#### get_fork_messages\n\nÇatallama için kullanıcı mesajlarının kullanılabilir olmasını sağlayın.\n\n```json\n{\"type\": \"get_fork_messages\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"get_fork_messages\",\n  \"success\": true,\n  \"data\": {\n    \"messages\": [\n      {\"entryId\": \"abc123\", \"text\": \"First prompt...\"},\n      {\"entryId\": \"def456\", \"text\": \"Second prompt...\"}\n    ]\n  }\n}\n```\n\n#### get_entries\n\nTüm oturum girişlerini ekleme sırasına göre alın (oturum başlığı hariç). Oturum, sabit kimliklere sahip yalnızca eklemeli bir giriş ağacıdır, dolayısıyla giriş kimliği dayanıklı bir imleç olarak çalışır: istemci yeniden başlatmalarında bile yalnızca ondan sonraki girişleri almak için gördüğünüz son giriş kimliğini `since` olarak iletin. `get_messages`'den farklı olarak bu, ön sıkıştırma geçmişini ve terk edilmiş dalları içerir.\n\n```json\n{\"type\": \"get_entries\"}\n```\n\nBir imleçle:\n```json\n{\"type\": \"get_entries\", \"since\": \"abc123\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"get_entries\",\n  \"success\": true,\n  \"data\": {\n    \"entries\": [\n      {\"type\": \"message\", \"id\": \"def456\", \"parentId\": \"abc123\", \"timestamp\": \"...\", \"message\": {\"role\": \"user\", \"...\": \"...\"}}\n    ],\n    \"leafId\": \"def456\"\n  }\n}\n```\n\n`leafId` geçerli yaprak girişinin kimliğidir (boş bir oturum için `null`), böylece müşteri tek bir gidiş-dönüş yolculuğunda aktif dalın taşınıp taşınmadığını anlayabilir. `since` herhangi bir giriş kimliğiyle eşleşmiyorsa yanıt `success: false` olur.\n\n#### get_tree\n\nOturumu bir giriş ağacı olarak alın. Her düğüm `{entry, children, label?, labelTimestamp?}`'dir. İyi biçimlendirilmiş bir oturumun tek bir kökü vardır; yetim girdiler (kırık ana zincir) de kök olarak görünür.\n\n```json\n{\"type\": \"get_tree\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"get_tree\",\n  \"success\": true,\n  \"data\": {\n    \"tree\": [\n      {\n        \"entry\": {\"type\": \"message\", \"id\": \"abc123\", \"parentId\": null, \"...\": \"...\"},\n        \"children\": [\n          {\"entry\": {\"type\": \"message\", \"id\": \"def456\", \"parentId\": \"abc123\", \"...\": \"...\"}, \"children\": []}\n        ]\n      }\n    ],\n    \"leafId\": \"def456\"\n  }\n}\n```\n\n#### get_last_assistant_text\n\nSon asistan mesajının metin içeriğini alın.\n\n```json\n{\"type\": \"get_last_assistant_text\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"get_last_assistant_text\",\n  \"success\": true,\n  \"data\": {\"text\": \"The assistant's response...\"}\n}\n```\n\nAsistan mesajı yoksa `{\"text\": null}` değerini döndürür.\n\n#### set_session_name\n\nGeçerli oturum için bir görünen ad belirleyin. Ad, oturum listelerinde görünür ve oturumların tanımlanmasına yardımcı olur.\n\n```json\n{\"type\": \"set_session_name\", \"name\": \"my-feature-work\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"set_session_name\",\n  \"success\": true\n}\n```\n\nGeçerli oturum adına `sessionName` alanında `get_state` aracılığıyla ulaşılabilir. RPC modunu başlatırken başlangıç ​​adını ayarlamak için `pi --mode rpc` işlemine `--name <name>` veya `-n <name>`'yi geçin.\n\n### Komutlar\n\n#### get_commands\n\nKullanılabilir komutları alın (uzantı komutları, prompt templates ve beceriler). Bunlar, `/` öneki eklenerek `prompt` komutu aracılığıyla çağrılabilir.\n\n```json\n{\"type\": \"get_commands\"}\n```\n\nCevap:\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"get_commands\",\n  \"success\": true,\n  \"data\": {\n    \"commands\": [\n      {\"name\": \"session-name\", \"description\": \"Set or clear session name\", \"source\": \"extension\", \"path\": \"/home/user/.pi/agent/extensions/session.ts\"},\n      {\"name\": \"fix-tests\", \"description\": \"Fix failing tests\", \"source\": \"prompt\", \"location\": \"project\", \"path\": \"/home/user/myproject/.pi/agent/prompts/fix-tests.md\"},\n      {\"name\": \"skill:brave-search\", \"description\": \"Web search via Brave API\", \"source\": \"skill\", \"location\": \"user\", \"path\": \"/home/user/.pi/agent/skills/brave-search/SKILL.md\"}\n    ]\n  }\n}\n```\n\nHer komutta şunlar bulunur:\n- `name`: Komut adı (`/name` ile çağırın)\n- `description`: İnsanların okuyabileceği açıklama (uzantı komutları için isteğe bağlı)\n- `source`: Ne tür bir komut:\n  - `\"extension\"`: Bir dahili numarada `pi.registerCommand()` aracılığıyla kaydedildi\n  - `\"prompt\"`: Bilgi istemi şablonu `.md` dosyasından yüklendi\n  - `\"skill\"`: Bir beceri dizininden yüklendi (adın önüne `skill:` eklenir)\n- `location`: Nereden yüklendiği (isteğe bağlı, uzantılar için mevcut değil):\n  - `\"user\"`: Kullanıcı düzeyi (`~/.pi/agent/`)\n  - `\"project\"`: Proje düzeyinde (`./.pi/agent/`)\n  - `\"path\"`: CLI veya ayarlar aracılığıyla açık yol\n- `path`: Komut kaynağına giden mutlak dosya yolu (isteğe bağlı)\n\n**Not**: Yerleşik TUI komutları (`/settings`, `/hotkeys` vb.) dahil değildir. Yalnızca etkileşimli modda işlenirler ve `prompt` aracılığıyla gönderilirse yürütülmezler.\n\n## Olaylar\n\nAracı işlemi sırasında olaylar stdout'ye JSON satırlar halinde aktarılır. Etkinlikler genellikle `id` alanı içermez; `bash_execution_update`, sağlandığı sırada kaynak `bash` komutunun `id`'sini içerir.\n\n### Etkinlik Türleri\n\n| Etkinlik | Tanım |\n|-------|-------------|\n| `agent_start` | Aracı işlemeye başlıyor |\n| `agent_end` | Bir düşük seviyeli aracı çalıştırması tamamlanır (ardından yeniden deneme, sıkıştırma veya sıraya alınmış devamlar gelebilir) |\n| `agent_settled` | Aracı çalıştırması tamamen çözüldü; otomatik yeniden deneme, sıkıştırma yeniden denemesi veya sıraya alınmış devam durumu kalmaz |\n| `turn_start` | Yeni dönüş başlıyor |\n| `turn_end` | Dönüş tamamlanır (asistan mesajını ve araç sonuçlarını içerir) |\n| `message_start` | Mesaj başlıyor |\n| `message_update` | Akış güncellemesi (metin/düşünme/araç çağrısı deltaları) |\n| `message_end` | Mesaj tamamlandı |\n| `bash_execution_update` | Doğrudan RPC bash komut çıktı öbeği |\n| `tool_execution_start` | Araç yürütülmeye başlar |\n| `tool_execution_update` | Araç yürütme ilerlemesi (akış çıktısı) |\n| `tool_execution_end` | Araç tamamlanır |\n| `queue_update` | Bekleyen yönlendirme/takip kuyruğu değiştirildi |\n| `compaction_start` | Sıkıştırma başlıyor |\n| `compaction_end` | Sıkıştırma tamamlandı |\n| `auto_retry_start` | Otomatik yeniden deneme başlar (geçici hatadan sonra) |\n| `auto_retry_end` | Otomatik yeniden deneme tamamlandı (başarılı veya nihai başarısızlık) |\n| `summarization_retry_scheduled` | Geçici sıkıştırma veya dal özeti özetleme hatası nedeniyle planlanmış yeniden deneme |\n| `summarization_retry_attempt_start` | Yeniden denenen özetleme isteği başlıyor |\n| `summarization_retry_finished` | Özetleme yeniden deneme döngüsü tamamlanır |\n| `extension_error` | Uzantı bir hata verdi |\n\n### ajan_başlangıç\n\nAracı bir istemi işlemeye başladığında yayılır.\n\n```json\n{\"type\": \"agent_start\"}\n```\n\n### ajan_end\n\nBir düşük seviyeli aracı çalıştırması tamamlandığında yayılır. Bu çalıştırma sırasında oluşturulan tüm mesajları içerir. `willRetry` doğruysa otomatik yeniden deneme yapılır.\n\n```json\n{\n  \"type\": \"agent_end\",\n  \"messages\": [...],\n  \"willRetry\": false\n}\n```\n\n### ajan_settled\n\nTam oturum düzeyinde çalıştırma tamamlandıktan sonra yayılır. Bu noktada Pi yeniden deneme, sıkıştırma yeniden denemesi veya sıraya alınmış takip mesajları yoluyla otomatik olarak devam etmeyecektir.\n\n```json\n{\"type\": \"agent_settled\"}\n```\n\n### dönüş_başlangıç ​​/ dönüş_son\n\nBir dönüş, bir asistan yanıtının yanı sıra bunun sonucunda ortaya çıkan araç çağrıları ve sonuçlarından oluşur.\n\n```json\n{\"type\": \"turn_start\"}\n```\n\n```json\n{\n  \"type\": \"turn_end\",\n  \"message\": {...},\n  \"toolResults\": [...]\n}\n```\n\n### message_start / message_end\n\nBir mesaj başladığında ve tamamlandığında yayılır. `message` alanı bir `AgentMessage` içerir.\n\n```json\n{\"type\": \"message_start\", \"message\": {...}}\n{\"type\": \"message_end\", \"message\": {...}}\n```\n\n### message_update (Akış)\n\nAsistan mesajlarının akışı sırasında yayılır. Kümülatif mesaj anlık görüntüsü olmayan bir delta olayı içerir.\n\n```json\n{\n  \"type\": \"message_update\",\n  \"assistantMessageEvent\": {\n    \"type\": \"text_delta\",\n    \"contentIndex\": 0,\n    \"delta\": \"Hello \"\n  }\n}\n```\n\n`assistantMessageEvent` alanı şu delta türlerinden birini içerir:\n\n| Tip | Tanım |\n|------|-------------|\n| `text_start` | Metin içeriği bloğu başlatıldı |\n| `text_delta` | Metin içeriği yığını |\n| `text_end` | Metin içeriği bloğu sona erdi |\n| `thinking_start` | Düşünme bloğu başladı |\n| `thinking_delta` | İçerik yığınını düşünme |\n| `thinking_end` | Düşünme engeli sona erdi |\n| `toolcall_start` | Araç çağrısı başlatıldı |\n| `toolcall_delta` | Araç çağrısı argümanları öbeği |\n| `toolcall_end` | Araç çağrısı sona erdi (tam `toolCall` nesnesini içerir) |\n\nBir metin yanıtının akışının örneği:\n```json\n{\"type\":\"message_update\",\"assistantMessageEvent\":{\"type\":\"text_start\",\"contentIndex\":0}}\n{\"type\":\"message_update\",\"assistantMessageEvent\":{\"type\":\"text_delta\",\"contentIndex\":0,\"delta\":\"Hello\"}}\n{\"type\":\"message_update\",\"assistantMessageEvent\":{\"type\":\"text_delta\",\"contentIndex\":0,\"delta\":\" world\"}}\n{\"type\":\"message_update\",\"assistantMessageEvent\":{\"type\":\"text_end\",\"contentIndex\":0,\"content\":\"Hello world\"}}\n```\n\n`message_update` önceki kümülatif `message` alanını kasıtlı olarak atlar ve\n`assistantMessageEvent.partial`. Canlı kısmi mesaja ihtiyaç duyan istemcilerin bunu birleştirmesi gerekir\n`message_start`'den ve `contentIndex`'yi kullanan sonraki olaylardan. Tedavi `message_end.message`\nyetkili olarak. Araç çağrıları için arabellek `toolcall_delta.delta`; `toolcall_end.toolCall`\ntamamlanan aramayı içerir.\n\n### bash_execution_update\n\nDoğrudan `bash` komutundan her çıktı öbeği için bir kez yayılır. `id` komutun `id` ile eşleşerek istemcilerin çıktıyı doğru komutla ilişkilendirmesine olanak tanır.\n\nSon `bash` yanıtının `output`'si kesilmiş olsa bile, komut çalışırken olaylar tüm çıktıyı yayınlar.\n\n```json\n{\n  \"type\": \"bash_execution_update\",\n  \"id\": \"req-1\",\n  \"delta\": \"total 48\\n\"\n}\n```\n\n### tool_execution_start / tool_execution_update / tool_execution_end\n\nBir araç başladığında, ilerleme akışı yapıldığında ve yürütmeyi tamamladığında yayılır.\n\n```json\n{\n  \"type\": \"tool_execution_start\",\n  \"toolCallId\": \"call_abc123\",\n  \"toolName\": \"bash\",\n  \"args\": {\"command\": \"ls -la\"}\n}\n```\n\nYürütme sırasında, `tool_execution_update` olayları kısmi sonuçların akışını sağlar (örneğin, bash geldiğinde çıktı):\n\n```json\n{\n  \"type\": \"tool_execution_update\",\n  \"toolCallId\": \"call_abc123\",\n  \"toolName\": \"bash\",\n  \"args\": {\"command\": \"ls -la\"},\n  \"partialResult\": {\n    \"content\": [{\"type\": \"text\", \"text\": \"partial output so far...\"}],\n    \"details\": {\"truncation\": null, \"fullOutputPath\": null}\n  }\n}\n```\n\nTamamlandığında:\n\n```json\n{\n  \"type\": \"tool_execution_end\",\n  \"toolCallId\": \"call_abc123\",\n  \"toolName\": \"bash\",\n  \"result\": {\n    \"content\": [{\"type\": \"text\", \"text\": \"total 48\\n...\"}],\n    \"details\": {...}\n  },\n  \"isError\": false\n}\n```\n\nOlayları ilişkilendirmek için `toolCallId` tuşunu kullanın. `tool_execution_update`'deki `partialResult`, o ana kadar biriken çıktıyı içerir (yalnızca deltayı değil), istemcilerin her güncellemede ekranlarını kolayca değiştirmelerine olanak tanır.\n\n### kuyruk_update\n\nBekleyen yönlendirme veya takip kuyruğu değiştiğinde yayılır.\n\n```json\n{\n  \"type\": \"queue_update\",\n  \"steering\": [\"Focus on error handling\"],\n  \"followUp\": [\"After that, summarize the result\"]\n}\n```\n\n### sıkıştırma_başlangıç ​​/ sıkıştırma_son\n\nİster manuel ister otomatik olsun, sıkıştırma çalıştırıldığında yayılır.\n\n```json\n{\"type\": \"compaction_start\", \"reason\": \"threshold\"}\n```\n\n`reason` alanı `\"manual\"`, `\"threshold\"` veya `\"overflow\"`'dir.\n\n```json\n{\n  \"type\": \"compaction_end\",\n  \"reason\": \"threshold\",\n  \"result\": {\n    \"summary\": \"Summary of conversation...\",\n    \"firstKeptEntryId\": \"abc123\",\n    \"tokensBefore\": 150000,\n    \"estimatedTokensAfter\": 32000,\n    \"usage\": {\n      \"input\": 32000,\n      \"output\": 1200,\n      \"cacheRead\": 0,\n      \"cacheWrite\": 0,\n      \"totalTokens\": 33200,\n      \"cost\": {\"input\": 0.01, \"output\": 0.02, \"cacheRead\": 0, \"cacheWrite\": 0, \"total\": 0.03}\n    },\n    \"details\": {}\n  },\n  \"aborted\": false,\n  \"willRetry\": false\n}\n```\n\n`reason`, `\"overflow\"` ise ve sıkıştırma başarılı olursa, `willRetry`, `true` olur ve aracı, istemi otomatik olarak yeniden deneyecektir.\n\nSıkıştırma iptal edildiyse, `result`, `null` ve `aborted`, `true` olur.\n\nSıkıştırma başarısız olursa (örneğin, API kota aşıldı), `result` `null`'dir, `aborted` `false`'dir ve `errorMessage` hata açıklamasını içerir.\n\n### auto_retry_start / auto_retry_end\n\nGeçici bir hatanın (aşırı yük, hız limiti, 5xx) ardından otomatik yeniden deneme tetiklendiğinde ortaya çıkar.\n\n```json\n{\n  \"type\": \"auto_retry_start\",\n  \"attempt\": 1,\n  \"maxAttempts\": 3,\n  \"delayMs\": 2000,\n  \"errorMessage\": \"529 {\\\"type\\\":\\\"error\\\",\\\"error\\\":{\\\"type\\\":\\\"overloaded_error\\\",\\\"message\\\":\\\"Overloaded\\\"}}\"\n}\n```\n\n```json\n{\n  \"type\": \"auto_retry_end\",\n  \"success\": true,\n  \"attempt\": 2\n}\n```\n\nNihai başarısızlık durumunda (maksimum yeniden deneme sayısı aşıldı):\n```json\n{\n  \"type\": \"auto_retry_end\",\n  \"success\": false,\n  \"attempt\": 3,\n  \"finalError\": \"529 overloaded_error: Overloaded\"\n}\n```\n\n### summarization_retry_scheduled / summarization_retry_attempt_start / summarization_retry_finished\n\nSıkıştırma veya dal özeti özetleme, geçici bir sağlayıcı hatasından sonra yeniden denendiğinde ortaya çıkar. Bu olaylar, otomatik asistan dönüşü yeniden denemeleriyle aynı yeniden deneme ayarlarını kullanır.\n\n```json\n{\n  \"type\": \"summarization_retry_scheduled\",\n  \"attempt\": 1,\n  \"maxAttempts\": 3,\n  \"delayMs\": 2000,\n  \"errorMessage\": \"terminated\"\n}\n```\n\n```json\n{\n  \"type\": \"summarization_retry_attempt_start\",\n  \"source\": \"compaction\",\n  \"reason\": \"threshold\"\n}\n```\n\nDal özetleri için `source`, `\"branchSummary\"`'dir ve `reason` yoktur.\n\n```json\n{\n  \"type\": \"summarization_retry_finished\"\n}\n```\n\n### extension_error\n\nBir uzantı hata verdiğinde ortaya çıkar.\n\n```json\n{\n  \"type\": \"extension_error\",\n  \"extensionPath\": \"/path/to/extension.ts\",\n  \"event\": \"tool_call\",\n  \"error\": \"Error message...\"\n}\n```\n\n## Uzantı Kullanıcı Arayüzü Protokolü\n\nExtensions, `ctx.ui.select()`, `ctx.ui.confirm()` vb. aracılığıyla kullanıcı etkileşimi talep edebilir. RPC modunda bunlar, temel komut/olay akışının üstünde bir istek/yanıt alt protokolüne dönüştürülür.\n\nUzantı kullanıcı arayüzü yöntemlerinin iki kategorisi vardır:\n\n- **İletişim yöntemleri** (`select`, `confirm`, `input`, `editor`): stdout'de bir `extension_ui_request` yayınlayın ve istemci, `id` ile eşleşen stdin'de bir `extension_ui_response` geri gönderene kadar bloke edin.\n- **Ateşle ve unut yöntemleri** (`notify`, `setStatus`, `setWidget`, `setTitle`, `set_editor_text`): stdout üzerinde `extension_ui_request` yayınlayın ancak yanıt beklemeyin. İstemci bilgileri görüntüleyebilir veya görmezden gelebilir.\n\nBir diyalog yöntemi bir `timeout` alanı içeriyorsa, aracı tarafı, zaman aşımı sona erdiğinde varsayılan bir değerle otomatik olarak çözümleyecektir. İstemcinin zaman aşımlarını izlemesine gerek yoktur.\n\nBazı `ExtensionUIContext` yöntemleri, doğrudan TUI erişimi gerektirdiğinden RPC modunda desteklenmez veya kalitesi düşürülmez:\n- `custom()` `undefined` değerini döndürür\n- `setWorkingMessage()`, `setWorkingIndicator()`, `setFooter()`, `setHeader()`, `setEditorComponent()`, `setToolsExpanded()` operasyon dışıdır\n- `getEditorText()` `\"\"` değerini döndürür\n- `getToolsExpanded()` `false` değerini döndürür\n- `pasteToEditor()` `setEditorText()`'ye yetki verir (yapıştırma/daraltma işlemi yoktur)\n- `getAllThemes()` `[]` değerini döndürür\n- `getTheme()` `undefined` değerini döndürür\n- `setTheme()` `{ success: false, error: \"...\" }` değerini döndürür\n\nNot: RPC modunda `ctx.mode` `\"rpc\"` ve `ctx.hasUI` `true`'dir çünkü diyalog ve ateşle ve unut yöntemleri, uzantı kullanıcı arayüzü alt protokolü aracılığıyla işlevseldir. Gerçek bir terminal gerektiren `custom()` gibi TUI'ye özgü özellikleri korumak için `ctx.mode === \"tui\"` kullanın.\n\n### Uzantı Kullanıcı Arayüzü İstekleri (stdout)\n\nTüm isteklerin `type: \"extension_ui_request\"`, benzersiz bir `id` ve `method` alanı vardır.\n\n#### seçme\n\nKullanıcıdan listeden seçim yapmasını isteyin. `timeout` alanına sahip iletişim yöntemleri milisaniye cinsinden zaman aşımını içerir; müşteri zamanında yanıt vermezse temsilci `undefined` ile otomatik olarak çözer.\n\n```json\n{\n  \"type\": \"extension_ui_request\",\n  \"id\": \"uuid-1\",\n  \"method\": \"select\",\n  \"title\": \"Allow dangerous command?\",\n  \"options\": [\"Allow\", \"Block\"],\n  \"timeout\": 10000\n}\n```\n\nBeklenen yanıt: `extension_ui_response` ile `value` (seçilen seçenek dizisi) veya `cancelled: true`.\n\n#### onaylamak\n\nKullanıcıdan evet/hayır onayı isteyin.\n\n```json\n{\n  \"type\": \"extension_ui_request\",\n  \"id\": \"uuid-2\",\n  \"method\": \"confirm\",\n  \"title\": \"Clear session?\",\n  \"message\": \"All messages will be lost.\",\n  \"timeout\": 5000\n}\n```\n\nBeklenen yanıt: `extension_ui_response` ile `confirmed: true/false` veya `cancelled: true`.\n\n#### giriş\n\nKullanıcıdan serbest biçimli metin isteyin.\n\n```json\n{\n  \"type\": \"extension_ui_request\",\n  \"id\": \"uuid-3\",\n  \"method\": \"input\",\n  \"title\": \"Enter a value\",\n  \"placeholder\": \"type something...\"\n}\n```\n\nBeklenen yanıt: `extension_ui_response` ile `value` (girilen metin) veya `cancelled: true`.\n\n#### editör\n\nİsteğe bağlı önceden doldurulmuş içeriğe sahip çok satırlı bir metin düzenleyiciyi açın.\n\n```json\n{\n  \"type\": \"extension_ui_request\",\n  \"id\": \"uuid-4\",\n  \"method\": \"editor\",\n  \"title\": \"Edit some text\",\n  \"prefill\": \"Line 1\\nLine 2\\nLine 3\"\n}\n```\n\nBeklenen yanıt: `extension_ui_response` ile `value` (düzenlenen metin) veya `cancelled: true`.\n\n#### bildirmek\n\nBir bildirim görüntüleyin. Ateşle ve unut, herhangi bir yanıt beklenmiyor.\n\n```json\n{\n  \"type\": \"extension_ui_request\",\n  \"id\": \"uuid-5\",\n  \"method\": \"notify\",\n  \"message\": \"Command blocked by user\",\n  \"notifyType\": \"warning\"\n}\n```\n\n`notifyType` alanı `\"info\"`, `\"warning\"` veya `\"error\"`'dir. Atlanırsa varsayılan olarak `\"info\"` olur.\n\n#### setDurum\n\nAlt bilgi/durum çubuğunda bir durum girişi ayarlayın veya temizleyin. Ateşle ve unut.\n\n```json\n{\n  \"type\": \"extension_ui_request\",\n  \"id\": \"uuid-6\",\n  \"method\": \"setStatus\",\n  \"statusKey\": \"my-ext\",\n  \"statusText\": \"Turn 3 running...\"\n}\n```\n\nSöz konusu tuşun durum girişini temizlemek için `statusText: undefined` gönderin (veya atlayın).\n\n#### setWidget'ı\n\nDüzenleyicinin üstünde veya altında görüntülenen bir widget'ı (metin satırları bloğu) ayarlayın veya temizleyin. Ateşle ve unut.\n\n```json\n{\n  \"type\": \"extension_ui_request\",\n  \"id\": \"uuid-7\",\n  \"method\": \"setWidget\",\n  \"widgetKey\": \"my-ext\",\n  \"widgetLines\": [\"--- My Widget ---\", \"Line 1\", \"Line 2\"],\n  \"widgetPlacement\": \"aboveEditor\"\n}\n```\n\nWidget'ı temizlemek için `widgetLines: undefined` gönderin (veya atlayın). `widgetPlacement` alanı `\"aboveEditor\"` (varsayılan) veya `\"belowEditor\"`'dir. RPC modunda yalnızca dize dizileri desteklenir; bileşen fabrikaları göz ardı edilir.\n\n#### setTitle\n\nTerminal penceresi/sekme başlığını ayarlayın. Ateşle ve unut.\n\n```json\n{\n  \"type\": \"extension_ui_request\",\n  \"id\": \"uuid-8\",\n  \"method\": \"setTitle\",\n  \"title\": \"pi - my project\"\n}\n```\n\n#### set_editor_text\n\nGiriş düzenleyicisinde metni ayarlayın. Ateşle ve unut.\n\n```json\n{\n  \"type\": \"extension_ui_request\",\n  \"id\": \"uuid-9\",\n  \"method\": \"set_editor_text\",\n  \"text\": \"prefilled text for the user\"\n}\n```\n\n### Uzantı Kullanıcı Arayüzü Yanıtları (stdin)\n\nYanıtlar yalnızca iletişim yöntemleri için gönderilir (`select`, `confirm`, `input`, `editor`). `id` istekle eşleşmelidir.\n\n#### Değer yanıtı (seç, gir, düzenle)\n\n```json\n{\"type\": \"extension_ui_response\", \"id\": \"uuid-1\", \"value\": \"Allow\"}\n```\n\n#### Onay yanıtı (onayla)\n\n```json\n{\"type\": \"extension_ui_response\", \"id\": \"uuid-2\", \"confirmed\": true}\n```\n\n#### İptal yanıtı (herhangi bir iletişim kutusu)\n\nHerhangi bir diyalog yöntemini reddedin. Uzantı `undefined` (seçim/giriş/düzenleyici için) veya `false` (onay için) alır.\n\n```json\n{\"type\": \"extension_ui_response\", \"id\": \"uuid-3\", \"cancelled\": true}\n```\n\n## Hata İşleme\n\nBaşarısız olan komutlar `success: false` ile bir yanıt döndürür:\n\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"set_model\",\n  \"success\": false,\n  \"error\": \"Model not found: invalid/model\"\n}\n```\n\nAyrıştırma hataları:\n\n```json\n{\n  \"type\": \"response\",\n  \"command\": \"parse\",\n  \"success\": false,\n  \"error\": \"Failed to parse command: Unexpected token...\"\n}\n```\n\n## Türler\n\nKaynak dosyaları:\n- [`packages/ai/src/types.ts`](../../ai/src/types.ts) - `Model`, `UserMessage`, `AssistantMessage`, `ToolResultMessage`\n- [`packages/agent/src/types.ts`](../../agent/src/types.ts) - `AgentMessage`, `AgentEvent`\n- [`src/core/messages.ts`](../src/core/messages.ts) - `BashExecutionMessage`\n- [`src/modes/json-event.ts`](../src/modes/json-event.ts) - `JsonAgentSessionEvent`\n- [`src/modes/rpc/rpc-types.ts`](../src/modes/rpc/rpc-types.ts) - RPC komut/yanıt türleri, uzantı kullanıcı arayüzü istek/yanıt türleri\n\n### Modeli\n\n```json\n{\n  \"id\": \"claude-sonnet-4-20250514\",\n  \"name\": \"Claude Sonnet 4\",\n  \"api\": \"anthropic-messages\",\n  \"provider\": \"anthropic\",\n  \"baseUrl\": \"https://api.anthropic.com\",\n  \"reasoning\": true,\n  \"input\": [\"text\", \"image\"],\n  \"contextWindow\": 200000,\n  \"maxTokens\": 16384,\n  \"cost\": {\n    \"input\": 3.0,\n    \"output\": 15.0,\n    \"cacheRead\": 0.3,\n    \"cacheWrite\": 3.75\n  }\n}\n```\n\n### Kullanıcı Mesajı\n\n```json\n{\n  \"role\": \"user\",\n  \"content\": \"Hello!\",\n  \"timestamp\": 1733234567890,\n  \"attachments\": []\n}\n```\n\n`content` alanı bir dize veya `TextContent`/`ImageContent` bloklardan oluşan bir dizi olabilir.\n\n### AsistanMesajı\n\n```json\n{\n  \"role\": \"assistant\",\n  \"content\": [\n    {\"type\": \"text\", \"text\": \"Hello! How can I help?\"},\n    {\"type\": \"thinking\", \"thinking\": \"User is greeting me...\"},\n    {\"type\": \"toolCall\", \"id\": \"call_123\", \"name\": \"bash\", \"arguments\": {\"command\": \"ls\"}}\n  ],\n  \"api\": \"anthropic-messages\",\n  \"provider\": \"anthropic\",\n  \"model\": \"claude-sonnet-4-20250514\",\n  \"usage\": {\n    \"input\": 100,\n    \"output\": 50,\n    \"cacheRead\": 0,\n    \"cacheWrite\": 0,\n    \"cost\": {\"input\": 0.0003, \"output\": 0.00075, \"cacheRead\": 0, \"cacheWrite\": 0, \"total\": 0.00105}\n  },\n  \"stopReason\": \"stop\",\n  \"timestamp\": 1733234567890\n}\n```\n\nDurdurma nedenleri: `\"stop\"`, `\"length\"`, `\"toolUse\"`, `\"error\"`, `\"aborted\"`\n\n### AraçSonucuMesajı\n\n```json\n{\n  \"role\": \"toolResult\",\n  \"toolCallId\": \"call_123\",\n  \"toolName\": \"bash\",\n  \"content\": [{\"type\": \"text\", \"text\": \"total 48\\ndrwxr-xr-x ...\"}],\n  \"usage\": {\n    \"input\": 100,\n    \"output\": 50,\n    \"cacheRead\": 0,\n    \"cacheWrite\": 0,\n    \"totalTokens\": 150,\n    \"cost\": {\"input\": 0.0003, \"output\": 0.00075, \"cacheRead\": 0, \"cacheWrite\": 0, \"total\": 0.00105}\n  },\n  \"isError\": false,\n  \"timestamp\": 1733234567890\n}\n```\n\n`usage` isteğe bağlıdır ve araç tarafından gerçekleştirilen iç içe geçmiş LLM çalışmasını raporlar. Mevcut olduğunda oturum belirtecine ve maliyet toplamlarına katkıda bulunur.\n\n### BashYürütmeMesajı\n\n`bash` RPC komutuyla oluşturulmuştur (LLM araç çağrıları tarafından değil):\n\n```json\n{\n  \"role\": \"bashExecution\",\n  \"command\": \"ls -la\",\n  \"output\": \"total 48\\ndrwxr-xr-x ...\",\n  \"exitCode\": 0,\n  \"cancelled\": false,\n  \"truncated\": false,\n  \"fullOutputPath\": null,\n  \"timestamp\": 1733234567890\n}\n```\n\n### EK\n\n```json\n{\n  \"id\": \"img1\",\n  \"type\": \"image\",\n  \"fileName\": \"photo.jpg\",\n  \"mimeType\": \"image/jpeg\",\n  \"size\": 102400,\n  \"content\": \"base64-encoded-data...\",\n  \"extractedText\": null,\n  \"preview\": null\n}\n```\n\n## Örnek: Temel İstemci (Python)\n\n```python\nimport subprocess\nimport json\n\nproc = subprocess.Popen(\n    [\"pi\", \"--mode\", \"rpc\", \"--no-session\"],\n    stdin=subprocess.PIPE,\n    stdout=subprocess.PIPE,\n    text=True\n)\n\ndef send(cmd):\n    proc.stdin.write(json.dumps(cmd) + \"\\n\")\n    proc.stdin.flush()\n\ndef read_events():\n    for line in proc.stdout:\n        yield json.loads(line)\n\n# Send prompt\nsend({\"type\": \"prompt\", \"message\": \"Hello!\"})\n\n# Process events\nfor event in read_events():\n    if event.get(\"type\") == \"message_update\":\n        delta = event.get(\"assistantMessageEvent\", {})\n        if delta.get(\"type\") == \"text_delta\":\n            print(delta[\"delta\"], end=\"\", flush=True)\n    \n    if event.get(\"type\") == \"agent_end\":\n        print()\n        break\n```\n\n## Örnek: Etkileşimli İstemci (Node.js)\n\nTam bir etkileşimli örnek için [`test/rpc-example.ts`](../test/rpc-example.ts)'ye veya yazılan bir istemci uygulaması için [`src/modes/rpc/rpc-client.ts`](../src/modes/rpc/rpc-client.ts)'ye bakın.\n\nUzantı kullanıcı arayüzü protokolünü işlemeye ilişkin tam bir örnek için, [`examples/extensions/rpc-demo.ts`](../examples/extensions/rpc-demo.ts) uzantısıyla eşleşen [`examples/rpc-extension-ui.ts`](../examples/rpc-extension-ui.ts)'ye bakın.\n\n```javascript\nconst { spawn } = require(\"child_process\");\nconst { StringDecoder } = require(\"string_decoder\");\n\nconst agent = spawn(\"pi\", [\"--mode\", \"rpc\", \"--no-session\"]);\n\nfunction attachJsonlReader(stream, onLine) {\n    const decoder = new StringDecoder(\"utf8\");\n    let buffer = \"\";\n\n    stream.on(\"data\", (chunk) => {\n        buffer += typeof chunk === \"string\" ? chunk : decoder.write(chunk);\n\n        while (true) {\n            const newlineIndex = buffer.indexOf(\"\\n\");\n            if (newlineIndex === -1) break;\n\n            let line = buffer.slice(0, newlineIndex);\n            buffer = buffer.slice(newlineIndex + 1);\n            if (line.endsWith(\"\\r\")) line = line.slice(0, -1);\n            onLine(line);\n        }\n    });\n\n    stream.on(\"end\", () => {\n        buffer += decoder.end();\n        if (buffer.length > 0) {\n            onLine(buffer.endsWith(\"\\r\") ? buffer.slice(0, -1) : buffer);\n        }\n    });\n}\n\nattachJsonlReader(agent.stdout, (line) => {\n    const event = JSON.parse(line);\n\n    if (event.type === \"message_update\") {\n        const { assistantMessageEvent } = event;\n        if (assistantMessageEvent.type === \"text_delta\") {\n            process.stdout.write(assistantMessageEvent.delta);\n        }\n    }\n});\n\n// Send prompt\nagent.stdin.write(JSON.stringify({ type: \"prompt\", message: \"Hello\" }) + \"\\n\");\n\n// Abort on Ctrl+C\nprocess.on(\"SIGINT\", () => {\n    agent.stdin.write(JSON.stringify({ type: \"abort\" }) + \"\\n\");\n});\n```","sourceFile":"rpc.md"},"sdk":{"title":"SDK","markdown":"> pi, SDK'yi kullanmanıza yardımcı olabilir. Kullanım durumunuz için bir entegrasyon oluşturmasını isteyin.\n\n\nSDK pi'nin aracı yeteneklerine programlı erişim sağlar. Pi'yi diğer uygulamalara eklemek, özel arayüzler oluşturmak veya otomatik iş akışlarıyla entegre etmek için kullanın.\n\n**Örnek kullanım durumları:**\n- Özel bir kullanıcı arayüzü oluşturun (web, masaüstü, mobil)\n- Aracı yeteneklerini mevcut uygulamalara entegre edin\n- Aracı mantığıyla otomatik işlem hatları oluşturun\n- Alt aracıları ortaya çıkaran özel araçlar oluşturun\n- Aracı davranışını programlı olarak test edin\n\nMinimumdan tam kontrole kadar çalışma örnekleri için [examples/sdk/](../examples/sdk/)'e bakın.\n\n## Hızlı Başlangıç\n\n```typescript\nimport { createAgentSession, ModelRuntime, SessionManager } from \"@earendil-works/pi-coding-agent\";\n\nconst modelRuntime = await ModelRuntime.create();\nconst { session } = await createAgentSession({\n  sessionManager: SessionManager.inMemory(),\n  modelRuntime,\n});\n\nsession.subscribe((event) => {\n  if (event.type === \"message_update\" && event.assistantMessageEvent.type === \"text_delta\") {\n    process.stdout.write(event.assistantMessageEvent.delta);\n  }\n});\n\nawait session.prompt(\"What files are in the current directory?\");\n```\n\n## Kurulum\n\n```bash\nnpm install @earendil-works/pi-coding-agent\n```\n\nSDK ana pakete dahildir. Ayrı bir kuruluma gerek yoktur.\n\n## Temel Kavramlar\n\n### createAgentSession()\n\nTek bir `AgentSession` için ana fabrika işlevi.\n\n`createAgentSession()`, uzantıları, becerileri, prompt templates, temaları ve context files sağlamak için `ResourceLoader`'yi kullanır. Eğer bir tane sağlamazsanız standart keşifle `DefaultResourceLoader` kullanır.\n\n```typescript\nimport { createAgentSession, SessionManager } from \"@earendil-works/pi-coding-agent\";\n\n// Minimal: defaults with DefaultResourceLoader\nconst { session } = await createAgentSession();\n\n// Custom: override specific options\nconst { session } = await createAgentSession({\n  model: myModel,\n  tools: [\"read\", \"bash\"],\n  sessionManager: SessionManager.inMemory(),\n});\n```\n\n### Temsilci Oturumu\n\nOturum, aracı yaşam döngüsünü, mesaj geçmişini, model durumunu, sıkıştırmayı ve olay akışını yönetir.\n\n```typescript\ninterface AgentSession {\n  // Send a prompt and wait for completion\n  prompt(text: string, options?: PromptOptions): Promise<void>;\n\n  // Queue messages during streaming\n  steer(text: string): Promise<void>;\n  followUp(text: string): Promise<void>;\n\n  // Subscribe to events (returns unsubscribe function)\n  subscribe(listener: (event: AgentSessionEvent) => void): () => void;\n\n  // Session info\n  sessionFile: string | undefined;\n  sessionId: string;\n\n  // Model control\n  setModel(model: Model): Promise<void>;\n  setThinkingLevel(level: ThinkingLevel): void;\n  cycleModel(): Promise<ModelCycleResult | undefined>;\n  cycleThinkingLevel(): ThinkingLevel | undefined;\n\n  // State access\n  agent: Agent;\n  model: Model | undefined;\n  thinkingLevel: ThinkingLevel;\n  messages: AgentMessage[];\n  isStreaming: boolean;\n\n  // In-place tree navigation within the current session file\n  navigateTree(targetId: string, options?: { summarize?: boolean; customInstructions?: string; replaceInstructions?: boolean; label?: string }): Promise<{ editorText?: string; cancelled: boolean }>;\n\n  // Compaction\n  compact(customInstructions?: string): Promise<CompactionResult>;\n  abortCompaction(): void;\n\n  // Abort current operation\n  abort(): Promise<void>;\n\n  // Cleanup\n  dispose(): void;\n}\n```\n\nYeni oturum, özgeçmiş, çatal ve içe aktarma gibi oturum değiştirme API'ler, `AgentSession`'de değil, `AgentSessionRuntime`'da yayındadır.\n\n### createAgentSessionRuntime() ve AgentSessionRuntime\n\nEtkin oturumu değiştirmeniz ve cwd'ye bağlı çalışma zamanı durumunu yeniden oluşturmanız gerektiğinde API çalışma zamanını kullanın.\nBu, yerleşik etkileşimli, yazdırma ve RPC modları tarafından kullanılan katmanın aynısıdır.\n\n`createAgentSessionRuntime()` çalışma zamanı fabrikasını artı başlangıç ​​cwd/oturum hedefini alır. Fabrika, süreç geneli sabit girdiler üzerinden kapanır, etkili cwd için cwd'ye bağlı hizmetleri yeniden oluşturur, bu hizmetlere göre oturum seçeneklerini çözümler ve tam çalışma zamanı sonucunu döndürür.\n\n```typescript\nimport {\n  type CreateAgentSessionRuntimeFactory,\n  createAgentSessionFromServices,\n  createAgentSessionRuntime,\n  createAgentSessionServices,\n  getAgentDir,\n  SessionManager,\n} from \"@earendil-works/pi-coding-agent\";\n\nconst createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {\n  const services = await createAgentSessionServices({ cwd });\n  return {\n    ...(await createAgentSessionFromServices({\n      services,\n      sessionManager,\n      sessionStartEvent,\n    })),\n    services,\n    diagnostics: services.diagnostics,\n  };\n};\n\nconst runtime = await createAgentSessionRuntime(createRuntime, {\n  cwd: process.cwd(),\n  agentDir: getAgentDir(),\n  sessionManager: SessionManager.create(process.cwd()),\n});\n```\n\n`AgentSessionRuntime` aşağıdakiler arasında etkin çalışma zamanının değiştirilmesine sahiptir:\n\n- `newSession()`\n- `switchSession()`\n- `fork()`\n- klon `fork(entryId, { position: \"at\" })` üzerinden akar\n- `importFromJsonl()`\n\nÖnemli davranış:\n\n- `runtime.session` bu işlemlerden sonraki değişiklikler\n- etkinlik abonelikleri belirli bir `AgentSession`'ye bağlıdır, bu nedenle değiştirdikten sonra yeniden abone olun\n- Uzantı kullanıyorsanız yeni oturum için `runtime.session.bindExtensions(...)`'ı tekrar arayın\n- oluşturma `runtime.diagnostics`'de teşhis döndürür\n- çalışma zamanı oluşturma veya değiştirme başarısız olursa, yöntem çalışır ve arayan kişi bunun nasıl ele alınacağına karar verir\n\n```typescript\nlet session = runtime.session;\nlet unsubscribe = session.subscribe(() => {});\n\nawait runtime.newSession();\n\nunsubscribe();\nsession = runtime.session;\nunsubscribe = session.subscribe(() => {});\n```\n\n### İstemde Bulunma ve Mesaj Kuyruğa Alma\n\n`PromptOptions` istem genişletmeyi, akış sırasında sıraya alma davranışını ve istem ön kontrol bildirimlerini kontrol eder:\n\n```typescript\ninterface PromptOptions {\n  expandPromptTemplates?: boolean;\n  images?: ImageContent[];\n  streamingBehavior?: \"steer\" | \"followUp\";\n  source?: InputSource;\n  preflightResult?: (success: boolean) => void;\n}\n```\n\n`preflightResult`, `prompt()` çağrı başına bir kez çağrılır:\n\n- `true` istemin kabul edildiği, kuyruğa alındığı veya hemen işlendiği zaman\n- `false` istem ön kontrolü kabul edilmeden önce reddedildiğinde\n\n`prompt()` çözümlenmeden önce ateşlenir. `prompt()` yeniden denemeler de dahil olmak üzere yalnızca kabul edilen çalıştırmanın tamamı bittikten sonra çözümlenmeye devam ediyor. Kabulden sonraki arızalar `preflightResult(false)` aracılığıyla değil, normal olay ve mesaj akışı aracılığıyla raporlanır.\n\n`prompt()` yöntemi prompt templates'yi, uzantı komutlarını ve mesaj göndermeyi yönetir:\n\n```typescript\n// Basic prompt (when not streaming)\nawait session.prompt(\"What files are here?\");\n\n// With images\nawait session.prompt(\"What's in this image?\", {\n  images: [{ type: \"image\", source: { type: \"base64\", mediaType: \"image/png\", data: \"...\" } }]\n});\n\n// During streaming: must specify how to queue the message\nawait session.prompt(\"Stop and do this instead\", { streamingBehavior: \"steer\" });\nawait session.prompt(\"After you're done, also check X\", { streamingBehavior: \"followUp\" });\n```\n\n**Davranış:**\n- **Uzantı komutları** (ör. `/mycommand`): Yayın sırasında bile hemen yürütülür. Kendi LLM etkileşimlerini `pi.sendMessage()` aracılığıyla yönetirler.\n- **Dosya tabanlı prompt templates** (`.md` dosyalardan): Göndermeden veya kuyruğa almadan önce içeriklerine genişletilir.\n- **`streamingBehavior` olmadan akış sırasında**: Bir hata verir. Doğrudan `steer()` veya `followUp()` kullanın veya seçeneği belirtin.\n- **`preflightResult(true)`**: İstemin hemen kabul edildiği, kuyruğa alındığı veya işlendiği anlamına gelir.\n- **`preflightResult(false)`**: Ön kontrolün kabul edilmeden önce reddedildiği anlamına gelir.\n\nAkış sırasında açık sıraya alma için:\n\n```typescript\n// Queue a steering message for delivery after the current assistant turn finishes its tool calls\nawait session.steer(\"New instruction\");\n\n// Wait for agent to finish (delivered only when agent stops)\nawait session.followUp(\"After you're done, also do this\");\n```\n\nHem `steer()` hem de `followUp()` dosya tabanlı prompt templates'yi genişletiyor ancak uzantı komutlarında hata var (uzantı komutları sıraya alınamıyor).\n\n### Acente ve Acente Durumu\n\n`Agent` sınıfı (`@earendil-works/pi-agent-core`'den itibaren) temel LLM etkileşimini yönetir. `session.agent` aracılığıyla erişin.\n\n```typescript\n// Access current state\nconst state = session.agent.state;\n\n// state.messages: AgentMessage[] - conversation history\n// state.model: Model - current model\n// state.thinkingLevel: ThinkingLevel - current thinking level\n// state.systemPrompt: string - system prompt\n// state.tools: AgentTool[] - available tools\n// state.streamingMessage?: AgentMessage - current partial assistant message\n// state.errorMessage?: string - latest assistant error\n\n// Replace messages (useful for branching or restoration)\nsession.agent.state.messages = messages; // copies the top-level array\n\n// Replace tools\nsession.agent.state.tools = tools; // copies the top-level array\n\n// Wait for agent to finish processing\nawait session.agent.waitForIdle();\n```\n\n### Olaylar\n\nAkış çıktısı ve yaşam döngüsü bildirimlerini almak için etkinliklere abone olun.\n\n```typescript\nsession.subscribe((event) => {\n  switch (event.type) {\n    // Streaming text from assistant\n    case \"message_update\":\n      if (event.assistantMessageEvent.type === \"text_delta\") {\n        process.stdout.write(event.assistantMessageEvent.delta);\n      }\n      if (event.assistantMessageEvent.type === \"thinking_delta\") {\n        // Thinking output (if thinking enabled)\n      }\n      break;\n    \n    // Tool execution\n    case \"tool_execution_start\":\n      console.log(`Tool: ${event.toolName}`);\n      break;\n    case \"tool_execution_update\":\n      // Streaming tool output\n      break;\n    case \"tool_execution_end\":\n      console.log(`Result: ${event.isError ? \"error\" : \"success\"}`);\n      break;\n    \n    // Message lifecycle\n    case \"message_start\":\n      // New message starting\n      break;\n    case \"message_end\":\n      // Message complete\n      break;\n    \n    // Agent lifecycle\n    case \"agent_start\":\n      // Agent started processing prompt\n      break;\n    case \"agent_end\":\n      // Agent finished (event.messages contains new messages)\n      break;\n    \n    // Turn lifecycle (one LLM response + tool calls)\n    case \"turn_start\":\n      break;\n    case \"turn_end\":\n      // event.message: assistant response\n      // event.toolResults: tool results from this turn\n      break;\n    \n    // Session events (queue, compaction, retry)\n    case \"queue_update\":\n      console.log(event.steering, event.followUp);\n      break;\n    case \"compaction_start\":\n    case \"compaction_end\":\n    case \"auto_retry_start\":\n    case \"auto_retry_end\":\n    case \"summarization_retry_scheduled\":\n    case \"summarization_retry_attempt_start\":\n    case \"summarization_retry_finished\":\n      break;\n  }\n});\n```\n\n## Seçenek Referansı\n\n### Dizinler\n\n```typescript\nconst { session } = await createAgentSession({\n  // Working directory for DefaultResourceLoader discovery\n  cwd: process.cwd(), // default\n  \n  // Global config directory\n  agentDir: \"~/.pi/agent\", // default (expands ~)\n});\n```\n\n`cwd`, `DefaultResourceLoader` tarafından şu amaçlarla kullanılır:\n- Proje uzantıları (`.pi/extensions/`)\n- Proje becerileri:\n  - `.pi/skills/`\n  - `cwd` ve ata dizinlerinde `.agents/skills/` (git repo köküne veya repoda olmadığında dosya sistemi köküne kadar)\n- Proje istemleri (`.pi/prompts/`)\n- Bağlam dosyaları (`AGENTS.md` cwd'den yukarı doğru yürürken)\n- Oturum dizini adlandırma\n\n`agentDir`, `DefaultResourceLoader` tarafından şu amaçlarla kullanılır:\n- Küresel uzantılar (`extensions/`)\n- Küresel beceriler:\n  - `skills/` `agentDir`'nin altında (örneğin `~/.pi/agent/skills/`)\n  - `~/.agents/skills/`\n- Genel istemler (`prompts/`)\n- Genel içerik dosyası (`AGENTS.md`)\n- Ayarlar (`settings.json`)\n- Özel modeller (`models.json`)\n- Kimlik Bilgileri (`auth.json`)\n- Oturumlar (`sessions/`)\n\nÖzel bir `ResourceLoader`, `cwd` ve `agentDir`'yi ilettiğinizde artık kaynak keşfi kontrol edilmez. Bunlar hâlâ oturum adlandırma ve araç yolu çözümlemesini etkilemektedir.\n\n### Modeli\n\n```typescript\nimport { getModel } from \"@earendil-works/pi-ai\";\nimport { ModelRuntime } from \"@earendil-works/pi-coding-agent\";\n\nconst modelRuntime = await ModelRuntime.create();\n\n// Find specific built-in model (doesn't check if API key exists)\nconst opus = getModel(\"anthropic\", \"claude-opus-4-5\");\nif (!opus) throw new Error(\"Model not found\");\n\n// Find any model by provider/id, including custom models from models.json\n// (doesn't check if API key exists)\nconst customModel = modelRuntime.getModel(\"my-provider\", \"my-model\");\n\n// Get only models that have valid authentication configured\nconst available = await modelRuntime.getAvailable();\n\nconst { session } = await createAgentSession({\n  model: opus,\n  thinkingLevel: \"medium\", // off, minimal, low, medium, high, xhigh, max\n  \n  // Models for cycling (Ctrl+P in interactive mode)\n  scopedModels: [\n    { model: opus, thinkingLevel: \"high\" },\n    { model: haiku, thinkingLevel: \"off\" },\n  ],\n  \n  modelRuntime,\n});\n```\n\nHerhangi bir model sağlanmadıysa:\n1. Oturumdan geri yüklemeye çalışır (devam ediyorsa)\n2. Ayarlardaki varsayılanı kullanır\n3. Mevcut ilk modele geri döner\n\nCLI model ayrıştırmayı eşleştirmek için dışa aktarılan çözümleyici yardımcılarını kullanın:\n\n```typescript\nimport {\n  resolveCliModel,\n  resolveModelScopeWithDiagnostics,\n} from \"@earendil-works/pi-coding-agent\";\n\nconst cliModel = resolveCliModel({\n  cliModel: \"anthropic/claude-opus-4-5:high\",\n  modelRuntime,\n});\nif (cliModel.error) throw new Error(cliModel.error);\nif (cliModel.warning) console.warn(cliModel.warning);\n\nconst { scopedModels, diagnostics } = await resolveModelScopeWithDiagnostics(\n  [\"anthropic/*:high\", \"gpt-5\"],\n  modelRuntime,\n);\nfor (const diagnostic of diagnostics) {\n  console.warn(diagnostic.message);\n}\n```\n\n`resolveCliModel()` tüm kayıtlı modelleri kullanır, böylece `--api-key` tarzı ilk kurulum, kayıtlı kimlik doğrulama mevcut olmadan önce bir modeli çözebilir. `resolveModelScopeWithDiagnostics()`, uyarıları yazdırmak yerine geri döndürürken `--models` ve `enabledModels` anlambilimiyle eşleşir.\n\n> Bkz. [examples/sdk/02-custom-model.ts](../examples/sdk/02-custom-model.ts)\n\n### API Tuşlar ve OAuth\n\nKimlik doğrulama çözümleme önceliği (`ModelRuntime` tarafından yönetilir):\n1. Çalışma zamanı geçersiz kılmaları (`setRuntimeApiKey` aracılığıyla, kalıcı değil)\n2. Kimlik bilgileri `auth.json` (API keys veya OAuth jetonları) içinde depolanır\n3. Ortam değişkenleri (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, vb.)\n4. Geri dönüş çözümleyici (`models.json`'den itibaren özel sağlayıcı anahtarları için)\n\n```typescript\nimport { InMemoryCredentialStore } from \"@earendil-works/pi-ai\";\nimport { createAgentSession, ModelRuntime } from \"@earendil-works/pi-coding-agent\";\n\n// Default: uses ~/.pi/agent/auth.json and ~/.pi/agent/models.json\nconst modelRuntime = await ModelRuntime.create();\n\n// Provider-owned auth methods and current status\nfor (const provider of modelRuntime.getProviders()) {\n  const status = await modelRuntime.checkAuth(provider.id);\n  console.log(provider.name, provider.auth, status);\n}\n\n// Runtime API key override (not persisted to disk)\nawait modelRuntime.setRuntimeApiKey(\"anthropic\", \"sk-my-temp-key\");\n\n// Custom credential and model locations\nconst customRuntime = await ModelRuntime.create({\n  authPath: \"/my/app/auth.json\",\n  modelsPath: \"/my/app/models.json\",\n});\n\n// Or inject any pi-ai CredentialStore\nconst credentials = new InMemoryCredentialStore();\nconst inMemoryRuntime = await ModelRuntime.create({ credentials });\n\nconst { session } = await createAgentSession({\n  modelRuntime: customRuntime,\n});\n```\n\n`login()`, `logout()`, `setRuntimeApiKey()` ve `removeRuntimeApiKey()`, etkilenen sağlayıcının önbelleğe alınmış/yerleşik kataloğu, kompozisyonu ve kullanılabilirlik anlık görüntüsünün yerel olarak tutarlı olmasından sonra çözümlenir. Uzaktan katalog tazeliğini beklemiyorlar. Kimlik bilgileri kaydedildiyse ancak yerel senkronizasyon başarısız olursa, dışa aktarılan `CredentialSynchronizationError` ile reddedilir; Kimlik bilgisi mutasyonunu körü körüne yeniden denemek yerine `providerId`, `operation`, `credential` ve `cause` alanlarını inceleyin.\n\nGenel model/kimlik doğrulama işlemleri ve `ModelRuntime.create({ signal })` isteğe bağlı iptal sinyallerini kabul eder ve atlandığında sınırsızdır. SDK uygulamaların uzaktan kataloğun güncellenmesi için kendi son tarih politikası:\n\n```typescript\nconst signal = AbortSignal.timeout(15_000);\nconst result = await modelRuntime.refresh({\n  providers: [\"anthropic\"],\n  signal,\n});\nif (result.aborted) console.warn(\"Catalog refresh timed out; using cached models\");\nfor (const [providerId, error] of result.errors) {\n  console.warn(`Could not refresh ${providerId}:`, error);\n}\n```\n\nBaşarısız olan veya zaman aşımına uğrayan bir ağ yenilemesi, başarılı bir kimlik bilgisi işlemini geri almaz. `refresh()` yeni bir sağlayıcı nesli başlatır, böylece eski durmuş yenilemenin arkasında beklemez ve eski nesiller daha sonra yayınlayamaz.\n\n> Bkz. [examples/sdk/09-api-keys-and-oauth.ts](../examples/sdk/09-api-keys-and-oauth.ts)\n\n### Sistem İstemi\n\nSistem istemini geçersiz kılmak için `ResourceLoader` kullanın:\n\n```typescript\nimport { createAgentSession, DefaultResourceLoader } from \"@earendil-works/pi-coding-agent\";\n\nconst loader = new DefaultResourceLoader({\n  systemPromptOverride: () => \"You are a helpful assistant.\",\n});\nawait loader.reload();\n\nconst { session } = await createAgentSession({ resourceLoader: loader });\n```\n\n> Bkz. [examples/sdk/03-custom-prompt.ts](../examples/sdk/03-custom-prompt.ts)\n\n### Aletler\n\nHangi yerleşik araçların etkinleştirileceğini belirtin:\n\n- Yerleşik araç adları: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`\n- Varsayılan yerleşikler: `read`, `bash`, `edit`, `write`\n- `noTools: \"all\"` tüm araçları devre dışı bırakır\n- `noTools: \"builtin\"` uzantıları ve özel araçları etkin tutarken varsayılan yerleşikleri devre dışı bırakır\n- `excludeTools` herhangi bir `tools` izin verilenler listesi uygulandıktan sonra belirli yerleşik, uzantı veya özel araç adlarını devre dışı bırakır\n\n`edit` aracı, Pi'nin TUI ekranı için `details.diff`'yi ve SDK tüketiciler için standart birleştirilmiş yama olarak `details.patch`'yi döndürür.\n\n```typescript\nimport { createAgentSession } from \"@earendil-works/pi-coding-agent\";\n\n// Read-only mode\nconst { session } = await createAgentSession({\n  tools: [\"read\", \"grep\", \"find\", \"ls\"],\n});\n\n// Pick specific tools\nconst { session } = await createAgentSession({\n  tools: [\"read\", \"bash\", \"grep\"],\n});\n\n// Disable one tool while keeping the rest available\nconst { session } = await createAgentSession({\n  excludeTools: [\"ask_question\"],\n});\n```\n\n#### Özel cwd'li araçlar\n\nÖzel bir `cwd` ilettiğinizde, `createAgentSession()` o cwd için seçilen yerleşik araçları oluşturur.\n\n```typescript\nimport { createAgentSession, SessionManager } from \"@earendil-works/pi-coding-agent\";\n\nconst cwd = \"/path/to/project\";\n\n// Use default tools for custom cwd\nconst { session } = await createAgentSession({\n  cwd,\n  sessionManager: SessionManager.inMemory(cwd),\n});\n\n// Or pick specific tools for custom cwd\nconst { session } = await createAgentSession({\n  cwd,\n  tools: [\"read\", \"bash\", \"grep\"],\n  sessionManager: SessionManager.inMemory(cwd),\n});\n```\n\n> Bkz. [examples/sdk/05-tools.ts](../examples/sdk/05-tools.ts)\n\n### Özel Araçlar\n\n```typescript\nimport { Type } from \"typebox\";\nimport { createAgentSession, defineTool } from \"@earendil-works/pi-coding-agent\";\n\n// Inline custom tool\nconst myTool = defineTool({\n  name: \"my_tool\",\n  label: \"My Tool\",\n  description: \"Does something useful\",\n  parameters: Type.Object({\n    input: Type.String({ description: \"Input value\" }),\n  }),\n  execute: async (_toolCallId, params) => ({\n    content: [{ type: \"text\", text: `Result: ${params.input}` }],\n    details: {},\n  }),\n});\n\n// Pass custom tools directly\nconst { session } = await createAgentSession({\n  customTools: [myTool],\n});\n```\n\nBağımsız tanımlar ve `customTools: [myTool]` gibi diziler için `defineTool()` kullanın. Satır içi `pi.registerTool({... })` parametre türlerini zaten doğru bir şekilde çıkarıyor.\n\n`customTools` aracılığıyla aktarılan özel araçlar, uzantıya kayıtlı araçlarla birleştirilir. ResourceLoader tarafından yüklenen Extensions aynı zamanda araçları `pi.registerTool()` aracılığıyla da kaydedebilir.\n\n`tools` değerini geçerseniz, etkinleştirilmesini istediğiniz her özel veya uzantı aracı adını ekleyin, örneğin `tools: [\"read\", \"bash\", \"my_tool\"]`.\n\n> Bkz. [examples/sdk/05-tools.ts](../examples/sdk/05-tools.ts)\n\n### Extensions\n\nExtensions, `ResourceLoader` tarafından yüklenir. `DefaultResourceLoader`, `~/.pi/agent/extensions/`, `.pi/extensions/` ve settings.json uzantı kaynaklarından uzantıları keşfeder.\n\n```typescript\nimport { createAgentSession, DefaultResourceLoader } from \"@earendil-works/pi-coding-agent\";\n\nconst loader = new DefaultResourceLoader({\n  additionalExtensionPaths: [\"/path/to/my-extension.ts\"],\n  extensionFactories: [\n    (pi) => {\n      pi.on(\"agent_start\", () => {\n        console.log(\"[Inline Extension] Agent starting\");\n      });\n    },\n  ],\n});\nawait loader.reload();\n\nconst { session } = await createAgentSession({ resourceLoader: loader });\n```\n\nExtensions araçları kaydedebilir, etkinliklere abone olabilir, komutlar ekleyebilir ve daha fazlasını yapabilir. API'nin tamamı için [extensions.md](extensions.md)'ye bakın.\n\n**Adlandırılmış satır içi uzantılar:** Varsayılan olarak, satır içi fabrikalar başlangıç ​​Extensions listesinde `<inline:1>`, `<inline:2>` vb. olarak görüntülenir. Bunun yerine açıklayıcı bir ad göstermek için fabrikayı sarın:\n\n```typescript\nimport type { InlineExtension } from \"@earendil-works/pi-coding-agent\";\n\nconst myProvider: InlineExtension = {\n  name: \"my-provider\",\n  factory: (pi) => {\n    pi.on(\"agent_start\", () => {\n      console.log(\"[my-provider] Agent starting\");\n    });\n  },\n};\n\nconst loader = new DefaultResourceLoader({\n  extensionFactories: [myProvider],\n});\n```\n\nBu, `<inline:1>` yerine `<inline:my-provider>` olarak görüntülenir. Geriye dönük uyumluluk açısından çıplak fabrika işlevleri hâlâ kabul edilmektedir.\n\n**Olay Veriyolu:** Extensions `pi.events` aracılığıyla iletişim kurabilir. Dışarıdan ses çıkarmanız veya dinlemeniz gerekiyorsa, paylaşılan `eventBus`'den `DefaultResourceLoader`'ye iletin:\n\n```typescript\nimport { createEventBus, DefaultResourceLoader } from \"@earendil-works/pi-coding-agent\";\n\nconst eventBus = createEventBus();\nconst loader = new DefaultResourceLoader({\n  eventBus,\n});\nawait loader.reload();\n\neventBus.on(\"my-extension:status\", (data) => console.log(data));\n```\n\n> Bkz. [examples/sdk/06-extensions.ts](../examples/sdk/06-extensions.ts) ve [docs/extensions.md](extensions.md)\n\n### Skills\n\n```typescript\nimport {\n  createAgentSession,\n  DefaultResourceLoader,\n  type Skill,\n} from \"@earendil-works/pi-coding-agent\";\n\nconst customSkill: Skill = {\n  name: \"my-skill\",\n  description: \"Custom instructions\",\n  filePath: \"/path/to/SKILL.md\",\n  baseDir: \"/path/to\",\n  source: \"custom\",\n};\n\nconst loader = new DefaultResourceLoader({\n  skillsOverride: (current) => ({\n    skills: [...current.skills, customSkill],\n    diagnostics: current.diagnostics,\n  }),\n});\nawait loader.reload();\n\nconst { session } = await createAgentSession({ resourceLoader: loader });\n```\n\n> Bkz. [examples/sdk/04-skills.ts](../examples/sdk/04-skills.ts)\n\n### Bağlam Dosyaları\n\n```typescript\nimport { createAgentSession, DefaultResourceLoader } from \"@earendil-works/pi-coding-agent\";\n\nconst loader = new DefaultResourceLoader({\n  agentsFilesOverride: (current) => ({\n    agentsFiles: [\n      ...current.agentsFiles,\n      { path: \"/virtual/AGENTS.md\", content: \"# Guidelines\\n\\n- Be concise\" },\n    ],\n  }),\n});\nawait loader.reload();\n\nconst { session } = await createAgentSession({ resourceLoader: loader });\n```\n\n> Bkz. [examples/sdk/07-context-files.ts](../examples/sdk/07-context-files.ts)\n\n### Eğik Çizgi Komutları\n\n```typescript\nimport {\n  createAgentSession,\n  DefaultResourceLoader,\n  type PromptTemplate,\n} from \"@earendil-works/pi-coding-agent\";\n\nconst customCommand: PromptTemplate = {\n  name: \"deploy\",\n  description: \"Deploy the application\",\n  source: \"(custom)\",\n  content: \"# Deploy\\n\\n1. Build\\n2. Test\\n3. Deploy\",\n};\n\nconst loader = new DefaultResourceLoader({\n  promptsOverride: (current) => ({\n    prompts: [...current.prompts, customCommand],\n    diagnostics: current.diagnostics,\n  }),\n});\nawait loader.reload();\n\nconst { session } = await createAgentSession({ resourceLoader: loader });\n```\n\n> Bkz. [examples/sdk/08-prompt-templates.ts](../examples/sdk/08-prompt-templates.ts)\n\n### Oturum Yönetimi\n\nOturumlar, yerinde dallanmaya olanak tanıyan `id`/`parentId` bağlantılı bir ağaç yapısı kullanır.\n\n```typescript\nimport {\n  type CreateAgentSessionRuntimeFactory,\n  createAgentSession,\n  createAgentSessionFromServices,\n  createAgentSessionRuntime,\n  createAgentSessionServices,\n  getAgentDir,\n  SessionManager,\n} from \"@earendil-works/pi-coding-agent\";\n\n// In-memory (no persistence)\nconst { session } = await createAgentSession({\n  sessionManager: SessionManager.inMemory(),\n});\n\n// New persistent session\nconst { session: persisted } = await createAgentSession({\n  sessionManager: SessionManager.create(process.cwd()),\n});\n\n// Continue most recent\nconst { session: continued, modelFallbackMessage } = await createAgentSession({\n  sessionManager: SessionManager.continueRecent(process.cwd()),\n});\nif (modelFallbackMessage) {\n  console.log(\"Note:\", modelFallbackMessage);\n}\n\n// Open specific file\nconst { session: opened } = await createAgentSession({\n  sessionManager: SessionManager.open(\"/path/to/session.jsonl\"),\n});\n\n// List sessions\nconst currentProjectSessions = await SessionManager.list(process.cwd());\nconst allSessions = await SessionManager.listAll(process.cwd());\n\n// Session replacement API for /new, /resume, /fork, /clone, and import flows.\nconst createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {\n  const services = await createAgentSessionServices({ cwd });\n  return {\n    ...(await createAgentSessionFromServices({\n      services,\n      sessionManager,\n      sessionStartEvent,\n    })),\n    services,\n    diagnostics: services.diagnostics,\n  };\n};\n\nconst runtime = await createAgentSessionRuntime(createRuntime, {\n  cwd: process.cwd(),\n  agentDir: getAgentDir(),\n  sessionManager: SessionManager.create(process.cwd()),\n});\n\n// Replace the active session with a fresh one\nawait runtime.newSession();\n\n// Replace the active session with another saved session\nawait runtime.switchSession(\"/path/to/session.jsonl\");\n\n// Replace the active session with a fork from a specific user entry\nawait runtime.fork(\"entry-id\");\n\n// Clone the active path through a specific entry\nawait runtime.fork(\"entry-id\", { position: \"at\" });\n```\n\n**SessionManager ağacı API:**\n\n```typescript\nconst sm = SessionManager.open(\"/path/to/session.jsonl\");\n\n// Session listing\nconst currentProjectSessions = await SessionManager.list(process.cwd());\nconst allSessions = await SessionManager.listAll(process.cwd());\n\n// Tree traversal\nconst entries = sm.getEntries();        // All entries (excludes header)\nconst tree = sm.getTree();              // Full tree structure\nconst path = sm.getPath();              // Path from root to current leaf\nconst leaf = sm.getLeafEntry();         // Current leaf entry\nconst entry = sm.getEntry(id);          // Get entry by ID\nconst children = sm.getChildren(id);    // Direct children of entry\n\n// Labels\nconst label = sm.getLabel(id);          // Get label for entry\nsm.appendLabelChange(id, \"checkpoint\"); // Set label\n\n// Branching\nsm.branch(entryId);                     // Move leaf to earlier entry\nsm.branchWithSummary(id, \"Summary...\");  // Branch with context summary\nsm.createBranchedSession(leafId);       // Extract path to new file\n```\n\n> Bkz. [examples/sdk/11-sessions.ts](../examples/sdk/11-sessions.ts) ve [Session Format](session-format.md)\n\n### Ayarlar Yönetimi\n\n```typescript\nimport { createAgentSession, SettingsManager, SessionManager } from \"@earendil-works/pi-coding-agent\";\n\n// Default: loads from files (global + project merged)\nconst { session } = await createAgentSession({\n  settingsManager: SettingsManager.create(),\n});\n\n// With overrides\nconst settingsManager = SettingsManager.create();\nsettingsManager.applyOverrides({\n  compaction: { enabled: false },\n  retry: { enabled: true, maxRetries: 5 },\n});\nconst { session } = await createAgentSession({ settingsManager });\n\n// In-memory (no file I/O, for testing)\nconst { session } = await createAgentSession({\n  settingsManager: SettingsManager.inMemory({ compaction: { enabled: false } }),\n  sessionManager: SessionManager.inMemory(),\n});\n\n// Custom directories\nconst { session } = await createAgentSession({\n  settingsManager: SettingsManager.create(\"/custom/cwd\", \"/custom/agent\"),\n});\n```\n\n**Statik fabrikalar:**\n- `SettingsManager.create(cwd?, agentDir?)` - Dosyalardan yükle\n- `SettingsManager.inMemory(settings?)` - Dosya G/Ç yok\n\n**Projeye özel ayarlar:**\n\nAyarlar iki konumdan yüklenir ve birleştirilir:\n1. Küresel: `~/.pi/agent/settings.json`\n2. Proje: `<cwd>/.pi/settings.json`\n\nProje globali geçersiz kılar. İç içe geçmiş nesneler anahtarları birleştirir. Ayarlayıcılar varsayılan olarak genel ayarları değiştirir.\n\n**Kalıcılık ve hata işleme anlambilimi:**\n\n- Ayar alıcıları/ayarlayıcıları bellek içi durum için eşzamanlıdır.\n- Ayarlayıcılar kalıcılık yazmalarını eşzamansız olarak kuyruğa alır.\n- Dayanıklılık sınırına ihtiyaç duyduğunuzda (örneğin, işlemden çıkmadan önce veya testlerde dosya içeriklerini belirtmeden önce) `await settingsManager.flush()`'ı çağırın.\n- `SettingsManager` ayarlar G/Ç hatalarını yazdırmaz. `settingsManager.drainErrors()` kullanın ve bunları uygulama katmanınızda raporlayın.\n\n> Bkz. [examples/sdk/10-settings.ts](../examples/sdk/10-settings.ts)\n\n## Kaynak Yükleyici\n\nUzantıları, becerileri, istemleri, temaları ve context files'yi keşfetmek için `DefaultResourceLoader`'yi kullanın.\n\n```typescript\nimport {\n  DefaultResourceLoader,\n  getAgentDir,\n} from \"@earendil-works/pi-coding-agent\";\n\nconst loader = new DefaultResourceLoader({\n  cwd,\n  agentDir: getAgentDir(),\n});\nawait loader.reload();\n\nconst extensions = loader.getExtensions();\nconst skills = loader.getSkills();\nconst prompts = loader.getPrompts();\nconst themes = loader.getThemes();\nconst contextFiles = loader.getAgentsFiles().agentsFiles;\n```\n\n## Dönüş Değeri\n\n`createAgentSession()` şunu döndürür:\n\n```typescript\ninterface CreateAgentSessionResult {\n  // The session\n  session: AgentSession;\n  \n  // Extensions result (for runner setup)\n  extensionsResult: LoadExtensionsResult;\n  \n  // Warning if session model couldn't be restored\n  modelFallbackMessage?: string;\n}\n\ninterface LoadExtensionsResult {\n  extensions: Extension[];\n  errors: Array<{ path: string; error: string }>;\n  runtime: ExtensionRuntime;\n}\n```\n\n## Tam Örnek\n\n```typescript\nimport { getModel } from \"@earendil-works/pi-ai\";\nimport { Type } from \"typebox\";\nimport {\n  createAgentSession,\n  DefaultResourceLoader,\n  defineTool,\n  ModelRuntime,\n  SessionManager,\n  SettingsManager,\n} from \"@earendil-works/pi-coding-agent\";\n\nconst modelRuntime = await ModelRuntime.create({\n  authPath: \"/custom/agent/auth.json\",\n  modelsPath: \"/custom/agent/models.json\",\n});\nif (process.env.MY_KEY) {\n  await modelRuntime.setRuntimeApiKey(\"anthropic\", process.env.MY_KEY);\n}\n\n// Inline tool\nconst statusTool = defineTool({\n  name: \"status\",\n  label: \"Status\",\n  description: \"Get system status\",\n  parameters: Type.Object({}),\n  execute: async () => ({\n    content: [{ type: \"text\", text: `Uptime: ${process.uptime()}s` }],\n    details: {},\n  }),\n});\n\nconst model = getModel(\"anthropic\", \"claude-opus-4-5\");\nif (!model) throw new Error(\"Model not found\");\n\n// In-memory settings with overrides\nconst settingsManager = SettingsManager.inMemory({\n  compaction: { enabled: false },\n  retry: { enabled: true, maxRetries: 2 },\n});\n\nconst loader = new DefaultResourceLoader({\n  cwd: process.cwd(),\n  agentDir: \"/custom/agent\",\n  settingsManager,\n  systemPromptOverride: () => \"You are a minimal assistant. Be concise.\",\n});\nawait loader.reload();\n\nconst { session } = await createAgentSession({\n  cwd: process.cwd(),\n  agentDir: \"/custom/agent\",\n\n  model,\n  thinkingLevel: \"off\",\n  modelRuntime,\n\n  tools: [\"read\", \"bash\", \"status\"],\n  customTools: [statusTool],\n  resourceLoader: loader,\n\n  sessionManager: SessionManager.inMemory(),\n  settingsManager,\n});\n\nsession.subscribe((event) => {\n  if (event.type === \"message_update\" && event.assistantMessageEvent.type === \"text_delta\") {\n    process.stdout.write(event.assistantMessageEvent.delta);\n  }\n});\n\nawait session.prompt(\"Get status and list files.\");\n```\n\n## Çalıştırma Modları\n\nSDK, `createAgentSession()`'nin üzerine özel arayüzler oluşturmak için çalışma modu yardımcı programlarını dışa aktarır:\n\n### Etkileşimli Mod\n\nDüzenleyici, sohbet geçmişi ve tüm yerleşik komutlarla tam TUI etkileşimli mod:\n\n```typescript\nimport {\n  type CreateAgentSessionRuntimeFactory,\n  createAgentSessionFromServices,\n  createAgentSessionRuntime,\n  createAgentSessionServices,\n  getAgentDir,\n  InteractiveMode,\n  SessionManager,\n} from \"@earendil-works/pi-coding-agent\";\n\nconst createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {\n  const services = await createAgentSessionServices({ cwd });\n  return {\n    ...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent })),\n    services,\n    diagnostics: services.diagnostics,\n  };\n};\nconst runtime = await createAgentSessionRuntime(createRuntime, {\n  cwd: process.cwd(),\n  agentDir: getAgentDir(),\n  sessionManager: SessionManager.create(process.cwd()),\n});\n\nconst mode = new InteractiveMode(runtime, {\n  migratedProviders: [],\n  modelFallbackMessage: undefined,\n  initialMessage: \"Hello\",\n  initialImages: [],\n  initialMessages: [],\n});\n\nawait mode.run();\n```\n\n### runPrintMode'u çalıştır\n\nTek çekim modu: istem gönderme, sonuç çıktısı, çıkış:\n\n```typescript\nimport {\n  type CreateAgentSessionRuntimeFactory,\n  createAgentSessionFromServices,\n  createAgentSessionRuntime,\n  createAgentSessionServices,\n  getAgentDir,\n  runPrintMode,\n  SessionManager,\n} from \"@earendil-works/pi-coding-agent\";\n\nconst createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {\n  const services = await createAgentSessionServices({ cwd });\n  return {\n    ...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent })),\n    services,\n    diagnostics: services.diagnostics,\n  };\n};\nconst runtime = await createAgentSessionRuntime(createRuntime, {\n  cwd: process.cwd(),\n  agentDir: getAgentDir(),\n  sessionManager: SessionManager.create(process.cwd()),\n});\n\nawait runPrintMode(runtime, {\n  mode: \"text\",\n  initialMessage: \"Hello\",\n  initialImages: [],\n  messages: [\"Follow up\"],\n});\n```\n\n### runRpcMode'u çalıştır\n\nAlt süreç entegrasyonu için JSON-RPC modu:\n\n```typescript\nimport {\n  type CreateAgentSessionRuntimeFactory,\n  createAgentSessionFromServices,\n  createAgentSessionRuntime,\n  createAgentSessionServices,\n  getAgentDir,\n  runRpcMode,\n  SessionManager,\n} from \"@earendil-works/pi-coding-agent\";\n\nconst createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => {\n  const services = await createAgentSessionServices({ cwd });\n  return {\n    ...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent })),\n    services,\n    diagnostics: services.diagnostics,\n  };\n};\nconst runtime = await createAgentSessionRuntime(createRuntime, {\n  cwd: process.cwd(),\n  agentDir: getAgentDir(),\n  sessionManager: SessionManager.create(process.cwd()),\n});\n\nawait runRpcMode(runtime);\n```\n\nJSON protokolü için [RPC documentation](rpc.md)'ye bakın.\n\n## RPC Mod Alternatifi\n\nSDK ile derleme yapmadan alt süreç tabanlı entegrasyon için doğrudan CLI'yi kullanın:\n\n```bash\npi --mode rpc --no-session\n```\n\nJSON protokolü için [RPC documentation](rpc.md)'ye bakın.\n\nSDK şu durumlarda tercih edilir:\n- Tip güvenliği istiyorsunuz\n- Siz de aynı Node.js sürecindesiniz\n- Temsilci durumuna doğrudan erişmeniz gerekiyor\n- Araçları/uzantıları programlı olarak özelleştirmek istiyorsunuz\n\nRPC modu şu durumlarda tercih edilir:\n- Başka bir dilden entegrasyon yapıyorsunuz\n- Süreç izolasyonu istiyorsunuz\n- Dilden bağımsız bir istemci oluşturuyorsunuz\n\n## İhracat\n\nAna giriş noktası ihracatları:\n\n```typescript\n// Factory\ncreateAgentSession\ncreateAgentSessionRuntime\nAgentSessionRuntime\n\n// Auth and Models\nModelRuntime // implements pi-ai Models and owns credential storage\nModelRegistry // synchronous extension compatibility facade\nCredentialSynchronizationError\nresolveCliModel\nresolveModelScopeWithDiagnostics\n\n// Resource loading\nDefaultResourceLoader\ntype ResourceLoader\ncreateEventBus\n\n// Constants and helpers\nCONFIG_DIR_NAME\ndefineTool\ngetAgentDir\ngetPackageDir\ngetReadmePath\ngetDocsPath\ngetExamplesPath\n\n// Session management\nSessionManager\nSettingsManager\n\n// Tool factories\ncreateCodingTools\ncreateReadOnlyTools\ncreateReadTool, createBashTool, createEditTool, createWriteTool\ncreateGrepTool, createFindTool, createLsTool\n\n// Types\ntype CreateAgentSessionOptions\ntype CreateAgentSessionResult\ntype ExtensionFactory\ntype InlineExtension\ntype ExtensionAPI\ntype ToolDefinition\ntype Skill\ntype PromptTemplate\ntype Tool\n```\n\nUzantı türleri için, API'nin tamamı için [extensions.md](extensions.md)'ye bakın.","sourceFile":"sdk.md"},"security":{"title":"Güvenlik","markdown":"Pi yerel bir kodlama aracısıdır. Kendisini başlatan kullanıcı hesabının izinleriyle çalışır ve bu kullanıcı tarafından yazılabilen dosyalara aynı yerel güven sınırı içindeymiş gibi davranır.\n\n## Proje Güveni\n\nProje güveni, pi'nin proje yerel ayarlarını, kaynaklarını, paketlerini ve uzantılarını yükleyip yüklemediğini kontrol eder. Bu bir sandbox değildir ve siz bir dizinde çalışmaya başladıktan sonra modelin araçlardan yapmasını isteyebileceklerini kısıtlamaz.\n\nPi bir projenin mevcut çalışma dizininde bunlardan herhangi birini bulması durumunda güven gerektiren kaynaklara sahip olduğunu kabul eder:\n\n- `.pi/settings.json`\n- `.pi/extensions`, `.pi/skills`, `.pi/prompts` veya `.pi/themes`\n- `.pi/SYSTEM.md` veya `.pi/APPEND_SYSTEM.md`\n- `.agents/skills` projesi geçerli dizinde veya bir ata dizinde\n\nÇıplak bir `.pi` dizini, güven gerektiren bir proje kaynağı olarak sayılmaz.\n\nGeçerli dizin veya üst dizin için güven gerektiren ve kayıtlı karar bulunmayan kaynaklara sahip bir projede etkileşimli bir oturum başlatıldığında, pi genel ayarlardan `defaultProjectTrust`'ı takip eder. Varsayılan değer `\"ask\"`'dir ve kullanıcı arayüzü mevcut olduğunda projeye güvenilip güvenilmeyeceğini sorar. Kaydedilen kararlar kurallı dizine göre `~/.pi/agent/trust.json`'de saklanır ve mevcut veya ana yola en yakın kaydedilen karar genel varsayılandan önce uygulanır.\n\nBir projeye güvenmek Pi'nin aşağıdakiler dahil olmak üzere güven gerektiren proje kaynaklarını yüklemesine olanak tanır:\n\n- `.pi/settings.json`\n- `.pi` uzantılar, beceriler, prompt templates, temalar ve sistem istem dosyaları gibi kaynaklar\n- proje ayarları aracılığıyla yapılandırılan eksik proje paketleri\n- proje yerel uzantıları ve proje paketi tarafından yönetilen uzantılar\n\nGüvenin azalması, korunan kaynakların atlanmasına neden olur. `AGENTS.override.md`, `AGENTS.md` ve `CLAUDE.md` gibi bağlam dosyaları, bağlam yükleme devre dışı bırakılmadığı sürece proje güvenine bakılmaksızın yüklenir. Güven çözümlenmeden önce pi yalnızca context files, kullanıcı/global uzantıları ve CLI `-e` uzantılarını yükler. Kullanıcı/global ve CLI uzantıları `project_trust` olayını işleyebilir; evet/hayır kararı veren ilk uzatma, kararın sahibidir.\n\nEtkileşimli olmayan modlar (`-p`, `--mode json` ve `--mode rpc`) bir güven istemi göstermez. Geçerli bir kaydedilmiş güven kararı olmadan, `defaultProjectTrust: \"ask\"` ve `\"never\"` bu tür kaynakları görmezden gelirken, `\"always\"` onlara güvenir. Bir çalıştırma için proje güvenini geçersiz kılmak için `--approve`/`-a` veya `--no-approve`/`-na` tuşlarını kullanın.\n\n## Yerleşik Korumalı Alan Yok\n\nPi yerleşik bir sandbox içermez. Yerleşik araçlar, pi işleminin izinleriyle dosyaları okuyabilir, dosya yazabilir, dosyaları düzenleyebilir ve kabuk komutlarını çalıştırabilir. Extensions aynı izinlerle çalışan TypeScript modüllerdir. Paket yüklemeleri, kabuk komutları, dil sunucuları, test komutları ve diğer geliştirici araçları sıradan yerel işlemler gibi davranır.\n\nBu kasıtlıdır. Pi yerel kaynak ağaçlar üzerinde çalışacak, proje araç zincirlerini çağıracak ve kullanıcının mevcut geliştirme ortamıyla bütünleşecek şekilde tasarlanmıştır. Kısmi bir süreç içi sandbox, ana bilgisayar kabuğuna, dosya sistemine, paket yöneticilerine, kimlik bilgilerine ve uzantı koduna bağlıyken bir güvenlik sınırı olarak yanlış anlaşılması kolay olacaktır. Gerçek izolasyonun işletim sisteminden veya sanallaştırma/konteyner sınırından gelmesi gerekir.\n\nProje güveni yalnızca girdi yükleme korumasıdır. Bir havuzun pi'nin ayarlarını veya uzantılarını siz onaylamadan önce sessizce değiştirmesini engeller. Güvenilmeyen kodu, güvenilmeyen istemleri veya güvenilmeyen model çıktısını güvenli hale getirmez. Depo dosyalarından, yorumlardan, belgelerden, context files veya derleme çıktısından hızlı enjeksiyon, beklenen yerel aracı riskidir ve pi tarafından güvenilir bir şekilde önlenemez.\n\n## Güvenilmeyen veya Denetlenmeyen Çalışmaları Çalıştırma\n\nGüvenilmeyen depolar, yakından izlemeyi düşünmediğiniz oluşturulan kodlar veya gözetimsiz otomasyon için pi'yi kapalı bir ortamda çalıştırın. Yalnızca görev için gereken dosya ve kimlik bilgilerine sahip bir kapsayıcı, VM, mikro VM, uzak sandbox veya politika kontrollü sandbox kullanın.\n\nYaygın modeller [Containerization](containerization.md)'de belgelenmiştir:\n\n- `pi` işleminin tamamını bir kap/sandbox içinde çalıştırın\n- yerleşik araç yürütmesini Gondolin mikro VM'ye yönlendirirken Host pi'yi çalıştırın\n- yalnızca aracının erişmesi gereken çalışma alanı yollarını bağlayın\n- Konteynerin ana bilgisayar oturumlarına, ayarlarına ve kimlik bilgilerine erişmesi gerekmediği sürece ana bilgisayarı `~/.pi/agent` bağlamaktan kaçının\n- Gerekli minimum API key sayısını geçin veya kısa ömürlü kimlik bilgilerini kullanın\n- görevin gerektirmediği durumlarda ağ erişimini kısıtla\n- Sonuçları güvenilir sistemlere kopyalamadan önce farkları ve çıktıları gözden geçirin\n\nBir ana bilgisayar çalışma alanını okuma/yazma olarak bağlarsanız, kapsayıcının veya VM'nin içinden yazma işlemleri yine de ana bilgisayar dosyalarını değiştirebilir. İstenmeyen yazma işlemlerine karşı daha güçlü korumaya ihtiyaç duyduğunuzda, salt okunur bağlamaları kullanın veya dosyaları sandbox içine ve dışına kopyalayın.\n\n## Güvenlik Sorunlarını Bildirmek\n\nBir güvenlik sorununu bildirmek için [Security Policy](https://github.com/earendil-works/pi-mono/blob/main/SECURITY.md) deposunu takip edin. Güvenlik açısından hassas raporlar için kamuya açık konu açmayın.\n\nBeklenen yerel aracı davranışı, yerleşik sandbox eksikliği, güvenilmeyen içerikten hızlı enjeksiyon ve kullanıcı tarafından yüklenen uzantıların veya becerilerin davranışı, rapor gerçek bir ayrıcalık sınırı atlaması göstermediği veya pi'nin yerel kullanıcının halihazırda sahip olmadığı erişimi nasıl verdiğini göstermediği sürece genellikle güvenlik sınırlarının dışındadır.","sourceFile":"security.md"},"session-format":{"title":"Oturum Dosyası Formatı","markdown":"Oturumlar JSONL (JSON Satır) dosyaları olarak saklanır. Her satır, `type` alanına sahip bir JSON nesnesidir. Oturum girişleri `id`/`parentId` alanları aracılığıyla bir ağaç yapısı oluşturarak yeni dosyalar oluşturmadan yerinde dallanmaya olanak tanır.\n\n## Dosya Konumu\n\n```\n~/.pi/agent/sessions/--<path>--/<timestamp>_<uuid>.jsonl\n```\n\nBurada `<path>`, `/`'nin `-` ile değiştirildiği çalışma dizini.\n\n## Oturumları Silme\n\nOturumlar, `~/.pi/agent/sessions/` altındaki `.jsonl` dosyaları silinerek kaldırılabilir.\n\nPi ayrıca oturumların `/resume`'den etkileşimli olarak silinmesini de destekler (bir oturum seçin ve `Ctrl+D` tuşuna basın, ardından onaylayın). Mevcut olduğunda pi, kalıcı olarak silinmeyi önlemek için `trash` CLI tuşlarını kullanır.\n\n## Oturum Sürümü\n\nOturumların başlığında bir sürüm alanı bulunur:\n\n- **Sürüm 1**: Doğrusal giriş sırası (eski, yükte otomatik olarak taşınan)\n- **Sürüm 2**: `id`/`parentId` bağlantılı ağaç yapısı\n- **Sürüm 3**: `hookMessage` rolü `custom` olarak yeniden adlandırıldı (uzantı birleştirme)\n\nMevcut oturumlar yüklendiğinde otomatik olarak geçerli sürüme (v3) taşınır.\n\n## Kaynak Dosyaları\n\nGitHub ([pi-mono](https://github.com/earendil-works/pi-mono))'deki kaynak:\n- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/session-manager.ts) - Oturum giriş türleri ve SessionManager\n- [`packages/coding-agent/src/core/messages.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/messages.ts) - Genişletilmiş mesaj türleri (BashExecutionMessage, CustomMessage, vb.)\n- [`packages/ai/src/types.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/types.ts) - Temel mesaj türleri (UserMessage, AssistantMessage, ToolResultMessage)\n- [`packages/agent/src/types.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/agent/src/types.ts) - AgentMessage birleşim türü\n\nProjenizdeki TypeScript tanımları için `node_modules/@earendil-works/pi-coding-agent/dist/` ve `node_modules/@earendil-works/pi-ai/dist/`'yi inceleyin.\n\n## Mesaj Türleri\n\nOturum girişleri `AgentMessage` nesne içerir. Bu türleri anlamak, oturumları ayrıştırmak ve uzantıları yazmak için çok önemlidir.\n\n### İçerik Blokları\n\nMesajlar, yazılan içerik bloklarından oluşan diziler içerir:\n\n```typescript\ninterface TextContent {\n  type: \"text\";\n  text: string;\n}\n\ninterface ImageContent {\n  type: \"image\";\n  data: string;      // base64 encoded\n  mimeType: string;  // e.g., \"image/jpeg\", \"image/png\"\n}\n\ninterface ThinkingContent {\n  type: \"thinking\";\n  thinking: string;\n}\n\ninterface ToolCall {\n  type: \"toolCall\";\n  id: string;\n  name: string;\n  arguments: Record<string, any>;\n}\n```\n\n### Temel Mesaj Türleri (pi-ai'den)\n\n```typescript\ninterface UserMessage {\n  role: \"user\";\n  content: string | (TextContent | ImageContent)[];\n  timestamp: number;  // Unix ms\n}\n\ninterface AssistantMessage {\n  role: \"assistant\";\n  content: (TextContent | ThinkingContent | ToolCall)[];\n  api: string;\n  provider: string;\n  model: string;\n  usage: Usage;\n  stopReason: \"stop\" | \"length\" | \"toolUse\" | \"error\" | \"aborted\";\n  errorMessage?: string;\n  timestamp: number;\n}\n\ninterface ToolResultMessage {\n  role: \"toolResult\";\n  toolCallId: string;\n  toolName: string;\n  content: (TextContent | ImageContent)[];\n  details?: any;      // Tool-specific metadata\n  usage?: Usage;      // Nested LLM work performed by the tool\n  isError: boolean;\n  timestamp: number;\n}\n\ninterface Usage {\n  input: number;\n  output: number;\n  cacheRead: number;\n  cacheWrite: number;\n  totalTokens: number;\n  cost: {\n    input: number;\n    output: number;\n    cacheRead: number;\n    cacheWrite: number;\n    total: number;\n  };\n}\n```\n\nDışa aktarılan pi-ai `StopReason` türü aynı zamanda `\"pending\"`'yi de içerir, ancak bu değer akış etkinliklerindeki kısmi mesajlar için ayrılmıştır. Terminal `done`/`error` mesajları, pi'nin asistan mesajını sürdürmesinden önce bunu bir tamamlanma nedeni ile değiştirir, bu nedenle `\"pending\"` JSONL oturumunda asla görünmemelidir.\n\n### Genişletilmiş Mesaj Türleri (pi-coding-agent'tan)\n\n```typescript\ninterface BashExecutionMessage {\n  role: \"bashExecution\";\n  command: string;\n  output: string;\n  exitCode: number | undefined;\n  cancelled: boolean;\n  truncated: boolean;\n  fullOutputPath?: string;\n  excludeFromContext?: boolean;  // true for !! prefix commands\n  timestamp: number;\n}\n\ninterface CustomMessage {\n  role: \"custom\";\n  customType: string;            // Extension identifier\n  content: string | (TextContent | ImageContent)[];\n  display: boolean;              // Show in TUI\n  details?: any;                 // Extension-specific metadata\n  timestamp: number;\n}\n\ninterface BranchSummaryMessage {\n  role: \"branchSummary\";\n  summary: string;\n  fromId: string;                // Entry we branched from\n  timestamp: number;\n}\n\ninterface CompactionSummaryMessage {\n  role: \"compactionSummary\";\n  summary: string;\n  tokensBefore: number;\n  timestamp: number;\n}\n```\n\n### AgentMessage Birliği\n\n```typescript\ntype AgentMessage =\n  | UserMessage\n  | AssistantMessage\n  | ToolResultMessage\n  | BashExecutionMessage\n  | CustomMessage\n  | BranchSummaryMessage\n  | CompactionSummaryMessage;\n```\n\n## Giriş Tabanı\n\nTüm girişler (`SessionHeader` hariç) `SessionEntryBase`'yi genişletir:\n\n```typescript\ninterface SessionEntryBase {\n  type: string;\n  id: string;           // 8-char hex ID\n  parentId: string | null;  // Parent entry ID (null for first entry)\n  timestamp: string;    // ISO timestamp\n}\n```\n\n## Giriş Türleri\n\n### Oturum Başlığı\n\nDosyanın ilk satırı. Yalnızca meta veriler, ağacın parçası değil (`id`/`parentId` yok).\n\n```json\n{\"type\":\"session\",\"version\":3,\"id\":\"uuid\",\"timestamp\":\"2024-12-03T14:00:00.000Z\",\"cwd\":\"/path/to/project\"}\n```\n\nEbeveynle yapılan oturumlar için (`/fork`, `/clone` veya `newSession({ parentSession })` aracılığıyla oluşturulan):\n\n```json\n{\"type\":\"session\",\"version\":3,\"id\":\"uuid\",\"timestamp\":\"2024-12-03T14:00:00.000Z\",\"cwd\":\"/path/to/project\",\"parentSession\":\"/path/to/original/session.jsonl\"}\n```\n\n### OturumMesajGirişi\n\nGörüşmede bir mesaj. `message` alanı bir `AgentMessage` içerir.\n\n```json\n{\"type\":\"message\",\"id\":\"a1b2c3d4\",\"parentId\":\"prev1234\",\"timestamp\":\"2024-12-03T14:00:01.000Z\",\"message\":{\"role\":\"user\",\"content\":\"Hello\"}}\n{\"type\":\"message\",\"id\":\"b2c3d4e5\",\"parentId\":\"a1b2c3d4\",\"timestamp\":\"2024-12-03T14:00:02.000Z\",\"message\":{\"role\":\"assistant\",\"content\":[{\"type\":\"text\",\"text\":\"Hi!\"}],\"provider\":\"anthropic\",\"model\":\"claude-sonnet-4-5\",\"usage\":{...},\"stopReason\":\"stop\"}}\n{\"type\":\"message\",\"id\":\"c3d4e5f6\",\"parentId\":\"b2c3d4e5\",\"timestamp\":\"2024-12-03T14:00:03.000Z\",\"message\":{\"role\":\"toolResult\",\"toolCallId\":\"call_123\",\"toolName\":\"bash\",\"content\":[{\"type\":\"text\",\"text\":\"output\"}],\"isError\":false}}\n```\n\n### Model Değişikliği Girişi\n\nKullanıcı oturumun ortasında modelleri değiştirdiğinde ortaya çıkar.\n\n```json\n{\"type\":\"model_change\",\"id\":\"d4e5f6g7\",\"parentId\":\"c3d4e5f6\",\"timestamp\":\"2024-12-03T14:05:00.000Z\",\"provider\":\"openai\",\"modelId\":\"gpt-4o\"}\n```\n\n### Düşünme Seviyesi Değişimi Girişi\n\nKullanıcı düşünme/akıl yürütme düzeyini değiştirdiğinde yayılır.\n\n```json\n{\"type\":\"thinking_level_change\",\"id\":\"e5f6g7h8\",\"parentId\":\"d4e5f6g7\",\"timestamp\":\"2024-12-03T14:06:00.000Z\",\"thinkingLevel\":\"high\"}\n```\n\n### Sıkıştırma Girişi\n\nBağlam sıkıştırıldığında oluşturulur. Önceki mesajların özetini saklar.\n\n```json\n{\"type\":\"compaction\",\"id\":\"f6g7h8i9\",\"parentId\":\"e5f6g7h8\",\"timestamp\":\"2024-12-03T14:10:00.000Z\",\"summary\":\"User discussed X, Y, Z...\",\"firstKeptEntryId\":\"c3d4e5f6\",\"tokensBefore\":50000}\n```\n\nDaha yeni donanımla oluşturulan sıkıştırmalar, tutulan sıkıştırma sonrası bağlamı `firstKeptEntryId` yerine doğrudan girişe yerleştirir:\n\n```json\n{\"type\":\"compaction\",\"id\":\"f6g7h8i9\",\"parentId\":\"e5f6g7h8\",\"timestamp\":\"2024-12-03T14:10:00.000Z\",\"summary\":\"User discussed X, Y, Z...\",\"tokensBefore\":50000,\"retainedTail\":[{\"role\":\"user\",\"content\":\"latest request\"},{\"role\":\"assistant\",\"content\":[{\"type\":\"text\",\"text\":\"latest reply\"}],\"provider\":\"anthropic\",\"model\":\"claude-sonnet-4-5\",\"usage\":{...},\"stopReason\":\"stop\"}]}\n```\n\nİsteğe bağlı alanlar:\n- `usage`: Özetin oluşturulmasından LLM kullanımı; oturum belirtecine ve maliyet toplamlarına dahil edilir\n- `retainedTail`: Sıkıştırıldıktan sonra saklanan materyalize `AgentMessage[]`. Bu yalnızca eski oturumlarla geriye dönük uyumluluk için isteğe bağlıdır. Daha yeni donanımla oluşturulan sıkıştırmalar bunu içerir, böylece sıkıştırma girişinden önce eski girişleri yürümeden bu kontrol noktasından bağlamı yeniden oluşturabiliriz.\n- `details`: Uygulamaya özel veriler (ör. varsayılan için `{ readFiles: string[], modifiedFiles: string[] }` veya uzantılar için özel veriler)\n- `fromHook`: `true` bir uzantı tarafından oluşturulmuşsa, `false`/`undefined` pi tarafından oluşturulmuşsa (eski alan adı)\n- `firstKeptEntryId`: eski giriş formatıyla uyumluluk için.\n\n### ŞubeÖzetGiriş\n\n`/tree` yoluyla dallar değiştirilirken, sol dalın ortak ataya kadar LLM tarafından oluşturulan bir özetiyle oluşturulur. Terk edilmiş yoldan bağlamı yakalar.\n\n```json\n{\"type\":\"branch_summary\",\"id\":\"g7h8i9j0\",\"parentId\":\"a1b2c3d4\",\"timestamp\":\"2024-12-03T14:15:00.000Z\",\"fromId\":\"f6g7h8i9\",\"summary\":\"Branch explored approach A...\"}\n```\n\nİsteğe bağlı alanlar:\n- `usage`: Özetin oluşturulmasından LLM kullanımı; oturum belirtecine ve maliyet toplamlarına dahil edilir\n- `details`: Varsayılan için dosya izleme verileri (`{ readFiles: string[], modifiedFiles: string[] }`) veya uzantılar için özel veriler\n- `fromHook`: `true` bir uzantı tarafından oluşturulmuşsa, `false`/`undefined` pi tarafından oluşturulmuşsa (eski alan adı)\n\n### Özel Giriş\n\nUzantı durumunun kalıcılığı. LLM bağlamına katılmaz.\n\n```json\n{\"type\":\"custom\",\"id\":\"h8i9j0k1\",\"parentId\":\"g7h8i9j0\",\"timestamp\":\"2024-12-03T14:20:00.000Z\",\"customType\":\"my-extension\",\"data\":{\"count\":42}}\n```\n\nYeniden yükleme sırasında uzantınızın girişlerini tanımlamak için `customType` tuşunu kullanın. İnteraktif mod, özel girişleri `pi.registerEntryRenderer(customType, renderer)` aracılığıyla işleyebilir ancak yine de Yüksek Lisans bağlamına katılmazlar.\n\n### ÖzelMesajGirişi\n\nLLM bağlamına katılan, uzantı enjekte edilen mesajlar.\n\n```json\n{\"type\":\"custom_message\",\"id\":\"i9j0k1l2\",\"parentId\":\"h8i9j0k1\",\"timestamp\":\"2024-12-03T14:25:00.000Z\",\"customType\":\"my-extension\",\"content\":\"Injected context...\",\"display\":true}\n```\n\nAlanlar:\n- `content`: Dize veya `(TextContent | ImageContent)[]` (KullanıcıMesajı ile aynı)\n- `display`: `true` = TUI'de farklı stilde göster, `false` = gizli\n- `details`: İsteğe bağlı uzantıya özgü meta veriler (LLM'ye gönderilmez)\n\n### Etiket Girişi\n\nBir girişteki kullanıcı tanımlı yer imi/işaretçi.\n\n```json\n{\"type\":\"label\",\"id\":\"j0k1l2m3\",\"parentId\":\"i9j0k1l2\",\"timestamp\":\"2024-12-03T14:30:00.000Z\",\"targetId\":\"a1b2c3d4\",\"label\":\"checkpoint-1\"}\n```\n\nBir etiketi temizlemek için `label`'ı `undefined` olarak ayarlayın.\n\n### Oturum Bilgisi Girişi\n\nOturum meta verileri (ör. kullanıcı tanımlı görünen ad). Uzantılarda `/name`, `--name` / `-n` veya `pi.setSessionName()` aracılığıyla ayarlayın.\n\n```json\n{\"type\":\"session_info\",\"id\":\"k1l2m3n4\",\"parentId\":\"j0k1l2m3\",\"timestamp\":\"2024-12-03T14:35:00.000Z\",\"name\":\"Refactor auth module\"}\n```\n\nOturum adı, ayarlandığında ilk mesaj yerine oturum seçicide (`/resume`) görüntülenir.\n\n## Ağaç Yapısı\n\nGirişler bir ağaç oluşturur:\n- İlk girişte `parentId: null` var\n- Sonraki her giriş `parentId` aracılığıyla ebeveynine işaret eder\n- Dallanma daha önceki bir girdiden yeni alt öğeler yaratır\n- \"Yaprak\" ağaçtaki mevcut konumdur\n\n```\n[user msg] ─── [assistant] ─── [user msg] ─── [assistant] ─┬─ [user msg] ← current leaf\n                                                            │\n                                                            └─ [branch_summary] ─── [user msg] ← alternate branch\n```\n\n## Bağlam Oluşturma\n\n`buildContextEntries()` mevcut yapraktan köke doğru yürür ve sıkıştırmayı dikkate alarak aktif giriş listesini üretir:\n\n1. Yoldaki tüm girişleri toplar\n2. Yol üzerinde bir `CompactionEntry` varsa:\n   - Önce sıkıştırma girişini içerir\n   - `retainedTail` mevcutsa, bağımsız bir kontrol noktası görevi görür ve sıkıştırma sonrasındaki girişler dahil edilir\n   - Aksi takdirde `firstKeptEntryId`'den sıkıştırmaya kadar olan girişler dahil edilir\n   - Daha sonra sıkıştırmadan sonraki girişler dahil edilir\n3. Etkileşimli modun bunları oluşturabilmesi için seçilen aralıktaki mesaj dışı girişleri korur\n\n`buildSessionContext()` Yüksek Lisans için mesaj listesini oluşturmak üzere bu giriş listesini temel alır:\n\n1. Geçerli modeli ve düşünme düzeyi ayarlarını tam yoldan çıkarır\n2. Seçilen girişleri mesajlara dönüştürür:\n   - `message` -> saklanan `AgentMessage`\n   - `compaction` -> `compactionSummary` artı `retainedTail` mevcut olduğunda\n   - `branch_summary` -> `branchSummary`\n   - `custom_message` -> `CustomMessage`\n   - `custom` -> içerik mesajı yok\n\nBu, daha yeni sıkıştırmaların müstakil kontrol noktaları gibi davranmasını sağlar. `retainedTail` isteğe bağlıdır, bu nedenle yalnızca `firstKeptEntryId` depolayan eski oturumlar doğru şekilde yüklenmeye devam eder.\n\n## Ayrıştırma Örneği\n\n```typescript\nimport { readFileSync } from \"fs\";\n\nconst lines = readFileSync(\"session.jsonl\", \"utf8\").trim().split(\"\\n\");\n\nfor (const line of lines) {\n  const entry = JSON.parse(line);\n\n  switch (entry.type) {\n    case \"session\":\n      console.log(`Session v${entry.version ?? 1}: ${entry.id}`);\n      break;\n    case \"message\":\n      console.log(`[${entry.id}] ${entry.message.role}: ${JSON.stringify(entry.message.content)}`);\n      break;\n    case \"compaction\":\n      console.log(`[${entry.id}] Compaction: ${entry.tokensBefore} tokens summarized`);\n      break;\n    case \"branch_summary\":\n      console.log(`[${entry.id}] Branch from ${entry.fromId}`);\n      break;\n    case \"custom\":\n      console.log(`[${entry.id}] Custom (${entry.customType}): ${JSON.stringify(entry.data)}`);\n      break;\n    case \"custom_message\":\n      console.log(`[${entry.id}] Extension message (${entry.customType}): ${entry.content}`);\n      break;\n    case \"label\":\n      console.log(`[${entry.id}] Label \"${entry.label}\" on ${entry.targetId}`);\n      break;\n    case \"model_change\":\n      console.log(`[${entry.id}] Model: ${entry.provider}/${entry.modelId}`);\n      break;\n    case \"thinking_level_change\":\n      console.log(`[${entry.id}] Thinking: ${entry.thinkingLevel}`);\n      break;\n  }\n}\n```\n\n## Oturum Yöneticisi API\n\nOturumlarla programlı olarak çalışmanın temel yöntemleri.\n\n### Statik Oluşturma Yöntemleri\n- `SessionManager.create(cwd, sessionDir?)` - Yeni oturum\n- `SessionManager.open(path, sessionDir?)` - Mevcut oturum dosyasını aç\n- `SessionManager.continueRecent(cwd, sessionDir?)` - En yeniye devam et veya yeni oluştur\n- `SessionManager.inMemory(cwd?)` - Dosya kalıcılığı yok\n- `SessionManager.forkFrom(sourcePath, targetCwd, sessionDir?)` - Başka bir projeden oturumu çatallayın\n\n### Statik Listeleme Yöntemleri\n- `SessionManager.list(cwd, sessionDir?, onProgress?)` - Bir dizindeki oturumları listeleyin\n- `SessionManager.listAll(onProgress?)` - Tüm projelerdeki tüm oturumları listeleyin\n\n### Örnek Yöntemleri - Oturum Yönetimi\n- `newSession(options?)` - Yeni bir oturum başlatın (seçenekler: `{ parentSession?: string }`)\n- `setSessionFile(path)` - Farklı bir oturum dosyasına geçin\n- `createBranchedSession(leafId)` - Şubeyi yeni oturum dosyasına çıkart\n\n### Örnek Yöntemleri - Ekleme (tüm dönüş giriş kimlikleri)\n- `appendMessage(message)` - Mesaj ekle\n- `appendThinkingLevelChange(level)` - Düşünce değişikliğini kaydedin\n- `appendModelChange(provider, modelId)` - Model değişikliğini kaydedin\n- `appendCompaction(summary, firstKeptEntryId, tokensBefore, details?, fromHook?)` - Sıkıştırma ekleyin\n- `appendCustomEntry(customType, data?)` - Uzantı durumu (bağlamda değil)\n- `appendSessionInfo(name)` - Oturumun görünen adını ayarlayın\n- `appendCustomMessageEntry(customType, content, display, details?)` - Uzantı mesajı (bağlamda)\n- `appendLabelChange(targetId, label)` - Etiketi ayarla/temizle\n\n### Örnek Yöntemleri - Ağaçta Gezinme\n- `getLeafId()` - Mevcut konum\n- `getLeafEntry()` - Mevcut yaprak girişini alın\n- `getEntry(id)` - Kimliğe göre giriş alın\n- `getBranch(fromId?)` - Girişten köke doğru yürüyün\n- `getTree()` - Tam ağaç yapısını elde edin\n- `getChildren(parentId)` - Doğrudan çocukları alın\n- `getLabel(id)` - Giriş için etiketi alın\n- `branch(entryId)` - Yaprağı önceki girişe taşı\n- `resetLeaf()` - Yaprağı null değerine sıfırla (herhangi bir girişten önce)\n- `branchWithSummary(entryId, summary, details?, fromHook?)` - Bağlam özetini içeren dal\n\n### Örnek Yöntemleri - Bağlam ve Bilgi\n- `buildContextEntries()` - Sıkıştırma uygulanmış aktif şube girişlerini alın\n- `buildSessionContext()` - Yüksek Lisans için mesajları, düşünce seviyesini ve modeli alın\n- `getEntries()` - Tüm girişler (başlık hariç)\n- `getHeader()` - Oturum başlığı meta verileri\n- `getSessionName()` - En son session_info girişinden görünen adı alın\n- `getCwd()` - Çalışma dizini\n- `getSessionDir()` - Oturum depolama dizini\n- `getSessionId()` - Oturum UUID'si\n- `getSessionFile()` - Oturum dosyası yolu (bellek içi için tanımsız)\n- `isPersisted()` - Oturumun diske kaydedilip kaydedilmeyeceği","sourceFile":"session-format.md"},"sessions":{"title":"Oturumlar","markdown":"Pi konuşmaları oturum olarak kaydeder, böylece çalışmaya devam edebilir, daha önceki dönüşlerden dallara ayrılabilir ve önceki yolları tekrar ziyaret edebilirsiniz.\n\n## Oturum Depolama\n\nOturumlar, çalışma dizinine göre düzenlenerek `~/.pi/agent/sessions/`'ye otomatik olarak kaydedilir. Her oturum ağaç yapısına sahip bir JSONL dosyasıdır.\n\n```bash\npi -c                  # Continue most recent session\npi -r                  # Browse and select from past sessions\npi --no-session        # Ephemeral mode; do not save\npi --name \"my task\"    # Set session display name at startup\npi --session <path|id> # Use a specific session file or partial session ID\npi --fork <path|id>    # Fork a session file or partial session ID into a new session\n```\n\nGeçerli oturum dosyasını, oturum kimliğini, mesaj sayısını, belirteçleri ve maliyeti görmek için etkileşimli modda `/session` tuşunu kullanın.\n\nJSONL dosya formatı ve SessionManager API için bkz. [Session Format](session-format.md).\n\n## Oturum Komutları\n\n| Emretmek | Tanım |\n|---------|-------------|\n| `/resume` | Önceki oturumlara göz atın ve seçin |\n| `/new` | Yeni bir oturum başlat |\n| `/name <name>` | Geçerli oturumun görünen adını ayarlayın |\n| `/session` | Oturum bilgilerini göster |\n| `/tree` | Mevcutta gezinin session tree |\n| `/fork` | Önceki bir kullanıcı mesajından yeni bir oturum oluşturun |\n| `/clone` | Geçerli etkin dalı yeni bir oturuma kopyala |\n| `/compact [prompt]` | Eski bağlamı özetleyin; bkz. [Compaction](compaction.md) |\n| `/export [file]` | Oturumu HTML'ye aktar |\n| `/share` | Paylaşılabilir HTML bağlantısıyla özel GitHub özet olarak yükleyin |\n\n## Oturumları Devam Ettirme ve Silme\n\n`/resume` mevcut proje için etkileşimli bir oturum seçiciyi açar. `pi -r` başlangıçta aynı seçiciyi açar.\n\nSeçicide şunları yapabilirsiniz:\n\n- yazarak arama\n- Yol görünümünü Ctrl+P ile değiştir\n- Ctrl+S ile sıralama moduna geçiş yapın\n- Ctrl+N ile adlandırılmış oturumlara filtre uygulayın\n- Ctrl+R ile yeniden adlandırın\n- Ctrl+D ile silin ve onaylayın\n\nPi, mümkün olduğunda dosyaları kalıcı olarak kaldırmak yerine silmek için `trash` CLI'yi kullanır.\n\n## Oturumları Adlandırma\n\nİnsanların okuyabileceği bir oturum adı ayarlamak için `/name <name>` tuşunu kullanın:\n\n```text\n/name Refactor auth module\n```\n\nAdı başlangıçta `--name` veya `-n` ile ayarlayın:\n\n```bash\npi --name \"Refactor auth module\"\npi --name \"CI audit\" -p \"Review this build failure\"\n```\n\nAdlandırılmış oturumları `/resume` ve `pi -r`'de bulmak daha kolaydır.\n\n## `/tree` ile dallanma\n\nOturumlar ağaç olarak depolanır. Her girişte `id` ve `parentId` bulunur ve mevcut konum aktif yapraktır. `/tree` yeni bir dosya oluşturmadan önceki herhangi bir noktaya atlamanızı ve oradan devam etmenizi sağlar.\n\n<p align=\"center\"><img src=\"images/tree-view.png\" alt=\"Tree View\" width=\"600\"></p>\n\nÖrnek şekil:\n\n```text\n├─ user: \"Hello, can you help...\"\n│  └─ assistant: \"Of course! I can...\"\n│     ├─ user: \"Let's try approach A...\"\n│     │  └─ assistant: \"For approach A...\"\n│     │     └─ user: \"That worked...\"  ← active\n│     └─ user: \"Actually, approach B...\"\n│        └─ assistant: \"For approach B...\"\n```\n\n### Ağaç Kontrolleri\n\n| Anahtar | Aksiyon |\n|-----|--------|\n| ↑/↓ | Görünür girişlerde gezinin |\n| ←/→ | Sayfa yukarı/aşağı |\n| Ctrl+←/Ctrl+→ veya Alt+←/Alt+→ | Dal bölümleri arasında katlama/açma veya atlama |\n| Üst Karakter+L | Seçilen girişte bir etiket ayarlayın veya temizleyin |\n| Üst Karakter+T | Etiket zaman damgalarını değiştir |\n| Girmek | Girişi seçin |\n| Kaçış/Ctrl+C | İptal etmek |\n| Ctrl+O | Döngü filtresi modu |\n\nFiltre modları şunlardır: varsayılan, araçsız, yalnızca kullanıcıya yönelik, yalnızca etiketli ve tümü. Varsayılanı [Settings](settings.md)'de `treeFilterMode` ile yapılandırın.\n\n### Seçim Davranışı\n\nBir kullanıcıyı veya özel mesajı seçme:\n\n1. Yaprağı seçilen mesajın üst öğesine taşır.\n2. Seçilen mesaj metnini düzenleyiciye yerleştirir.\n3. Yeni bir şube oluşturarak düzenlemenizi ve yeniden göndermenizi sağlar.\n\nBir asistan, alet, sıkıştırma veya kullanıcı dışı başka bir girişin seçilmesi:\n\n1. Yaprağı o girişe taşır.\n2. Düzenleyiciyi boş bırakır.\n3. Bu noktadan devam etmenizi sağlar.\n\nKök kullanıcı mesajını seçmek, yaprağı boş bir konuşmaya sıfırlar ve orijinal istemi düzenleyiciye yerleştirir.\n\n## `/tree`, `/fork` ve `/clone`\n\n| Özellik | `/tree` | `/fork` | `/clone` |\n|---------|---------|---------|----------|\n| Çıkış | Aynı oturum dosyası | Yeni oturum dosyası | Yeni oturum dosyası |\n| Görüş | Tam ağaç | Kullanıcı mesajı seçici | Mevcut aktif şube |\n| Tipik kullanım | Alternatifleri yerinde keşfedin | Daha önceki bir istemden yeni bir oturum başlatın | Devam etmeden önce mevcut çalışmayı çoğaltın |\n| Özet | İsteğe bağlı dal özeti | Hiçbiri | Hiçbiri |\n\nAlternatifleri bir arada tutmak istediğinizde `/tree` kullanın. Ayrı bir oturum dosyası istediğinizde `/fork` veya `/clone` tuşlarını kullanın.\n\n## Şube Özetleri\n\n`/tree` bir daldan diğerine geçtiğinde, pi terk edilen dalı özetleyebilir ve bu özeti yeni konuma ekleyebilir. Bu, tüm dalı tekrar oynatmadan, bıraktığınız yoldan önemli bağlamı korur.\n\nİstendiğinde aşağıdakilerden birini seçin:\n\n1. özet yok\n2. varsayılan istemle özetle\n3. özel odaklama talimatlarıyla özetleme\n\nbranch summarization iç parçalar ve uzatma kancaları için [Compaction](compaction.md)'ye bakın.\n\n## Oturum Formatı\n\nOturum dosyaları JSONL boyutundadır ve mesaj girişlerini, model değişikliklerini, düşünme düzeyindeki değişiklikleri, etiketleri, sıkıştırmaları, dal özetlerini ve uzantı girişlerini içerir.\n\nAyrıştırıcılar, uzantılar, SDK kullanımı ve tam SessionManager API için, bkz. [Session Format](session-format.md).","sourceFile":"sessions.md"},"settings":{"title":"Ayarlar","markdown":"Pi, proje ayarlarının genel ayarları geçersiz kıldığı JSON ayar dosyalarını kullanır.\n\n| Konum | Kapsam |\n|----------|-------|\n| `~/.pi/agent/settings.json` | Küresel (tüm projeler) |\n| `.pi/settings.json` | Proje (geçerli dizin) |\n\nDoğrudan düzenleyin veya ortak seçenekler için `/settings` kullanın.\n\n## Proje Güveni\n\nEtkileşimli başlangıçta pi, proje yerel ayarlarını, kaynaklarını veya proje `.agents/skills`'yi içeren ve `~/.pi/agent/trust.json`'deki klasör veya ana klasör için kayıtlı bir kararı olmayan bir proje klasörüne güvenmeden önce sorar. Bir projeye güvenmek pi'nin `.pi/settings.json` ve `.pi` kaynakları yüklemesine, eksik proje paketlerini yüklemesine ve proje uzantılarını yürütmesine olanak tanır.\n\nEtkileşimli olmayan modlar (`-p`, `--mode json` ve `--mode rpc`) bir güven istemi göstermez. Geçerli bir kayıtlı güven kararı olmadan, genel ayarlardan `defaultProjectTrust` kullanırlar: `ask` (varsayılan) ve `never` bu proje kaynaklarını yok sayarken, `always` onlara güvenir. Bir çalıştırma için proje güvenini geçersiz kılmak için `--approve`/`-a` veya `--no-approve`/`-na`'yi geçin.\n\nHiçbir uzatma veya kayıtlı karar geçerli değilse, `defaultProjectTrust` geri dönüş davranışını kontrol eder. `~/.pi/agent/settings.json`'de `\"ask\"`, `\"always\"` veya `\"never\"` olarak ayarlayın veya `/settings` ile değiştirin.\n\n`pi config` ve paket komutları aynı proje güven akışını kullanır, ancak `pi update` hiçbir zaman istemde bulunmaz. Bir komut için proje yerel ayarlarına güvenmek için `--approve` veya bunları yok saymak için `--no-approve` iletin.\n\nYakın ana klasöre yönelik güven de dahil olmak üzere gelecekteki oturumlar için bir proje güveni kararını kaydetmek için etkileşimli modda `/trust` tuşunu kullanın. Sadece `~/.pi/agent/trust.json` yazıyor; geçerli oturum yeniden yüklenmediğinden değişikliklerin etkili olması için pi'yi yeniden başlatın.\n\n## Tüm Ayarlar\n\n### Modelleme ve Düşünme\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `defaultProvider` | sicim | - | Varsayılan sağlayıcı (ör. `\"anthropic\"`, `\"openai\"`) |\n| `defaultModel` | sicim | - | Varsayılan model kimliği |\n| `defaultThinkingLevel` | sicim | - | `\"off\"`, `\"minimal\"`, `\"low\"`, `\"medium\"`, `\"high\"`, `\"xhigh\"`, `\"max\"` |\n| `hideThinkingBlock` | boolean | `false` | Çıktıdaki düşünme bloklarını gizle |\n| `showCacheMissNotices` | boolean | `false` | Önemli bilgi istemi önbellek eksiklikleri için transkript bildirimlerini göster |\n| `thinkingBudgets` | nesne | - | Düşünce düzeyi başına özel token bütçeleri |\n\n#### düşünmeBütçeler\n\n```json\n{\n  \"thinkingBudgets\": {\n    \"minimal\": 1024,\n    \"low\": 4096,\n    \"medium\": 10240,\n    \"high\": 32768\n  }\n}\n```\n\n### Kullanıcı Arayüzü ve Ekran\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `theme` | sicim | `\"dark\"` | Tema adı (`\"dark\"`, `\"light\"` veya özel) |\n| `externalEditor` | sicim | `$VISUAL`, ardından `$EDITOR`, ardından Windows'ta Not Defteri veya başka bir yerde `nano` | Ctrl+G harici düzenleyici komutu; ortam değişkenlerine göre önceliklidir |\n| `quietStartup` | boolean | `false` | Başlangıç ​​başlığını gizle |\n| `defaultProjectTrust` | sicim | `\"ask\"` | Geri dönüş projesi güven davranışı: `\"ask\"`, `\"always\"` veya `\"never\"`. Yalnızca genel ayar |\n| `collapseChangelog` | boolean | `false` | Güncellemelerden sonra yoğunlaştırılmış değişiklik günlüğünü göster |\n| `enableInstallTelemetry` | boolean | `true` | İlk kurulumdan veya değişiklik günlüğü tarafından algılanan güncellemelerden sonra anonim bir kurulum/güncelleme sürümü ping'i gönderin. Bu güncelleme kontrollerini kontrol etmez |\n| `enableAnalytics` | boolean | `false` | Analitik veri paylaşımını etkinleştirin. Şu anda yalnızca deneysel ilk kurulum sırasında sorulur (`PI_EXPERIMENTAL=1`) |\n| `trackingId` | sicim | - | `enableAnalytics` açıldığında oluşturulan Analytics izleme tanımlayıcısı |\n| `doubleEscapeAction` | sicim | `\"tree\"` | Çift kaçış eylemi: `\"tree\"`, `\"fork\"` veya `\"none\"` |\n| `treeFilterMode` | sicim | `\"default\"` | `/tree` için varsayılan filtre: `\"default\"`, `\"no-tools\"`, `\"user-only\"`, `\"labeled-only\"`, `\"all\"` |\n| `editorPaddingX` | sayı | `0` | Giriş düzenleyicisi için yatay dolgu (0-3) |\n| `outputPad` | sayı | `1` | Kullanıcı mesajları, asistan mesajları ve düşünme için yatay dolgu (0 veya 1) |\n| `autocompleteMaxVisible` | sayı | `5` | Otomatik tamamlama açılır menüsünde maksimum görünür öğe (3-20) |\n| `showHardwareCursor` | boolean | `false` | TUI IME desteği için konumlandırırken terminal imlecini gösterin |\n| `tuiMode` | sicim | `\"regular\"` | Etkileşimli TUI modu: `\"regular\"` veya deneysel `\"fullscreen\"`. `/settings`'den itibaren yapılan değişiklikler hemen uygulanır; `--tui-mode` başlangıçta bu ayarı geçersiz kılar |\n| `fullscreenExitOutput` | sicim | `\"transcript\"` | Tam ekran çıkış çıktısı: `\"transcript\"` son metni ve devam etme ipucunu yazdırırken, `\"resume-hint\"` önceki ekranı geri yükler ve yalnızca devam etme ipucunu yazdırır. Normal TUI modunda hiçbir etkisi yoktur |\n| `fullscreenScrollbar` | sicim | `\"auto\"` | Tam ekran transkript kaydırma çubuğu: `\"auto\"` kaydırma sırasında bunu geçici olarak gösterir, `\"always\"` en sağdaki sütunu ayırır ve görünür tutar ve `\"hidden\"` onu gizler. Normal TUI modunda hiçbir etkisi yoktur |\n\nVS Kodu için `--wait` ekleyin, böylece editör çıktıktan sonra pi devam eder:\n\n```json\n{\n  \"externalEditor\": \"code --wait\"\n}\n```\n\n### Telemetri ve güncelleme kontrolleri\n\n`enableInstallTelemetry` yalnızca `https://pi.dev/api/report-install`'ye olan anonim kurulum/güncelleme pingini kontrol eder. Telemetriyi devre dışı bırakmak güncelleme kontrollerini devre dışı bırakmaz; Pi en son sürümü aramak için yine de `https://pi.dev/api/latest-version`'yi getirebilir.\n\nPi sürüm güncelleme kontrolünü devre dışı bırakmak için `PI_SKIP_VERSION_CHECK=1` öğesini ayarlayın. Güncelleme kontrolleri, paket güncelleme kontrolleri ve kurulum/güncelleme telemetrisi dahil olmak üzere burada açıklanan tüm başlangıç ​​ağ işlemlerini devre dışı bırakmak için `--offline` veya `PI_OFFLINE=1` tuşlarını kullanın.\n\n### Ağ\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `httpProxy` | sicim | - | HTTP proxy URL'si `HTTP_PROXY` ve `HTTPS_PROXY` olarak uygulandı. Yalnızca genel ayar. |\n\n```json\n{\n  \"httpProxy\": \"http://127.0.0.1:7890\"\n}\n```\n\n### Uyarılar\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `warnings.anthropicExtraUsage` | boolean | `true` | Antropik abonelik kimlik doğrulaması ücretli ekstra kullanımı kullanabileceğinde bir uyarı göster |\n\n```json\n{\n  \"warnings\": {\n    \"anthropicExtraUsage\": false\n  }\n}\n```\n\n### Sıkıştırma\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `compaction.enabled` | boolean | `true` | Otomatik sıkıştırmayı etkinleştir |\n| `compaction.reserveTokens` | sayı | `16384` | LLM yanıtı için ayrılan jetonlar |\n| `compaction.keepRecentTokens` | sayı | `20000` | Saklanacak en son belirteçler (özetlenmemiş) |\n\n```json\n{\n  \"compaction\": {\n    \"enabled\": true,\n    \"reserveTokens\": 16384,\n    \"keepRecentTokens\": 20000\n  }\n}\n```\n\n### Şube Özeti\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `branchSummary.reserveTokens` | sayı | `16384` | branch summarization için ayrılmış jetonlar |\n| `branchSummary.skipPrompt` | boolean | `false` | \"Dal özetlensin mi?\" atla `/tree` gezinmede istem (varsayılan olarak özet yoktur) |\n\n### Yeniden dene\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `retry.enabled` | boolean | `true` | Geçici hatalarda aracı düzeyinde otomatik yeniden denemeyi etkinleştir |\n| `retry.maxRetries` | sayı | `3` | Maksimum aracı düzeyinde yeniden deneme sayısı |\n| `retry.baseDelayMs` | sayı | `2000` | Aracı düzeyinde üstel geri çekilme için temel gecikme (2 sn, 4 sn, 8 sn) |\n| `retry.provider.timeoutMs` | sayı | SDK varsayılan | Sağlayıcı/SDK milisaniye cinsinden istek zaman aşımı |\n| `retry.provider.maxRetries` | sayı | `0` | Sağlayıcı/SDK yeniden deneme girişimleri |\n| `retry.provider.maxRetryDelayMs` | sayı | `60000` | Başarısız olmadan önce sunucu tarafından istenen maksimum gecikme (60s) |\n\nBir sağlayıcı `retry.provider.maxRetryDelayMs`'den daha uzun bir yeniden deneme gecikmesi talep ettiğinde, istek sessizce beklemek yerine bilgilendirici bir hatayla hemen başarısız olur. Sınırı devre dışı bırakmak için `0` olarak ayarlayın.\n\nSağlayıcı düzeyinde yeniden denemelere açıkça ihtiyaç duyulmadığı sürece `retry.provider.maxRetries`'yi `0`'de tutun. Bunu `0` değerinin üzerine ayarlamak, SDK/sağlayıcı yeniden denemelerinin kullanım sınırı dışı hataları Pi görmeden önce ele almasını sağlayabilir ve bu da bazı durumlarda sağlayıcı kotası sıfırlanana kadar aracıyı engelleyebilir.\n\n```json\n{\n  \"retry\": {\n    \"enabled\": true,\n    \"maxRetries\": 3,\n    \"baseDelayMs\": 2000,\n    \"provider\": {\n      \"timeoutMs\": 3600000,\n      \"maxRetries\": 0,\n      \"maxRetryDelayMs\": 60000\n    }\n  }\n}\n```\n\n### Mesaj Gönderimi\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `steeringMode` | sicim | `\"one-at-a-time\"` | Yönlendirme mesajları nasıl gönderilir: `\"all\"` veya `\"one-at-a-time\"` |\n| `followUpMode` | sicim | `\"one-at-a-time\"` | Takip mesajları nasıl gönderilir: `\"all\"` veya `\"one-at-a-time\"` |\n| `transport` | sicim | `\"auto\"` | Birden fazla aktarımı destekleyen sağlayıcılar için tercih edilen aktarım: `\"sse\"`, `\"websocket\"`, `\"websocket-cached\"` veya `\"auto\"` |\n| `httpIdleTimeoutMs` | sayı | `300000` | Milisaniye cinsinden HTTP üstbilgisi/gövdesi boşta kalma zaman aşımı, açık akış boşta kalma zaman aşımlarına sahip sağlayıcılar tarafından da kullanılır. Devre dışı bırakmak için `0` olarak ayarlayın. |\n| `websocketConnectTimeoutMs` | sayı | `15000` | WebSocket aktarımlarını destekleyen sağlayıcılar için milisaniye cinsinden WebSocket bağlantısı/açma anlaşması zaman aşımı. Devre dışı bırakmak için `0` olarak ayarlayın. |\n\n### Terminal ve Görseller\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `terminal.showImages` | boolean | `true` | Resimleri terminalde göster (destekleniyorsa) |\n| `terminal.imageWidthCells` | sayı | `60` | Terminal hücrelerinde tercih edilen satır içi görüntü genişliği |\n| `terminal.clearOnShrink` | boolean | `false` | İçerik küçüldüğünde boş satırları temizleyin (titremeye neden olabilir) |\n| `images.autoResize` | boolean | `true` | Resimleri maksimum 2000x2000 olarak yeniden boyutlandırın. Araçlar tarafından döndürülen `@file` ekler, `read` ve resimler için geçerlidir |\n| `images.blockImages` | boolean | `false` | Tüm görsellerin LLM'ye gönderilmesini engelle |\n\n### Kabuk\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `shellPath` | sicim | - | Özel kabuk yolu (örneğin, Windows'ta Cygwin için); giriş dizini için baştaki `~` karakterini destekler |\n| `shellCommandPrefix` | sicim | - | Her bash komutu için önek (ör. `\"shopt -s expand_aliases\"`) |\n| `npmCommand` | sicim[] | - | npm paket arama/yükleme işlemleri için kullanılan argv komutu (ör. `[\"mise\", \"exec\", \"node@20\", \"--\", \"npm\"]`) |\n\n```json\n{\n  \"npmCommand\": [\"mise\", \"exec\", \"node@20\", \"--\", \"npm\"]\n}\n```\n\n`npmCommand`, git paketleri içindeki kurulumlar, kaldırmalar ve bağımlılık kurulumları dahil olmak üzere tüm npm paket yöneticisi işlemleri için kullanılır. Kullanıcı kapsamlı npm paketleri `~/.pi/agent/npm/` altına kurulur; proje kapsamlı npm paketleri `.pi/npm/` altına kurulur. Argv tarzı girişleri tam olarak işlemin başlatılması gerektiği gibi kullanın. `npmCommand` yapılandırıldığında, git paketi bağımlılığı kurulumları, sarmalayıcılarda veya alternatif paket yöneticilerinde npm'ye özgü işaretlerden kaçınmak için düz `install` kullanır.\n\n### Oturumlar\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `sessionDir` | sicim | - | Oturum dosyalarının saklandığı dizin. Mutlak veya göreceli yolları ve artı `~`'yi kabul eder. |\n\n```json\n{ \"sessionDir\": \".pi/sessions\" }\n```\n\nBirden fazla kaynak bir oturum dizini belirttiğinde, settings.json'da öncelik `--session-dir`, `PI_CODING_AGENT_SESSION_DIR` ve ardından `sessionDir` olur.\n\n### Model Bisiklet\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `enabledModels` | sicim[] | - | Ctrl+P döngüsü için model desenleri (`--models` CLI bayrağıyla aynı format) |\n\n```json\n{\n  \"enabledModels\": [\"claude-*\", \"gpt-4o\", \"gemini-2*\"]\n}\n```\n\n### Markdown\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `markdown.codeBlockIndent` | sicim | `\"  \"` | Kod blokları için girinti |\n| `markdown.mermaid` | sicim | `\"streaming\"` | Deniz kızı oluşturma modu: `\"off\"`, `\"final\"` veya `\"streaming\"` |\n\n### Kaynaklar\n\nBu ayarlar uzantıların, becerilerin, istemlerin ve temaların nereden yükleneceğini tanımlar.\n\n`~/.pi/agent/settings.json` içindeki yollar `~/.pi/agent`'ye göre çözümlenir. `.pi/settings.json` içindeki yollar `.pi`'ye göre çözümlenir. Mutlak yollar ve `~` desteklenir.\n\n| Ayar | Tip | Varsayılan | Tanım |\n|---------|------|---------|-------------|\n| `packages` | sıralamak | `[]` | Kaynakları yüklemek için npm/git paketleri |\n| `extensions` | sicim[] | `[]` | Yerel uzantılı dosya yolları veya dizinleri |\n| `skills` | sicim[] | `[]` | Yerel beceri dosyası yolları veya dizinleri |\n| `prompts` | sicim[] | `[]` | Yerel bilgi istemi şablon yolları veya dizinleri |\n| `themes` | sicim[] | `[]` | Yerel tema dosya yolları veya dizinleri |\n| `enableSkillCommands` | boolean | `true` | Becerileri `/skill:name` komutları olarak kaydedin |\n\nDiziler glob kalıplarını ve hariç tutmaları destekler. Hariç tutmak için `!pattern` tuşunu kullanın. Tam bir yolu zorunlu olarak dahil etmek için `+path` tuşunu, tam bir yolu zorla hariç tutmak için ise `-path` tuşunu kullanın.\n\n#### paketler\n\nDize formu bir paketteki tüm kaynakları yükler:\n\n```json\n{\n  \"packages\": [\"pi-skills\", \"@org/my-extension\"]\n}\n```\n\nNesne formu hangi kaynakların yükleneceğini filtreler:\n\n```json\n{\n  \"packages\": [\n    {\n      \"source\": \"pi-skills\",\n      \"skills\": [\"brave-search\", \"transcribe\"],\n      \"extensions\": []\n    }\n  ]\n}\n```\n\nPaket yönetimi ayrıntıları için [packages.md](packages.md)'e bakın.\n\n## Örnek\n\n```json\n{\n  \"defaultProvider\": \"anthropic\",\n  \"defaultModel\": \"claude-sonnet-4-20250514\",\n  \"defaultThinkingLevel\": \"medium\",\n  \"theme\": \"dark\",\n  \"compaction\": {\n    \"enabled\": true,\n    \"reserveTokens\": 16384,\n    \"keepRecentTokens\": 20000\n  },\n  \"retry\": {\n    \"enabled\": true,\n    \"maxRetries\": 3\n  },\n  \"enabledModels\": [\"claude-*\", \"gpt-4o\"],\n  \"warnings\": {\n    \"anthropicExtraUsage\": true\n  },\n  \"packages\": [\"pi-skills\"]\n}\n```\n\n## Proje Geçersiz Kılmaları\n\nProje ayarları (`.pi/settings.json`) genel ayarları geçersiz kılar. İç içe geçmiş nesneler birleştirilir:\n\n```json\n// ~/.pi/agent/settings.json (global)\n{\n  \"theme\": \"dark\",\n  \"compaction\": { \"enabled\": true, \"reserveTokens\": 16384 }\n}\n\n// .pi/settings.json (project)\n{\n  \"compaction\": { \"reserveTokens\": 8192 }\n}\n\n// Result\n{\n  \"theme\": \"dark\",\n  \"compaction\": { \"enabled\": true, \"reserveTokens\": 8192 }\n}\n```","sourceFile":"settings.md"},"shell-aliases":{"title":"Kabuk Takma Adları","markdown":"Pi, bash'yi etkileşimli olmayan modda (`bash -c`) çalıştırır; bu, varsayılan olarak takma adları genişletmez.\n\nKabuk takma adlarınızı etkinleştirmek için `~/.pi/agent/settings.json`'ye ekleyin:\n\n```json\n{\n  \"shellCommandPrefix\": \"shopt -s expand_aliases\\neval \\\"$(grep '^alias ' ~/.zshrc)\\\"\"\n}\n```\n\nYolu (`~/.zshrc`, `~/.bashrc`, vb.) kabuk yapılandırmanıza uyacak şekilde ayarlayın.","sourceFile":"shell-aliases.md"},"skills":{"title":"Skills","markdown":"> pi beceriler yaratabilir. Kullanım durumunuz için bir tane oluşturmasını isteyin.\n\n\nSkills, aracının talep üzerine yüklediği bağımsız yetenek paketleridir. Beceri, belirli görevlere yönelik özel iş akışları, kurulum talimatları, yardımcı komut dosyaları ve referans belgeleri sağlar.\n\nPi [Agent Skills standard](https://agentskills.io/specification)'ı uygulayarak çoğu ihlal hakkında uyarıda bulunur ancak hoşgörülü davranır. Pi standart izin vermese bile beceri adlarının ana dizinlerinden farklı olmasına izin verir; bu kural, birden fazla aracı sistemi arasında kullanılan paylaşılan beceri dizinleri için optimalin altındadır.\n\n## İçindekiler\n\n- [Locations](#locations)\n- [How Skills Work](#how-skills-work)\n- [Skill Commands](#skill-commands)\n- [Skill Structure](#skill-structure)\n- [Frontmatter](#frontmatter)\n- [Validation](#validation)\n- [Example](#example)\n- [Skill Repositories](#skill-repositories)\n\n## Konumlar\n\n> **Güvenlik:** Skills modele herhangi bir eylemi gerçekleştirme talimatı verebilir ve modelin çağırdığı yürütülebilir kodu içerebilir. Kullanmadan önce beceri içeriğini gözden geçirin.\n\nPi becerileri şunlardan yükler:\n\n- Küresel:\n  - `~/.pi/agent/skills/`\n  - `~/.agents/skills/`\n- Proje (yalnızca projeye güvenildikten sonra):\n  - `.pi/skills/`\n  - `cwd` ve ata dizinlerinde `.agents/skills/` (git repo köküne veya repoda olmadığında dosya sistemi köküne kadar)\n- Paketler: `skills/` dizinler veya `package.json` içindeki `pi.skills` girişler\n- Ayarlar: `skills` dosya veya dizin içeren dizi\n- CLI: `--skill <path>` (tekrarlanabilir, `--no-skills` ile bile toplanabilir)\n\nKeşif kuralları:\n- `~/.pi/agent/skills/` ve `.pi/skills/`'de, doğrudan kök `.md` dosyaları bireysel beceriler olarak keşfedilir\n- Tüm beceri konumlarında, `SKILL.md` içeren dizinler yinelemeli olarak keşfedilir\n- `~/.agents/skills/` ve `.agents/skills/` projesinde kök `.md` dosyaları göz ardı edilir\n\n`--no-skills` ile bulmayı devre dışı bırakın (açık `--skill` yolları hala yükleniyor).\n\n### Diğer Kayışlardan Skills Kullanımı\n\nClaude Code veya OpenAI Codex'teki becerileri kullanmak için dizinlerini ayarlara ekleyin:\n\n```json\n{\n  \"skills\": [\n    \"~/.claude/skills\",\n    \"~/.codex/skills\"\n  ]\n}\n```\n\nProje düzeyinde Claude Kodu becerileri için `.pi/settings.json`'a ekleyin:\n\n```json\n{\n  \"skills\": [\"../.claude/skills\"]\n}\n```\n\n## Skills Nasıl Çalışır?\n\n1. Pi başlangıçta beceri konumlarını tarar ve adları ve açıklamaları çıkarır\n2. Sistem istemi, [specification](https://agentskills.io/integrate-skills) uyarınca XML biçiminde mevcut becerileri içerir.\n3. Bir görev eşleştiğinde aracı, SKILL.md dosyasının tamamını yüklemek için `read` tuşunu kullanır (modeller bunu her zaman yapmaz; zorlamak için istemi veya `/skill:name` tuşunu kullanın)\n4. Aracı, komut dosyalarına ve varlıklara referans vermek için ilgili yolları kullanarak talimatları takip eder\n\nBu aşamalı bir açıklamadır: yalnızca açıklamalar her zaman bağlam içindedir, tüm talimatlar isteğe bağlı olarak yüklenir.\n\n## Beceri Komutları\n\nSkills `/skill:name` komutları olarak kaydolun:\n\n```bash\n/skill:brave-search           # Load and execute the skill\n/skill:pdf-tools extract      # Load skill with arguments\n```\n\nKomuttan sonraki argümanlar beceri içeriğine `User: <args>` olarak eklenir.\n\nBeceri komutlarını etkileşimli modda `/settings` veya `settings.json` ile değiştirin:\n\n```json\n{\n  \"enableSkillCommands\": true\n}\n```\n\n## Beceri Yapısı\n\nBeceri, `SKILL.md` dosyasına sahip bir dizindir. Geriye kalan her şey serbest biçimlidir.\n\n```\nmy-skill/\n├── SKILL.md              # Required: frontmatter + instructions\n├── scripts/              # Helper scripts\n│   └── process.sh\n├── references/           # Detailed docs loaded on-demand\n│   └── api-reference.md\n└── assets/\n    └── template.json\n```\n\n### SKILL.md Formatı\n\n````markdown\n---\nname: my-skill\ndescription: What this skill does and when to use it. Be specific.\n---\n\n# My Skill\n\n## Setup\n\nRun once before first use:\n```bash\ncd /yol/giden/beceri && npm kurulum\n```\n\n## Usage\n\n```bash\n./scripts/process.sh <input>\n```\n````\n\nBeceri dizinindeki göreceli yolları kullanın:\n\n```markdown\nSee [the reference guide](references/REFERENCE.md) for details.\n```\n\n## Ön madde\n\n[Agent Skills specification](https://agentskills.io/specification#frontmatter-required) başına:\n\n| Alan | Gerekli | Tanım |\n|-------|----------|-------------|\n| `name` | Evet | Maksimum 64 karakter. Küçük harf a-z, 0-9, kısa çizgiler. Standarttan farklı olarak, Pi bunun ana dizinle eşleşmesini gerektirmez çünkü bu standart gereksinim, paylaşılan beceri dizinleri için optimalin altındadır. |\n| `description` | Evet | Maksimum 1024 karakter. Beceri ne yapar ve ne zaman kullanılır? |\n| `license` | HAYIR | Lisans adı veya paketlenmiş dosyaya referans. |\n| `compatibility` | HAYIR | Maksimum 500 karakter. Çevre gereksinimleri. |\n| `metadata` | HAYIR | Keyfi anahtar/değer eşlemesi. |\n| `allowed-tools` | HAYIR | Önceden onaylanmış araçların boşlukla ayrılmış listesi (deneysel). |\n| `disable-model-invocation` | HAYIR | `true` olduğunda, beceri sistem isteminde gizlenir. Kullanıcılar `/skill:name` kullanmalıdır. |\n\n### İsim Kuralları\n\n- 1-64 karakter\n- Yalnızca küçük harfler, sayılar ve kısa çizgiler\n- Başta/sonda tire yok\n- Ardışık tire yok\nPi ismin ana dizinle eşleşmesini gerektirmez. Agent Skills standardı bunu yapar ancak bu gereksinim, birden fazla araç tarafından kullanılan paylaşılan beceri dizinleri için optimalin altındadır.\n\nGeçerli: `pdf-processing`, `data-analysis`, `code-review`\nGeçersiz: `PDF-Processing`, `-pdf`, `pdf--processing`\n\n### Açıklama En İyi Uygulamalar\n\nAçıklama, aracının beceriyi ne zaman yükleyeceğini belirler. Spesifik olun.\n\nİyi:\n```yaml\ndescription: Extracts text and tables from PDF files, fills PDF forms, and merges multiple PDFs. Use when working with PDF documents.\n```\n\nFakir:\n```yaml\ndescription: Helps with PDFs.\n```\n\n## Doğrulama\n\nPi becerileri Temsilci Skills standardına göre doğrular. Çoğu sorun uyarı verir ancak yine de beceriyi yükler:\n\n- Ad 64 karakteri aşıyor veya geçersiz karakterler içeriyor\n- Ad kısa çizgiyle başlıyor/bitiyor veya ardışık kısa çizgiler içeriyor\n- Açıklama 1024 karakteri aşıyor\n\nBilinmeyen ön madde alanları göz ardı edilir.\n\n**İstisna:** Skills eksik açıklamalarla yüklenmez.\n\nİsim çarpışmaları (farklı konumlardan aynı isim) bulunan ilk beceriyi uyarır ve korur.\n\n## Örnek\n\n```\nbrave-search/\n├── SKILL.md\n├── search.js\n└── content.js\n```\n\n**SKILL.md:**\n````markdown\n---\nname: brave-search\ndescription: Web search and content extraction via Brave Search API. Use for searching documentation, facts, or any web content.\n---\n\n# Brave Search\n\n## Setup\n\n```bash\ncd /path/to/brave-search && npm kurulum\n```\n\n## Search\n\n```bash\n./search.js \"sorgu\" # Temel arama\n./search.js \"query\" --content # Sayfa içeriğini dahil et\n```\n\n## Extract Page Content\n\n```bash\n./content.js https://example.com\n```\n````\n\n## Beceri Depoları\n\n- [Anthropic Skills](https://github.com/anthropics/skills) - Belge işleme (docx, pdf, pptx, xlsx), web geliştirme\n- [Pi Skills](https://github.com/badlogic/pi-skills) - Web araması, tarayıcı otomasyonu, Google API'ler, transkripsiyon","sourceFile":"skills.md"},"terminal-setup":{"title":"Terminal Kurulumu","markdown":"Pi güvenilir değiştirici tuş tespiti için [Kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/)'yi kullanır. Çoğu modern terminal bu protokolü destekler, ancak bazıları yapılandırma gerektirir.\n\n## Kitty, iTerm2\n\nKutunun dışında çalışın.\n\n## Elma Terminali\n\nPi mevcut olduğunda gelişmiş anahtar raporlamayı etkinleştirir. Terminal.app hala `Shift+Enter` için düz Dönüş gönderiyorsa pi, bu Dönüşü `Shift+Enter` olarak değerlendirmek için yerel bir macOS değiştirici geri dönüşü kullanır.\n\nBu geri dönüş yalnızca pi, Terminal.app ile aynı Mac'te çalıştığında çalışır. Uzaktan kumanda SSH üzerinden yerel klavyeyi algılayamıyor.\n\n## Hayalet gibi\n\nGhostty yapılandırmanıza ekleyin (macOS'te `~/Library/Application Support/com.mitchellh.ghostty/config`, Linux'ta `~/.config/ghostty/config`):\n\n```\nkeybind = alt+backspace=text:\\x1b\\x7f\n```\n\nDaha eski Claude Kodu versiyonları bu Ghostty eşlemesini eklemiş olabilir:\n\n```\nkeybind = shift+enter=text:\\n\n```\n\nBu eşleme ham bir satır besleme baytı gönderir. Pi'nin içinde bu, `Ctrl+J`'den ayırt edilemez, dolayısıyla tmux ve pi artık gerçek bir `shift+enter` anahtar olayı görmüyor.\n\nBu eşlemeyi eklemenizin tek nedeni Claude Code 2.x veya daha yenisiyse, hala Ghostty eşlemesinin gerekli olduğu tmux'da Claude Code'u kullanmak istemediğiniz sürece onu kaldırabilirsiniz.\n\nPi, `Ctrl+J`'yi varsayılan yeni satır takma adı olarak bağlar, bu nedenle `Shift+Enter`, fazladan pi yapılandırması olmadan bu remap aracılığıyla tmux'de çalışmaya devam eder.\n\n## WezTerm\n\nWezTerm genellikle xterm changeOtherKeys aracılığıyla `Shift+Enter` için kutudan çıktığı haliyle çalışır. Kitty klavye protokolünü açıkça kullanmak için `~/.wezterm.lua` oluşturun:\n\n```lua\nlocal wezterm = require 'wezterm'\nlocal config = wezterm.config_builder()\nconfig.enable_kitty_keyboard = true\nreturn config\n```\n\nMacOS'ta WezTerm, varsayılan olarak `Option+Enter`'yi tam ekrana bağlar. Pi takip kuyruğunda `Option+Enter` kullanmak için şu anahtarı geçersiz kılmayı ekleyin:\n\n```lua\nlocal wezterm = require 'wezterm'\nlocal config = wezterm.config_builder()\nconfig.keys = {\n  {\n    key = 'Enter',\n    mods = 'ALT',\n    action = wezterm.action.SendString('\\x1b[13;3u'),\n  },\n}\nreturn config\n```\n\nZaten bir `config.keys` tablonuz varsa girişi buna ekleyin.\n\nWSL'de WezTerm, IME aday penceresi konumlandırması için görünür bir donanım imleci gerektirebilir. CJK IME adayları metin imlecini takip etmiyorsa pi'yi çalıştırmadan önce `PI_HARDWARE_CURSOR=1` ayarlayın veya ayarlarda `showHardwareCursor`'yi `true` olarak ayarlayın.\n\n## Alakrity\n\nAlacritty genellikle `Shift+Enter` karşılığında kutunun dışında çalışır. MacOS'ta `Option+Enter` düz `Enter` olarak gelebilir. Pi takip kuyruğu için `Option+Enter` kullanmak için `~/.config/alacritty/alacritty.toml`'ye ekleyin:\n\n```toml\n[[keyboard.bindings]]\nkey = \"Enter\"\nmods = \"Alt\"\nchars = \"\\u001b[13;3u\"\n```\n\nYapılandırmayı değiştirdikten sonra Alacritty'yi yeniden başlatın.\n\n## VS Kodu (Entegre Terminal)\n\nVS Code 1.109.5 ve daha yenisi, entegre terminalde Kitty klavye protokolünü varsayılan olarak etkinleştirir; dolayısıyla `Shift+Enter` kutudan çıktığı gibi çalışmalıdır.\n\n1.109.5'ten daha eski VS Code sürümleri, `Shift+Enter` için açık bir terminal tuş bağlamasına ihtiyaç duyar.\n\n`keybindings.json` konumlar:\n- macOS: `~/Library/Application Support/Code/User/keybindings.json`\n- Linux: `~/.config/Code/User/keybindings.json`\n- Pencereler: `%APPDATA%\\\\Code\\\\User\\\\keybindings.json`\n\n`keybindings.json`'e ekle:\n\n```json\n{\n  \"key\": \"shift+enter\",\n  \"command\": \"workbench.action.terminal.sendSequence\",\n  \"args\": { \"text\": \"\\u001b[13;2u\" },\n  \"when\": \"terminalFocus\"\n}\n```\n\n## Windows Terminali\n\npi'nin kullandığı değiştirilmiş Enter tuşlarını iletmek için `settings.json`'ye ekleyin (Ctrl+Shift+ veya Ayarlar → JSON dosyasını aç):\n\n```json\n{\n  \"actions\": [\n    {\n      \"command\": { \"action\": \"sendInput\", \"input\": \"\\u001b[13;2u\" },\n      \"keys\": \"shift+enter\"\n    },\n    {\n      \"command\": { \"action\": \"sendInput\", \"input\": \"\\u001b[13;3u\" },\n      \"keys\": \"alt+enter\"\n    }\n  ]\n}\n```\n\n- `Shift+Enter` yeni bir satır ekler.\n- Windows Terminali varsayılan olarak `Alt+Enter`'yi tam ekrana bağlar. Bu, pi'nin takip kuyruğu için `Alt+Enter` almasını engeller.\n- `Alt+Enter`'yi `sendInput`'ye yeniden eşlemek, bunun yerine gerçek anahtar akoru pi'ye iletir.\n\nZaten bir `actions` diziniz varsa nesneleri ona ekleyin. Eski tam ekran davranışı devam ederse Windows Terminalini tamamen kapatıp yeniden açın.\n\n## xfce4 terminali, sonlandırıcı\n\nBu terminaller sınırlı kaçış dizisi desteğine sahiptir. `Ctrl+Enter` ve `Shift+Enter` gibi değiştirilmiş Enter tuşları düz `Enter`'den ayırt edilemez, bu da `submit: [\"ctrl+enter\"]` gibi özel tuş atamalarının çalışmasını engeller.\n\nEn iyi deneyim için Kitty klavye protokolünü destekleyen bir terminal kullanın:\n- [Kitty](https://sw.kovidgoyal.net/kitty/)\n- [Ghostty](https://ghostty.org/)\n- [WezTerm](https://wezfurlong.org/wezterm/)\n- [iTerm2](https://iterm2.com/)\n- [Alacritty](https://github.com/alacritty/alacritty) (Kitty protokol desteğiyle derleme gerektirir)\n\n## IntelliJ IDEA (Entegre Terminal)\n\nYerleşik terminalin kaçış dizisi desteği sınırlıdır. IntelliJ terminalinde Shift+Enter, Enter'dan ayırt edilemez.\n\nDonanım imlecinin görünmesini istiyorsanız pi'yi çalıştırmadan önce `PI_HARDWARE_CURSOR=1` değerini ayarlayın (uyumluluk nedeniyle varsayılan olarak devre dışıdır).\n\nEn iyi deneyim için özel bir terminal emülatörü kullanmayı düşünün.","sourceFile":"terminal-setup.md"},"termux":{"title":"Termux (Android) Kurulumu","markdown":"Pi, Android için bir terminal emülatörü ve Linux ortamı olan [Termux](https://termux.dev/) aracılığıyla Android'de çalışır.\n\n## Önkoşullar\n\n1. [Termux](https://github.com/termux/termux-app#installation)'ı GitHub veya F-Droid'den yükleyin (Google Play değil, bu sürüm kullanımdan kaldırılmıştır)\n2. Pano ve diğer cihaz entegrasyonları için GitHub veya F-Droid'den [Termux:API](https://github.com/termux/termux-api#installation) yükleyin\n\n## Kurulum\n\n```bash\n# Update packages\npkg update && pkg upgrade\n\n# Install dependencies\npkg install nodejs termux-api git\n\n# Install pi\nnpm install -g --ignore-scripts @earendil-works/pi-coding-agent\n\n# Create config directory\nmkdir -p ~/.pi/agent\n\n# Run pi\npi\n```\n\n## Pano Desteği\n\nPano işlemleri Termux'de çalışırken `termux-clipboard-set` ve `termux-clipboard-get`'yi kullanır. Bunların çalışması için Termux:API uygulamasının yüklenmesi gerekir.\n\nResim panosu Termux'de desteklenmemektedir (`ctrl+v` resim yapıştırma özelliği çalışmayacaktır).\n\n## Termux için örnek AGENTS.md\n\nAracının Termux ortamını anlamasına yardımcı olmak için `~/.pi/agent/AGENTS.md` oluşturun:\n\n````markdown\n# Agent Environment: Termux on Android\n\n## Location\n- **OS**: Android (Termux terminal emulator)\n- **Home**: `/data/data/com.termux/files/home`\n- **Prefix**: `/data/data/com.termux/files/usr`\n- **Shared storage**: `/storage/emulated/0` (Downloads, Documents, etc.)\n\n## Opening URLs\n```bash\ntermux-open-url \"https://example.com\"\n```\n\n## Opening Files\n```bash\ntermux-open file.pdf # Varsayılan uygulamayla açılır\ntermux-open --chooser image.jpg # Uygulamayı seç\n```\n\n## Clipboard\n```bash\ntermux-clipboard-set \"metin\" # Kopyala\ntermux-clipboard-get # Yapıştır\n```\n\n## Notifications\n```bash\ntermux-bildirim -t \"Başlık\" -c \"İçerik\"\n```\n\n## Device Info\n```bash\ntermux-pil-durumu # Pil bilgisi\ntermux-wifi-connectioninfo # WiFi bilgisi\ntermux-telephony-deviceinfo # Cihaz bilgisi\n```\n\n## Sharing\n```bash\ntermux-share -a dosya gönder.txt # Dosyayı paylaş\n```\n\n## Other Useful Commands\n```bash\ntermux-tost \"mesajı\" # Hızlı kızartma açılır penceresi\ntermux-vibrate # Cihazı titret\ntermux-tts-speak \"merhaba\" # Metinden konuşmaya\ntermux-kamera-fotoğraf çıkışı.jpg # Fotoğraf çek\n```\n\n## Notes\n- Termux:API app must be installed for `termux-*` commands\n- Use `pkg install termux-api` for the command-line tools\n- Storage permission needed for `/storage/emulated/0` access\n````\n\n## Sınırlamalar\n\n- **Resim panosu yok**: Termux pano API yalnızca metni destekler\n- **Yerel ikili dosyalar yok**: Bazı isteğe bağlı yerel bağımlılıklar (pano modülü gibi) Android ARM64'te mevcut değildir ve kurulum sırasında atlanır\n- **Depolama erişimi**: `/storage/emulated/0` içindeki dosyalara (İndirilenler vb.) erişmek için izinleri vermek üzere `termux-setup-storage` komutunu bir kez çalıştırın\n\n## Sorun giderme\n\n### Pano çalışmıyor\n\nHer iki uygulamanın da kurulu olduğundan emin olun:\n1. Termux (GitHub veya F-Droid'den)\n2. Termux:API (GitHub veya F-Droid'den)\n\nArdından CLI araçlarını yükleyin:\n```bash\npkg install termux-api\n```\n\n### Paylaşılan depolama için izin reddedildi\n\nDepolama izinlerini vermek için bir kez çalıştırın:\n```bash\ntermux-setup-storage\n```\n\n### Node.js kurulum sorunları\n\nnpm başarısız olursa önbelleği temizlemeyi deneyin:\n```bash\nnpm cache clean --force\n```","sourceFile":"termux.md"},"themes":{"title":"Temalar","markdown":"> pi temalar oluşturabilir. Kurulumunuz için bir tane oluşturmasını isteyin.\n\n\nTemalar, TUI için renkleri tanımlayan JSON dosyalardır.\n\n## İçindekiler\n\n- [Locations](#locations)\n- [Selecting a Theme](#selecting-a-theme)\n- [Creating a Custom Theme](#creating-a-custom-theme)\n- [Theme Format](#theme-format)\n- [Color Tokens](#color-tokens)\n- [Color Values](#color-values)\n- [Tips](#tips)\n\n## Konumlar\n\nPi temaları şuradan yükler:\n\n- Dahili: `dark`, `light`\n- Küresel: `~/.pi/agent/themes/*.json`\n- Proje: `.pi/themes/*.json` (yalnızca projeye güvenildikten sonra)\n- Paketler: `themes/` dizinler veya `package.json` içindeki `pi.themes` girişler\n- Ayarlar: `themes` dosya veya dizin içeren dizi\n- CLI: `--theme <path>` (tekrarlanabilir)\n\n`--no-themes` ile keşfi devre dışı bırakın.\n\n## Tema Seçme\n\n`/settings` veya `settings.json` aracılığıyla bir tema seçin:\n\n```json\n{\n  \"theme\": \"my-theme\"\n}\n```\n\nİlk çalıştırmada pi, terminal arka planınızı algılar ve varsayılan olarak `dark` veya `light` olur.\n\n## Özel Tema Oluşturma\n\n1. Bir tema dosyası oluşturun:\n\n```bash\nmkdir -p ~/.pi/agent/themes\nvim ~/.pi/agent/themes/my-theme.json\n```\n\n2. Temayı gerekli tüm renklerle tanımlayın (bkz. [Color Tokens](#color-tokens)):\n\n```json\n{\n  \"$schema\": \"https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json\",\n  \"name\": \"my-theme\",\n  \"vars\": {\n    \"primary\": \"#00aaff\",\n    \"secondary\": 242\n  },\n  \"colors\": {\n    \"accent\": \"primary\",\n    \"border\": \"primary\",\n    \"borderAccent\": \"#00ffff\",\n    \"borderMuted\": \"secondary\",\n    \"success\": \"#00ff00\",\n    \"error\": \"#ff0000\",\n    \"warning\": \"#ffff00\",\n    \"muted\": \"secondary\",\n    \"dim\": 240,\n    \"text\": \"\",\n    \"thinkingText\": \"secondary\",\n    \"selectedBg\": \"#2d2d30\",\n    \"scrollbarThumb\": \"#555566\",\n    \"userMessageBg\": \"#2d2d30\",\n    \"userMessageText\": \"\",\n    \"customMessageBg\": \"#2d2d30\",\n    \"customMessageText\": \"\",\n    \"customMessageLabel\": \"primary\",\n    \"toolPendingBg\": \"#1e1e2e\",\n    \"toolSuccessBg\": \"#1e2e1e\",\n    \"toolErrorBg\": \"#2e1e1e\",\n    \"toolTitle\": \"primary\",\n    \"toolOutput\": \"\",\n    \"mdHeading\": \"#ffaa00\",\n    \"mdLink\": \"primary\",\n    \"mdLinkUrl\": \"secondary\",\n    \"mdCode\": \"#00ffff\",\n    \"mdCodeBlock\": \"\",\n    \"mdCodeBlockBorder\": \"secondary\",\n    \"mdQuote\": \"secondary\",\n    \"mdQuoteBorder\": \"secondary\",\n    \"mdHr\": \"secondary\",\n    \"mdListBullet\": \"#00ffff\",\n    \"toolDiffAdded\": \"#00ff00\",\n    \"toolDiffRemoved\": \"#ff0000\",\n    \"toolDiffContext\": \"secondary\",\n    \"syntaxComment\": \"secondary\",\n    \"syntaxKeyword\": \"primary\",\n    \"syntaxFunction\": \"#00aaff\",\n    \"syntaxVariable\": \"#ffaa00\",\n    \"syntaxString\": \"#00ff00\",\n    \"syntaxNumber\": \"#ff00ff\",\n    \"syntaxType\": \"#00aaff\",\n    \"syntaxOperator\": \"primary\",\n    \"syntaxPunctuation\": \"secondary\",\n    \"thinkingOff\": \"secondary\",\n    \"thinkingMinimal\": \"primary\",\n    \"thinkingLow\": \"#00aaff\",\n    \"thinkingMedium\": \"#00ffff\",\n    \"thinkingHigh\": \"#ff00ff\",\n    \"thinkingXhigh\": \"#ff0000\",\n    \"thinkingMax\": \"#ff0088\",\n    \"bashMode\": \"#ffaa00\"\n  }\n}\n```\n\n3. `/settings` ile temayı seçin.\n\n**Çalışırken yeniden yükleme:** Şu ​​anda etkin olan özel tema dosyasını düzenlediğinizde, pi anında görsel geri bildirim için dosyayı otomatik olarak yeniden yükler.\n\n## Tema Formatı\n\n```json\n{\n  \"$schema\": \"https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json\",\n  \"name\": \"my-theme\",\n  \"vars\": {\n    \"blue\": \"#0066cc\",\n    \"gray\": 242\n  },\n  \"colors\": {\n    \"accent\": \"blue\",\n    \"muted\": \"gray\",\n    \"text\": \"\",\n    ...\n  }\n}\n```\n\n- `name` gereklidir, benzersiz olmalı ve `/` içermemelidir.\n- `vars` isteğe bağlıdır. Yeniden kullanılabilir renkleri burada tanımlayın ve ardından `colors`'de bunlara referans verin.\n- `colors` gerekli 51 jetonun tamamını tanımlamalıdır. `thinkingMax` isteğe bağlıdır ve `thinkingXhigh`'ye geri döner; `scrollbarThumb` isteğe bağlıdır ve `selectedBg`'ye geri döner.\n\n`$schema` alanı, düzenleyicinin otomatik tamamlamasını ve doğrulamasını sağlar.\n\n## Renk Jetonları\n\nHer tema gerekli 51 renk jetonunun tümünü tanımlamalıdır. `thinkingMax` ve `scrollbarThumb` mevcut temalarla uyumluluk açısından isteğe bağlıdır; atlandığında sırasıyla `thinkingXhigh` ve `selectedBg`'yi kullanırlar.\n\n### Çekirdek kullanıcı arayüzü (11 renk)\n\n| Jeton | Amaç |\n|-------|---------|\n| `accent` | Birincil vurgu (logo, seçilen öğeler, imleç) |\n| `border` | Normal sınırlar |\n| `borderAccent` | Vurgulanan kenarlıklar |\n| `borderMuted` | İnce kenarlıklar (editör) |\n| `success` | Başarı durumları |\n| `error` | Hata durumları |\n| `warning` | Uyarı durumları |\n| `muted` | İkincil metin |\n| `dim` | Üçüncül metin |\n| `text` | Varsayılan metin (genellikle `\"\"`) |\n| `thinkingText` | Düşünme bloğu metni |\n\n### Arka Planlar ve İçerik (11 gerekli, 1 isteğe bağlı)\n\n| Jeton | Amaç |\n|-------|---------|\n| `selectedBg` | Seçilen satır arka planı |\n| `scrollbarThumb` | Tam ekran kaydırma çubuğu başparmak arka planı; isteğe bağlı, `selectedBg`'ye geri döner |\n| `userMessageBg` | Kullanıcı mesajı arka planı |\n| `userMessageText` | Kullanıcı mesaj metni |\n| `customMessageBg` | Uzantı mesajı arka planı |\n| `customMessageText` | Uzantı mesaj metni |\n| `customMessageLabel` | Uzantı mesaj etiketi |\n| `toolPendingBg` | Araç kutusu (beklemede) |\n| `toolSuccessBg` | Alet kutusu (başarı) |\n| `toolErrorBg` | Alet kutusu (hata) |\n| `toolTitle` | Araç başlığı |\n| `toolOutput` | Araç çıktı metni |\n\n### Markdown (10 renk)\n\n| Jeton | Amaç |\n|-------|---------|\n| `mdHeading` | Başlıklar |\n| `mdLink` | Bağlantı metni |\n| `mdLinkUrl` | Bağlantı URL'si |\n| `mdCode` | Satır içi kod |\n| `mdCodeBlock` | Kod bloğu içeriği |\n| `mdCodeBlockBorder` | Kod bloğu çitleri |\n| `mdQuote` | Blok alıntı metni |\n| `mdQuoteBorder` | Blok alıntı sınırı |\n| `mdHr` | Yatay kural |\n| `mdListBullet` | Madde işaretlerini listele |\n\n### Araç Farkları (3 renk)\n\n| Jeton | Amaç |\n|-------|---------|\n| `toolDiffAdded` | Eklenen satırlar |\n| `toolDiffRemoved` | Kaldırılan satırlar |\n| `toolDiffContext` | Bağlam satırları |\n\n### Sözdizimi Vurgulama (9 renk)\n\n| Jeton | Amaç |\n|-------|---------|\n| `syntaxComment` | Yorumlar |\n| `syntaxKeyword` | Anahtar Kelimeler |\n| `syntaxFunction` | İşlev adları |\n| `syntaxVariable` | Değişkenler |\n| `syntaxString` | Dizeler |\n| `syntaxNumber` | Sayılar |\n| `syntaxType` | Türler |\n| `syntaxOperator` | Operatörler |\n| `syntaxPunctuation` | Noktalama |\n\n### Düşünme Düzeyi Sınırları (6 gerekli, 1 isteğe bağlı)\n\nDüşünme düzeyini gösteren düzenleyici kenarlık renkleri (inceden göze çarpana doğru görsel hiyerarşi):\n\n| Jeton | Amaç |\n|-------|---------|\n| `thinkingOff` | Düşünmek |\n| `thinkingMinimal` | Minimal düşünme |\n| `thinkingLow` | Düşük düşünme |\n| `thinkingMedium` | Orta düşünme |\n| `thinkingHigh` | Yüksek düşünme |\n| `thinkingXhigh` | Ekstra yüksek düşünme |\n| `thinkingMax` | Maksimum düşünme; isteğe bağlı, `thinkingXhigh`'ye geri döner |\n\n### Bash Modu (1 renk)\n\n| Jeton | Amaç |\n|-------|---------|\n| `bashMode` | bash modunda düzenleyici kenarlığı (`!` öneki) |\n\n### HTML Dışa Aktarma (isteğe bağlı)\n\n`export` bölümü, `/export` HTML çıktısının renklerini kontrol eder. Atlanırsa renkler `userMessageBg`'den türetilir.\n\n```json\n{\n  \"export\": {\n    \"pageBg\": \"#18181e\",\n    \"cardBg\": \"#1e1e24\",\n    \"infoBg\": \"#3c3728\"\n  }\n}\n```\n\n## Renk Değerleri\n\nDört format desteklenir:\n\n| Biçim | Örnek | Tanım |\n|--------|---------|-------------|\n| Altıgen | `\"#ff0000\"` | 6 haneli altıgen RGB |\n| 256 renkli | `39` | xterm 256 renk paleti dizini (0-255) |\n| Değişken | `\"primary\"` | `vars` girişine referans |\n| Varsayılan | `\"\"` | Terminalin varsayılan rengi |\n\n### 256 Renk Paleti\n\n- `0-15`: Temel ANSI renkleri (terminale bağlı)\n- `16-231`: 6×6×6 RGB küp (`16 + 36×R + 6×G + B` burada R,G,B 0-5'tir)\n- `232-255`: Gri tonlamalı rampa\n\n### Terminal Uyumluluğu\n\nPi 24 bit RGB renkleri kullanır. Çoğu modern terminal bunu destekler (iTerm2, Kitty, WezTerm, Windows Terminal, VS Code). Yalnızca 256 renk desteğine sahip eski terminaller için pi, en yakın yaklaşıma geri döner.\n\nTruecolor desteğini kontrol edin:\n\n```bash\necho $COLORTERM  # Should output \"truecolor\" or \"24bit\"\n```\n\n## İpuçları\n\n**Koyu terminaller:** Daha yüksek kontrastlı, parlak, doygun renkler kullanın.\n\n**Açık terminaller:** Daha düşük kontrastlı, daha koyu, yumuşak renkler kullanın.\n\n**Renk uyumu:** Temel bir paletle başlayın (Nord, Gruvbox, Tokyo Night), onu `vars` ile tanımlayın ve tutarlı bir şekilde referans verin.\n\n**Test:** Farklı mesaj türleri, araç durumları, işaretleme içeriği ve uzun sarılmış metinlerle temanızı kontrol edin.\n\n**VS Kodu:** Doğru renkler için `terminal.integrated.minimumContrastRatio`'ı `1` olarak ayarlayın.\n\n## Örnekler\n\nYerleşik temalara bakın:\n- [dark.json](../src/modes/interactive/theme/dark.json)\n- [light.json](../src/modes/interactive/theme/light.json)","sourceFile":"themes.md"},"tmux":{"title":"tmux Kurulum","markdown":"Pi, tmux'nin içinde çalışır, ancak tmux, varsayılan olarak belirli tuşlardan değiştirici bilgileri çıkarır. Yapılandırma olmadan, `Shift+Enter` ve `Ctrl+Enter` genellikle düz `Enter`'den ayırt edilemez.\n\n## Önerilen Yapılandırma\n\n`~/.tmux.conf`'e ekle:\n\n```tmux\nset -g extended-keys on\nset -g extended-keys-format csi-u\n```\n\nArdından tmux'yi tamamen yeniden başlatın:\n\n```bash\ntmux kill-server\ntmux\n```\n\nPi Kitty klavye protokolü mevcut olmadığında otomatik olarak genişletilmiş anahtar raporlama ister. `extended-keys-format csi-u`, tmux ile değiştirilmiş anahtarlar CSI-u formatında iletilir, bu en güvenilir konfigürasyondur. `extended-keys-format` seçeneği tmux 3,5 veya üzerini gerektirir.\n\n## Neden `csi-u` Önerilir?\n\nYalnızca:\n\n```tmux\nset -g extended-keys on\n```\n\ntmux varsayılan olarak `extended-keys-format xterm` olur. Bir uygulama genişletilmiş anahtar raporlaması talep ettiğinde, değiştirilen anahtarlar aşağıdaki gibi xterm `modifyOtherKeys` formatında iletilir:\n\n- `Ctrl+C` → `\\x1b[27;5;99~`\n- `Ctrl+D` → `\\x1b[27;5;100~`\n- `Ctrl+Enter` → `\\x1b[27;5;13~`\n\n`extended-keys-format csi-u` ile aynı tuşlar şu şekilde iletilir:\n\n- `Ctrl+C` → `\\x1b[99;5u`\n- `Ctrl+D` → `\\x1b[100;5u`\n- `Ctrl+Enter` → `\\x1b[13;5u`\n\nPi her iki formatı da destekler, ancak `csi-u` önerilen tmux kurulumudur.\n\n## Bu Neyi Düzeltiyor\n\ntmux genişletilmiş tuşlar olmadan, değiştirilmiş Enter tuşları eski dizilere daraltılır:\n\n| Anahtar | Harici anahtarlar olmadan | `csi-u` ile |\n|-----|-----------------|--------------|\n| Girmek | `\\r` | `\\r` |\n| Shift+Enter | `\\r` | `\\x1b[13;2u` |\n| Ctrl+Enter | `\\r` | `\\x1b[13;5u` |\n| Alt/Option+Enter | `\\x1b\\r` | `\\x1b[13;3u` |\n\nBu, varsayılan tuş atamalarını (göndermek için `Enter`, yeni satır için `Shift+Enter`) ve değiştirilmiş Enter'ı kullanan tüm özel tuş atamalarını etkiler.\n\n## Gereksinimler\n\n- tmux `extended-keys-format csi-u` için 3,5 veya üzeri (kontrol etmek için `tmux -V` komutunu çalıştırın)\n- Genişletilmiş anahtarları destekleyen bir terminal emülatörü (Ghostty, Kitty, iTerm2, WezTerm, Windows Terminali)\n\ntmux 3,2 ila 3,4 arasında `extended-keys-format csi-u`'yi çıkarın; Pi hala tmux'nin varsayılan xterm `modifyOtherKeys` biçimini desteklemektedir.","sourceFile":"tmux.md"},"tui":{"title":"TUI Bileşenler","markdown":"> pi TUI bileşen oluşturabilir. Kullanım durumunuz için bir tane oluşturmasını isteyin.\n\n\nExtensions ve özel araçlar, etkileşimli kullanıcı arayüzleri için özel TUI bileşenleri oluşturabilir. Bu sayfa bileşen sistemini ve mevcut yapı taşlarını kapsar.\n\n**Kaynak:** [`@earendil-works/pi-tui`](https://github.com/earendil-works/pi-mono/tree/main/packages/tui)\n\n## Bileşen Arayüzü\n\nTüm bileşenler şunları uygular:\n\n```typescript\ninterface Component {\n  render(width: number): string[];\n  handleInput?(data: string): void;\n  wantsKeyRelease?: boolean;\n  invalidate(): void;\n}\n```\n\n| Yöntem | Tanım |\n|--------|-------------|\n| `render(width)` | Dize dizisini döndürür (satır başına bir tane). Her satır **`width`** değerini aşmamalıdır. |\n| `handleInput?(data)` | Bileşen odaklandığında klavye girişini alın. |\n| `wantsKeyRelease?` | Doğruysa, bileşen önemli sürüm olaylarını alır (Kitty protokolü). Varsayılan: yanlış. |\n| `invalidate()` | Önbelleğe alınmış oluşturma durumunu temizleyin. Tema değişiklikleri çağrısında bulunuldu. |\n\nTUI, oluşturulan her satırın sonuna tam bir SGR sıfırlaması ve OSC 8 sıfırlaması ekler. Stiller çizgiler boyunca taşınmaz. Stil içeren çok satırlı metin yayınlıyorsanız, stilleri her satıra yeniden uygulayın veya `wrapTextWithAnsi()` kullanın, böylece stiller her sarılmış satır için korunur.\n\n## Odaklanabilir Arayüz (IME Desteği)\n\nMetin imleci görüntüleyen ve IME (Giriş Yöntemi Düzenleyicisi) desteğine ihtiyaç duyan bileşenler `Focusable` arayüzünü uygulamalıdır:\n\n```typescript\nimport { CURSOR_MARKER, type Component, type Focusable } from \"@earendil-works/pi-tui\";\n\nclass MyInput implements Component, Focusable {\n  focused: boolean = false;  // Set by TUI when focus changes\n  \n  render(width: number): string[] {\n    const marker = this.focused ? CURSOR_MARKER : \"\";\n    // Emit marker right before the fake cursor\n    return [`> ${beforeCursor}${marker}\\x1b[7m${atCursor}\\x1b[27m${afterCursor}`];\n  }\n}\n```\n\nBir `Focusable` bileşeni odağa sahip olduğunda, TUI:\n1. Bileşende `focused = true` değerini ayarlar\n2. Oluşturulan çıktıyı `CURSOR_MARKER` (sıfır genişlikli bir APC kaçış dizisi) için tarar\n3. Donanım terminali imlecini bu konuma konumlandırır\n4. Donanım imlecini yalnızca `showHardwareCursor` etkinleştirildiğinde gösterir\n\nİmleç varsayılan olarak gizli kalır. Bu, donanım imlecini gizli imleçlerle IME aday pencerelerini izleyen terminaller için konumlandırmaya devam ederken, sahte imleç oluşturmayı korur. Bazı terminaller, IME konumlandırması için görünür bir donanım imleci gerektirir; `showHardwareCursor`, `setShowHardwareCursor(true)` veya `PI_HARDWARE_CURSOR=1` ile etkinleştirin. `Editor` ve `Input` yerleşik bileşenleri bu arayüzü zaten uygulamaktadır.\n\n### Yerleşik Girişlere Sahip Konteyner Bileşenleri\n\nBir kapsayıcı bileşeni (iletişim kutusu, seçici vb.) bir `Input` veya `Editor` alt öğesi içerdiğinde, kapsayıcının `Focusable` uygulamasını yapması ve odak durumunu alt öğeye yayması gerekir. Aksi takdirde donanım imleci IME girişi için doğru şekilde konumlandırılmayacaktır.\n\n```typescript\nimport { Container, type Focusable, Input } from \"@earendil-works/pi-tui\";\n\nclass SearchDialog extends Container implements Focusable {\n  private searchInput: Input;\n\n  // Focusable implementation - propagate to child input for IME cursor positioning\n  private _focused = false;\n  get focused(): boolean {\n    return this._focused;\n  }\n  set focused(value: boolean) {\n    this._focused = value;\n    this.searchInput.focused = value;\n  }\n\n  constructor() {\n    super();\n    this.searchInput = new Input();\n    this.addChild(this.searchInput);\n  }\n}\n```\n\nBu yayılma olmadan, IME (Çince, Japonca, Korece vb.) ile yazmak aday pencereyi ekranda yanlış konumda gösterecektir.\n\n## Bileşenleri Kullanma\n\n**Uzantılarda** `ctx.ui.custom()` aracılığıyla:\n\n```typescript\npi.on(\"session_start\", async (_event, ctx) => {\n  const result = await ctx.ui.custom<string | null>((tui, theme, keybindings, done) =>\n    new MyComponent({\n      theme,\n      keybindings,\n      onChange: () => tui.requestRender(),\n      onSelect: (value) => done(value),\n      onCancel: () => done(null),\n    })\n  );\n});\n```\n\n**Özel araçlarda** `ctx.ui.custom()` aracılığıyla:\n\n```typescript\nasync execute(toolCallId, params, signal, onUpdate, ctx) {\n  const result = await ctx.ui.custom<string | null>((tui, theme, keybindings, done) =>\n    new MyComponent({\n      theme,\n      keybindings,\n      onChange: () => tui.requestRender(),\n      onSelect: (value) => done(value),\n      onCancel: () => done(null),\n    })\n  );\n  // Use result...\n}\n```\n\n## Kaplamalar\n\nKaplamalar, ekranı temizlemeden bileşenleri mevcut içeriğin üzerine işler. `{ overlay: true }`'den `ctx.ui.custom()`'e geçin:\n\n```typescript\nconst result = await ctx.ui.custom<string | null>(\n  (tui, theme, keybindings, done) => new MyDialog({ onClose: done }),\n  { overlay: true }\n);\n```\n\nKonumlandırma ve boyutlandırma için `overlayOptions` kullanın:\n\n```typescript\nconst result = await ctx.ui.custom<string | null>(\n  (tui, theme, keybindings, done) => new SidePanel({ onClose: done }),\n  {\n    overlay: true,\n    overlayOptions: {\n      // Size: number or percentage string\n      width: \"50%\",          // 50% of terminal width\n      minWidth: 40,          // minimum 40 columns\n      maxHeight: \"80%\",      // max 80% of terminal height\n\n      // Position: anchor-based (default: \"center\")\n      anchor: \"right-center\", // 9 positions: center, top-left, top-center, etc.\n      offsetX: -2,            // offset from anchor\n      offsetY: 0,\n\n      // Or percentage/absolute positioning\n      row: \"25%\",            // 25% from top\n      col: 10,               // column 10\n\n      // Margins\n      margin: 2,             // all sides, or { top, right, bottom, left }\n\n      // Responsive: hide on narrow terminals\n      visible: (termWidth, termHeight) => termWidth >= 80,\n    },\n    // Get handle for programmatic focus and visibility control\n    onHandle: (handle) => {\n      // handle.focus() - focus this overlay and bring it to the visual front\n      // handle.unfocus() - release input to normal fallback\n      // handle.unfocus({ target }) - release input to a specific component or null\n      // handle.setHidden(true/false) - toggle visibility\n      // handle.hide() - permanently remove\n    },\n  }\n);\n```\n\n### Yer Paylaşımlı Odak\n\nOdaklanmış görünür bir yer paylaşımı, geçici yer paylaşımlı olmayan kullanıcı arayüzünde giriş sahipliğini korur. Bir kaplama, `{ overlay: true }` olmadan başka bir `ctx.ui.custom()` bileşeni açarsa, bu yedek kullanıcı arayüzü, etkinken girişi alır; kapandığında odaklanan katman girişi geri alabilir.\n\nGörünür bir kaplamanın girdi sahibi olmayı bırakması gerektiğinde `handle.unfocus()` kullanın ve TUI'nin başka bir görünür yakalama katmanına veya önceki odak hedefine geri dönmesine izin verin. Kaplama görünür kalırken belirli bir bileşenin girdi alması gerektiğinde `handle.unfocus({ target })` tuşunu kullanın. `{ target: null }`'yi kasıtlı olarak geçmek, odak yeniden ayarlanana kadar odaklanılan hiçbir bileşeni bırakmaz.\n\n### Yer Paylaşımı Yaşam Döngüsü\n\nKaplama bileşenleri kapatıldığında atılır. Referansları yeniden kullanmayın; yeni örnekler oluşturun:\n\n```typescript\n// Wrong - stale reference\nlet menu: MenuComponent;\nawait ctx.ui.custom((_, __, ___, done) => {\n  menu = new MenuComponent(done);\n  return menu;\n}, { overlay: true });\nsetActiveComponent(menu);  // Disposed\n\n// Correct - re-call to re-show\nconst showMenu = () => ctx.ui.custom((_, __, ___, done) => \n  new MenuComponent(done), { overlay: true });\n\nawait showMenu();  // First show\nawait showMenu();  // \"Back\" = just call again\n```\n\nBağlantıları, kenar boşluklarını, yığınlamayı, duyarlı görünürlüğü ve animasyonu kapsayan kapsamlı örnekler için [overlay-qa-tests.ts](../examples/extensions/overlay-qa-tests.ts)'e bakın.\n\n## Yerleşik Bileşenler\n\n`@earendil-works/pi-tui`'den içe aktar:\n\n```typescript\nimport { Text, Box, Container, Spacer, Markdown } from \"@earendil-works/pi-tui\";\n```\n\n### Metin\n\nKelime kaydırmalı çok satırlı metin.\n\n```typescript\nconst text = new Text(\n  \"Hello World\",    // content\n  1,                // paddingX (default: 1)\n  1,                // paddingY (default: 1)\n  (s) => bgGray(s)  // optional background function\n);\ntext.setText(\"Updated\");\n```\n\n### Kutu\n\nDolgu ve arka plan rengine sahip kapsayıcı.\n\n```typescript\nconst box = new Box(\n  1,                // paddingX\n  1,                // paddingY\n  (s) => bgGray(s)  // background function\n);\nbox.addChild(new Text(\"Content\", 0, 0));\nbox.setBgFn((s) => bgBlue(s));\n```\n\n### Konteyner\n\nAlt bileşenleri dikey olarak gruplandırır.\n\n```typescript\nconst container = new Container();\ncontainer.addChild(component1);\ncontainer.addChild(component2);\ncontainer.removeChild(component1);\n```\n\n### Ara parçası\n\nBoş dikey alan.\n\n```typescript\nconst spacer = new Spacer(2);  // 2 empty lines\n```\n\n### Markdown\n\nSözdizimi vurgulamayla işaretlemeyi oluşturur.\n\n```typescript\nconst md = new Markdown(\n  \"# Title\\n\\nSome **bold** text\",\n  1,        // paddingX\n  1,        // paddingY\n  theme     // MarkdownTheme (see below)\n);\nmd.setText(\"Updated markdown\");\n```\n\n### Resim\n\nDesteklenen terminallerdeki (Kitty, iTerm2, Ghostty, WezTerm, Warp) görüntüleri işler.\n\n```typescript\nconst image = new Image(\n  base64Data,   // base64-encoded image\n  \"image/png\",  // MIME type\n  theme,        // ImageTheme\n  { maxWidthCells: 80, maxHeightCells: 24 }\n);\n```\n\n## Klavye Girişi\n\nAnahtar tespiti için `matchesKey()` kullanın:\n\n```typescript\nimport { matchesKey, Key } from \"@earendil-works/pi-tui\";\n\nhandleInput(data: string) {\n  if (matchesKey(data, Key.up)) {\n    this.selectedIndex--;\n  } else if (matchesKey(data, Key.enter)) {\n    this.onSelect?.(this.selectedIndex);\n  } else if (matchesKey(data, Key.escape)) {\n    this.onCancel?.();\n  } else if (matchesKey(data, Key.ctrl(\"c\"))) {\n    // Ctrl+C\n  }\n}\n```\n\n**Anahtar tanımlayıcılar** (otomatik tamamlama veya dize değişmezleri için `Key.*` kullanın):\n- Temel tuşlar: `Key.enter`, `Key.escape`, `Key.tab`, `Key.space`, `Key.backspace`, `Key.delete`, `Key.home`, `Key.end`\n- Ok tuşları: `Key.up`, `Key.down`, `Key.left`, `Key.right`\n- Değiştiricilerle: `Key.ctrl(\"c\")`, `Key.shift(\"tab\")`, `Key.alt(\"left\")`, `Key.ctrlShift(\"p\")`\n- Dize formatı da çalışır: `\"enter\"`, `\"ctrl+c\"`, `\"shift+tab\"`, `\"ctrl+shift+p\"`\n\n## Çizgi Genişliği\n\n**Kritik:** `render()`'den itibaren her satır `width` parametresini aşmamalıdır.\n\n```typescript\nimport { visibleWidth, truncateToWidth } from \"@earendil-works/pi-tui\";\n\nrender(width: number): string[] {\n  // Truncate long lines\n  return [truncateToWidth(this.text, width)];\n}\n```\n\nYardımcı programlar:\n- `visibleWidth(str)` - Ekran genişliğini al (ANSI kodlarını yok sayar)\n- `truncateToWidth(str, width, ellipsis?)` - İsteğe bağlı üç noktayla kesme\n- `wrapTextWithAnsi(str, width)` - ANSI kodlarını koruyan kelime kaydırma\n\n## Özel Bileşenler Oluşturma\n\nÖrnek: Etkileşimli seçici\n\n```typescript\nimport {\n  matchesKey, Key,\n  truncateToWidth, visibleWidth\n} from \"@earendil-works/pi-tui\";\n\nclass MySelector {\n  private items: string[];\n  private selected = 0;\n  private cachedWidth?: number;\n  private cachedLines?: string[];\n  \n  public onSelect?: (item: string) => void;\n  public onCancel?: () => void;\n\n  constructor(items: string[]) {\n    this.items = items;\n  }\n\n  handleInput(data: string): void {\n    if (matchesKey(data, Key.up) && this.selected > 0) {\n      this.selected--;\n      this.invalidate();\n    } else if (matchesKey(data, Key.down) && this.selected < this.items.length - 1) {\n      this.selected++;\n      this.invalidate();\n    } else if (matchesKey(data, Key.enter)) {\n      this.onSelect?.(this.items[this.selected]);\n    } else if (matchesKey(data, Key.escape)) {\n      this.onCancel?.();\n    }\n  }\n\n  render(width: number): string[] {\n    if (this.cachedLines && this.cachedWidth === width) {\n      return this.cachedLines;\n    }\n\n    this.cachedLines = this.items.map((item, i) => {\n      const prefix = i === this.selected ? \"> \" : \"  \";\n      return truncateToWidth(prefix + item, width);\n    });\n    this.cachedWidth = width;\n    return this.cachedLines;\n  }\n\n  invalidate(): void {\n    this.cachedWidth = undefined;\n    this.cachedLines = undefined;\n  }\n}\n```\n\nBir uzantıda kullanım:\n\n```typescript\npi.registerCommand(\"pick\", {\n  description: \"Pick an item\",\n  handler: async (_args, ctx) => {\n    const items = [\"Option A\", \"Option B\", \"Option C\"];\n    const selected = await ctx.ui.custom<string | null>((tui, _theme, _keybindings, done) => {\n      const selector = new MySelector(items);\n      selector.onSelect = done;\n      selector.onCancel = () => done(null);\n\n      return {\n        render: (width) => selector.render(width),\n        handleInput: (data) => {\n          selector.handleInput(data);\n          tui.requestRender();\n        },\n        invalidate: () => selector.invalidate(),\n      };\n    });\n\n    if (selected !== null) {\n      ctx.ui.notify(`Selected: ${selected}`, \"info\");\n    }\n  }\n});\n```\n\n## Tema\n\nBileşenler stillendirme için tema nesnelerini kabul eder.\n\n**`renderCall`/`renderResult`**'de `theme` parametresini kullanın:\n\n```typescript\nrenderResult(result, options, theme, context) {\n  // Use theme.fg() for foreground colors\n  return new Text(theme.fg(\"success\", \"Done!\"), 0, 0);\n  \n  // Use theme.bg() for background colors\n  const styled = theme.bg(\"toolPendingBg\", theme.fg(\"accent\", \"text\"));\n}\n```\n\n**Ön plan renkleri** (`theme.fg(color, text)`):\n\n| Kategori | Renkler |\n|----------|--------|\n| Genel | `text`, `accent`, `muted`, `dim` |\n| Durum | `success`, `error`, `warning` |\n| Kenarlıklar | `border`, `borderAccent`, `borderMuted` |\n| Mesajlar | `userMessageText`, `customMessageText`, `customMessageLabel` |\n| Aletler | `toolTitle`, `toolOutput` |\n| Farklar | `toolDiffAdded`, `toolDiffRemoved`, `toolDiffContext` |\n| Markdown | `mdHeading`, `mdLink`, `mdLinkUrl`, `mdCode`, `mdCodeBlock`, `mdCodeBlockBorder`, `mdQuote`, `mdQuoteBorder`, `mdHr`, `mdListBullet` |\n| Sözdizimi | `syntaxComment`, `syntaxKeyword`, `syntaxFunction`, `syntaxVariable`, `syntaxString`, `syntaxNumber`, `syntaxType`, `syntaxOperator`, `syntaxPunctuation` |\n| Düşünme | `thinkingOff`, `thinkingMinimal`, `thinkingLow`, `thinkingMedium`, `thinkingHigh`, `thinkingXhigh`, `thinkingMax` |\n| Modlar | `bashMode` |\n\n**Arka plan renkleri** (`theme.bg(color, text)`):\n\n`selectedBg`, `userMessageBg`, `customMessageBg`, `toolPendingBg`, `toolSuccessBg`, `toolErrorBg`\n\n**Markdown** için `getMarkdownTheme()` kullanın:\n\n```typescript\nimport { getMarkdownTheme } from \"@earendil-works/pi-coding-agent\";\nimport { Markdown } from \"@earendil-works/pi-tui\";\n\nrenderResult(result, options, theme, context) {\n  const mdTheme = getMarkdownTheme();\n  return new Markdown(result.details.markdown, 0, 0, mdTheme);\n}\n```\n\n**Özel bileşenler için** kendi tema arayüzünüzü tanımlayın:\n\n```typescript\ninterface MyTheme {\n  selected: (s: string) => string;\n  normal: (s: string) => string;\n}\n```\n\n## Hata ayıklama günlüğü\n\nstdout'ye yazılan ham ANSI akışını yakalamak için `PI_TUI_WRITE_LOG`'yi ayarlayın.\n\n```bash\nPI_TUI_WRITE_LOG=/tmp/tui-ansi.log npx tsx packages/tui/test/chat-simple.ts\n```\n\n## Performans\n\nMümkün olduğunda oluşturulan çıktıyı önbelleğe alın:\n\n```typescript\nclass CachedComponent {\n  private cachedWidth?: number;\n  private cachedLines?: string[];\n\n  render(width: number): string[] {\n    if (this.cachedLines && this.cachedWidth === width) {\n      return this.cachedLines;\n    }\n    // ... compute lines ...\n    this.cachedWidth = width;\n    this.cachedLines = lines;\n    return lines;\n  }\n\n  invalidate(): void {\n    this.cachedWidth = undefined;\n    this.cachedLines = undefined;\n  }\n}\n```\n\nDurum değiştiğinde `invalidate()` çağrısını yapın, ardından yeniden oluşturmayı tetiklemek için enjekte edilen `tui.requestRender()` öğesini kullanın.\n\n## Geçersiz Kılma ve Tema Değişiklikleri\n\nTema değiştiğinde, TUI tüm bileşenlerin önbelleklerini temizlemek için `invalidate()`'yi çağırır. Tema değişikliklerinin etkili olmasını sağlamak için bileşenlerin `invalidate()`'yi düzgün bir şekilde uygulaması gerekir.\n\n### Sorun\n\nBir bileşen, tema renklerini dizeler halinde önceden hazırlıyorsa (`theme.fg()`, `theme.bg()` vb. yoluyla) ve bunları önbelleğe alıyorsa, önbelleğe alınan dizeler eski temadan ANSI çıkış kodları içerir. Bileşen temalı içeriği ayrı olarak saklıyorsa, yalnızca oluşturma önbelleğini temizlemek yeterli değildir.\n\n**Yanlış yaklaşım** (tema renkleri güncellenmiyor):\n\n```typescript\nclass BadComponent extends Container {\n  private content: Text;\n\n  constructor(message: string, theme: Theme) {\n    super();\n    // Pre-baked theme colors stored in Text component\n    this.content = new Text(theme.fg(\"accent\", message), 1, 0);\n    this.addChild(this.content);\n  }\n  // No invalidate override - parent's invalidate only clears\n  // child render caches, not the pre-baked content\n}\n```\n\n### Çözüm\n\nTema renkleriyle içerik oluşturan bileşenlerin, `invalidate()` çağrıldığında bu içeriği yeniden oluşturması gerekir:\n\n```typescript\nclass GoodComponent extends Container {\n  private message: string;\n  private content: Text;\n\n  constructor(message: string) {\n    super();\n    this.message = message;\n    this.content = new Text(\"\", 1, 0);\n    this.addChild(this.content);\n    this.updateDisplay();\n  }\n\n  private updateDisplay(): void {\n    // Rebuild content with current theme\n    this.content.setText(theme.fg(\"accent\", this.message));\n  }\n\n  override invalidate(): void {\n    super.invalidate();  // Clear child caches\n    this.updateDisplay(); // Rebuild with new theme\n  }\n}\n```\n\n### Desen: Geçersiz Kılma Durumunda Yeniden Oluşturma\n\nKarmaşık içeriğe sahip bileşenler için:\n\n```typescript\nclass ComplexComponent extends Container {\n  private data: SomeData;\n\n  constructor(data: SomeData) {\n    super();\n    this.data = data;\n    this.rebuild();\n  }\n\n  private rebuild(): void {\n    this.clear();  // Remove all children\n\n    // Build UI with current theme\n    this.addChild(new Text(theme.fg(\"accent\", theme.bold(\"Title\")), 1, 0));\n    this.addChild(new Spacer(1));\n\n    for (const item of this.data.items) {\n      const color = item.active ? \"success\" : \"muted\";\n      this.addChild(new Text(theme.fg(color, item.label), 1, 0));\n    }\n  }\n\n  override invalidate(): void {\n    super.invalidate();\n    this.rebuild();\n  }\n}\n```\n\n### Bu Önemli Olduğunda\n\nBu model şu durumlarda gereklidir:\n\n1. **Ön pişirme tema renkleri** - Alt bileşenlerde saklanan stilize dizeler oluşturmak için `theme.fg()` veya `theme.bg()` kullanma\n2. **Sözdizimi vurgulama** - Temaya dayalı sözdizimi renklerini uygulayan `highlightCode()` kullanımı\n3. **Karmaşık düzenler** - Tema renklerini içeren alt bileşen ağaçları oluşturma\n\nBu desen şu durumlarda gerekli DEĞİLDİR:\n\n1. **Tema geri çağırmalarını kullanma** - Oluşturma sırasında çağrılan `(text) => theme.fg(\"accent\", text)` gibi işlevlerin iletilmesi\n2. **Basit kapsayıcılar** - Temalı içerik eklemeden yalnızca diğer bileşenleri gruplandırma\n3. **Durum bilgisi olmayan işleme** - Her `render()` aramada temalı çıktının yeni olarak hesaplanması (önbelleğe alma yok)\n\n## Ortak Desenler\n\nBu modeller, uzantılardaki en yaygın kullanıcı arayüzü ihtiyaçlarını kapsar. **Sıfırdan oluşturmak yerine bu kalıpları kopyalayın.**\n\n### Model 1: Seçim İletişim Kutusu (SelectList)\n\nKullanıcıların seçenekler listesinden seçim yapmasına izin vermek için. Çerçeveleme için `@earendil-works/pi-tui`'den `SelectList`'yi `DynamicBorder` ile kullanın.\n\n```typescript\nimport type { ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\nimport { DynamicBorder } from \"@earendil-works/pi-coding-agent\";\nimport { Container, type SelectItem, SelectList, Text } from \"@earendil-works/pi-tui\";\n\npi.registerCommand(\"pick\", {\n  handler: async (_args, ctx) => {\n    const items: SelectItem[] = [\n      { value: \"opt1\", label: \"Option 1\", description: \"First option\" },\n      { value: \"opt2\", label: \"Option 2\", description: \"Second option\" },\n      { value: \"opt3\", label: \"Option 3\" },  // description is optional\n    ];\n\n    const result = await ctx.ui.custom<string | null>((tui, theme, _kb, done) => {\n      const container = new Container();\n\n      // Top border\n      container.addChild(new DynamicBorder((s: string) => theme.fg(\"accent\", s)));\n\n      // Title\n      container.addChild(new Text(theme.fg(\"accent\", theme.bold(\"Pick an Option\")), 1, 0));\n\n      // SelectList with theme\n      const selectList = new SelectList(items, Math.min(items.length, 10), {\n        selectedPrefix: (t) => theme.fg(\"accent\", t),\n        selectedText: (t) => theme.fg(\"accent\", t),\n        description: (t) => theme.fg(\"muted\", t),\n        scrollInfo: (t) => theme.fg(\"dim\", t),\n        noMatch: (t) => theme.fg(\"warning\", t),\n      });\n      selectList.onSelect = (item) => done(item.value);\n      selectList.onCancel = () => done(null);\n      container.addChild(selectList);\n\n      // Help text\n      container.addChild(new Text(theme.fg(\"dim\", \"↑↓ navigate • enter select • esc cancel\"), 1, 0));\n\n      // Bottom border\n      container.addChild(new DynamicBorder((s: string) => theme.fg(\"accent\", s)));\n\n      return {\n        render: (w) => container.render(w),\n        invalidate: () => container.invalidate(),\n        handleInput: (data) => { selectList.handleInput(data); tui.requestRender(); },\n      };\n    });\n\n    if (result) {\n      ctx.ui.notify(`Selected: ${result}`, \"info\");\n    }\n  },\n});\n```\n\n**Örnekler:** [preset.ts](../examples/extensions/preset.ts), [tools.ts](../examples/extensions/tools.ts)\n\n### Model 2: İptal ile Eşzamansız İşlem (BorderedLoader)\n\nZaman alan ve iptal edilmesi gereken işlemler için. `BorderedLoader` bir döndürücüyü gösterir ve iptal etmek için kaçış işlemlerini gerçekleştirir.\n\n```typescript\nimport { BorderedLoader } from \"@earendil-works/pi-coding-agent\";\n\npi.registerCommand(\"fetch\", {\n  handler: async (_args, ctx) => {\n    const result = await ctx.ui.custom<string | null>((tui, theme, _kb, done) => {\n      const loader = new BorderedLoader(tui, theme, \"Fetching data...\");\n      loader.onAbort = () => done(null);\n\n      // Do async work\n      fetchData(loader.signal)\n        .then((data) => done(data))\n        .catch(() => done(null));\n\n      return loader;\n    });\n\n    if (result === null) {\n      ctx.ui.notify(\"Cancelled\", \"info\");\n    } else {\n      ctx.ui.setEditorText(result);\n    }\n  },\n});\n```\n\n**Örnekler:** [qna.ts](../examples/extensions/qna.ts), [handoff.ts](../examples/extensions/handoff.ts)\n\n### Desen 3: Ayarlar/Geçişler (AyarlarList)\n\nBirden fazla ayarı değiştirmek için. `@earendil-works/pi-tui`'den `SettingsList`'yi `getSettingsListTheme()` ile kullanın.\n\n```typescript\nimport { getSettingsListTheme } from \"@earendil-works/pi-coding-agent\";\nimport { Container, type SettingItem, SettingsList, Text } from \"@earendil-works/pi-tui\";\n\npi.registerCommand(\"settings\", {\n  handler: async (_args, ctx) => {\n    const items: SettingItem[] = [\n      { id: \"verbose\", label: \"Verbose mode\", currentValue: \"off\", values: [\"on\", \"off\"] },\n      { id: \"color\", label: \"Color output\", currentValue: \"on\", values: [\"on\", \"off\"] },\n    ];\n\n    await ctx.ui.custom((_tui, theme, _kb, done) => {\n      const container = new Container();\n      container.addChild(new Text(theme.fg(\"accent\", theme.bold(\"Settings\")), 1, 1));\n\n      const settingsList = new SettingsList(\n        items,\n        Math.min(items.length + 2, 15),\n        getSettingsListTheme(),\n        (id, newValue) => {\n          // Handle value change\n          ctx.ui.notify(`${id} = ${newValue}`, \"info\");\n        },\n        () => done(undefined),  // On close\n        { enableSearch: true }, // Optional: enable fuzzy search by label\n      );\n      container.addChild(settingsList);\n\n      return {\n        render: (w) => container.render(w),\n        invalidate: () => container.invalidate(),\n        handleInput: (data) => settingsList.handleInput?.(data),\n      };\n    });\n  },\n});\n```\n\n**Örnekler:** [tools.ts](../examples/extensions/tools.ts)\n\n### Desen 4: Kalıcı Durum Göstergesi\n\nOluşturmalarda devam eden alt bilgideki durumu gösterin. Mod göstergeleri için iyi.\n\n```typescript\n// Set status (shown in footer)\nctx.ui.setStatus(\"my-ext\", ctx.ui.theme.fg(\"accent\", \"● active\"));\n\n// Clear status\nctx.ui.setStatus(\"my-ext\", undefined);\n```\n\n**Örnekler:** [status-line.ts](../examples/extensions/status-line.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts)\n\n### Desen 4b: Çalışma Göstergesinin Özelleştirilmesi\n\nPi bir yanıt akışı yaparken gösterilen satır içi çalışma göstergesini özelleştirin.\n\n```typescript\n// Static indicator\nctx.ui.setWorkingIndicator({ frames: [ctx.ui.theme.fg(\"accent\", \"●\")] });\n\n// Custom animated indicator\nctx.ui.setWorkingIndicator({\n  frames: [\n    ctx.ui.theme.fg(\"dim\", \"·\"),\n    ctx.ui.theme.fg(\"muted\", \"•\"),\n    ctx.ui.theme.fg(\"accent\", \"●\"),\n    ctx.ui.theme.fg(\"muted\", \"•\"),\n  ],\n  intervalMs: 120,\n});\n\n// Hide the indicator entirely\nctx.ui.setWorkingIndicator({ frames: [] });\n\n// Restore pi's default spinner\nctx.ui.setWorkingIndicator();\n```\n\nBu yalnızca normal akış çalışma göstergesini etkiler. Sıkıştırma ve yeniden deneme yükleyicileri yerleşik stillerini korur. Özel çerçeveler kelimesi kelimesine işlenir, bu nedenle gerektiğinde uzantıların kendi renklerini eklemesi gerekir.\n\n**Örnekler:** [working-indicator.ts](../examples/extensions/working-indicator.ts)\n\n### Desen 5: Düzenleyicinin Üstü/Altındaki Widget'lar\n\nKalıcı içeriği giriş düzenleyicisinin üstünde veya altında gösterin. Yapılacaklar listeleri için iyi, ilerleme.\n\n```typescript\n// Simple string array (above editor by default)\nctx.ui.setWidget(\"my-widget\", [\"Line 1\", \"Line 2\"]);\n\n// Render below the editor\nctx.ui.setWidget(\"my-widget\", [\"Line 1\", \"Line 2\"], { placement: \"belowEditor\" });\n\n// Or with theme\nctx.ui.setWidget(\"my-widget\", (_tui, theme) => {\n  const lines = items.map((item, i) =>\n    item.done\n      ? theme.fg(\"success\", \"✓ \") + theme.fg(\"muted\", item.text)\n      : theme.fg(\"dim\", \"○ \") + item.text\n  );\n  return {\n    render: () => lines,\n    invalidate: () => {},\n  };\n});\n\n// Clear\nctx.ui.setWidget(\"my-widget\", undefined);\n```\n\n**Örnekler:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts)\n\n### Desen 6: Özel Alt Bilgi\n\nAltbilgiyi değiştirin. `footerData` uzantıların başka şekilde erişemeyeceği verileri açığa çıkarır.\n\n```typescript\nctx.ui.setFooter((tui, theme, footerData) => ({\n  invalidate() {},\n  render(width: number): string[] {\n    // footerData.getGitBranch(): string | null\n    // footerData.getExtensionStatuses(): ReadonlyMap<string, string>\n    return [`${ctx.model?.id} (${footerData.getGitBranch() || \"no git\"})`];\n  },\n  dispose: footerData.onBranchChange(() => tui.requestRender()), // reactive\n}));\n\nctx.ui.setFooter(undefined); // restore default\n```\n\nToken istatistikleri `ctx.sessionManager.getBranch()` ve `ctx.model` üzerinden kullanılabilir.\n\n**Örnekler:** [custom-footer.ts](../examples/extensions/custom-footer.ts)\n\n### Desen 7: Özel Düzenleyici (vim modu vb.)\n\nAna giriş düzenleyicisini özel bir uygulamayla değiştirin. Modal düzenleme (vim), farklı tuş atamaları (emacs) veya özel giriş işleme için kullanışlıdır.\n\n```typescript\nimport { CustomEditor, type ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\nimport { matchesKey, truncateToWidth } from \"@earendil-works/pi-tui\";\n\ntype Mode = \"normal\" | \"insert\";\n\nclass VimEditor extends CustomEditor {\n  private mode: Mode = \"insert\";\n\n  handleInput(data: string): void {\n    // Escape: switch to normal mode, or pass through for app handling\n    if (matchesKey(data, \"escape\")) {\n      if (this.mode === \"insert\") {\n        this.mode = \"normal\";\n        return;\n      }\n      // In normal mode, escape aborts agent (handled by CustomEditor)\n      super.handleInput(data);\n      return;\n    }\n\n    // Insert mode: pass everything to CustomEditor\n    if (this.mode === \"insert\") {\n      super.handleInput(data);\n      return;\n    }\n\n    // Normal mode: vim-style navigation\n    switch (data) {\n      case \"i\": this.mode = \"insert\"; return;\n      case \"h\": super.handleInput(\"\\x1b[D\"); return; // Left\n      case \"j\": super.handleInput(\"\\x1b[B\"); return; // Down\n      case \"k\": super.handleInput(\"\\x1b[A\"); return; // Up\n      case \"l\": super.handleInput(\"\\x1b[C\"); return; // Right\n    }\n    // Pass unhandled keys to super (ctrl+c, etc.), but filter printable chars\n    if (data.length === 1 && data.charCodeAt(0) >= 32) return;\n    super.handleInput(data);\n  }\n\n  render(width: number): string[] {\n    const lines = super.render(width);\n    // Add mode indicator to bottom border (use truncateToWidth for ANSI-safe truncation)\n    if (lines.length > 0) {\n      const label = this.mode === \"normal\" ? \" NORMAL \" : \" INSERT \";\n      const lastLine = lines[lines.length - 1]!;\n      // Pass \"\" as ellipsis to avoid adding \"...\" when truncating\n      lines[lines.length - 1] = truncateToWidth(lastLine, width - label.length, \"\") + label;\n    }\n    return lines;\n  }\n}\n\nexport default function (pi: ExtensionAPI) {\n  pi.on(\"session_start\", (_event, ctx) => {\n    // Factory receives the TUI, theme, and keybindings from the app\n    ctx.ui.setEditorComponent((tui, theme, keybindings) =>\n      new VimEditor(tui, theme, keybindings)\n    );\n  });\n}\n```\n\n**Önemli noktalar:**\n\n- **Uygulama tuş atamalarını almak için `CustomEditor`** (temel `Editor` değil) öğesini genişletin (iptal etmek için kaçış, çıkmak için ctrl+d, model değiştirme vb.)\n- **Elinizde olmayan anahtarlar için `super.handleInput(data)`**'ı arayın\n- **Fabrika modeli**: `setEditorComponent`, `tui`, `theme` ve `keybindings` elde eden bir fabrika işlevi alır\n- **Varsayılan düzenleyiciyi geri yüklemek için `undefined`** iletin: `ctx.ui.setEditorComponent(undefined)`\n\n**Örnekler:** [modal-editor.ts](../examples/extensions/modal-editor.ts)\n\n## Temel Kurallar\n\n1. **Temayı her zaman geri aramadan kullan** - Temayı doğrudan içe aktarmayın. `ctx.ui.custom((tui, theme, keybindings, done) =>...)` geri aramasından `theme` kullanın.\n\n2. **Her zaman DynamicBorder renk parametresini yazın** - `(s) => theme.fg(\"accent\", s)` değil, `(s: string) => theme.fg(\"accent\", s)` yazın.\n\n3. **Durum değişikliklerinden sonra tui.requestRender()'ı çağırın** - `handleInput`'da, durumu güncelledikten sonra `tui.requestRender()`'yi çağırın.\n\n4. **Üç yöntemli nesneyi döndür** - Özel bileşenlerin `{ render, invalidate, handleInput }` olması gerekir.\n\n5. **Mevcut bileşenleri kullanın** - `SelectList`, `SettingsList`, `BorderedLoader` vakaların %90'ını kapsar. Onları yeniden inşa etmeyin.\n\n## Örnekler\n\n- **Seçim Kullanıcı Arayüzü**: [examples/extensions/preset.ts](../examples/extensions/preset.ts) - DynamicBorder çerçevelemeli SelectList\n- **İptal ile eşzamansız**: [examples/extensions/qna.ts](../examples/extensions/qna.ts) - Yüksek Lisans çağrıları için BorderedLoader\n- **Ayarlar arasında geçiş yapar**: [examples/extensions/tools.ts](../examples/extensions/tools.ts) - Araç etkinleştirme/devre dışı bırakma için AyarlarList\n- **Durum göstergeleri**: [examples/extensions/plan-mode/index.ts](../examples/extensions/plan-mode/index.ts) - setStatus ve setWidget\n- **Çalışma göstergesi**: [examples/extensions/working-indicator.ts](../examples/extensions/working-indicator.ts) - setWorkingIndicator\n- **Özel altbilgi**: [examples/extensions/custom-footer.ts](../examples/extensions/custom-footer.ts) - istatistiklerle setFooter\n- **Özel düzenleyici**: [examples/extensions/modal-editor.ts](../examples/extensions/modal-editor.ts) - Vim benzeri kalıcı düzenleme\n- **Yılan oyunu**: [examples/extensions/snake.ts](../examples/extensions/snake.ts) - Klavye girişiyle tam oyun, oyun döngüsü\n- **Özel araç oluşturma**: [examples/extensions/todo.ts](../examples/extensions/todo.ts) - renderCall ve renderResult","sourceFile":"tui.md"},"usage":{"title":"Pi kullanımı","markdown":"Bu sayfa, hızlı başlangıç ​​sayfasına sığmayan günlük kullanım ayrıntılarını toplar.\n\n## İnteraktif Mod\n\n<p align=\"center\"><img src=\"images/interactive-mode.png\" alt=\"Interactive Mode\" width=\"600\"></p>\n\nArayüzün dört ana alanı vardır:\n\n- **Başlangıç ​​başlığı** - kısayollar, yüklü context files, prompt templates, beceriler ve uzantılar\n- **Mesajlar** - kullanıcı mesajları, asistan yanıtları, araç çağrıları, araç sonuçları, bildirimler, hatalar ve uzantı kullanıcı arayüzü\n- **Editör** - yazdığınız yer; kenarlık rengi mevcut düşünme düzeyini gösterir\n- **Altbilgi** - çalışma dizini, oturum adı, belirteç/önbellek kullanımı, maliyet, içerik kullanımı ve geçerli model. Toplamlar; asistan yanıtlarını, araçlar tarafından bildirilen kullanımı ve özet oluşturmayı içerir.\n\nDüzenleyici, `/settings` gibi yerleşik kullanıcı arayüzü veya özel uzantı kullanıcı arayüzü ile geçici olarak değiştirilebilir.\n\n### Düzenleyici Özellikleri\n\n| Özellik | Nasıl |\n|---------|-----|\n| Dosya referansı | Proje dosyalarını bulanık aramak için `@` yazın |\n| Yol tamamlama | Yolları tamamlamak için Sekme tuşuna basın |\n| Çok hatlı giriş | Windows Terminalinde Shift+Enter veya Ctrl+Enter |\n| Yanıtı kopyala | Ctrl+X son yardımcı mesajını kopyalar; `/tree`'de seçilen mesajı kopyalar |\n| Görseller | Windows'ta Ctrl+V, Alt+V ile yapıştırın veya terminale sürükleyin |\n| Kabuk komutu | `!command` çalıştırır ve çıktıyı modele gönderir |\n| Gizli kabuk komutu | `!!command` modele çıktı göndermeden çalışır |\n| Harici editör | Ctrl+G, Windows'ta `externalEditor`, `$VISUAL`, `$EDITOR`, Not Defteri'ni veya başka yerde `nano`'yi açar |\n\nTüm kısayollar ve özelleştirme için [Keybindings](keybindings.md)'ye bakın.\n\n## Eğik Çizgi Komutları\n\nKomut tamamlamayı açmak için düzenleyiciye `/` yazın. Extensions özel komutları kaydedebilir, beceriler `/skill:name` olarak mevcuttur ve prompt templates, `/templatename` aracılığıyla genişletilir.\n\n| Emretmek | Tanım |\n|---------|-------------|\n| `/login`, `/logout` | OAuth veya API anahtar kimlik bilgilerini yönetin |\n| [`/llama`](llama-cpp.md) | llama.cpp yönlendirici modellerini indirin, yükleyin ve kaldırın |\n| `/model` | Modelleri değiştir |\n| `/scoped-models` | Ctrl+P döngüsü için modelleri etkinleştirme/devre dışı bırakma |\n| `/settings` | Düşünme düzeyi, tema, mesaj iletimi, aktarım |\n| `/resume` | Önceki oturumlardan Pick |\n| `/new` | Yeni bir oturum başlat |\n| `/name <name>` | Oturumun görünen adını ayarlayın |\n| `/session` | Oturum dosyasını, kimliği, mesajları, belirteçleri ve maliyeti göster |\n| `/tree` | Oturumun herhangi bir noktasına atlayın ve oradan devam edin |\n| `/trust` | Gelecek oturumlar için proje güven kararını kaydedin |\n| `/fork` | Önceki bir kullanıcı mesajından yeni bir oturum oluşturun |\n| `/clone` | Geçerli etkin dalı yeni bir oturuma kopyala |\n| `/compact [prompt]` | İsteğe bağlı olarak özel talimatlarla bağlamı manuel olarak sıkıştırın |\n| `/copy` | Son asistan mesajını panoya kopyala |\n| `/export [file]` | Oturumu HTML'ye aktar veya JSONL |\n| `/import <file>` | JSONL dosyasından bir oturumu içe aktarın ve devam ettirin |\n| `/share` | Paylaşılabilir HTML bağlantısıyla özel GitHub özet olarak yükleyin |\n| `/reload` | Tuş atamalarını, uzantıları, becerileri, istemleri, temaları ve context files'yi yeniden yükleyin |\n| `/hotkeys` | Tüm klavye kısayollarını göster |\n| `/changelog` | Sürüm geçmişini görüntüle |\n| `/quit` | pi'den çık |\n\n## Mesaj Sırası\n\nTemsilci hâlâ çalışırken mesaj gönderebilirsiniz:\n\n- **Enter**, geçerli asistan sırasının araç çağrılarını yürütmesi tamamlandıktan sonra iletilen bir direksiyon mesajını sıraya koyar.\n- **Alt+Enter**, aracı tüm işi tamamladıktan sonra teslim edilecek bir takip mesajını sıraya koyar.\n- **Escape** sıradaki iletileri iptal eder ve düzenleyiciye geri yükler.\n- **Alt+Up** sıraya alınmış mesajları düzenleyiciye geri getirir.\n\nWindows Terminalinde Alt+Enter varsayılan olarak tam ekrandır. Pi'nin kısayolu almasını istiyorsanız, [Terminal setup](terminal-setup.md)'de açıklandığı gibi yeniden eşleyin.\n\n[Settings](settings.md)'de teslimatı `steeringMode` ve `followUpMode` ile yapılandırın.\n\n## Oturumlar\n\nOturumlar, çalışma dizinine göre düzenlenerek otomatik olarak `~/.pi/agent/sessions/`'ye kaydedilir.\n\n```bash\npi -c                  # Continue most recent session\npi -r                  # Browse and select a session\npi --no-session        # Ephemeral mode; do not save\npi --name \"my task\"    # Set session display name at startup\npi --session <path|id> # Use a specific session file or session ID\npi --fork <path|id>    # Fork a session into a new session file\n```\n\nYararlı oturum komutları:\n\n- `/session` geçerli oturum dosyasını ve kimliğini gösterir.\n- `/tree` dosya içi session tree içinde gezinir ve terkedilmiş dalları özetleyebilir.\n- `/fork` daha önceki bir kullanıcı mesajından yeni bir oturum oluşturur.\n- `/clone` mevcut aktif dalı yeni bir oturum dosyasına kopyalar.\n- `/compact` eski mesajları serbest bağlamda özetler.\n\nAyrıntılar için [Sessions](sessions.md) ve [Compaction](compaction.md)'e bakın.\n\n## Bağlam Dosyaları\n\nPi başlangıçta `AGENTS.md` veya `CLAUDE.md`'yi yükler:\n\n- `~/.pi/agent/AGENTS.md` genel talimatlar için\n- ana dizinler, geçerli çalışma dizininden yukarı doğru yürüme\n- geçerli dizin\n\nBir dizin `AGENTS.override.md` içeriyorsa, Pi o dizindeki `AGENTS.md` veya `CLAUDE.md` yerine onu yükler. Diğer dizinlerdeki içerik dosyaları hala normal şekilde katmanlanıyor.\n\nProje kuralları, komutlar, güvenlik kuralları ve tercihler için context files kullanın. `--no-context-files` veya `-nc` ile yüklemeyi devre dışı bırakın.\n\n### Sistem Bilgi İstemi Dosyaları\n\nVarsayılan sistem istemini şununla değiştirin:\n\n- `.pi/SYSTEM.md` bir proje için\n- `~/.pi/agent/SYSTEM.md` küresel olarak\n\nHer iki konumda da `APPEND_SYSTEM.md` ile değiştirmeden varsayılan istemi ekleyin.\n\n### Proje Güveni\n\nEtkileşimli başlangıçta pi, proje yerel ayarlarını, kaynaklarını veya proje `.agents/skills`'yi içeren ve `~/.pi/agent/trust.json`'deki klasör veya ana klasör için kayıtlı bir kararı olmayan bir proje klasörüne güvenmeden önce sorar. Bir projeye güvenmek pi'nin `.pi/settings.json` ve `.pi` kaynakları yüklemesine, eksik proje paketlerini yüklemesine ve proje uzantılarını yürütmesine olanak tanır.\n\nGüven kararından önce pi yalnızca context files, kullanıcı/global uzantıları ve CLI `-e` uzantılarını yükler, böylece `project_trust` olayını işleyebilirler. Proje yerel uzantıları, proje paketi tarafından yönetilen uzantılar ve proje ayarları yalnızca projeye güvenildikten sonra yüklenir. Bu bölünme, mevcut süreçte güveni çözülmemiş farklı bir cwd'den oturuma geçiş yaparken de geçerlidir.\n\nEtkileşimli olmayan modlar (`-p`, `--mode json` ve `--mode rpc`) bir güven istemi göstermez. Geçerli bir kayıtlı güven kararı olmadan, genel ayarlardan `defaultProjectTrust` kullanırlar: `ask` (varsayılan) ve `never` bu proje kaynaklarını yok sayarken, `always` onlara güvenir. Bir çalıştırma için proje güvenini geçersiz kılmak için `--approve`/`-a` veya `--no-approve`/`-na`'yi geçin.\n\nHiçbir uzatma veya kayıtlı karar geçerli değilse, `defaultProjectTrust` geri dönüş davranışını kontrol eder. `~/.pi/agent/settings.json`'de `\"ask\"`, `\"always\"` veya `\"never\"` olarak ayarlayın veya `/settings` ile değiştirin.\n\n`pi config` ve paket komutları aynı proje güven akışını kullanır, ancak `pi update` hiçbir zaman istemde bulunmaz. Bir komut için proje yerel ayarlarına güvenmek için `--approve` veya bunları yok saymak için `--no-approve` iletin.\n\nYakın ana klasöre yönelik güven de dahil olmak üzere gelecekteki oturumlar için bir proje güveni kararını kaydetmek için etkileşimli modda `/trust` tuşunu kullanın. Sadece `~/.pi/agent/trust.json` yazıyor; geçerli oturum yeniden yüklenmediğinden değişikliklerin etkili olması için pi'yi yeniden başlatın.\n\n\n## Oturumları Dışa Aktarma ve Paylaşma\n\nHTML'ye bir oturum yazmak için `/export [file]` tuşunu kullanın.\n\nPaylaşılabilir bir HTML bağlantısına sahip özel bir GitHub özetini yüklemek için `/share` kullanın.\n\nAçık kaynak çalışması için pi kullanıyorsanız ve model, bilgi istemi, araç ve değerlendirme araştırması için oturumlar yayınlamak istiyorsanız, bkz. [`badlogic/pi-share-hf`](https://github.com/badlogic/pi-share-hf). Oturumları Hugging Face veri kümesine yayınlar.\n\n## CLI Referans\n\n```bash\npi [options] [@files...] [messages...]\n```\n\n### Paket Komutları\n\n```bash\npi install <source> [-l]     # Install package, -l for project-local\npi remove <source> [-l]      # Remove package\npi uninstall <source> [-l]   # Alias for remove\npi update [source|self|pi]   # Update pi only, or one package source\npi update --all              # Update pi and packages; reconcile pinned git refs\npi update --extensions       # Update packages only; reconcile pinned git refs\npi update --models           # Refresh model catalogs only\npi update --self             # Update pi only\npi update --extension <src>  # Update one package\npi list                      # List installed packages\npi config                    # Enable/disable package resources\n```\n\nBu komutlar pi paketlerini yönetir ve `pi update` pi CLI kurulumunu güncelleyebilir. Pi'nin kendisini kaldırmak için bkz. [Quickstart](quickstart.md#uninstall). `pi config` ve proje paketi komutları, bir komut için proje yerel ayarlarına güvenmek veya bunları yok saymak için `--approve`/`--no-approve`'yi kabul eder. `pi update` hiçbir zaman proje güvenini istemez.\n\nPaket kaynakları ve güvenlik notları için [Pi Packages](packages.md)'a bakın.\n\n### Modlar\n\n| Bayrak | Tanım |\n|------|-------------|\n| varsayılan | Etkileşimli mod |\n| `-p`, `--print` | Yanıtı yazdır ve çık |\n| `--mode json` | Tüm olayları JSON satır olarak çıktılayın; bkz. [JSON mode](json.md) |\n| `--mode rpc` | RPC modu stdin/stdout üzerinde; bkz. [RPC mode](rpc.md) |\n| `--export <in> [out]` | Bir oturumu HTML'ye aktarma |\n\nYazdırma modunda pi ayrıca borulu stdin'yi okur ve bunu ilk komut istemiyle birleştirir:\n\n```bash\ncat README.md | pi -p \"Summarize this text\"\n```\n\n### Model Seçenekleri\n\n| Seçenek | Tanım |\n|--------|-------------|\n| `--provider <name>` | Sağlayıcı, örneğin `anthropic`, `openai` veya `google` |\n| `--model <pattern>` | Model modeli veya kimliği; `provider/id` ve isteğe bağlı `:<thinking>`'yi destekler |\n| `--api-key <key>` | API key, ortam değişkenlerini geçersiz kılma |\n| `--thinking <level>` | `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max` |\n| `--models <patterns>` | Ctrl+P döngüsü için virgülle ayrılmış desenler |\n| `--list-models [search]` | Mevcut modelleri listele |\n\n### Oturum Seçenekleri\n\n| Seçenek | Tanım |\n|--------|-------------|\n| `-c`, `--continue` | En son oturuma devam et |\n| `-r`, `--resume` | Bir oturuma göz atın ve seçin |\n| `--session <yol\\ | kimlik>` | Belirli bir oturum dosyası veya kısmi UUID kullanın |\n| `--fork <yol\\ | kimlik>` | Bir oturum dosyasını veya kısmi UUID'yi yeni bir oturuma çatallayın |\n| `--session-dir <dir>` | Özel oturum depolama dizini |\n| `--no-session` | Geçici mod; kaydetme |\n| `--name <name>`, `-n <name>` | Oturumun görünen adını başlangıçta ayarla |\n\n### Araç Seçenekleri\n\n| Seçenek | Tanım |\n|--------|-------------|\n| `--tools <list>`, `-t <list>` | Belirli yerleşik, uzantı ve özel araçları izin verilenler listesine ekleyin |\n| `--exclude-tools <list>`, `-xt <list>` | Belirli yerleşik, uzantı ve özel araçları devre dışı bırakın |\n| `--no-builtin-tools`, `-nbt` | Yerleşik araçları devre dışı bırakın ancak uzantıyı/özel araçları etkin tutun |\n| `--no-tools`, `-nt` | Tüm araçları devre dışı bırak |\n\nYerleşik araçlar: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`.\n\n### Kaynak Seçenekleri\n\n| Seçenek | Tanım |\n|--------|-------------|\n| `-e`, `--extension <source>` | Yoldan, npm veya git'ten bir uzantı yükleyin; tekrarlanabilir |\n| `--no-extensions` | Uzantı bulmayı devre dışı bırak |\n| `--skill <path>` | Bir beceri yükleyin; tekrarlanabilir |\n| `--no-skills` | Beceri keşfini devre dışı bırak |\n| `--prompt-template <path>` | Bir bilgi istemi şablonu yükleyin; tekrarlanabilir |\n| `--no-prompt-templates` | Bilgi istemi şablonu bulmayı devre dışı bırak |\n| `--theme <path>` | Bir tema yükleyin; tekrarlanabilir |\n| `--no-themes` | Tema bulmayı devre dışı bırak |\n| `--no-context-files`, `-nc` | `AGENTS.md` ve `CLAUDE.md` bulmayı devre dışı bırakın |\n\nAyarları göz ardı ederek tam olarak ihtiyacınız olanı yüklemek için `--no-*`'yi açık işaretlerle birleştirin. Örnek:\n\n```bash\npi --no-extensions -e ./my-extension.ts\n```\n\n### Diğer Seçenekler\n\n| Seçenek | Tanım |\n|--------|-------------|\n| `--system-prompt <text>` | Varsayılan istemi değiştirin; context files ve beceriler hâlâ eklidir |\n| `--append-system-prompt <text>` | Sistem istemine ekle |\n| `--tui-mode <mode>` | TUI modu: `regular` (varsayılan) veya deneysel `fullscreen` |\n| `--verbose` | Ayrıntılı başlatmayı zorla |\n| `-a`, `--approve` | Bu çalıştırma için proje yerel dosyalarına güvenin |\n| `-na`, `--no-approve` | Bu çalıştırma için proje yerel dosyalarını yoksay |\n| `-h`, `--help` | Yardımı göster |\n| `-v`, `--version` | Sürümü göster |\n\n`fullscreen` modunda, sıradaki mesajlar, çalışma durumu, uzantı widget'ları, düzenleyici ve alt bilgi altta sabit kalırken transkript terminal görünüm penceresinin içinde kayar. Fare/izleme dörtgeni girişi işaretçinin altındaki bölgeyi kaydırır; klavye görünüm alanı eylemleri her zaman kullanılabilir durumda kalır. Satır içi görüntüler, Kitty ve Ghostty dahil, Kitty grafik protokolünü destekleyen terminallerde çalışır. iTerm2'de satır içi görüntü protokolü, uygulamaya ait kaydırma sırasında yerleşimleri silemediğinden veya kırpamadığından metin yer tutucuları olarak oluşturulurlar. `regular` modunda pi, ana ekranı ve terminale ait geri kaydırmayı kullanır ve iTerm2 satır içi görüntüleri normal şekilde oluşturulmaya devam eder.\n\n`regular` ve `fullscreen` arasında hemen geçiş yapmak için `/settings`'de **TUI modunu** ayarlayın ve gelecek oturumlar için varsayılanı seçin. **Tam ekran çıkış çıkışı**, tam ekrandan çıkmanın son transkripti mi yazdıracağını yoksa önceki ekranı geri yükleyip yalnızca oturum devam ettirme ipucunu mu yazdıracağını kontrol eder.\n\n### Dosya Bağımsız Değişkenleri\n\nMesaja eklemek için dosyaların önüne `@` ekleyin:\n\n```bash\npi @prompt.md \"Answer this\"\npi -p @screenshot.png \"What's in this image?\"\npi @code.ts @test.ts \"Review these files\"\n```\n\n### Örnekler\n\n```bash\n# Interactive with initial prompt\npi \"List all .ts files in src/\"\n\n# Non-interactive\npi -p \"Summarize this codebase\"\n\n# Non-interactive with piped stdin\ncat README.md | pi -p \"Summarize this text\"\n\n# Named one-shot session\npi --name \"release audit\" -p \"Audit this repository\"\n\n# Different model\npi --provider openai --model gpt-4o \"Help me refactor\"\n\n# Model with provider prefix\npi --model openai/gpt-4o \"Help me refactor\"\n\n# Model with thinking level shorthand\npi --model sonnet:high \"Solve this complex problem\"\n\n# Limit model cycling\npi --models \"claude-*,gpt-4o\"\n\n# Read-only mode\npi --tools read,grep,find,ls -p \"Review the code\"\n\n# Disable one extension or built-in tool while keeping the rest available\npi --exclude-tools ask_question\n```\n\n## Tasarım İlkeleri\n\nPi çekirdeği küçük tutar ve iş akışına özgü davranışı uzantılara, becerilere, prompt templates ve paketlere aktarır.\n\nKasıtlı olarak yerleşik MCP, alt aracıları, izin açılır pencerelerini, plan modunu, yapılacak işleri veya arka planı bash içermez. Bu iş akışlarını uzantılar veya paketler halinde oluşturabilir veya yükleyebilir ya da kapsayıcılar ve tmux gibi harici araçları kullanabilirsiniz.\n\nGerekçenin tamamı için [blog post](https://mariozechner.at/posts/2025-11-30-pi-coding-agent/) bölümünü okuyun.","sourceFile":"usage.md"},"windows":{"title":"Windows Kurulumu","markdown":"Pi, Windows'ta bash kabuğu gerektirir. Kontrol edilen yerler (sırasıyla):\n\n1. `~/.pi/agent/settings.json`'den itibaren özel yol\n2. Git Bash (`C:\\Program Files\\Git\\bin\\bash.exe`)\n3. `bash.exe` PATH'de (Cygwin, MSYS2, WSL)\n\nÇoğu kullanıcı için [Git for Windows](https://git-scm.com/download/win) yeterlidir.\n\n## Özel Kabuk Yolu\n\n```json\n{\n  \"shellPath\": \"C:\\\\cygwin64\\\\bin\\\\bash.exe\"\n}\n```","sourceFile":"windows.md"}}},"navigation":{"tr":[{"title":"Buradan başlayın","items":[{"title":"Pi Belgeler","path":"/docs/latest","slug":"index"},{"title":"Hızlı başlangıç","path":"/docs/latest/quickstart","slug":"quickstart"},{"title":"Pi kullanımı","path":"/docs/latest/usage","slug":"usage"},{"title":"Providers","path":"/docs/latest/providers","slug":"providers"},{"title":"Güvenlik","path":"/docs/latest/security","slug":"security"},{"title":"Konteynerizasyon","path":"/docs/latest/containerization","slug":"containerization"},{"title":"Ayarlar","path":"/docs/latest/settings","slug":"settings"},{"title":"Tuş atamaları","path":"/docs/latest/keybindings","slug":"keybindings"},{"title":"Oturumlar","path":"/docs/latest/sessions","slug":"sessions"},{"title":"Sıkıştırma ve Dal Özetleme","path":"/docs/latest/compaction","slug":"compaction"}]},{"title":"Özelleştirme","items":[{"title":"Extensions","path":"/docs/latest/extensions","slug":"extensions"},{"title":"Skills","path":"/docs/latest/skills","slug":"skills"},{"title":"Bilgi İstemi Şablonları","path":"/docs/latest/prompt-templates","slug":"prompt-templates"},{"title":"Temalar","path":"/docs/latest/themes","slug":"themes"},{"title":"Pi Packages","path":"/docs/latest/packages","slug":"packages"},{"title":"Özel Models","path":"/docs/latest/models","slug":"models"},{"title":"Özel Providers","path":"/docs/latest/custom-provider","slug":"custom-provider"}]},{"title":"Referans","items":[{"title":"Oturum Dosyası Formatı","path":"/docs/latest/session-format","slug":"session-format"}]},{"title":"Programatik kullanım","items":[{"title":"SDK","path":"/docs/latest/sdk","slug":"sdk"},{"title":"RPC Modu","path":"/docs/latest/rpc","slug":"rpc"},{"title":"JSON Etkinlik Akışı Modu","path":"/docs/latest/json","slug":"json"},{"title":"TUI Bileşenler","path":"/docs/latest/tui","slug":"tui"}]},{"title":"Platform kurulumu","items":[{"title":"Windows Kurulumu","path":"/docs/latest/windows","slug":"windows"},{"title":"Termux (Android) Kurulumu","path":"/docs/latest/termux","slug":"termux"},{"title":"tmux Kurulum","path":"/docs/latest/tmux","slug":"tmux"},{"title":"Terminal Kurulumu","path":"/docs/latest/terminal-setup","slug":"terminal-setup"},{"title":"Kabuk Takma Adları","path":"/docs/latest/shell-aliases","slug":"shell-aliases"}]},{"title":"Geliştirme","items":[{"title":"Gelişim","path":"/docs/latest/development","slug":"development"}]}]}}
