Konfigurasi, kustomisasi, pengaturan platform, dan referensi API untuk Pi.

Pemadatan & Peringkasan Cabang

LLM memiliki jendela konteks terbatas. Ketika percakapan menjadi terlalu panjang, Pi menggunakan pemadatan untuk meringkas konten lama sambil mempertahankan karya terbaru. Halaman ini mencakup pemadatan otomatis dan branch summarization.

File sumber (pi-mono):

Untuk definisi TypeScript dalam proyek Anda, periksa node_modules/@earendil-works/pi-coding-agent/dist/.

Ringkasan

Pi memiliki dua mekanisme peringkasan:

Mekanisme Pemicu Tujuan
Pemadatan Konteks melebihi ambang batas, atau /compact Ringkaslah pesan-pesan lama untuk membebaskan konteks
Ringkasan cabang /tree navigasi Pertahankan konteks saat berpindah cabang

Keduanya menggunakan format ringkasan terstruktur yang sama dan melacak operasi file secara kumulatif. Permintaan pemadatan dan ringkasan cabang menggunakan ID sesi perutean baru dan, jika didukung oleh penyedia, menonaktifkan penulisan prompt-cache karena permintaan satu kali ini kemungkinan tidak akan digunakan kembali.

Pemadatan

Ketika Itu Terpicu

Pemadatan otomatis terpicu ketika:

contextTokens > contextWindow - reserveTokens

Secara default, reserveTokens adalah 16384 token (dapat dikonfigurasi dalam ~/.pi/agent/settings.json atau <project-dir>/.pi/settings.json). Hal ini memberikan ruang bagi tanggapan LLM.

Anda juga dapat memicu secara manual dengan /compact [instructions], dengan instruksi opsional yang memfokuskan ringkasan.

Cara Kerjanya

  1. Temukan titik potong: Berjalan mundur dari pesan terbaru, mengumpulkan perkiraan token hingga keepRecentTokens (default 20k, dapat dikonfigurasi dalam ~/.pi/agent/settings.json atau <project-dir>/.pi/settings.json) tercapai
  2. Ekstrak pesan: Kumpulkan pesan dari batas yang disimpan sebelumnya (atau permulaan sesi) hingga titik potong
  3. Buat ringkasan: Panggil LLM untuk meringkas dengan format terstruktur, meneruskan ringkasan sebelumnya sebagai konteks berulang jika ada
  4. Tambahkan entri: Simpan CompactionEntry dengan ringkasan dan firstKeptEntryId
  5. Muat ulang: Sesi dimuat ulang, menggunakan ringkasan + pesan dari firstKeptEntryId dan seterusnya
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

Pada pemadatan berulang, rentang yang diringkas dimulai dari batas pemadatan sebelumnya (firstKeptEntryId), bukan pada entri pemadatan itu sendiri, kembali ke entri setelah pemadatan sebelumnya jika entri yang disimpan tersebut tidak dapat ditemukan di jalurnya. Hal ini mempertahankan pesan-pesan yang bertahan dari pemadatan sebelumnya dengan memasukkannya ke dalam proses rangkuman berikutnya juga. Pi juga menghitung ulang tokensBefore dari konteks sesi yang dibangun kembali sebelum menulis CompactionEntry baru, sehingga jumlah token mencerminkan konteks pra-pemadatan sebenarnya yang diganti.

Putaran Terpisah

Sebuah "giliran" dimulai dengan pesan pengguna dan mencakup semua respons asisten dan panggilan alat hingga pesan pengguna berikutnya. Biasanya, pemadatan dilakukan pada batas belokan.

Ketika satu putaran melebihi keepRecentTokens, titik potong mendarat di tengah putaran pada pesan asisten. Ini adalah "giliran terpisah":

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]

Untuk putaran terpisah, Pi menghasilkan dua ringkasan dan menggabungkannya:

  1. Ringkasan riwayat: Konteks sebelumnya (jika ada)
  2. Ringkasan awalan giliran: Bagian awal giliran split

Aturan Titik Potong

Titik potong yang valid adalah:

  • Pesan pengguna
  • Pesan asisten
  • Pesan BashExecution
  • Pesan khusus (pesan_khusus, ringkasan_cabang)

Jangan pernah memotong hasil alat (hasil alat tersebut harus tetap sesuai dengan panggilan alatnya).

Struktur Entri Pemadatan

Didefinisikan dalam session-manager.ts:

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 dapat menyimpan data apa pun yang dapat diserialkan JSON di details. Pemadatan default melacak operasi file, namun penerapan ekstensi khusus dapat menggunakan strukturnya sendiri. Ringkasan yang dihasilkan dan disediakan ekstensi menyimpan LLM usage bila tersedia sehingga total sesi mencakup pekerjaan ringkasan.

