Pi için yapılandırma, özelleştirme, platform kurulumu ve API referansları.

Sıkıştırma ve Dal Özetleme

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.

Kaynak dosyalar (pi-mono):

Projenizdeki TypeScript tanımları için node_modules/@earendil-works/pi-coding-agent/dist/'yi inceleyin.

Genel Bakış

Pi'nin iki özetleme mekanizması vardır:

Mekanizma Tetiklemek Amaç
Sıkıştırma Bağlam eşiği aşıyor veya /compact Bağlamı boşaltmak için eski mesajları özetleyin
Şube özeti /tree navigasyon Dalları değiştirirken bağlamı koruyun

Her 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.

Sıkıştırma

Tetiklendiğinde

Otomatik sıkıştırma şu durumlarda tetiklenir:

contextTokens > contextWindow - reserveTokens

Varsayı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.

İsteğe bağlı talimatların özete odaklandığı /compact [instructions] ile manuel olarak da tetikleyebilirsiniz.

Nasıl Çalışır?

  1. 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
  2. Mesajları çıkar: Önceki tutulan sınırdan (veya oturum başlangıcından) kesme noktasına kadar olan mesajları toplayın
  3. Ö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
  4. Girişi ekle: CompactionEntry'yi özet ve firstKeptEntryId ile kaydedin
  5. Yeniden yükle: firstKeptEntryId tarihinden itibaren özet ve mesajlar kullanılarak oturum yeniden yüklenir
Before compaction:

  entry:  0     1     2     3      4     5     6      7      8     9
        ┌─────┬─────┬─────┬─────┬──────┬─────┬──── ─┬──────┬─────┬─────┐
        │ hdr │ usr │ ass │ tool │ usr │ ass │ tool │ tool │ ass │ tool│
        └─────┴─────┴─────┴──────┴─────┴─────┴──────┴──────┴─────┴─────┘
                └────────┬───────┘ └──────────────┬──────────────┘
               messagesToSummarize            kept messages
                                   ↑
                          firstKeptEntryId (entry 4)

After compaction (new entry appended):

  entry:  0     1     2     3      4     5     6      7      8     9     10
        ┌─────┬─────┬─────┬─────┬──────┬─────┬──── ─┬──────┬─────┬─────┬─────┐
        │ hdr │ usr │ ass │ tool │ usr │ ass │ tool │ tool │ ass │ tool│ cmp │
        └─────┴─────┴─────┴──────┴─────┴─────┴──────┴──────┴─────┴─────┴─────┘
               └──────────┬──────┘ └──────────────────────┬───────────────────┘
                 not sent to LLM                    sent to LLM
                                                         ↑
                                              starts from firstKeptEntryId

What the LLM sees:

  ┌────────┬─────────┬─────┬─────┬──────┬──────┬─────┬──────┐
  │ system │ summary │ usr │ ass │ tool │ tool │ ass │ tool │
  └────────┴─────────┴─────┴─────┴──────┴──────┴─────┴──────┘
       ↑         ↑      └─────────────────┬────────────────┘
    prompt   from cmp          messages from firstKeptEntryId

Tekrarlanan 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.

Bölünmüş Dönüşler

Bir "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.

Tek 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:

Split turn (one huge turn exceeds budget):

  entry:  0     1     2      3     4      5      6     7      8
        ┌─────┬─────┬─────┬──────┬─────┬──────┬──────┬─────┬──────┐
        │ hdr │ usr │ ass │ tool │ ass │ tool │ tool │ ass │ tool │
        └─────┴─────┴─────┴──────┴─────┴──────┴──────┴─────┴──────┘
                ↑                                     ↑
         turnStartIndex = 1                  firstKeptEntryId = 7
                │                                     │
                └──── turnPrefixMessages (1-6) ───────┘
                                                      └── kept (7-8)

  isSplitTurn = true
  messagesToSummarize = []  (no complete turns before)
  turnPrefixMessages = [usr, ass, tool, ass, tool, tool]

Bölünmüş dönüşler için Pi iki özet oluşturur ve bunları birleştirir:

  1. Geçmiş özeti: Önceki bağlam (varsa)
  2. Dönüş öneki özeti: Ayrık dönüşün ilk kısmı

