pi-mono/packages/durable/test/examples/01-documents.ts
Mario Zechner 837d8a16bd feat(durable): first runnable chat turn (Package 15)
Submissions with request-ID deduplication and handles, the pi.live run
control and presentation document, the built-in pi.generation task
(system prompt preparation, streamed durable partials, retries, deferred
polling, abort), typed entry tokens, stream options and retry policy,
TaskRuntime reads, Tx.settleSubmission, registry conversation setups,
Storage.scanSubmissions, Harness.inspect, and byTaskId attribution.
Waiting calls enable scheduling. The scratch tour is split into
test/examples.
2026-09-29 14:08:28 +02:00

45 lines
2 KiB
TypeScript

// Store document state next to transcript entries.
// Run from packages/durable:
// node --conditions=source --experimental-strip-types test/examples/01-documents.ts
import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
import { createSession, defineDoc, MemoryStorage } from "../../src/index.ts";
const context = BACKGROUND_CONTEXT;
const session = createSession(new MemoryStorage());
// A document is a JSON object attached to something; here, one per conversation.
// "rewindable" keeps old values readable, so you can ask what the document
// looked like when a particular entry was written.
// `fork` says what a forked copy of the conversation starts with (see 02-forks.ts).
const Notes = defineDoc<{ text: string }>({
kind: "example.notes",
version: 1,
scope: "conversation",
history: "rewindable",
fork: "asOf", // a fork starts with the value these notes had at the fork entry
initial: () => ({ text: "" }),
});
const chat = await session.commit((tx) => tx.createConversation({ ownership: { kind: "ownerless" } }), context);
// tx.doc() returns an editable copy of the document (created on first use).
// Plain assignments to it are saved when the commit finishes.
const firstEntry = await session.commit(async (tx) => {
const entry = await tx.appendEntry(chat.id, { kind: "note", data: "hello" });
(await tx.doc(Notes, chat.id)).text = "after hello";
return entry;
}, context);
const secondEntry = await session.commit(async (tx) => {
const entry = await tx.appendEntry(chat.id, { kind: "note", data: "goodbye" });
(await tx.doc(Notes, chat.id)).text = "after goodbye";
return entry;
}, context);
// snapshot() reads the latest value. snapshotAsOf() reads the value that was
// saved in the same commit as the given entry.
console.log("latest notes:", await session.snapshot(Notes, chat.id, context));
console.log("notes at first entry:", await session.snapshotAsOf(Notes, chat.id, firstEntry.id, context));
console.log("notes at second entry:", await session.snapshotAsOf(Notes, chat.id, secondEntry.id, context));
await session.close(context);