npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@alma-harness/conversation

v0.12.0

Published

Governed buffered and settled-step streaming conversations for Alma.

Readme

@alma-harness/conversation

Governed buffered and settled-step streaming conversations. Use matching core, execution, loop and single-call packages. createConversationRunner(config) composes durable session admission, operation roots, governed model steps and final result storage. It is the sole conversation entrypoint; the standalone agent and its legacy lease/claim, streaming and financial writers have been removed (spec: retire-legacy-conversation-engine).

Supply step: GovernedStepConfig, admissions, rootResults, sessions, ordinary agent prompt/policy/tools/profiles/hooks/media/recall options, caps, prices, policyVersion, priceVersion, configRevision, resultContractVersion, resultRetentionMs, runTimeoutMs, maxCalls, maxInputChars and consumers. runTimeoutMs is at most five minutes. Clients must be single-dispatch. Ordinary configuration is copied; store/client/policy/schema implementations and revision mappings are trusted host capabilities. Tools use ConversationTool and receive ConversationToolCtx, including models.direct({tier,sensitivity,prompt}) for a single tool-free child call, and the narrowing models.delegate gateway.

runTurn({scope,sessionId,idempotencyKey,input,intent,trigger?,toolProfile?,signal?}) accepts an inline user Msg and a required stable delivery key. It snapshots bounded plain JSON before I/O and derives scoped root identity and input/config bindings. Retries return original outcomes without renewing deadlines or dispatching again; changed content/options/config conflicts. Use immutable media references, not inline wire content. Host configuration revisions must cover all behavior, and referenced media bytes must remain bound to the original request. Undefined optional object fields are omitted; arrays remain ordered. Non-JSON/accessor/cyclic/oversized input is rejected before admission. The canonical payload ceiling includes 4 KiB metadata overhead in addition to maxInputChars; traversal is bounded at 64 levels/100k nodes.

conversationRootKey(scope,sessionId,idempotencyKey) lets a host call read without loading content. createConversationDescriptor(config,input,deadlineAt) is a pure helper for explicit hosts interoperating with simple requests. runTurn also accepts existing explicit input. Its reserved conversation-v1 identities use the same narrow clock-race rule: differing proposed deadlines reuse the first descriptor only if all other bindings match. This is a trusted-host convention, not proof of hashed content. Arbitrary explicit roots keep exact binding semantics. Generic or lost claim ACKs never grant ownership. Input signal is execution cancellation, not a socket signal.

The legacy run method is removed (spec: canonical-conversation-api-cutover). Use runTurn for both simple and explicit input. It always returns a Promise; invalid input rejects that promise and can be handled with .catch(). Input normalization and snapshot happen immediately during the call, before any await. Constructor and streamTurn validation remain synchronous. @alma-harness/runtime/memory and /postgres provide storage composition.

Canonical APIs first observe the scoped admission and compare original bindings. Matching retries never resolve policy again. For unseen work, policy.resolve must be synchronous, pure and bounded: it receives only a copied RoutingIntent, including task. A throw or absent selected client returns {status:"not_admitted",reason:"routing_unavailable"} before any claim, context, hook, provider validation or financial write. A final admission read takes precedence if a matching competitor became visible; conflicts still reject. Lookup failure or cancellation never claims a routing refusal.

This refusal is not durable and describes this invocation, not global absence. read returns null for an unadmitted key and may observe a later competing claim. Fix the configuration with a new configRevision before retrying; do not retry a configuration refusal automatically. No receipt or session release is fabricated. Successful validation snapshots the complete main choice for all main steps; summary/direct/delegate routing remains independent. Post-admission uncertainty still retains occupancy, including pre-existing failed admissions.

Settled-step streaming

streamTurn(input) accepts the same input as runTurn and starts the same engine eagerly. It returns one async iterator and an independent result promise:

const stream = runner.streamTurn(input);
try {
  for await (const event of stream) {
    if (event.type === "text") showProgress(event.step, event.text);
    if (event.type === "result") showStatus(event.view.status);
  }
} catch (error) {
  if (!(error instanceof ConversationStreamResyncError)) throw error;
  // Resynchronize using runner.read(scope, originalRootKey).
} finally {
  const view = await stream.result; // Worker completion is independent of the reader.
}

Import ConversationStreamResyncError from this package. Text spans arrive in main-step block order only after settlement and fresh authorization; there are no provider-token deltas. A preamble may be visible before a later tool failure, cap stop or uncertain root. Progress is not final completion and concatenated progress is not generally the final reply. Final-message channels should use runTurn.