Lihat prepareCompaction() dan compact() untuk implementasinya. Untuk peringkasan terprogram langsung, generateSummary() mengembalikan teks ringkasan dan generateSummaryWithUsage() mengembalikan { text, usage }.

Ringkasan Cabang

Ketika Itu Terpicu

Saat Anda menggunakan /tree untuk menavigasi ke cabang lain, Pi menawarkan untuk meringkas pekerjaan yang Anda tinggalkan. Ini memasukkan konteks dari cabang kiri ke cabang baru.

Cara Kerjanya

  1. Temukan nenek moyang yang sama: Node terdalam yang dimiliki bersama oleh posisi lama dan baru
  2. Kumpulkan entri: Berjalan dari daun tua kembali ke nenek moyang yang sama
  3. Persiapkan dengan anggaran: Sertakan pesan hingga anggaran token (yang terbaru terlebih dahulu)
  4. Buat ringkasan: Hubungi LLM dengan format terstruktur
  5. Tambahkan entri: Simpan BranchSummaryEntry di titik navigasi
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)

Pelacakan File Kumulatif

Baik pemadatan maupun branch summarization file track secara kumulatif. Saat membuat ringkasan, pi mengekstrak operasi file dari:

  • Alat memanggil pesan yang diringkas
  • Ringkasan pemadatan atau cabang sebelumnya details (jika ada)

Ini berarti pelacakan file terakumulasi di beberapa pemadatan atau ringkasan cabang yang disarangkan, menjaga riwayat lengkap file yang dibaca dan dimodifikasi.

Struktur Entri Ringkasan Cabang

Didefinisikan dalam session-manager.ts:

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[];
}

Sama seperti pemadatan, ekstensi dapat menyimpan data khusus dalam details.

Lihat collectEntriesForBranchSummary(), prepareBranchEntries(), dan generateBranchSummary() untuk penerapannya.

Format Ringkasan

Pemadatan dan branch summarization menggunakan format terstruktur yang sama:

## 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>

Serialisasi Pesan

Sebelum diringkas, pesan diserialkan menjadi teks melalui serializeConversation():

[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

Hal ini mencegah model memperlakukannya sebagai percakapan yang berlanjut.

Hasil alat dipotong menjadi 2000 karakter selama serialisasi. Konten yang melebihi batas tersebut diganti dengan penanda yang menunjukkan berapa banyak karakter yang terpotong. Hal ini menjaga permintaan peringkasan tetap dalam anggaran token yang masuk akal, karena hasil alat (terutama dari read dan bash) biasanya merupakan kontributor terbesar terhadap ukuran konteks.

Peringkasan Khusus melalui Extensions

Extensions dapat mencegat dan menyesuaikan pemadatan dan branch summarization. Lihat extensions/types.ts untuk definisi jenis peristiwa.

sesi_sebelum_kompak

Ditembakkan sebelum pemadatan otomatis atau /compact. Dapat membatalkan atau memberikan ringkasan khusus. Lihat SessionBeforeCompactEvent dan CompactionPreparation di file jenis.

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 */ },
    }
  };
});

Mengubah Pesan menjadi Teks

Untuk membuat ringkasan dengan model Anda sendiri, ubah pesan menjadi teks menggunakan serializeConversation:

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,
    }
  };
});

Lihat custom-compaction.ts untuk contoh lengkap menggunakan model yang berbeda.

sesi_sebelum_pohon

Ditembakkan sebelum navigasi /tree. Selalu aktif terlepas dari apakah pengguna memilih untuk meringkas. Dapat membatalkan navigasi atau memberikan ringkasan khusus.

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 */ },
      }
    };
  }
});

Lihat SessionBeforeTreeEvent dan TreePreparation di file jenis.

Pengaturan

Konfigurasikan pemadatan di ~/.pi/agent/settings.json atau <project-dir>/.pi/settings.json:

{
  "compaction": {
    "enabled": true,
    "reserveTokens": 16384,
    "keepRecentTokens": 20000
  }
}
Pengaturan Bawaan Keterangan
enabled true Aktifkan pemadatan otomatis
reserveTokens 16384 Token untuk dicadangkan untuk respons LLM
keepRecentTokens 20000 Token terkini yang harus disimpan (tidak diringkas)

Nonaktifkan pemadatan otomatis dengan "enabled": false. Anda masih dapat memadatkannya secara manual dengan /compact.