Kesim Noktası Kuralları

Geçerli kesme noktaları şunlardır:

  • Kullanıcı mesajları
  • Asistan mesajları
  • Bash Yürütme mesajları
  • Özel mesajlar (custom_message, Branch_summary)

Hiçbir zaman takım sonuçlarında kesme yapmayın (takım çağrılarıyla kalmaları gerekir).

Sıkıştırma Giriş Yapısı

session-manager.ts'de tanımlanmış:

interface CompactionEntry<T = unknown> {
  type: "compaction";
  id: string;
  parentId: string;
  timestamp: number;
  summary: string;
  firstKeptEntryId: string;
  tokensBefore: number;
  usage?: Usage;       // LLM usage that generated the summary
  fromHook?: boolean;  // true if provided by extension (legacy field name)
  details?: T;         // implementation-specific data
}

// Default compaction uses this for details (from compaction.ts):
interface CompactionDetails {
  readFiles: string[];
  modifiedFiles: string[];
}

Extensions 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.

Uygulama için prepareCompaction() ve compact()'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.

Şube Özetleme

Tetiklendiğinde

Farklı 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.

Nasıl Çalışır?

  1. Ortak atayı bul: Eski ve yeni konumların paylaştığı en derin düğüm
  2. Girişleri toplayın: Eski yapraktan ortak ataya doğru yürüyün
  3. Bütçeyle hazırlanın: Belirteç bütçesine kadar olan mesajları dahil edin (önce en yenisi)
  4. Özet oluştur: Yapılandırılmış formatla LLM'yi arayın
  5. Girişi ekle: Gezinme noktasında BranchSummaryEntry kaydet
Tree before navigation:

         ┌─ B ─ C ─ D (old leaf, being abandoned)
    A ───┤
         └─ E ─ F (target)

Common ancestor: A
Entries to summarize: B, C, D

After navigation with summary:

         ┌─ B ─ C ─ D
    A ───┤
         └─ E ─ F ─ [summary of B,C,D] (new leaf)

Kümülatif Dosya Takibi

Hem 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:

  • Özetlenen mesajlardaki araç çağrıları
  • Önceki sıkıştırma veya dallanma özeti details (varsa)

Bu, 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.

ŞubeÖzetGiriş Yapısı

session-manager.ts'de tanımlanmış:

interface BranchSummaryEntry<T = unknown> {
  type: "branch_summary";
  id: string;
  parentId: string;
  timestamp: number;
  summary: string;
  fromId: string;      // Entry we navigated from
  usage?: Usage;       // LLM usage that generated the summary
  fromHook?: boolean;  // true if provided by extension (legacy field name)
  details?: T;         // implementation-specific data
}

// Default branch summarization uses this for details (from branch-summarization.ts):
interface BranchSummaryDetails {
  readFiles: string[];
  modifiedFiles: string[];
}

Sıkıştırmayla aynı şekilde, uzantılar özel verileri details'de depolayabilir.

Uygulama için collectEntriesForBranchSummary(), prepareBranchEntries() ve generateBranchSummary()'ye bakın.

Özet Formatı

Hem sıkıştırma hem de branch summarization aynı yapılandırılmış formatı kullanır:

## Goal
[What the user is trying to accomplish]

## Constraints & Preferences
- [Requirements mentioned by user]

## Progress
### Done
- [x] [Completed tasks]

### In Progress
- [ ] [Current work]

### Blocked
- [Issues, if any]

## Key Decisions
- **[Decision]**: [Rationale]

## Next Steps
1. [What should happen next]

## Critical Context
- [Data needed to continue]

<read-files>
path/to/file1.ts
path/to/file2.ts
</read-files>

<modified-files>
path/to/changed.ts
</modified-files>

Mesaj Serileştirme

Özetlemeden önce mesajlar serializeConversation() aracılığıyla metne serileştirilir:

[User]: What they said
[Assistant thinking]: Internal reasoning
[Assistant]: Response text
[Assistant tool calls]: read(path="foo.ts"); edit(path="bar.ts", ...)
[Tool result]: Output from tool

