pi-schema: opt-in coercion, compile(schema, { coerce: true }) with coerce() and
parse(), the superset of TypeBox's Value.Convert rules and pi-ai's old coercion;
unresolvedRefs option; url and json-pointer-uri-fragment formats.
pi-ai: Tool takes any JSON Schema; validation through pi-schema; Type, Static
and TSchema are no longer exported (breaking). pi-agent-core and pi-durable:
tools on pi-schema, no TypeBox dependency. Coding agent: extensions keep Type,
Static, TSchema and StringEnum through an extension view of pi-ai; built-in
tools stay on TypeBox.
Conversation.submit(tx, draft) and ConversationHandle.submit(tx, draft) run
the same admission inside the caller's commit and return the submission ID,
so a host's own checks and writes and the admission are stored together or
not at all. Admission must come before the commit's first table write, once
per commit, and throws ReadAfterWrite otherwise on every path. A first
argument that is not a draft is taken as a transaction; one of another
Session, or a wrapped one, is refused. The handle form also rejects once its
invocation is aborted. The pi.durable.submit span covers the admission only.
closes#11149
An input with whenIdle: "reject" is refused with the new ConversationIdle
when the conversation has no run, before any write, so it never starts a
run. With whenBusy: "steer" it steers the current run or is refused.
Request-ID deduplication runs first.