Dokümanlar menüsü
Zaman yolculuğu & run çatallama (fork)
Bir run'ın journal'ından herhangi bir adımdaki durumu yeniden kur (reconstructState) veya o noktadan yeni bir dala çatalla (forkRun) — hata ayıklama ve 'what-if' için.
Ne işe yarar / ne zaman kullanılır#
Bir agent run'ı journal'a adım adım (model ve tool girdileri olarak) yazılır. Zaman zaman "step 3'te model tam olarak ne görüyordu?" ya da "bu adımdan itibaren farklı bir tool/model ile ne olurdu?" sorularını yanıtlamak gerekir.
reconstructState journal entry'lerini SAF (yan etkisiz) olarak yürüyüp belirli bir adıma kadarki mesaj listesini ve henüz sonuçlanmamış (pending) tool-call'ları materyalize eder — hata ayıklama/inceleme (Studio inspector, log analizi) için idealdir.
forkRun ise bunun bir adım ötesi: kaynak run'ın ilk N model adımını + ilişkili tool kayıtlarını + orijinal girdisini YENİ bir runId'ye kopyalar. N'den sonrası kopyalanmaz — resumeRun ile devam ettirildiğinde prefix journal'dan replay edilir (side effect'ler TEKRAR çalışmaz), adım N'den itibaren ise CANLI koşar. Böylece "aynı noktadan farklı model/tool ile ne olurdu" senaryosu (what-if / A-B hata ayıklama) kaynak run'ı bozmadan denenebilir.
Kurulum / import#
Her iki fonksiyon da @gnldev/durable ana giriş noktasından dışa açılır — ayrı bir alt-yol gerekmez:
import { reconstructState, forkRun } from '@gnldev/durable';
import { runDurable, resumeRun } from '@gnldev/durable';Adım adım kullanım#
Önce normal bir runDurable çağrısıyla journal'a adımlar yazılır (aşağıdaki örnekte model bir charge aracını çağırıp sonra metinle bitiriyor):
await runDurable({
runId: 'r',
journal,
model: srcModel(),
tools: tools(),
stopWhen: stepCountIs(6),
prompt: 'x',
});Adım 1'den (ilk model adımından sonra) yeni bir dala çatalla — kaynağın model:0 girdisi ve ona bağlı tool kaydı + orijinal :input yeni fork1 runId'sine kopyalanır, model:1 ve sonrası KOPYALANMAZ:
const fork = await forkRun(journal, 'r', 1, 'fork1');
// fork => { newRunId: 'fork1', copiedModel: 1, copiedTool: 1 }Ardından fork'u FARKLI bir model/tool mantığıyla resumeRun ile devam ettir: adım 0 (charge tool-call'ı) journal'dan replay edilir — yan etkisi (ör. tekrar ücretlendirme) TEKRAR çalışmaz — adım 1'den itibaren ise gerçekten canlı çalışır ve kaynaktan farklı bir sonuca varabilir:
const r2 = await resumeRun('fork1', {
journal,
model: forkModel(),
tools: tools(),
stopWhen: stepCountIs(6),
});
// r2.text may differ (e.g. 'FORK-final'); the charge counter does NOT increase (replay).Sadece durumu incelemek (fork açmadan) için reconstructState yeterlidir — journal entry dizisini ve istenen adımı verir:
const entries = await journal.readRun('r');
const state = reconstructState(entries, 1);
// state => { step: 1, messages: [...], pending: [{ toolCallId: 'c1', toolName: 'pay' }] }
// Pass a seed to prepend the original user input as well:
const withSeed = reconstructState(entries, 3, { prompt: 'ode' });API referansı#
reconstructStateJournal entry dizisini SAF olarak yürüyüp uptoStep'e kadarki mesajları ve pending tool-call'ları döner; opsiyonel seed ile orijinal girdi başa eklenir.
forkRunsrcRunId'in ilk `step` model adımını + ilgili tool kayıtlarını + :input'u newRunId altına kopyalar; sonrası kopyalanmaz, resumeRun ile step'ten canlı devam eder.
ReconstructedStatereconstructState dönüş tipi: { step, messages, pending }.
ReconstructSeedreconstructState için opsiyonel seed girdisi: { system?, messages?, prompt? }.
ForkResultforkRun dönüş tipi: { newRunId, copiedModel, copiedTool }.
forkRun, journal'ın hem yazma hem okuma (Journal & JournalReader) sağladığı bir kaynak ister — kopyalanan prefix journal'dan replay edildiği için adım N'den önceki side effect'ler (ör. ücretlendirme) fork'ta TEKRAR çalışmaz; yalnız N'den itibaren gerçekten canlı koşar.