Progress tool/provider events contain metadata only; reasoning and child output are withheld. Usage events are original main-call receipts; child costs can make the final total larger than their sum. The terminal result event preserves the existing host-facing ConversationView, including authorized tool/provider blocks in its reply. Chat renderers select text blocks rather than serializing the envelope. Fresh root authorization precedes final delivery and preserves owner/replay flags.

Break, return, throw and socket closure detach only the reader. Keep the worker alive and await result separately; never wire socket close to input.signal. Only that execution signal/deadline cancels execution. Detach is not durable background scheduling, and uncertain execution still requires reconciliation.

Each stream permits one iterator and one pending next. Queues hold references, not output, with limits of 128 references and 256 KiB metadata. Overflow, erased/ expired/denied step output or a failed authorization read detach with typed reasons overflow, unavailable, or read_failed. Reconnect through read; there is no durable intermediate replay. A late first iterator after result settlement receives only a freshly authorized final view, unless already overflowed. That view may be unavailable after erasure even if the earlier result promise completed. Detached iterators cannot reattach, and pending store reads cannot deliver late events.

runTurn({root,intent,loadInput,trigger?,toolProfile?,signal?}) requires the root's closed request descriptor. Its configuration/output versions and retention must match construction, caps must match, maxCalls may narrow, and the declared root sensitivity must equal the intent. The host assigns inputRevision to the complete immutable request, including profile/trigger/intent. Changed metadata conflicts before content access; never accept browser/model identities as authority. The root ID is the turn ID; only the runner allocates child slots, IDs and parents.

Admission, root claim and pending final-result reservation precede loadInput, hooks, recall, history and media. Busy/replayed requests run nothing. Successful steps expose usable output only behind governed receipts. Main, direct, delegate and cold-start summary calls share the root; inclusive totals are not new charges. Explicit warn caps preserve results. Numeric/explicit block caps retain their stopping behavior, including zero-cost preflight refusal. The legacy SpendStore.add and AuditLog.cost writers are never called by this runner.

Final results and deployment

rootResults MUST be physically separate from step.results. For PostgreSQL, create a dedicated schema and pool whose search_path resolves only that schema, then use migrateExecutionResultStore/PostgresExecutionResultStore there. Configure the same scoped roles and grant schema USAGE. Object inequality is checked but cannot prove database isolation: two adapters pointing to the same table are an invalid host composition. Final IDs are scoped root keys in this namespace; no billable call or ordinal is fabricated. Do not use untrusted search_path entries.

Deploy all execution/accounting/admission migrations before the matching readers. Register both result namespaces and sessions in host erasure/retention workflows; createMemoryErasure's single results handle alone cannot cover both. Erasure or expiry of completed output returns unavailable and never regenerates content. Provider live smokes, publication and product delivery are separate evidence.

Completion and reconciliation

The result is a status view: completed with a TurnResult, busy with a root key, in_progress, reconciliation_required, unavailable, or a non-durable not_admitted routing refusal. read(scope,key) rechecks admission, closed root, financial completion and authorized final content. It does not dispatch, repair effects or load conversation context. Replays retain original usage/cost and mark replayed: true; do not add them to new spend. Root warnings are historical deduplicated evidence; notification delivery is a host concern.

Normal completion awaits handlers/children, append and turn:end, closes the root, persists and rechecks the final envelope, then finishes admission. A lost finish ACK is accepted only after reading back matching owner release, never operator resolution. Other uncertain writes, failures, cancellation and timeouts retain occupancy for explicit operator reconciliation. Available content alone is not proof of session/effect completion. No runner path calls resolve or retries append. If the public timeout races with an already-started finish after all work is quiescent, that finish may commit later; a subsequent read can verify completion. This exception never authorizes a finish after an earlier uncertain operation.

Handlers MUST await all external work. The harness tracks started model children, poisons swallowed child failures, and revokes gateways after each handler settles; it cannot discover arbitrary detached work hidden inside trusted host code. An ordinary handler rejection is uncertain even if labelled read-only. Hanging or failed context/hook work cannot authorize further effects. Timed-out dependencies may finish late; settlement evidence can drain in the background, but the turn never resumes automatically. Operators must reconcile effects/writes and establish quiescence before resolution. Use the step runner's recovery APIs for accounting; that does not complete a conversation.

Governed output preserves cross-category block order and omits reasoning from the reply. Refusal/truncation obey the governed-step output contract. There is no token streaming or automatic reactive context-window retry. Cold-start rotation is supported; uncertain provider failures require reconciliation. Batch/routines, history import and channel delivery remain separate adoption work.

