// The standing conversation serves the console and chat. SQLite stays outside the world. import { BACKGROUND_CONTEXT as context } from '@earendil-works/chord/context'; import { proxyModels } from './proxy-models'; import { Harness, createRegistry } from '@earendil-works/pi-durable'; import { CodingTools } from './environment'; import { openStorage } from './sqlite'; import { environment, conversationChains } from './environment'; import { CredentialRequests, startRequests } from './credentials'; import { serve } from './input'; import { harnessApi } from './harness-api'; import { loadExtensions } from './extensions'; const proxy = await Deno.core.ops.op_model_proxy(); const models = await proxyModels(proxy, () => Deno.core.ops.op_model_proxy()); const registry = createRegistry(); registry.install(CodingTools); registry.install(CredentialRequests); export const storage = await openStorage(globalThis.storagePath); const harness = await Harness.open(storage, { models, registry, settings: { followUpMode: 'all', get extensions() { return registry.snapshot().installed(); } }, env: async (target: any) => environment(target.cwd ?? '/', await chain(target.conversationId)), }, context); const chain = conversationChains(harness, context); await harness.root(context, {agent:{cwd:'/src/sausage'}}); const stopRequests = await startRequests(harness, context); const extensions = await loadExtensions(harness, registry, storage, models, context, [CodingTools, CredentialRequests]); const standing = await extensions.standing(); if (!standing) throw new Error('The world needs the models and subagents extensions for its standing agent'); const conversation = (await harness.conversation(standing.conversationId, context))!; const watch = await conversation.watch(context); const emitted = new Map(); let partial = ''; const text = (message: any) => message?.content?.filter((b: any) => b.type === 'text').map((b: any) => b.text).join('') ?? ''; const render = (view: any) => { for (const entry of view.entries) { if (entry.kind !== 'pi.assistant') continue; const value = text(entry.model?.[0]); if (emitted.has(entry.id)) continue; if (value.startsWith(partial)) Deno.core.ops.op_output(value.slice(partial.length)); else Deno.core.ops.op_output(value); partial = ''; emitted.set(entry.id, value); } const live = text(view.docs['pi.live']?.generation?.message); if (live.startsWith(partial)) Deno.core.ops.op_output(live.slice(partial.length)); partial = live; }; // Do not replay the historical transcript to the console. for (const entry of watch.value.entries) { if (entry.kind === 'pi.assistant') emitted.set(entry.id, text(entry.model?.[0])); } if (globalThis.consoleEnabled) watch.start((event: any) => { if (event.kind === 'value') render(event.value); }); const api = harnessApi(harness, models, extensions, context); harness.resume(); await serve(harness, context, globalThis.consoleEnabled ? async () => { await harness.waitForIdle(context); const final = await conversation.watch(context); render(final.value); await final.stop(); Deno.core.ops.op_output('\n'); } : undefined, api, async () => (await extensions.standing())!.conversationId); await api.close(); await extensions.close(); await stopRequests(); await watch.stop(); await harness.close(context);