mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
Session workers now host a durable Harness over a per-session sqlite storage. The server keeps each session in <sessionDir>/<id>/ with meta.json and session.sqlite and never opens the storage itself. Workers hold retirement while the Harness task graph has live tasks and resume interrupted work on open. Transcript serves the root conversation's durable view directly, Models follows the conversation's agent document, and AgentController maps prompt, steer, follow-up, queue cancellation, abort, and compaction onto the root conversation, plus waitForPrompt. navigate, nextRun, and resume are dropped (see experimental/services/README.md TODO). The durable TUI and the worker share harness-setup.ts. pi-server exports its own SessionMetadata and no longer depends on pi-agent-core. Chord accepts readonly JSON types in service contracts without walking them, which recursive JSON types like pi-ai's made too deep.
39 lines
1.7 KiB
TypeScript
39 lines
1.7 KiB
TypeScript
import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
|
|
import { createModels, type FauxProviderHandle, type FauxResponseStep, fauxProvider } from "@earendil-works/pi-ai";
|
|
import { type Conversation, createRegistry, Harness, MemoryStorage } from "@earendil-works/pi-durable";
|
|
|
|
export interface FauxConversation {
|
|
readonly faux: FauxProviderHandle;
|
|
readonly harness: Harness;
|
|
readonly conversation: Conversation;
|
|
close(): Promise<void>;
|
|
}
|
|
|
|
/** An in-memory durable Harness whose root conversation answers with the faux provider. */
|
|
export async function openFauxConversation(responses: FauxResponseStep[] = []): Promise<FauxConversation> {
|
|
const faux = fauxProvider();
|
|
faux.setResponses(responses);
|
|
const models = createModels();
|
|
models.setProvider(faux.provider);
|
|
const harness = await Harness.open(new MemoryStorage(), { models, registry: createRegistry() }, BACKGROUND_CONTEXT);
|
|
const model = faux.getModel();
|
|
const conversation = await harness.root(BACKGROUND_CONTEXT, {
|
|
agent: { model: { provider: model.provider, modelId: model.id } },
|
|
});
|
|
return { faux, harness, conversation, close: () => harness.close(BACKGROUND_CONTEXT) };
|
|
}
|
|
|
|
/** A faux response that never arrives; it ends only when its generation is aborted. */
|
|
export function pendingResponse(): { readonly step: FauxResponseStep; readonly reached: Promise<void> } {
|
|
let reach!: () => void;
|
|
const reached = new Promise<void>((resolve) => {
|
|
reach = resolve;
|
|
});
|
|
const step: FauxResponseStep = (_context, options) =>
|
|
new Promise((_resolve, reject) => {
|
|
reach();
|
|
const signal = options!.signal!;
|
|
signal.addEventListener("abort", () => reject(signal.reason), { once: true });
|
|
});
|
|
return { step, reached };
|
|
}
|