The full PostgreSQL-backed gate exercises deterministic conversation composition, separate result namespaces, durable replay/erasure and lost append acknowledgements. No Prumo tour scene is added here: its source budget is nearly full, and the new capability's executable acceptance path is packages/conversation/test. A tour integration needs a separate budget-preserving scene slice.

Tools can use ctx.models.tryDelegate to handle structural delegation refusals. Returning that exact invocation-local object emits an error tool result while the parent continues. A refusal is not evidence that the handler had no effects; throwing handlers, failed siblings, outstanding children and persistence failures still require reconciliation. The existing delegate method retains its throwing contract. S5 demonstrates explicit forwarding and settled parent/child accounting.

Safe context rotation

Cold rotation is unchanged. Reactive rotation requires a retained, authorized Anthropic pre-generation rejection plus its original zero call/root receipts. One summary and one replacement main call use new child identities under the same root/caps/deadline. Generic errors, ordinary zero usage, contradictory content, erased/expired proof, lost acknowledgements and cancellation cannot permit continuation. Earlier tools are never replayed. The OpenAI/OpenRouter parity exception remains for consolidated maintainer acceptance before cutover (spec: safe-context-rejection-rotation).

When an attested refusal finishes without another rotation (no policy, no removable head, or a second refusal), the view is completed, result.terminalReason is completed, result.stopReason is context_window_exceeded, and result.reply.blocks is empty. Hosts must inspect stopReason, not just the completed status: show a context-limit outcome instead of delivering a blank answer as success. This replaces the legacy typed, retryable window error. The same admitted key replays the original outcome; it does not retry the provider. A new attempt requires a deliberate host decision and an appropriate context change. Generic provider errors without attestation still require reconciliation.

The four product-visible differences (main-only progress usage, unpersisted input after a start-hook failure, withheld truncated tool closures, and completed context refusal) are enumerated for explicit owner acceptance in the review packet.

Private feature tests exercise volatile context, reasoning persistence and parent/delegate request-control isolation through this canonical API. Scripted usage remains explicit; missing evidence is never converted into a free call.

Deferred and provider-tool integration tests use the same canonical fixture, including grant isolation, settled search receipts, pause continuation and uncertainty when a search cannot be priced.

Media/wire tests also cover explicit lazy inline input, reference-only simple input, history replay and truncation suppression with retained receipts.

Financial feature tests pin requested versus served tier pricing, root warning attribution, sibling blocks and rejection of the removed per-turn override surface.

Output/text feature tests preserve tool ceilings and redaction, measured recall, Unicode repair for tools, invalid provider-text refusal and owning reply identity.

Recall feature tests distinguish normal content gating from source uncertainty, pre-admission cancellation and delegate sensitivity, with bounded timeout evidence.

Hook-boundary tests preserve request narrowing and shape-only trails, including retained uncertainty after sink failure or mutation of frozen hook input.

Recall uses the loop's single deadline with lifecycle-guarded source access. Cancellation clears the timer even if the source never settles; late source results cannot append, dispatch or release uncertain session ownership.

Basic engine feature tests cover schema/scope, profiles, nested grants and actual root/call correlation. Structural delegation refusals are explicit; execution failures retain uncertainty and suppress subsequent host lifecycle effects.

Construction rejects missing or noncallable spend readers. Persistent-cap tests use original governed receipts and counters, including tenant isolation and retained uncertainty when reads or settlement fail.

Lifecycle tests pin listener cleanup, frozen registration and awaited audit failures. A pre-aborted request is never admitted; a poisoned start hook leaves buffered input unpersisted. The final append is one user/assistant batch. Failure views withhold private errors and partial replies while original known receipts remain readable.

Final integration parity covers complete replay snapshots, daily budget-stop replay, no TTL takeover, main-only steps and duration before end hooks, cold summary history, and documented settled-stream consumption. The test ledger maps all remaining legacy cases and their explicitly superseded contracts.

Malformed cap configuration rejects with TypeError from the canonical financial normalizer, replacing legacy AgentConfigError. Invalid path scope rejects with InvalidScopeError before admission. Neither error authorizes execution.

Tool selection remains host-owned at the model-request boundary. The governed step projection retains toolChoice in execution controls, while step:pre cannot inject or change it, on parent or delegated steps. No global conversation selection setting is added: one-call structured extraction uses the existing createGovernedStepRunner from @alma-harness/single-call without session append, recall or automatic memory extraction. The text-only ctx.models.direct gateway rejects a supplied toolChoice rather than discarding it; invalid child work retains the normal uncertain lifecycle.