From 07ac9fc5dd6bb5c5fd804f8cafb65f17b6198f00 Mon Sep 17 00:00:00 2001 From: Andrei Savu Date: Fri, 11 Sep 2026 12:51:43 -0700 Subject: [PATCH] refactor ambion package entry points --- packages/ambion/package.json | 12 ++ packages/ambion/src/host.ts | 19 +++ packages/ambion/src/index.ts | 104 ++-------------- packages/ambion/src/internal.ts | 124 ++++++++++++++++++++ packages/ambion/src/node.ts | 8 ++ packages/ambion/src/protocol.ts | 22 ++++ packages/ambion/src/seat/seat.ts | 10 ++ packages/ambion/test/assistant.test.ts | 2 +- packages/ambion/test/chaos.test.ts | 2 +- packages/ambion/test/checkpoint.test.ts | 4 +- packages/ambion/test/consistency.test.ts | 2 +- packages/ambion/test/doubt.test.ts | 2 +- packages/ambion/test/hosts.test.ts | 2 +- packages/ambion/test/lease.test.ts | 2 +- packages/ambion/test/live/control.test.ts | 2 +- packages/ambion/test/live/exchange.test.ts | 2 +- packages/ambion/test/live/judgment.test.ts | 2 +- packages/ambion/test/live/loop.test.ts | 2 +- packages/ambion/test/live/record.test.ts | 2 +- packages/ambion/test/live/support.ts | 2 +- packages/ambion/test/live/workspace.test.ts | 2 +- packages/ambion/test/log.test.ts | 2 +- packages/ambion/test/matrix.test.ts | 2 +- packages/ambion/test/package.test.ts | 51 ++++++-- packages/ambion/test/presence.test.ts | 2 +- packages/ambion/test/property.test.ts | 2 +- packages/ambion/test/restart.test.ts | 2 +- packages/ambion/test/roster.test.ts | 4 +- packages/ambion/test/runtime.test.ts | 2 +- packages/ambion/test/seat.test.ts | 2 +- packages/ambion/test/session.test.ts | 2 +- packages/ambion/test/split.test.ts | 2 +- packages/ambion/test/support/cast.ts | 2 +- packages/ambion/test/support/chaos.ts | 2 +- packages/ambion/test/support/child.ts | 2 +- packages/ambion/test/support/clock.ts | 2 +- packages/ambion/test/support/history.ts | 2 +- packages/ambion/test/support/invariants.ts | 2 +- packages/ambion/test/support/room.ts | 2 +- packages/ambion/test/support/scenarios.ts | 2 +- packages/ambion/test/support/storage.ts | 2 +- packages/ambion/test/support/transport.ts | 4 +- packages/ambion/test/wire.test.ts | 2 +- packages/ambion/test/workspace.test.ts | 2 +- packages/ambion/tsdown.config.ts | 2 +- packages/cli/src/main.ts | 3 +- packages/cloudflare/src/configure.ts | 10 +- packages/cloudflare/src/room-object.ts | 24 +--- packages/cloudflare/src/seat-object.ts | 9 +- packages/cloudflare/src/storage.ts | 4 +- packages/cloudflare/test/restart.test.ts | 4 +- packages/cloudflare/test/room.test.ts | 3 +- packages/cloudflare/test/seat.test.ts | 3 +- packages/cloudflare/test/storage.test.ts | 2 +- 54 files changed, 310 insertions(+), 182 deletions(-) create mode 100644 packages/ambion/src/host.ts create mode 100644 packages/ambion/src/internal.ts create mode 100644 packages/ambion/src/node.ts create mode 100644 packages/ambion/src/protocol.ts diff --git a/packages/ambion/package.json b/packages/ambion/package.json index e1896b6..53c36bc 100644 --- a/packages/ambion/package.json +++ b/packages/ambion/package.json @@ -22,6 +22,18 @@ "types": "./dist/index.d.mts", "import": "./dist/index.mjs" }, + "./host": { + "types": "./dist/host.d.mts", + "import": "./dist/host.mjs" + }, + "./protocol": { + "types": "./dist/protocol.d.mts", + "import": "./dist/protocol.mjs" + }, + "./node": { + "types": "./dist/node.d.mts", + "import": "./dist/node.mjs" + }, "./package.json": "./package.json" }, "main": "./dist/index.mjs", diff --git a/packages/ambion/src/host.ts b/packages/ambion/src/host.ts new file mode 100644 index 0000000..108ec43 --- /dev/null +++ b/packages/ambion/src/host.ts @@ -0,0 +1,19 @@ +/** APIs for hosts which own runtimes, persistence, transports, and lifecycle. */ +export type { CreateRuntimeOptions, RunningRoom, Runtime, Transport } from './host/runtime.ts'; +export { createRuntime, defaultRuntime, sessionsOver, systemClock } from './host/runtime.ts'; +export type { Sql, SqlValue } from './host/sqlite.ts'; +export { sqliteSessions } from './host/sqlite.ts'; +export type { SeatContext } from './seat/seat.ts'; +export { createSeatActor, inProcessTransport } from './seat/seat.ts'; +export type { ReadSessionOptions, ResumeSessionOptions, SessionView, Visit } from './session.ts'; +export { readSession, resumeSession, stopSession, visitSession } from './session.ts'; +export { attentive, passive, seated } from './define.ts'; +export { destroyWorkspace } from './tools/workspace.ts'; +export type { + Clock, + FencedSession, + ModelResolver, + SessionOpener, + WorkspaceBackend, +} from './types.ts'; +export { isPresence, isSeatedAgent, isSpoken, isSummary } from './types.ts'; diff --git a/packages/ambion/src/index.ts b/packages/ambion/src/index.ts index ca2a52c..32ecc16 100644 --- a/packages/ambion/src/index.ts +++ b/packages/ambion/src/index.ts @@ -1,85 +1,22 @@ -/** - * The Ambion runtime: five primitives, and a dependency for every other concern. - * - * `defineAgent` makes an agent, `defineHuman` names a person, `defineTool` - * gives agents hands, `defineWorkspace` names the identity and data boundary - * an agent's tools reach into, `seated` chooses what wakes a seat — with - * `passive` and `attentive` for the two points worth naming — and - * `startSession` brings up a named room the agents work in and people visit. - * A person's question opens an exchange, the room works, and quiescence - * closes it — the exchange every other feature reads. `stopSession` takes - * the room down, `readSession` reads a name without starting anything, - * `visitSession` puts a person in a running room, and `destroyWorkspace` - * retires a workspace for good. The room's assistant composes the room at - * the open of an exchange, from the agents held in reserve, and writes the - * one message a person reads when the exchange closes. The design contracts - * live in docs/agent.md, docs/exchange.md, docs/presence.md, - * docs/assistant.md, docs/workspace.md and docs/roster.md. +/** The small, application-facing Ambion API. Host integration and wire + * contracts live at `./host` and `./protocol`; Node adapters live at `./node`. */ - -export type { - ExecutionEnv, - SessionMetadata, - SessionRepo, - SessionStorage, -} from '@earendil-works/pi-agent-core'; -// Storage is Pi's, re-exported — Ambion adds no storage abstraction of its own. -// `ExecutionEnv` is what a workspace backend's `connect` returns, and Pi's too. -export { - InMemorySessionRepo, - InMemorySessionStorage, - JsonlSessionRepo, -} from '@earendil-works/pi-agent-core'; export type { DefineAgentOptions, DefineHumanOptions, DefineToolOptions } from './define.ts'; -export { attentive, defineAgent, defineHuman, defineTool, passive, seated } from './define.ts'; -export type { - CreateRuntimeOptions, - RunningRoom, - Runtime, - SessionRepoLike, - Transport, -} from './host/runtime.ts'; -export { createRuntime, defaultRuntime, sessionsOver, systemClock } from './host/runtime.ts'; -export { type Sql, SqliteSessionStorage, type SqlValue, sqliteSessions } from './host/sqlite.ts'; -export type { SeatContext } from './seat/seat.ts'; -export { inProcessTransport, SeatActor } from './seat/seat.ts'; -export type { - ReadSessionOptions, - ResumeSessionOptions, - Session, - SessionView, - StartSessionOptions, - Visit, -} from './session.ts'; -export { readSession, resumeSession, startSession, stopSession, visitSession } from './session.ts'; -export type { - MemoryBackendFile, - MemoryBackendOptions, - MemoryWorkspaceBackend, - SeedWriter, -} from './tools/just-bash.ts'; -// A workspace over a real directory, or the in-memory default with seeding -// and read-back. Neither import is needed for the in-memory default's own -// use inside `defineWorkspace` — only a host that wants to seed or read it. -export { directoryBackend, memoryBackend } from './tools/just-bash.ts'; -export type { DefineWorkspaceOptions } from './tools/workspace.ts'; -export { defineWorkspace, destroyWorkspace } from './tools/workspace.ts'; +export { defineAgent, defineHuman, defineTool } from './define.ts'; +export type { Session, StartSessionOptions } from './session.ts'; +export { startSession } from './session.ts'; export type { AgentDefinition, AgentSeat, AgentSeatInfo, AmbionTool, Attention, - Clock, ClosedExchange, Exchange, - FencedSession, HumanDefinition, HumanSeatInfo, Message, - ModelResolver, Participant, - PresenceChange, PresenceMessage, PresenceStatus, SeatedAgent, @@ -87,38 +24,11 @@ export type { SeatStatus, Seq, SessionEvent, - SessionOpener, SpokenMessage, SummaryMessage, ToolContext, Workspace, - WorkspaceBackend, WorkspaceHandle, } from './types.ts'; -export { isPresence, isSeatedAgent, isSpoken, isSummary } from './types.ts'; -export type { - ActivationView, - CheckpointRow, - CloseRow, - Commit, - CommitResponse, - CompositionRow, - EndReason, - Hand, - Intent, - Lease, - LeaseHold, - LeaseResponse, - LeaseRow, - RunRow, - SeatPort, - SeatRoom, - SeatRow, - Stale, - ViewResponse, - Wake, -} from './wire.ts'; -export { assertWire, roundTrip } from './wire.ts'; - -/** Kept in step with package.json by a test. */ -export const PACKAGE_NAME = '@ambionframework/ambion'; +export type { DefineWorkspaceOptions } from './tools/workspace.ts'; +export { defineWorkspace } from './tools/workspace.ts'; diff --git a/packages/ambion/src/internal.ts b/packages/ambion/src/internal.ts new file mode 100644 index 0000000..ca2a52c --- /dev/null +++ b/packages/ambion/src/internal.ts @@ -0,0 +1,124 @@ +/** + * The Ambion runtime: five primitives, and a dependency for every other concern. + * + * `defineAgent` makes an agent, `defineHuman` names a person, `defineTool` + * gives agents hands, `defineWorkspace` names the identity and data boundary + * an agent's tools reach into, `seated` chooses what wakes a seat — with + * `passive` and `attentive` for the two points worth naming — and + * `startSession` brings up a named room the agents work in and people visit. + * A person's question opens an exchange, the room works, and quiescence + * closes it — the exchange every other feature reads. `stopSession` takes + * the room down, `readSession` reads a name without starting anything, + * `visitSession` puts a person in a running room, and `destroyWorkspace` + * retires a workspace for good. The room's assistant composes the room at + * the open of an exchange, from the agents held in reserve, and writes the + * one message a person reads when the exchange closes. The design contracts + * live in docs/agent.md, docs/exchange.md, docs/presence.md, + * docs/assistant.md, docs/workspace.md and docs/roster.md. + */ + +export type { + ExecutionEnv, + SessionMetadata, + SessionRepo, + SessionStorage, +} from '@earendil-works/pi-agent-core'; +// Storage is Pi's, re-exported — Ambion adds no storage abstraction of its own. +// `ExecutionEnv` is what a workspace backend's `connect` returns, and Pi's too. +export { + InMemorySessionRepo, + InMemorySessionStorage, + JsonlSessionRepo, +} from '@earendil-works/pi-agent-core'; +export type { DefineAgentOptions, DefineHumanOptions, DefineToolOptions } from './define.ts'; +export { attentive, defineAgent, defineHuman, defineTool, passive, seated } from './define.ts'; +export type { + CreateRuntimeOptions, + RunningRoom, + Runtime, + SessionRepoLike, + Transport, +} from './host/runtime.ts'; +export { createRuntime, defaultRuntime, sessionsOver, systemClock } from './host/runtime.ts'; +export { type Sql, SqliteSessionStorage, type SqlValue, sqliteSessions } from './host/sqlite.ts'; +export type { SeatContext } from './seat/seat.ts'; +export { inProcessTransport, SeatActor } from './seat/seat.ts'; +export type { + ReadSessionOptions, + ResumeSessionOptions, + Session, + SessionView, + StartSessionOptions, + Visit, +} from './session.ts'; +export { readSession, resumeSession, startSession, stopSession, visitSession } from './session.ts'; +export type { + MemoryBackendFile, + MemoryBackendOptions, + MemoryWorkspaceBackend, + SeedWriter, +} from './tools/just-bash.ts'; +// A workspace over a real directory, or the in-memory default with seeding +// and read-back. Neither import is needed for the in-memory default's own +// use inside `defineWorkspace` — only a host that wants to seed or read it. +export { directoryBackend, memoryBackend } from './tools/just-bash.ts'; +export type { DefineWorkspaceOptions } from './tools/workspace.ts'; +export { defineWorkspace, destroyWorkspace } from './tools/workspace.ts'; +export type { + AgentDefinition, + AgentSeat, + AgentSeatInfo, + AmbionTool, + Attention, + Clock, + ClosedExchange, + Exchange, + FencedSession, + HumanDefinition, + HumanSeatInfo, + Message, + ModelResolver, + Participant, + PresenceChange, + PresenceMessage, + PresenceStatus, + SeatedAgent, + SeatInfo, + SeatStatus, + Seq, + SessionEvent, + SessionOpener, + SpokenMessage, + SummaryMessage, + ToolContext, + Workspace, + WorkspaceBackend, + WorkspaceHandle, +} from './types.ts'; +export { isPresence, isSeatedAgent, isSpoken, isSummary } from './types.ts'; +export type { + ActivationView, + CheckpointRow, + CloseRow, + Commit, + CommitResponse, + CompositionRow, + EndReason, + Hand, + Intent, + Lease, + LeaseHold, + LeaseResponse, + LeaseRow, + RunRow, + SeatPort, + SeatRoom, + SeatRow, + Stale, + ViewResponse, + Wake, +} from './wire.ts'; +export { assertWire, roundTrip } from './wire.ts'; + +/** Kept in step with package.json by a test. */ +export const PACKAGE_NAME = '@ambionframework/ambion'; diff --git a/packages/ambion/src/node.ts b/packages/ambion/src/node.ts new file mode 100644 index 0000000..fa51c97 --- /dev/null +++ b/packages/ambion/src/node.ts @@ -0,0 +1,8 @@ +/** Filesystem-backed workspace adapters for Node.js hosts. */ +export type { + MemoryBackendFile, + MemoryBackendOptions, + MemoryWorkspaceBackend, + SeedWriter, +} from './tools/just-bash.ts'; +export { directoryBackend, memoryBackend } from './tools/just-bash.ts'; diff --git a/packages/ambion/src/protocol.ts b/packages/ambion/src/protocol.ts new file mode 100644 index 0000000..5327adb --- /dev/null +++ b/packages/ambion/src/protocol.ts @@ -0,0 +1,22 @@ +/** Stable JSON values exchanged by a room and a remote seat. */ +export type { + ActivationView, + CloseRow, + Commit, + CommitResponse, + EndReason, + Hand, + Intent, + Lease, + LeaseResponse, + LeaseRow, + CompositionRow, + RunRow, + SeatPort, + SeatRoom, + SeatRow, + Stale, + ViewResponse, + Wake, +} from './wire.ts'; +export { assertWire, roundTrip } from './wire.ts'; diff --git a/packages/ambion/src/seat/seat.ts b/packages/ambion/src/seat/seat.ts index b0d90cd..769cb52 100644 --- a/packages/ambion/src/seat/seat.ts +++ b/packages/ambion/src/seat/seat.ts @@ -338,6 +338,16 @@ export class SeatActor implements SeatPort { } } +/** Build the seat side of a host transport without exposing its implementation class. */ +export function createSeatActor( + room: SeatRoom, + context: SeatContext, +): SeatPort & { + run(activation: string): Promise; +} { + return new SeatActor(room, context); +} + // -- the transport ------------------------------------------------------------ /** Every seat is an actor in this process, holding the room directly. */ diff --git a/packages/ambion/test/assistant.test.ts b/packages/ambion/test/assistant.test.ts index 4cbe039..5e9b520 100644 --- a/packages/ambion/test/assistant.test.ts +++ b/packages/ambion/test/assistant.test.ts @@ -19,7 +19,7 @@ import { startSession, stopSession, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { renderRecord } from '../src/render.ts'; import { fakeClock } from './support/clock.ts'; import { assistantEnded, collect, deferred, roomName as name, tick } from './support/room.ts'; diff --git a/packages/ambion/test/chaos.test.ts b/packages/ambion/test/chaos.test.ts index 20a70c0..f8e0dd1 100644 --- a/packages/ambion/test/chaos.test.ts +++ b/packages/ambion/test/chaos.test.ts @@ -26,7 +26,7 @@ import { type Session, stopSession, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { agents, priya, type Question, questions, sam, script, TIMING } from './support/cast.ts'; import { idle, liveLeases, outcome, World, within } from './support/chaos.ts'; import { type FakeClock, fakeClock } from './support/clock.ts'; diff --git a/packages/ambion/test/checkpoint.test.ts b/packages/ambion/test/checkpoint.test.ts index e4a42b5..92acee8 100644 --- a/packages/ambion/test/checkpoint.test.ts +++ b/packages/ambion/test/checkpoint.test.ts @@ -5,7 +5,7 @@ * messages stay, and a room that folds the rest behaves the same. */ import { describe, expect, it } from 'vitest'; -import type { CompositionRow, Seq } from '../src/index.ts'; +import type { CompositionRow, Seq } from '../src/internal.ts'; import { createRuntime, defineAgent, @@ -17,7 +17,7 @@ import { startSession, stopSession, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { RoomLog } from '../src/log/log.ts'; import { checkpointOf, foldRoom, type RoomState } from '../src/room/fold.ts'; import { type FakeClock, fakeClock } from './support/clock.ts'; diff --git a/packages/ambion/test/consistency.test.ts b/packages/ambion/test/consistency.test.ts index c68e4a7..9028b49 100644 --- a/packages/ambion/test/consistency.test.ts +++ b/packages/ambion/test/consistency.test.ts @@ -20,7 +20,7 @@ import { stopSession, type Visit, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { foldRoom } from '../src/room/fold.ts'; import { agents, assistant, colleague, priya, product, sam, troubled } from './support/cast.ts'; import { liveLeases } from './support/chaos.ts'; diff --git a/packages/ambion/test/doubt.test.ts b/packages/ambion/test/doubt.test.ts index 429bec6..f95db33 100644 --- a/packages/ambion/test/doubt.test.ts +++ b/packages/ambion/test/doubt.test.ts @@ -13,7 +13,7 @@ import { type SessionEvent, startSession, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { fakeClock } from './support/clock.ts'; import { collect, roomName, rowsOf } from './support/room.ts'; import { diff --git a/packages/ambion/test/hosts.test.ts b/packages/ambion/test/hosts.test.ts index 647202c..210ce83 100644 --- a/packages/ambion/test/hosts.test.ts +++ b/packages/ambion/test/hosts.test.ts @@ -15,7 +15,7 @@ import { startSession, stopSession, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { agents, assistant, diff --git a/packages/ambion/test/lease.test.ts b/packages/ambion/test/lease.test.ts index 0b8d066..5dd5ab9 100644 --- a/packages/ambion/test/lease.test.ts +++ b/packages/ambion/test/lease.test.ts @@ -22,7 +22,7 @@ import { stopSession, type Visit, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { type FakeClock, fakeClock } from './support/clock.ts'; import { assistant, collect, deferred, enter, roomName, rowsOf, tick } from './support/room.ts'; import { diff --git a/packages/ambion/test/live/control.test.ts b/packages/ambion/test/live/control.test.ts index 4b09e2f..ae7f556 100644 --- a/packages/ambion/test/live/control.test.ts +++ b/packages/ambion/test/live/control.test.ts @@ -5,7 +5,7 @@ * a real one has an open HTTP stream to close. */ import { expect, it } from 'vitest'; -import { stopSession } from '../../src/index.ts'; +import { stopSession } from '../../src/internal.ts'; import { enter } from '../support/room.ts'; import { agent, diff --git a/packages/ambion/test/live/exchange.test.ts b/packages/ambion/test/live/exchange.test.ts index 22749e4..0125521 100644 --- a/packages/ambion/test/live/exchange.test.ts +++ b/packages/ambion/test/live/exchange.test.ts @@ -8,7 +8,7 @@ */ import { Type } from 'typebox'; import { expect, it } from 'vitest'; -import { defineHuman, defineTool, isPresence, isSummary, stopSession } from '../../src/index.ts'; +import { defineHuman, defineTool, isPresence, isSummary, stopSession } from '../../src/internal.ts'; import { enter } from '../support/room.ts'; import { activationsOf, diff --git a/packages/ambion/test/live/judgment.test.ts b/packages/ambion/test/live/judgment.test.ts index 88fec41..0a93440 100644 --- a/packages/ambion/test/live/judgment.test.ts +++ b/packages/ambion/test/live/judgment.test.ts @@ -6,7 +6,7 @@ */ import { Type } from 'typebox'; import { expect, it } from 'vitest'; -import { defineTool, passive, stopSession } from '../../src/index.ts'; +import { defineTool, passive, stopSession } from '../../src/internal.ts'; import { enter } from '../support/room.ts'; import { activationsOf, diff --git a/packages/ambion/test/live/loop.test.ts b/packages/ambion/test/live/loop.test.ts index 9b95534..b7989ec 100644 --- a/packages/ambion/test/live/loop.test.ts +++ b/packages/ambion/test/live/loop.test.ts @@ -5,7 +5,7 @@ */ import { Type } from 'typebox'; import { expect, it } from 'vitest'; -import { defineTool, stopSession } from '../../src/index.ts'; +import { defineTool, stopSession } from '../../src/internal.ts'; import { enter } from '../support/room.ts'; import { agent, diff --git a/packages/ambion/test/live/record.test.ts b/packages/ambion/test/live/record.test.ts index 5e072f6..045410e 100644 --- a/packages/ambion/test/live/record.test.ts +++ b/packages/ambion/test/live/record.test.ts @@ -11,7 +11,7 @@ import { startSession, stopSession, visitSession, -} from '../../src/index.ts'; +} from '../../src/internal.ts'; import { collect, roomName } from '../support/room.ts'; import { agent, diff --git a/packages/ambion/test/live/support.ts b/packages/ambion/test/live/support.ts index 244fb01..1903e2f 100644 --- a/packages/ambion/test/live/support.ts +++ b/packages/ambion/test/live/support.ts @@ -23,7 +23,7 @@ import { type SessionEvent, type StartSessionOptions, startSession, -} from '../../src/index.ts'; +} from '../../src/internal.ts'; import { collect, roomName } from '../support/room.ts'; /** The model every live seat runs on. The example reads the same variable. */ diff --git a/packages/ambion/test/live/workspace.test.ts b/packages/ambion/test/live/workspace.test.ts index fec6609..9b71a75 100644 --- a/packages/ambion/test/live/workspace.test.ts +++ b/packages/ambion/test/live/workspace.test.ts @@ -5,7 +5,7 @@ * pick them up and use them against a filesystem it has never seen. */ import { expect, it } from 'vitest'; -import { defineWorkspace, destroyWorkspace, memoryBackend, stopSession } from '../../src/index.ts'; +import { defineWorkspace, destroyWorkspace, memoryBackend, stopSession } from '../../src/internal.ts'; import { enter, roomName } from '../support/room.ts'; import { agent, diff --git a/packages/ambion/test/log.test.ts b/packages/ambion/test/log.test.ts index 91866de..7981591 100644 --- a/packages/ambion/test/log.test.ts +++ b/packages/ambion/test/log.test.ts @@ -6,7 +6,7 @@ import { describe, expect, it } from 'vitest'; import { sessionsOver } from '../src/host/runtime.ts'; -import { InMemorySessionRepo, type SpokenMessage } from '../src/index.ts'; +import { InMemorySessionRepo, type SpokenMessage } from '../src/internal.ts'; import { RoomLog } from '../src/log/log.ts'; import { deferred, roomName } from './support/room.ts'; import { faultyOpener, memory } from './support/storage.ts'; diff --git a/packages/ambion/test/matrix.test.ts b/packages/ambion/test/matrix.test.ts index 3046ef0..7635766 100644 --- a/packages/ambion/test/matrix.test.ts +++ b/packages/ambion/test/matrix.test.ts @@ -4,7 +4,7 @@ * through to disk and reads back. */ import { describe, expect, it } from 'vitest'; -import { createRuntime, inProcessTransport } from '../src/index.ts'; +import { createRuntime, inProcessTransport } from '../src/internal.ts'; import { fakeClock } from './support/clock.ts'; import { roomName } from './support/room.ts'; import { scenarios } from './support/scenarios.ts'; diff --git a/packages/ambion/test/package.test.ts b/packages/ambion/test/package.test.ts index dd0181c..8cc6646 100644 --- a/packages/ambion/test/package.test.ts +++ b/packages/ambion/test/package.test.ts @@ -1,10 +1,47 @@ -import { readFile } from 'node:fs/promises'; -import { fileURLToPath } from 'node:url'; import { expect, it } from 'vitest'; -import { PACKAGE_NAME } from '../src/index.ts'; +import * as application from '../src/index.ts'; +import * as host from '../src/host.ts'; +import * as node from '../src/node.ts'; +import * as protocol from '../src/protocol.ts'; -it('keeps the exported package name in step with the manifest', async () => { - const manifestPath = fileURLToPath(new URL('../package.json', import.meta.url)); - const manifest = JSON.parse(await readFile(manifestPath, 'utf8')) as { name: string }; - expect(PACKAGE_NAME).toBe(manifest.name); +it('keeps the default entry point to the five application primitives', () => { + expect(Object.keys(application).sort()).toEqual([ + 'defineAgent', + 'defineHuman', + 'defineTool', + 'defineWorkspace', + 'startSession', + ]); +}); + +it('lists the host adapter API', () => { + expect(Object.keys(host).sort()).toEqual([ + 'attentive', + 'createRuntime', + 'createSeatActor', + 'defaultRuntime', + 'destroyWorkspace', + 'inProcessTransport', + 'isPresence', + 'isSeatedAgent', + 'isSpoken', + 'isSummary', + 'passive', + 'readSession', + 'resumeSession', + 'seated', + 'sessionsOver', + 'sqliteSessions', + 'stopSession', + 'systemClock', + 'visitSession', + ]); +}); + +it('lists the protocol API', () => { + expect(Object.keys(protocol).sort()).toEqual(['assertWire', 'roundTrip']); +}); + +it('lists the Node adapter API', () => { + expect(Object.keys(node).sort()).toEqual(['directoryBackend', 'memoryBackend']); }); diff --git a/packages/ambion/test/presence.test.ts b/packages/ambion/test/presence.test.ts index dc2a2eb..8162cf0 100644 --- a/packages/ambion/test/presence.test.ts +++ b/packages/ambion/test/presence.test.ts @@ -14,7 +14,7 @@ import { startSession, stopSession, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { andrei, assistant, collect, deferred, roomName as name } from './support/room.ts'; import { contextText, quiet, scripted } from './support/scripted.ts'; import { type FaultyOpener, faultyOpener, memory } from './support/storage.ts'; diff --git a/packages/ambion/test/property.test.ts b/packages/ambion/test/property.test.ts index 9f57f21..f0587e4 100644 --- a/packages/ambion/test/property.test.ts +++ b/packages/ambion/test/property.test.ts @@ -23,7 +23,7 @@ import { stopSession, type Visit, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { liveLeases } from './support/chaos.ts'; import { type FakeClock, fakeClock } from './support/clock.ts'; import { invariants } from './support/invariants.ts'; diff --git a/packages/ambion/test/restart.test.ts b/packages/ambion/test/restart.test.ts index b8a5361..6179c60 100644 --- a/packages/ambion/test/restart.test.ts +++ b/packages/ambion/test/restart.test.ts @@ -19,7 +19,7 @@ import { startSession, stopSession, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { type FakeClock, fakeClock } from './support/clock.ts'; import { collect, crash, deferred, roomName, rowsOf, tick } from './support/room.ts'; import { diff --git a/packages/ambion/test/roster.test.ts b/packages/ambion/test/roster.test.ts index 8f9ba8f..8aaee7b 100644 --- a/packages/ambion/test/roster.test.ts +++ b/packages/ambion/test/roster.test.ts @@ -16,7 +16,7 @@ import { startSession, stopSession, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { fakeClock } from './support/clock.ts'; import { assistantEnded, collect, deferred, roomName as name, tick } from './support/room.ts'; import { @@ -591,7 +591,7 @@ describe('the host', () => { started.pop(); // the record says who was seated, and a read of the stopped room folds it - const { readSession } = await import('../src/index.ts'); + const { readSession } = await import('../src/internal.ts'); const stopped = readSession(session.name, { runtime }); expect(kinds(await stopped.messages())).toEqual(['seated']); expect(seatNames(stopped as Session)).toEqual(['product', 'assistant', 'surveyor']); diff --git a/packages/ambion/test/runtime.test.ts b/packages/ambion/test/runtime.test.ts index 71a5e49..3c15341 100644 --- a/packages/ambion/test/runtime.test.ts +++ b/packages/ambion/test/runtime.test.ts @@ -15,7 +15,7 @@ import { startSession, stopSession, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { fakeClock } from './support/clock.ts'; import { andrei, assistant, roomName } from './support/room.ts'; import { quiet, scripted } from './support/scripted.ts'; diff --git a/packages/ambion/test/seat.test.ts b/packages/ambion/test/seat.test.ts index 8eaabea..4a3feec 100644 --- a/packages/ambion/test/seat.test.ts +++ b/packages/ambion/test/seat.test.ts @@ -17,7 +17,7 @@ import { type SeatRoom, type ViewResponse, type Wake, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { fakeClock } from './support/clock.ts'; import { deferred, tick } from './support/room.ts'; import { quiet, scripted } from './support/scripted.ts'; diff --git a/packages/ambion/test/session.test.ts b/packages/ambion/test/session.test.ts index b0c7eeb..0953e53 100644 --- a/packages/ambion/test/session.test.ts +++ b/packages/ambion/test/session.test.ts @@ -13,7 +13,7 @@ import { startSession, stopSession, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { andrei, assistant, collect, deferred, enter, roomName } from './support/room.ts'; import { byAgent, contextText, quiet, scripted, speak } from './support/scripted.ts'; diff --git a/packages/ambion/test/split.test.ts b/packages/ambion/test/split.test.ts index 32195e3..5606d1c 100644 --- a/packages/ambion/test/split.test.ts +++ b/packages/ambion/test/split.test.ts @@ -23,7 +23,7 @@ import { startSession, stopSession, visitSession, -} from '../src/index.ts'; +} from '../src/internal.ts'; import type { LogEntry } from '../src/log/log.ts'; import { foldRoom } from '../src/room/fold.ts'; import { diff --git a/packages/ambion/test/support/cast.ts b/packages/ambion/test/support/cast.ts index c342e8e..60fae66 100644 --- a/packages/ambion/test/support/cast.ts +++ b/packages/ambion/test/support/cast.ts @@ -9,7 +9,7 @@ import { defineAgent, defineHuman, type HumanDefinition, -} from '../../src/index.ts'; +} from '../../src/internal.ts'; import { answersEveryQuestion, answersLastQuestion, diff --git a/packages/ambion/test/support/chaos.ts b/packages/ambion/test/support/chaos.ts index 25d308b..9b38bf3 100644 --- a/packages/ambion/test/support/chaos.ts +++ b/packages/ambion/test/support/chaos.ts @@ -28,7 +28,7 @@ import { type SessionOpener, startSession, visitSession, -} from '../../src/index.ts'; +} from '../../src/internal.ts'; import { foldLeases, isLive } from '../../src/room/lease.ts'; import type { LeaseRow } from '../../src/wire.ts'; import { diff --git a/packages/ambion/test/support/child.ts b/packages/ambion/test/support/child.ts index 4dc00d6..885a0de 100644 --- a/packages/ambion/test/support/child.ts +++ b/packages/ambion/test/support/child.ts @@ -7,7 +7,7 @@ * * node --experimental-transform-types child.ts */ -import { createRuntime, startSession, visitSession } from '../../src/index.ts'; +import { createRuntime, startSession, visitSession } from '../../src/internal.ts'; import { agents, assistant, diff --git a/packages/ambion/test/support/clock.ts b/packages/ambion/test/support/clock.ts index fee2311..aab29c1 100644 --- a/packages/ambion/test/support/clock.ts +++ b/packages/ambion/test/support/clock.ts @@ -1,4 +1,4 @@ -import type { Clock } from '../../src/index.ts'; +import type { Clock } from '../../src/internal.ts'; /** A clock a test moves by hand. Alarms fire inside `advance`, in order. */ export interface FakeClock extends Clock { diff --git a/packages/ambion/test/support/history.ts b/packages/ambion/test/support/history.ts index 80cd023..5589f35 100644 --- a/packages/ambion/test/support/history.ts +++ b/packages/ambion/test/support/history.ts @@ -13,7 +13,7 @@ * is one message, one attempt at a wake or a draft runs at a time, and * nothing is pending once the room drains. */ -import type { Clock, LeaseRow, Message, Seq } from '../../src/index.ts'; +import type { Clock, LeaseRow, Message, Seq } from '../../src/internal.ts'; import type { RoomState } from '../../src/room/fold.ts'; import { activationId, parseId } from '../../src/room/lease.ts'; diff --git a/packages/ambion/test/support/invariants.ts b/packages/ambion/test/support/invariants.ts index 7dec0b5..e89479d 100644 --- a/packages/ambion/test/support/invariants.ts +++ b/packages/ambion/test/support/invariants.ts @@ -9,7 +9,7 @@ import { type SessionEvent, type SessionOpener, type SessionView, -} from '../../src/index.ts'; +} from '../../src/internal.ts'; import { standing } from './history.ts'; import { rowsOf } from './room.ts'; diff --git a/packages/ambion/test/support/room.ts b/packages/ambion/test/support/room.ts index c4bb0d6..957e1c4 100644 --- a/packages/ambion/test/support/room.ts +++ b/packages/ambion/test/support/room.ts @@ -7,7 +7,7 @@ import { type SessionEvent, type SessionOpener, visitSession, -} from '../../src/index.ts'; +} from '../../src/internal.ts'; /** A trivial assistant: every room seats one, and nothing that uses it tests what it writes. */ export const assistant = defineAgent({ diff --git a/packages/ambion/test/support/scenarios.ts b/packages/ambion/test/support/scenarios.ts index 18077c7..8758882 100644 --- a/packages/ambion/test/support/scenarios.ts +++ b/packages/ambion/test/support/scenarios.ts @@ -17,7 +17,7 @@ import { startSession, stopSession, visitSession, -} from '../../src/index.ts'; +} from '../../src/internal.ts'; import { invariants } from './invariants.ts'; import { collect, deferred } from './room.ts'; import { diff --git a/packages/ambion/test/support/storage.ts b/packages/ambion/test/support/storage.ts index 3614da5..309078b 100644 --- a/packages/ambion/test/support/storage.ts +++ b/packages/ambion/test/support/storage.ts @@ -24,7 +24,7 @@ import { sessionsOver, sqliteSessions, type WorkspaceBackend, -} from '../../src/index.ts'; +} from '../../src/internal.ts'; export interface OpenedStorage { readonly sessions: SessionOpener; diff --git a/packages/ambion/test/support/transport.ts b/packages/ambion/test/support/transport.ts index ac1bff4..a74eb63 100644 --- a/packages/ambion/test/support/transport.ts +++ b/packages/ambion/test/support/transport.ts @@ -2,8 +2,8 @@ * Transports for the tests: one that proves every request and response is * plain JSON, and one that loses, repeats or delays them on purpose. */ -import type { Clock, RunningRoom, SeatPort, Transport } from '../../src/index.ts'; -import { assertWire, roundTrip } from '../../src/index.ts'; +import type { Clock, RunningRoom, SeatPort, Transport } from '../../src/internal.ts'; +import { assertWire, roundTrip } from '../../src/internal.ts'; export interface SerializingTransport extends Transport { /** Every value that would not have survived the wire. Empty when the design holds. */ diff --git a/packages/ambion/test/wire.test.ts b/packages/ambion/test/wire.test.ts index 817cd39..02d9de6 100644 --- a/packages/ambion/test/wire.test.ts +++ b/packages/ambion/test/wire.test.ts @@ -17,7 +17,7 @@ import { roundTrip, type ViewResponse, type Wake, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { fakeClock } from './support/clock.ts'; import { roomName, rowsOf } from './support/room.ts'; import { oneExchange } from './support/scenarios.ts'; diff --git a/packages/ambion/test/workspace.test.ts b/packages/ambion/test/workspace.test.ts index bb5bd24..9541139 100644 --- a/packages/ambion/test/workspace.test.ts +++ b/packages/ambion/test/workspace.test.ts @@ -20,7 +20,7 @@ import { stopSession, type ToolContext, type WorkspaceBackend, -} from '../src/index.ts'; +} from '../src/internal.ts'; import { BashEnv, DEFAULT_TIMEOUT_SECONDS } from '../src/tools/bash-env.ts'; import { MEMORY_LIMIT_BYTES, memoryBackend } from '../src/tools/just-bash.ts'; import { assistant, enter, roomName as name } from './support/room.ts'; diff --git a/packages/ambion/tsdown.config.ts b/packages/ambion/tsdown.config.ts index d8aebc7..5761ed2 100644 --- a/packages/ambion/tsdown.config.ts +++ b/packages/ambion/tsdown.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from 'tsdown'; export default defineConfig({ - entry: ['src/index.ts'], + entry: ['src/index.ts', 'src/host.ts', 'src/protocol.ts', 'src/node.ts'], format: ['esm'], dts: true, clean: true, diff --git a/packages/cli/src/main.ts b/packages/cli/src/main.ts index f3220e8..1e30593 100644 --- a/packages/cli/src/main.ts +++ b/packages/cli/src/main.ts @@ -5,9 +5,10 @@ * Importing PACKAGE_NAME is the point: it proves turbo built the runtime first * and that the CLI resolved it across the workspace. */ -import { PACKAGE_NAME } from '@ambionframework/ambion'; import { cliVersion } from './lib/version.ts'; +const PACKAGE_NAME = '@ambionframework/ambion'; + function help(version: string): string { return [ `ambion ${version}`, diff --git a/packages/cloudflare/src/configure.ts b/packages/cloudflare/src/configure.ts index 7f33039..1c4bf45 100644 --- a/packages/cloudflare/src/configure.ts +++ b/packages/cloudflare/src/configure.ts @@ -3,13 +3,9 @@ * by name, and the model call they make. A worker configures it once at * module scope, and every object in the isolate reads it. */ -import type { - AgentDefinition, - CreateRuntimeOptions, - Runtime, - SessionEvent, -} from '@ambionframework/ambion'; -import { createRuntime } from '@ambionframework/ambion'; +import type { CreateRuntimeOptions, Runtime } from '@ambionframework/ambion/host'; +import type { AgentDefinition, SessionEvent } from '@ambionframework/ambion'; +import { createRuntime } from '@ambionframework/ambion/host'; /** * One event a seat raised inside its own object, flat enough to be a log diff --git a/packages/cloudflare/src/room-object.ts b/packages/cloudflare/src/room-object.ts index 5db4972..a4f6789 100644 --- a/packages/cloudflare/src/room-object.ts +++ b/packages/cloudflare/src/room-object.ts @@ -6,31 +6,17 @@ */ import { DurableObject } from 'cloudflare:workers'; +import type { Attention, Message, SeatInfo, Seq, Session } from '@ambionframework/ambion'; +import type { Clock, RunningRoom, Runtime, Transport, Visit } from '@ambionframework/ambion/host'; import type { - Attention, - Clock, Commit, CommitResponse, Lease, LeaseResponse, - Message, - RunningRoom, - Runtime, - SeatInfo, - Seq, - Session, - Transport, ViewResponse, - Visit, -} from '@ambionframework/ambion'; -import { - defineHuman, - resumeSession, - seated, - startSession, - stopSession, - visitSession, -} from '@ambionframework/ambion'; +} from '@ambionframework/ambion/protocol'; +import { resumeSession, seated, stopSession, visitSession } from '@ambionframework/ambion/host'; +import { defineHuman, startSession } from '@ambionframework/ambion'; import { definitionOf, runtimeFor } from './configure.ts'; import type { SeatObject } from './seat-object.ts'; import { sqlSessions } from './storage.ts'; diff --git a/packages/cloudflare/src/seat-object.ts b/packages/cloudflare/src/seat-object.ts index f600429..abfa8be 100644 --- a/packages/cloudflare/src/seat-object.ts +++ b/packages/cloudflare/src/seat-object.ts @@ -8,8 +8,9 @@ */ import { DurableObject } from 'cloudflare:workers'; -import type { SeatRoom, SessionEvent, Wake } from '@ambionframework/ambion'; -import { SeatActor, systemClock } from '@ambionframework/ambion'; +import type { SessionEvent } from '@ambionframework/ambion'; +import { createSeatActor, systemClock } from '@ambionframework/ambion/host'; +import type { SeatRoom, Wake } from '@ambionframework/ambion/protocol'; import type { SeatEvent } from './configure.ts'; import { runtimeFor, seatEvent } from './configure.ts'; import type { Env } from './room-object.ts'; @@ -41,7 +42,7 @@ function seatLine(room: string, seat: string, activation: string, event: Session } export class SeatObject extends DurableObject { - private actor: SeatActor | undefined; + private actor: ReturnType | undefined; /** * A wake for the activation the object holds, or for a fresh one when it @@ -113,7 +114,7 @@ export class SeatObject extends DurableObject { } await this.ctx.storage.put('phase', 'running'); const runtime = runtimeFor({ sessions: sqlSessions(this.ctx), clock: systemClock() }); - this.actor = new SeatActor(seatRoom, { + this.actor = createSeatActor(seatRoom, { clock: runtime.clock, catalog: runtime.catalog, room, diff --git a/packages/cloudflare/src/storage.ts b/packages/cloudflare/src/storage.ts index 51512c4..eca73fe 100644 --- a/packages/cloudflare/src/storage.ts +++ b/packages/cloudflare/src/storage.ts @@ -3,8 +3,8 @@ * owns the schema and every statement (`sqliteSessions`); this file wraps * `ctx.storage.sql` in the two calls the core makes. */ -import type { SessionOpener, Sql, SqlValue } from '@ambionframework/ambion'; -import { sqliteSessions } from '@ambionframework/ambion'; +import type { SessionOpener, Sql, SqlValue } from '@ambionframework/ambion/host'; +import { sqliteSessions } from '@ambionframework/ambion/host'; /** The object's SQLite as the core reaches it. */ export function sqlOver(storage: SqlStorage): Sql { diff --git a/packages/cloudflare/test/restart.test.ts b/packages/cloudflare/test/restart.test.ts index f68854d..13668da 100644 --- a/packages/cloudflare/test/restart.test.ts +++ b/packages/cloudflare/test/restart.test.ts @@ -8,8 +8,8 @@ * and serves the same activation, so the work in flight is not lost. */ import { env, runInDurableObject } from 'cloudflare:test'; -import type { LeaseRow, RunRow } from '@ambionframework/ambion'; -import { isSpoken } from '@ambionframework/ambion'; +import { isSpoken } from '@ambionframework/ambion/host'; +import type { LeaseRow, RunRow } from '@ambionframework/ambion/protocol'; import { expect, it } from 'vitest'; import { sqlSessions } from '../src/storage.ts'; import { until } from './until.ts'; diff --git a/packages/cloudflare/test/room.test.ts b/packages/cloudflare/test/room.test.ts index 5c4c7de..1146dbc 100644 --- a/packages/cloudflare/test/room.test.ts +++ b/packages/cloudflare/test/room.test.ts @@ -3,7 +3,8 @@ * repeated delivery key once. */ import { env, runInDurableObject } from 'cloudflare:test'; -import type { Message, RunRow } from '@ambionframework/ambion'; +import type { Message } from '@ambionframework/ambion'; +import type { RunRow } from '@ambionframework/ambion/protocol'; import { expect, it } from 'vitest'; import { sqlSessions } from '../src/storage.ts'; import { until } from './until.ts'; diff --git a/packages/cloudflare/test/seat.test.ts b/packages/cloudflare/test/seat.test.ts index b58c5f5..d63a614 100644 --- a/packages/cloudflare/test/seat.test.ts +++ b/packages/cloudflare/test/seat.test.ts @@ -6,7 +6,8 @@ */ import { env, runDurableObjectAlarm, runInDurableObject } from 'cloudflare:test'; -import type { LeaseRow, Message } from '@ambionframework/ambion'; +import type { Message } from '@ambionframework/ambion'; +import type { LeaseRow } from '@ambionframework/ambion/protocol'; import { expect, it } from 'vitest'; import { sqlSessions } from '../src/storage.ts'; import { until } from './until.ts'; diff --git a/packages/cloudflare/test/storage.test.ts b/packages/cloudflare/test/storage.test.ts index 4b1f84c..4985f12 100644 --- a/packages/cloudflare/test/storage.test.ts +++ b/packages/cloudflare/test/storage.test.ts @@ -5,7 +5,7 @@ */ import { env, runInDurableObject } from 'cloudflare:test'; -import { assertWire, roundTrip } from '@ambionframework/ambion'; +import { assertWire, roundTrip } from '@ambionframework/ambion/protocol'; import { expect, it } from 'vitest'; import { sqlSessions } from '../src/storage.ts';