Bu, modelin bunu devam edecek bir konuşma olarak ele almasını engeller.

Araç 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.

Extensions aracılığıyla Özel Özetleme

Extensions hem sıkıştırmayı hem de branch summarization'yi engelleyebilir ve özelleştirebilir. Etkinlik türü tanımları için extensions/types.ts'e bakın.

session_before_compact

Otomatik 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.

pi.on("session_before_compact", async (event, ctx) => {
  const { preparation, branchEntries, customInstructions, reason, willRetry, signal } = event;

  // preparation.messagesToSummarize - messages to summarize
  // preparation.turnPrefixMessages - split turn prefix (if isSplitTurn)
  // preparation.previousSummary - previous compaction summary
  // preparation.fileOps - extracted file operations
  // preparation.tokensBefore - context tokens before compaction
  // preparation.firstKeptEntryId - where kept messages start
  // preparation.settings - compaction settings

  // branchEntries - all entries on current branch (for custom state)
  // reason - "manual" (/compact), "threshold", or "overflow"
  // willRetry - whether the aborted turn is retried after compaction (overflow recovery)
  // signal - AbortSignal (pass to LLM calls)

  // Cancel:
  return { cancel: true };

  // Custom summary:
  return {
    compaction: {
      summary: "Your summary...",
      firstKeptEntryId: preparation.firstKeptEntryId,
      tokensBefore: preparation.tokensBefore,
      // usage: summaryResponse.usage, // Optional; included in session totals
      details: { /* custom data */ },
    }
  };
});

Mesajları Metne Dönüştürme

Kendi modelinizle bir özet oluşturmak için serializeConversation kullanarak mesajları metne dönüştürün:

import { convertToLlm, serializeConversation } from "@earendil-works/pi-coding-agent";

pi.on("session_before_compact", async (event, ctx) => {
  const { preparation } = event;
  
  // Convert AgentMessage[] to Message[], then serialize to text
  const conversationText = serializeConversation(
    convertToLlm(preparation.messagesToSummarize)
  );
  // Returns:
  // [User]: message text
  // [Assistant thinking]: thinking content
  // [Assistant]: response text
  // [Assistant tool calls]: read(path="..."); bash(command="...")
  // [Tool result]: output text

  // Now send to your model for summarization
  const { summary, usage } = await myModel.summarize(conversationText);
  
  return {
    compaction: {
      summary,
      firstKeptEntryId: preparation.firstKeptEntryId,
      tokensBefore: preparation.tokensBefore,
      usage,
    }
  };
});

Farklı bir modelin kullanıldığı tam bir örnek için custom-compaction.ts'e bakın.

session_before_tree

/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.

pi.on("session_before_tree", async (event, ctx) => {
  const { preparation, signal } = event;

  // preparation.targetId - where we're navigating to
  // preparation.oldLeafId - current position (being abandoned)
  // preparation.commonAncestorId - shared ancestor
  // preparation.entriesToSummarize - entries that would be summarized
  // preparation.userWantsSummary - whether user chose to summarize

  // Cancel navigation entirely:
  return { cancel: true };

  // Provide custom summary (only used if userWantsSummary is true):
  if (preparation.userWantsSummary) {
    return {
      summary: {
        summary: "Your summary...",
        // usage: summaryResponse.usage, // Optional; included in session totals
        details: { /* custom data */ },
      }
    };
  }
});

Türler dosyasında SessionBeforeTreeEvent ve TreePreparation'ye bakın.

Ayarlar

Sıkıştırmayı ~/.pi/agent/settings.json veya <project-dir>/.pi/settings.json olarak yapılandırın:

{
  "compaction": {
    "enabled": true,
    "reserveTokens": 16384,
    "keepRecentTokens": 20000
  }
}
Ayar Varsayılan Tanım
enabled true Otomatik sıkıştırmayı etkinleştir
reserveTokens 16384 LLM yanıtı için rezerve edilecek jetonlar
keepRecentTokens 20000 Saklanacak en son belirteçler (özetlenmemiş)

"enabled": false ile otomatik sıkıştırmayı devre dışı bırakın. /compact ile manuel olarak sıkıştırmaya devam edebilirsiniz.