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

@polycrestlabs/agentkit-ui

v0.4.1

Published

The AgentKit conversation UI kit for Angular: the v2 frame vocabulary (loaded/token/tool/question/questionForm/followups/citation/usage/heartbeat/message/done/error), the agent-turn state machine with an ordered rich timeline and durable hydration, and th

Readme

@polycrestlabs/agentkit-ui

The AgentKit conversation UI kit for Angular — the UI half of the AgentKit library (one repo, one version, one CHANGELOG with the .NET half). 0.4.0 completes the extraction the 0.2.0 intake started: the full conversation surface (transcript, composer, question cards, proposal presentation, followup chips, streaming) ported from its most evolved sibling copies (the aws chat kit and vacadock's Ask lane) and restyled onto --agentkit-* tokens.

What's in the box

| Module | What it is | | --- | --- | | frames | The v2 core frame union: loaded · token · tool · question · questionForm · followups · citation · usage · heartbeat · message · done · error, plus AgentFrameOf<TDomain> for host domain frames — mirrored 1:1 from the C# Wire/AgentFrames.cs and conformance-tested against protocol/fixtures/ | | sse | parseFrame / readSseStream / httpErrorMessage — the fetch+SSE plumbing (hardened: object-only payloads, event-name guard, the event name is the sole discriminant) | | turn-state | AgentTurnState v2 — the ordered rich timeline (messages, durable question/form cards, domain entries), streamingText/activeTool/followups/citations/usage, hydrate() from host persistence, capability-gated stop(), liveness (working, dead-air), refusals, and the attachment upload-then-chip flow | | tokens | AGENT_TRANSPORT (required slot) and AGENT_CONFIRM (optional slot, package-owned default), plus the optional AgentChatCapable / AgentAttachmentCapable capabilities and AgentTransportCapabilities (serverCancel gates the visible Stop) | | components/ | <agent-chat-panel> (the assembled surface), <agent-transcript>, <agent-composer>, <agent-question-card>, <agent-proposal-card> + <agent-proposal-list> (presentation-only — proposals are host-domain data), <agent-followup-chips>, <agent-thinking>, and the *agentCard host-domain template directive | | testing/ | scriptedTransport(frames[][]) — the fixture-replaying stub transport; demos, specs and host prototyping run key-less against the real frame contract | | chat-rail | <agent-chat-rail> — the multi-chat list rail (list / new / delete-with-confirm / in-progress pulse); optional | | markdown.pipe | agentMarkdown — sanitizer-friendly markdown-to-HTML for assistant text |

Styling: one import, tokens only

The kit ships a single stylesheet driven entirely by --agentkit-* custom properties. Import it once in the host:

/* styles.css or a vendor layer */
@import '@polycrestlabs/agentkit-ui/styles.css';

Then map the tokens to your design system in one block (all have working light defaults):

:root {
  --agentkit-accent: var(--brand-primary);
  --agentkit-accent-strong: var(--brand-primary-strong);
  /* … */
}

Dark mode is opt-in only: set data-agentkit-theme="dark" on an ancestor. The kit never activates dark from prefers-color-scheme, so a light host cannot acquire an untested half-dark surface. Styling hooks are the stable agentkit-* classes and data-agentkit-part attributes — data-testid values are test API, never styling API.

The assembled surface

<agent-chat-panel [starters]="['What can you do?']">
  <!-- host domain cards project by frame type -->
  <ng-template agentCard="suggestion" let-data let-entry="entry">
    <my-suggestion-card [suggestion]="data" />
  </ng-template>
</agent-chat-panel>

agent-chat-panel injects AGENT_TRANSPORT, builds the turn state, and assembles transcript / chips / composer in a min-h-0 flex column (the transcript owns the scroll region; the composer is flex-pinned — never a calc(100vh-…) magic number). Hosts wanting different chrome compose the pieces directly and pass their own AgentTurnState.

Behavioral contracts baked in:

  • Followup chips prefill the composer and focus it — never auto-send.
  • message is the authoritative final text; streamed tokens are the fallback only when no message arrived before done.
  • Question cards are non-blocking: the stream ends normally; the answer is the next user turn; a later message locks earlier cards; hosts hydrate durable answers.
  • Stop renders only on a serverCancel transport and appends "Stopped." only after the server confirmed the cancellation. Quiet abort() remains teardown.
  • Scroll sticks to the bottom — never while the user scrolled up to read; a jump-to-latest button brings them back.
  • hydrate() preserves pending composer chips ON PURPOSE (an unsent upload survives a refresh) — so when hydrate means a different scope (another thread/job whose asset ids the chips cannot ride), the host must call clearPending() first, and should also call it on surface teardown: chip preview URLs live in the state machine, not the host.
  • Markdown renders model-controlled text. Angular's sanitizer strips scripts and event handlers, but <img src="https://…"> survives — a prompt-injected reply can beacon data out through an image URL with zero clicks. Serve a restrictive img-src CSP (or post-process the markdown) if that matters to your deployment.

The transport contract

The kit never sees routes, auth headers, or wire bodies. A host implements the minimal required core against its own /api/* routes:

interface AgentTransport<TFrame extends { type: string }> {
  streamTurn(body: AgentTurnBody, onFrame: (frame: TFrame) => void, signal?: AbortSignal): Promise<void>;
  capabilities?: { serverCancel?: boolean };
  cancelTurn?(): Promise<void>; // required when serverCancel — must actually cancel server work
}

Rules a transport must follow:

  • The transport owns the wire body. The kit hands it the composed turn ({ text, attachmentAssetIds?, ...extras }); the transport maps that onto its route's shape.
  • Resolve when the stream closes; resolve QUIETLY when signal aborts — a caller hanging up is not a failure.
  • Reject with AgentTurnRefusal(message, status) for non-SSE refusals — the state machine maps 409 to the busy line and 503 to the latched unavailable signal. Build the message with httpErrorMessage(response, fallback).
  • Advertise serverCancel only when abort genuinely cancels server-side turn execution (and implement cancelTurn). Without it no Stop control ever renders.

Chat CRUD (AgentChatCapable) and attachment upload (AgentAttachmentCapable) are optional capabilities a transport may also implement. Asset ids are strings — hosts choose their own identity scheme.

The frame vocabulary (v2)

One kit-owned wire protocol, defined in this repo and spoken by both halves. The SSE event: name is the sole discriminant; payloads are single-line JSON objects that never repeat it. The canonical fixtures live in ../protocol/fixtures/ and are conformance-tested from both C# (round-trip) and TS (parse) — drift on either side fails CI.

| Frame | Payload | Semantics | | --- | --- | --- | | loaded | turnId, provider, model | Always first; informational | | token | delta | Streamed assistant text (live streamingText) | | tool | name, phase, label? | Tool activity pill; label is server-supplied | | question / questionForm | question / form | Non-blocking question cards; durable | | followups | prompts[] | Ephemeral chips; prefill, never auto-send | | citation | title?, url? | Deduped citations footer | | usage | inputTokens?, outputTokens? | Optional usage line | | heartbeat | seq | Liveness only — never rendered | | message | text | Authoritative final text, after host finalization | | done | turnId, title? | Terminal success — never before the host commit | | error | code, detail?, turnId? | Stable code; detail only when explicitly safe |

A healthy turn always ends with message + done or error. The state machine treats silence as failure: any frame resets the dead-air timer (default 90 s, configurable via AgentTurnStateOptions.deadAirMs); starvation transitions to the error state exactly once and hangs up. Unknown frame types fall through to onDomainFrame — never an error.

Build & test

npm ci
npm run build   # ng-packagr → dist/ (styles.css ships as a package asset)
npm test        # vitest + jsdom (+ the Angular compiler plugin for component specs)

Angular (@angular/core, @angular/common ^22) and rxjs are peerDependencies — the kit never pins a host's Angular version.