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

@pstdio/sdk

v0.39.0

Published

The public TypeScript SDK for Prompt Studio. It provides extension contracts, the HTTP client, and prompt helpers. The package is ESM-only; import a declared subpath.

Readme

@pstdio/sdk

The public TypeScript SDK for Prompt Studio. It provides extension contracts, the HTTP client, and prompt helpers. The package is ESM-only; import a declared subpath.

bun add @pstdio/sdk

| Entry point | Purpose | | --- | --- | | @pstdio/sdk/extensions | Contributions, typed refs, commands, storage contracts, and webview clients | | @pstdio/sdk/extensions/react | React query and mutation hooks for webviews | | @pstdio/sdk/client | HTTP client | | @pstdio/sdk/api | API request and response types | | @pstdio/sdk/resources | Product resource types | | @pstdio/sdk/prompts | Prompt rendering | | @pstdio/sdk/hooks | Hook API contracts | | @pstdio/sdk/data | Draft layout, frontmatter, and ID/name resolution helpers | | @pstdio/sdk/testing | Command contexts and in-memory adapters for extension tests |

Native extension entries work without React. The React entry requires its declared React and TanStack Query peers. Public declarations include their private contract dependencies and support skipLibCheck: false outside the repository.

Build an extension

Start with the workbench cookbook and Extension Lab. Existing examples cover saved edits, inspectors, shared panels, custom modes, provider refs, and webview cleanup.

Keep package identity in package.json. Export defineExtension(...) from the manifest's main. Install through pst extensions dev <path> from a linked project. The same workflow watches native TypeScript, contribution declarations, and webview assets.

A view supplies content. A page owns its route, routed resource, and page panels. A mode supplies shared panels and chrome. Use ResourceRef with type, id, and optional label across these contracts. Main, Side, and Secondary are the panel regions.

A page declares resource: { kinds } separately from main. Main can show a view or a collection of peer panels with an empty view. Additional slots expose generated refs such as page.panels.inspector. Slots and mode placements share the same static-view or resource-binding item union.

Page targets change location. Panel targets preserve it. Compound targets contain only page and panel steps, prepared before one commit. Commands and external links remain standalone actions. Omitted mode chrome retains host navigation for custom modes too.

Use qualifyRef(owner, ref) in provider contract modules. Keep definitions local and pass qualified refs between extensions. For webviews, declare capabilities and call the typed GuestHost; placement.close closes the calling placement through the normal tab controller.

Workspace creation

Workspace creation belongs to the host. Use ctx.workspaces.listProviders() to check whether additional workspaces can be created. The existing project workspace is returned separately by ctx.workspaces.getDefault().

A tree action can call the public host command workbench.workspace.create:

const createWorkspace = commandRef<CreateWorkspaceCommandParams>({
  extensionId: "pstdio",
  id: "workbench.workspace.create",
});

It accepts optional anchors and shorthand_base parameters. The host shows the available providers and their declared inputs, then creates the workspace with those resource links. Provider parameters stay nested and are passed unchanged. Cloud providers do not need Git or a local directory; creation may return while provisioning is still running.

For programmatic creation, call ctx.workspaces.create() with an explicit provider_id and provider params.

Dashboard URLs

Use serializePageUrl({ projectId, page, resource }) to return a dashboard link from a command. The page descriptor contains its id, qualified ref, and declared path; resource is optional. The workbench uses the same route and resource codec.

Use parsePageUrl({ url, projectId, pages }) to resolve a saved link against the expected project and allowed page descriptors. It accepts root-relative URLs and returns a page ID and optional resource, or undefined for an unsupported destination. It never fetches the URL. The caller still checks its supported resource kind and owner. A URL grants no access.

Page and panel navigation targets remain the API for opening views and tabs.

Webview change subscriptions

To run webview commands in a selected workspace, pass { workspaceId } to createWebviewClient(host, options). Without that option, commands use the project's default workspace. The host resolves the workspace target and checks project ownership. The low-level commands.execute bridge accepts the same workspaceId field.

Use the typed client's events.subscribe(event, listener) to refetch after a command changes data:

const client = createWebviewClient<typeof commands>(host);
const stop = client.events.subscribe(
  { kind: "event", id: "notes.changed" },
  () => void reloadNotes(),
);
// Dispose when the view unmounts.
stop();

Local event refs use the client's extension owner: { kind: "event", id: "notes.changed" } resolves to <extensionId>.event.notes.changed. Qualified event refs can name another extension in the same project. String IDs are already resolved and stay unchanged. Host-owned and command-lifecycle refs follow the runtime's rules through the shared resolveEventReferenceId helper. Commands emit events after committing their changes through ctx.events.emit.

The host delivers only events matching the view's project. Projectless events reach global views only. Listeners also run when host sync connects or reconnects, so a mounted view can reconcile missed changes. Load current data when mounting, then subscribe; events are invalidations, not stored records or an exactly-once stream. Duplicate refetches must be safe. The subscription does not reload the webview document or grant new permissions.

Package delivery

Development and installed consumers both load built SDK entries. Repository development builds this package before starting the source CLI. Builds stage release files under .publish through the shared release script. Package verification installs those same staged artifacts into a temporary directory outside the monorepo and checks every entry point.

Host authors should use the workbench guide. Extension authors should use this SDK and public UI packages.

Workspace contracts

The host opens one folder per project and uses workspace APIs for execution and files. Use ctx.projectFiles for the project's default workspace and ctx.workspaceFiles for the invocation's working files. Project file operations check the current workspace readiness and file capabilities. Remote workspaces never fall back to local files.

ctx.workspaces.getDefault() returns the project workspace. ctx.workspaces.listProviders() returns available providers, their optional icon, and their parameters. Render these declared parameters after the user selects a workspace type. The Git provider supplies a Base branch selection; cloud providers supply their own fields. A command that creates a workspace can declare params.workspace({ providers }). The dashboard then renders this same form, and the command receives { providerId, params }. Local setup failures reject creation with the saved workspace ID and setup error. The workspace remains available for diagnosis and retry. Workspace context records expose root_path for a local directory. Remote workspaces have no local root.

The SDK client exposes client.workspaces.listProviders(projectId) and client.filesystem.createDirectory({ parent_path, name }). Directory creation accepts one child name under an existing parent.

Webviews can set workspaceId in createWebviewClient(host, { workspaceId }) to run commands in that workspace. The host validates project ownership.

EXTENSION_API_VERSION is the current host API version, such as 0.1.0. Declare a caret range in engines.pstdio, such as ^0.1.0, so the extension keeps loading across additive host releases. Raise the minimum only when the extension uses a newer API. On 0.x, a new minor is a breaking release. See API versioning.