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

@episcloud/agent

v0.6.0

Published

EpisCloud coding agent SDK — typed tools, permissions, streaming, sub-agents, handoffs, guardrails, structured outputs.

Downloads

1,532

Readme

@episcloud/agent

A TypeScript SDK for building coding agents on top of the EpisCloud AI platform. Built for the same patterns developers know from other agent toolkits: a query() async generator, typed tool definitions backed by Zod, a permission system, hooks, and a streaming result protocol.

npm install @episcloud/agent

Node 20+ required.

Quick start

import { query } from '@episcloud/agent';

for await (const msg of query('Review src/auth.ts for OWASP issues', {
  apiKey: process.env.EPISCLOUD_API_KEY!,           // epis_sk_…
  allowedTools: ['Read', 'Glob', 'Grep'],           // read-only inspection
})) {
  if (msg.type === 'stream_event') process.stdout.write(msg.delta);
  if (msg.type === 'tool_use')      console.log('\n→', msg.name, msg.input);
  if (msg.type === 'result')        console.log('\n✓', msg.usage);
}

How it works

The SDK calls the EpisCloud Chat API (/v1/chat/completions) over HTTPS with your epis_sk_ Bearer token. Each tool the agent invokes is run inside your Node process — the SDK never executes anything server-side.

your code  ──►  @episcloud/agent  ──►  paas-ai.episcloud.com
                       │                       │
                       │                       ▼
                       │              ┌──────────────────┐
                       │              │  EpisCloud Chat  │
                       │              │  (auth + bill +  │
                       │              │   model loop)    │
                       │              └──────────────────┘
                       │
                       ▼ runs locally
              Read · Glob · Grep · Edit · Write · Bash · …

Built-in tools

| Tool | Purpose | Default permission | |--------------|------------------------------------------------------|--------------------| | Read | Read file with line offset / limit | allow | | Write | Create / overwrite a file | ask | | Edit | Replace exact string in an existing file | ask | | Glob | Match files by glob (src/**/*.ts) | allow | | Grep | Search regex across the working directory | allow | | Bash | Run a shell command | ask | | TodoWrite | Agent's internal multi-step task tracker | allow |

By default query() enables only the read-only set (Read, Glob, Grep, TodoWrite). Opt in to mutators explicitly:

query(prompt, {
  apiKey: '…',
  allowedTools: ['Read', 'Glob', 'Grep', 'Edit', 'Write', 'Bash'],
  permissions: { Bash: 'ask', Edit: 'allow', Write: 'allow' },
});

Custom tools

import { z } from 'zod';
import { tool, query } from '@episcloud/agent';

const dbQuery = tool({
  name: 'db_query',
  description: 'Run a read-only SQL query against the analytics DB',
  parameters: z.object({
    sql: z.string().describe('SELECT only — DDL/DML rejected'),
    limit: z.number().int().min(1).max(1000).default(100),
  }),
  defaultPermission: 'allow',
  async execute({ sql, limit }) {
    if (!/^\s*select/i.test(sql)) return 'error: only SELECT allowed';
    const rows = await runQuery(sql, limit);
    return JSON.stringify(rows);
  },
});

for await (const msg of query('How many sign-ups last week?', {
  apiKey: process.env.EPISCLOUD_API_KEY!,
  tools: [dbQuery],
})) {
  // …
}

Permission modes

Pass permissionMode to set a coarse policy that overrides per-tool defaults:

| Mode | Effect | |-----------------------|-------------------------------------------------------------------| | default | Honor each tool's defaultPermission + your permissions map | | acceptEdits | Auto-approve file-mutating tools (Write/Edit/MultiEdit) | | plan | Refuse every tool — model must produce a plan in prose | | bypassPermissions | Allow everything (CI / unattended only) |

When a tool is gated by ask, the SDK invokes your onToolApproval:

query(prompt, {
  apiKey: '…',
  onToolApproval: ({ name, input, description }) => {
    if (name === 'Bash' && /rm\s+-rf/.test((input as any).command)) {
      return 'deny';
    }
    return 'allow';
  },
});

Hooks

Hooks fire at lifecycle points and can observe, mutate, or block:

query(prompt, {
  apiKey: '…',
  hooks: {
    PreToolUse: ({ name }) => {
      if (name === 'Write') return { permission: 'deny', reason: 'frozen tree' };
      return {};
    },
    PostToolUse: ({ name, result }) => {
      metrics.record(name, result.length);
    },
    UserPromptSubmit: ({ prompt }) => ({
      prompt: prompt.replace(/<SECRET>/g, '[REDACTED]'),
    }),
  },
});

Available hooks:

  • PreToolUse — before a tool runs; can deny
  • PostToolUse — after a tool returns
  • UserPromptSubmit — before the user prompt reaches the model
  • Stop — when the agent decides to finalize; can force another turn
  • Notification — surface info/warn events to your UI

Cancellation & budgets

const ctrl = new AbortController();
setTimeout(() => ctrl.abort(), 30_000);   // hard 30s cap

const gen = query(prompt, {
  apiKey: '…',
  signal: ctrl.signal,
  maxTurns: 12,                            // tool-loop iteration cap
  maxCostMicroUSD: 100_000,                // $0.10 budget
  requestTimeoutMs: 60_000,                // per model call
});

for await (const msg of gen) {
  if (msg.type === 'result' && msg.subtype === 'cancelled') {
    console.log('partial result:', msg.result);
  }
}

Messages

query() yields a discriminated union (SDKMessage). Each message carries session_id. Branch on .type:

| Type | When | |----------------|-------------------------------------------------| | system | Once at start (resolved options, tool catalog) | | user | Echo of the prompt | | assistant | One per turn — text + tool calls | | tool_use | The agent invoked a tool | | tool_result | The tool returned (success or is_error=true) | | stream_event | Incremental text/reasoning chunk | | result | Final — has usage, duration_ms, result |

Error handling

import { InsufficientBalanceError, RateLimitError } from '@episcloud/agent';

try {
  for await (const msg of query(prompt, { apiKey: '…' })) { /* … */ }
} catch (err) {
  if (err instanceof InsufficientBalanceError) {
    promptUserToTopUp();
  } else if (err instanceof RateLimitError) {
    await sleep((err.retryAfterSec ?? 5) * 1000);
  } else {
    throw err;
  }
}

Typed errors: AuthenticationError, InsufficientBalanceError, RateLimitError, InvalidOptionsError, MaxTurnsExceededError, BudgetExceededError, ToolExecutionError, ToolDeniedError, TransportError.

CLI

npm install -g @episcloud/agent
episctl-agent run "refactor src/api/client.ts to use fetch"
episctl-agent chat          # interactive REPL

CLI looks for ~/.episcloud/agent-settings.json and the EPISCLOUD_API_KEY env var.

License

MIT