GNL 0.17: erken aşamada ve hızlı ilerliyor — API'ler sürümden sürüme değişebilirBize katıl

GNL
Dokümanlar menüsü
Core · Ücretsiz@gnldev/durable

Deterministik replay & çökme kurtarma

Journal'a yazılan her model/araç adımı sayesinde yarıda kesilen bir run aynı runId ile kaldığı yerden, prompt'u yeniden vermeden deterministik olarak devam eder.

Ne işe yarar / ne zaman kullanılır#

Uzun süren bir agent koşusu ortasında process çöker, deploy yeniden başlatır ya da bir araç onay bekleyip askıya alınır (bkz. human-in-loop-approvals). Klasik generateText bu noktadan sonra hiçbir şey bilmez — konuşmayı ve tüm araç sonuçlarını yeniden üretmeniz gerekir. runDurable her model adımını ve her araç çağrısının sonucunu journal'a yazar; aynı runId ile tekrar çağrıldığında (veya resumeRun ile) daha önce üretilmiş adımları modele YENİDEN sormaz — journal'dan okur, kaldığı yerden devam eder. Sonuç: yan-etkili bir araç (ör. ödeme tahsili) çökme sonrası ikinci kez çalışmaz, model aynı token'ları ikinci kez harcamaz.

Mekanizmadan değil de yaşadığın sorundan mı geliyorsun? Süreç çöktükten sonra generateText ajanını devam ettirmek aynı konuyu sorun tarafından anlatıyor.

Kurulum / import#

Paket tek girişten dışa açılır — alt-yol gerekmez (yalnız kalıcı depolama adaptörleri @gnldev/durable/sqlite ve @gnldev/durable/postgres ayrı export'tur, bkz. storage-adapters).

import { runDurable, resumeRun, InMemoryJournal } from '@gnldev/durable';

Adım adım kullanım#

Aşağıdaki örnek gerçek test senaryosundan alınmıştır: 5000 birim tahsilat isteyen bir araç çağrısı, guard tarafından onaya (require-approval) düşürülür — run askıya alınır. Prompt hiçbir yerde tekrar yazılmaz; resumeRun yalnızca runId ve onay bilgisiyle çağrılır.

1. İlk çalıştırma — araç onay bekleyip askıya alınır
const journal = new InMemoryJournal();

const r1 = await runDurable({
  runId: 'o1',
  journal,
  model: makeModel(),
  tools: makeTools(counter),
  guard,
  prompt: 'charge 5000',
  stopWhen: stepCountIs(6),
});

// nothing has been charged yet — the guard suspended it
console.log(counter.charges);       // 0
console.log(r1.interrupts.length);  // 1
2. Çökme / yeniden başlatma sonrası devam — prompt YENİDEN verilmiyor
const r2 = await resumeRun('o1', {
  journal,
  model: makeModel(),
  tools: makeTools(counter),
  guard,
  approvals: { 'call-c': true },
  stopWhen: stepCountIs(6),
});

console.log(counter.charges); // 1 — exactly once
console.log(r2.text);         // 'Done.'

resumeRun içeride, ilk çağrıda journal'a yazılmış girdiyi (prompt/messages/system) okuyup runDurable'ı aynı runId ile tekrar çağırır — self-contained resume budur. Kayıtlı girdi yoksa (bilinmeyen runId) anlamlı bir hata fırlatır.

API referansı#

fnrunDurable

generateText'in yerine geçer: model + araçları durable sarmalayıcılarla çalıştırır, her adımı journal'a yazar. Aynı runId ile tekrar çağrılırsa kayıtlı adımları yeniden çalıştırmaz.

fnresumeRun

runId'ye kayıtlı girdiyi (prompt/messages/system) journal'dan okuyup runDurable'ı tekrar çağırır — prompt'u yeniden vermeye gerek yok, sadece runId + agent config + approvals.

typeResumeAgentConfig

resumeRun için agent yapılandırması: model, tools?, guard?, stopWhen?, replay? — Studio embed ve resume çağrılarında ortak kesit.

fnreconstructState

Saf fonksiyon: journal entry'lerinden (JournalEntry[]) belirli bir adıma (uptoStep) kadar konuşma durumunu materyalize eder — time-travel ve fork'un temeli (bkz. time-travel-fork).

classDivergenceError

replay: 'strict' modunda, replay sırasında bir aracın yeniden üretilen argümanları kayıtlı argsHash ile uyuşmazsa fırlatılır (non-determinizm tespiti). Varsayılan 'lenient' modda yalnız uyarı basar.

classRunBusyError

Aynı runId eşzamanlı başka bir process/çağrı tarafından çalıştırılıyorsa (opt-in run-level lock veya tool execute in-flight) fırlatılır.

fnloadReplayCache

Dahili optimizasyon: journal bir readRun (JournalReader) sağlıyorsa (ör. SQLite/Postgres) resume'da tüm model/araç kayıtlarını tek sorguda önceden yükler. runDurable/resumeRun tarafından otomatik kullanılır — genelde doğrudan çağırmanız gerekmez.

classInMemoryJournal

Test/geliştirme için bellek-içi journal (Journal + JournalReader). Prod'da kalıcılık için SQLite/Postgres adaptörleri aynı arayüzü uygular (bkz. storage-adapters).

Lenient vs strict
runDurable'a verilen replay: 'strict' seçeneği, replay sırasında bir aracın girdisi kayıtlı hash'iyle uyuşmazsa (ör. model prompt değişmiş, non-deterministik bir üretim yapmış) çalışmayı DivergenceError ile durdurur. Varsayılan 'lenient' modda drift yalnızca konsola uyarı olarak düşer, kayıtlı çıktı yine de döner.
Yan-etkili araçlar
Yeniden deneme (retry) korumasız bir araç, journal'da failed kaydıyla kalan yan-etkili (ör. ödeme) bir çağrıyı otomatik tekrar çalıştırmaz — çift tahsilat riskine karşı kullanıcının açıkça approvals ile onay vermesi gerekir. Aynı davranış aynı runId içindeki her araç çağrısı için geçerlidir — bkz. exactly-once-tools.