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

@speles7172/ai-console

v0.2.1

Published

React UI for the AI module — a Bedrock model picker per AI flow, and the grammar and translation assistants, over a transport you supply.

Downloads

405

Readme

@speles7172/ai-console

The two faces of the AI module, in React.

<AiModelsConsole> is what an administrator sees: one row per AI flow, each pointed at a model chosen from the whole live Bedrock catalog, changeable without a deploy. <AiAssistPanel> is what everybody else sees: ask, read, accept or discard — for correcting a draft and for translating one.

npm install @speles7172/ai-console

React 18 or 19. Browser-only, and it calls nothing itself: the consuming application exposes endpoints backed by @speles7172/ai-client and supplies a transport.

The settings page

import { AiModelsConsole } from '@speles7172/ai-console';
import '@speles7172/ai-console/styles.css';

// Module scope, not inline in JSX — see below.
const transport = {
  settings: () => fetch('/api/ai/settings').then((r) => r.json()),
  models: () => fetch('/api/ai/models').then((r) => r.json()),
  save: (body) =>
    fetch('/api/ai/settings', { method: 'PUT', body: JSON.stringify(body) }).then(() => undefined),
  saveTone: (body) =>
    fetch('/api/ai/tone', { method: 'PUT', body: JSON.stringify(body) }).then(() => undefined),
};

<AiModelsConsole transport={transport} />;

Every capability is optional and inferred from the transport: no save, and the page is a read-only view of what is configured; no saveTone, and there is no tone row. A button that always fails is worse than no button.

The assistant

import { AiAssistPanel } from '@speles7172/ai-console';

const [draft, setDraft] = useState('');

<textarea value={draft} onChange={(event) => setDraft(event.target.value)} />
<AiAssistPanel transport={transport} text={draft} onAccept={setDraft} context={thread} />

It never edits the draft. The host owns the text, the panel asks for a suggestion, and applying one is an explicit click — which is what lets the same component sit behind a message composer, a description field and a document editor without knowing anything about any of them.

The endpoints behind it

Four, and each one is a seam worth thinking about:

| Method | Backed by | |---|---| | settings() | the feature registry plus the stored model per flow | | models() | listBedrockModels() | | save({ feature, modelId }) | writing AI_MODEL_<FEATURE> | | correctGrammar / translate | ai.correctGrammar / ai.translate |

Put the first three behind whatever your application means by "administrator", and the assistants behind whatever it means by "may use AI". This package applies no access control of its own, deliberately — the same stance audit-client and file-client take. Note what crosses the seam: a feature key and a model id, never a prompt template and never a model invoked directly, so a page cannot be talked into spending a Bedrock budget on something else.

Without the markup

useAiModels and useAiAssist are the state without any of it — the two-speed load, the reload-after-write, the race guards, the error handling — for an application with its own design system.

Styling

The components render aic- class names and no styling dependency. The stylesheet is optional, driven entirely by custom properties on .aic, and includes @speles7172/controls' own because every picker here is one of its controls. theme is light (the default), dark or auto.

Traps

The transport must be identity-stable. Both components key their effects on it, so an object literal written inline in JSX is a new transport on every render and therefore an endless reload. Module constant, or useMemo. Same rule every console in this repository follows.

A flow following its default is not pre-filled with that default. Showing the effective value in the box looks identical to a value somebody set, and saving it turns "follows the default" into "pinned to today's default" — silently detaching the setting from a default the next release was going to change. The row says which it is instead.

The model picker takes a typed id. The catalog is a convenience, not the permitted set: a model id copied from the AWS console, or an application inference profile ARN — which no list call ever returns — must be enterable, and a configured value the catalog does not know is kept selected rather than rendered as an empty box.

The catalog loads separately from the settings, on purpose. The settings are one row per flow and arrive immediately; the catalog is two Bedrock control-plane calls and does not. Waiting for both would leave the page blank for a second to populate a dropdown nobody has opened yet — and a catalog that fails costs the suggestions, not the page.

A suggestion is dropped the moment the draft changes under it. A suggestion for a draft that has since been edited is a suggestion for a different draft, and accepting it would silently discard whatever was typed in between.

Licence

MIT.