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

@felan-ai/agent-core

v0.12.0

Published

Portable Felan agent contracts and composition

Readme

@felan-ai/agent-core

Portable Felan agent contracts and the Node.js host runtime.

@felan-ai/agent-core is the portable composition layer between a Felan host and the pinned Pi packages. It is intended for applications and portable extensions, not as a complete end-user CLI.

import { HostAgentRuntime } from '@felan-ai/agent-core';

const runtime = new HostAgentRuntime(process.cwd(), {
  sessionStorageRoot: '/var/lib/felan/sessions/current',
  agentStorageRoot: '/var/lib/felan/agent',
  agentDir: '/etc/felan',
  pathAccess: 'host',
});
const result = await runtime.exec('node', ['--version']);

HostAgentRuntime uses its immutable cwd to resolve relative paths. The default pathAccess: 'workspace' contains ordinary file operations and process working directories to that cwd. pathAccess: 'host' permits any path available to the current user. Use exec(command, args) for literal argument boundaries and shell(command) only when shell parsing is intentional. File reads and writes use Uint8Array so binary content is preserved. Reads accept a maxBytes bound, and writes support exclusive creation for race-safe new files. listFiles supports recursive, glob-filtered traversal with ignored-directory, depth, and result-count bounds; host implementations enumerate one directory at a time rather than materializing an unbounded recursive scan. exec and shell accept an optional maxOutputBytes cap; capped results set truncated without turning normal command completion into cancellation.

Shell calls use the host's default shell unless they request the explicit shellFlavor: 'posix' option. POSIX hosts use /bin/sh; native Windows hosts validate and use a same-host Git Bash installation discovered through FELAN_POSIX_SHELL, PATH, or standard Git-for-Windows locations. The HostAgentRuntimeOptions.posixShell override is available to embedding hosts. The default Windows cmd.exe behavior is unchanged, and WSL is not selected automatically because its process and path namespace is separate from the host.

Every AgentRuntime exposes scoped storage through storage(scope). The default storage() handle is identical to storage('session') and belongs to one root session plus all of its subagents. Session storage is readable through ordinary runtime reads and shares a filesystem namespace with shell, allowing tools to return absolute output paths that regular agents can inspect.

storage('agent') holds longer-retention extension state owned by the runtime host. Host consumers provide exact sessionStorageRoot and agentStorageRoot paths; each storage handle preserves binary content, rejects lexical and symlink escapes, and cannot remove its root. Workspace path access excludes agent storage, while host path access lets ordinary operations inspect both storage scopes. Storage handles also support appendFile for host log files. Every runtime has a structured logger; hosts inject the destination. Runtimes may also expose an optional classifier capability. Its single classify(state, questions, signal) operation supports discriminated choice, bool, and score questions and answers. canEvaluate is an optional admission helper for bounded evidence packing, not a second inference operation. createPiClassifier(modelRuntime, model) delegates requests to Pi's native classify; hosts select an authenticated catalog model and own credentials. The bridge validates JSON-object state and answers, packs complete question sets against the existing byte budgets, and maps native usage metadata. Unknown catalog pricing is not reported as verified free inference. There is no owned HTTP client or environment-key discovery in Agent Core.

validateClassifierRequest and validateClassifierAnswers expose boundary checks to portable consumers, including custom classifier hosts. The explicit request validator requires JSON-object state and rejects functions, circular references, nonfinite numbers, accessors, and non-JSON objects. The existing bridge retains its JSON serialization behavior for programmatic callers. Reserved property names remain ordinary question IDs. The public Pi composition surface also exports ImageApi, ImageModel, AssistantImages, ImagesContext, and ImagesOptions; image feature behavior belongs in extensions, not AgentRuntime.

In classifier-enabled root sessions, Agent Core exposes the optional FelanExtensionAPI.turnClassification registry. Extensions register a unique producer ID and a prepare(input, context, signal) contribution during initialization, returning questions and optional JSON state or skipping the turn. Core captures one sanitized input.session snapshot, namespaces question IDs as producer:question and state as extensions[producer], and makes one logical classification call. Consumers await result(id, { prompt, imageCount }, context) in their before_agent_start handler; returned answers use their original keys. Questions are independent, so conditional branches must state their premises. Eligibility, thresholds, actions and fallbacks stay feature-owned.

The existing 2-second root budget covers preparation and inference, including custom classifiers. Invalid preparation is isolated; timeout or incomplete answers fail closed. Expansion supersedes an earlier prompt; continuation turns are not reclassified. Existing bridge byte budgets can split transport requests. Registration resets on reload; pending work is isolated per root session and cancelled on lifecycle/manual changes. Without composed root registration, extensions retain static guidance. Later explicit classifier calls remain outside this preflight. See classifier lifecycle.

collectClassifierSessionEvidence handles branch/compaction summaries, bounds conversation and tool metadata, omits images/raw thinking/tool-result bodies and redacts recognized credential patterns. Arbitrary secrets cannot be guaranteed safe. Additional producer state is also validated and redacted before dispatch.

The optional selectionAutomation service exposes temporary ownership and selection provenance. Workflow owners acquire a release callback; regular effort selection pauses until ownership releases. updateDefault: false model/thinking changes remain session-local and are distinguishable from manual choices, even across asynchronous transitions. Manual choices stay authoritative; stale release callbacks cannot clear a newer owner. Core owns this mechanism, not feature modes. onManualThinkingSelection observes explicit effort choices, including reselecting the current level. Composed sessions detect this at Pi's public setter boundary; implicit model-switch clamps and automated selections do not produce this signal.

Session composition accepts an optional dynamicThinking capability. When the runtime has a classifier, it starts eligible effort selection at input and applies it on before_agent_start, not queued follow-ups or tool continuations, without persisting the user's default. Eligible GPT-6 requests on official OpenAI or Codex Responses are classified only when the Codex extension is loaded; eligible Anthropic models use Pi's mid-conversation effort support. Explicit thinking changes take precedence for the remainder of the session. Absent the option or the classifier, composition does not enable this feature.

With an optional savings reporter, Agent Core reports a heuristic API-equivalent estimate for any supported model's automatic high → low or high → medium change when the run settles without tool failures and its first assistant response includes reasoning-token usage. It estimates 5% extra reasoning output at high, keeps observed input, cache and visible-output usage unchanged, and subtracts reported classifier cost. Missing classifier pricing leaves that overhead unknown; estimates are not a complete bill. No change, a return to high, other models/levels, missing usage, or a failed response produces no measurement. The unvalidated cross-model assumption and quality caveats are in the public benchmark notes.

Host runtimes expose optional persistent process operations for extensions that need incremental output and stdin. startShell() keeps process ownership in the runtime adapter and returns a bounded polling handle with write, terminate, interrupt, and dispose operations. startStdio() uses literal argv and exposes separate bounded stdout and stderr streams for protocols whose stdout must stay machine-readable. The optional privateRuntime.ensureDirectory() capability creates or validates owner-private short-lived coordination directories. The separate optional terminals capability allocates a real operating-system PTY with terminal input; adapters without PTY support omit that capability. The optional readAgentFile() boundary reads only inside the configured agentDir; ordinary runtime file operations follow the configured path access mode.

Host mode runs with the current user's filesystem and process permissions. It does not provide OS isolation or a sandbox boundary. Run untrusted workloads in an isolated runtime instead.

The package also composes Pi sessions with inline Felan extensions, optional explicitly supplied native Pi extension paths, and runtime-backed coding tools. createAgentCoreSession returns a headless, inactive session, while createAgentCoreSessionRuntimeFactory provides the typed seam used with Pi's createAgentSessionRuntime. Applications retain ownership of model credentials, settings, session storage, stream wrappers, feature extensions, and presentation listeners. FelanExtensionAPI adds the selected AgentRuntime, application agent directory, and session-aware model selection options to Pi's extension API; feature-specific contracts remain in their owning extension packages. Feature automation can pass { updateDefault: false } to setModel or setThinkingLevel to update the active session without changing the user's default model or thinking preference. Session-only model switches carry the active thinking level instead of applying persisted global or per-model defaults. Ordinary selections retain Pi's default-updating behavior.

Applications may also pass adapter-neutral inlineExtensions directly into session composition for host-owned integration such as presentation controls; these remain opt-in and are not discovered from ambient configuration. Runtime-backed coding tools are installed during composition as hidden fallback extension tools, so feature extensions can override standard tool names while explicit application customTools retain final precedence.

Agent Core owns the exact Pi dependency versions used by its consumers. Its public entry point exposes the Pi model, credential, streaming, session, resource, skill, tool, and context-inspection symbols needed to compose Felan applications, so consumers import those symbols from @felan-ai/agent-core without declaring Pi packages directly.

The composition surface re-exports Pi's createCodemodeExtension and CodemodeExtensionOptions. Registration alone leaves codemode inactive; the host must activate it and owns its configuration and lifecycle. Agent Core does not enable it automatically. Felan's local host supports codemode.mode values off, on, and only, defaults to off, and disables the sandbox's extra model helpers with models: false.

Agent Core 0.12 follows Pi 1.1's public contracts. Extension integrations must handle aborted on agent_settled events, include durationMs and outputPad when implementing Pi tool-render callbacks, and provide ToolLoadout.getPromptGuidelines(). Custom stream functions should return an AssistantMessageEventStream, typically created by createAssistantMessageEventStream().

Agent Core also exposes shared xhigh, high, medium, and low model tiers for extensions that need model-strength selection:

import { selectModelForTier } from '@felan-ai/agent-core';

const models = ctx.scopedModels.length > 0
  ? ctx.scopedModels.map(({ model }) => model)
  : ctx.modelRegistry.getAvailable();
const selection = selectModelForTier('low', models, {
  preferredModel: ctx.model,
});

Callers provide the models already allowed and authenticated by their host. Selection prefers candidates from the current provider and model family, then falls back across the supplied model scope. getModelFamily and getModelStrength classify the host's live model list with version-independent family and role names, so Claude Fable, GPT Astra, Opus, Sonnet, Haiku, Sol, Terra, Luna, Pro, Flash, Max, and similar releases do not require an exact-ID catalog update. Aggregate providers including OpenCode, OpenCode Go, OpenRouter, and GitHub Copilot are classified from each model's identity rather than treated as one family. Unknown naming schemes default to medium, and hosts can pass a custom classifyModel function to selectModelForTier. Model tiers do not imply a thinking level. xhigh is reserved for exceptional model-assisted work such as complex architecture, design, planning, difficult debugging, and high-stakes code review; it is not a routine default. FELAN_THINKING_LEVELS separately defines off, low, medium, high, xhigh, and max; minimal is outside the Felan-facing scale. Agent Core also re-exports Pi's clampThinkingLevel so extensions can resolve a requested effort against a host-provided model without duplicating provider capability rules. Agent Core does not load model-tier configuration or resolve credentials.

Agent Core owns the runtime-neutral Felan base system prompt. Every composed session uses this prompt; consumers extend it with appendSystemPrompt and cannot replace it. During composition, Agent Core also reads at most one instruction file from the session cwd through AgentRuntime, with AGENTS.md taking precedence over CLAUDE.md. Missing, unreadable, and blank instruction files are nonfatal. The selected file is delivered by Pi's context transform as a path-labelled, hidden user-role context message on each model request. It follows the system prompt and is not part of the system prompt or persisted conversation history. getProjectInstructions(resourceLoader) lets hosts inspect the selected path and content without adding it to Pi's prompt resources. Inline extensions can contribute model-facing behavior during initialization:

const extension: FelanExtension = (pi) => {
  pi.registerCapability({
    id: 'review',
    instructions: 'Review changed code and report concrete findings.',
  });
};

Capability IDs and instructions are validated, duplicate IDs report both extension sources, and contributions retain extension load and registration order across resource reloads. Agent Core renders enabled capabilities as one section after the base prompt. Consumer appends follow that section; Pi then adds explicit skills and the current working directory. The separate context transform supplies cwd project instructions after the leading system prompt.

Tool definitions sent with the model request remain the authoritative tool inventory. The Felan-owned prompt intentionally does not render Pi's default promptSnippet or promptGuidelines sections; extensions use named capabilities for multi-tool workflow guidance.

Applications may pass explicit skills or skillPaths into session composition. Agent Core exposes only those resources while ambient project, user, and package skill discovery remains disabled. Ambient system prompt, append prompt, and context discovery are also disabled; the selected cwd instruction file is the only built-in project-instruction input.

Extension settings

Extensions declare configuration with defineExtensionConfig and configField. Defaulted fields retain their defaults through resolution. Use configField.optionalEnum(['normal', 'fast'], { description: 'Request priority' }) when omission has meaning: the resolved configuration omits the key until an explicit choice is supplied. Optional enum properties are optional in InferExtensionConfig, and explicit invalid values, including null, are rejected. Hosts can display an unset value without saving a synthetic default.

Fields may carry a deprecated message. Deprecated fields remain valid for configuration and CLI compatibility; Felan's /settings hides them.

Package boundary

Agent Core owns AgentRuntime, HostAgentRuntime, the Felan base prompt, cwd project instructions, provider-aware model tiers, runtime-backed coding tools, capabilities, session/resource composition, and the public Pi composition exports. Hosts own credentials, settings, storage roots, model scope, presentation, and feature extension selection. Feature-specific behavior such as tasks, memory scheduling, progressive context, and Prewalk belongs in its own extension or application.

Host mode is deliberately not a sandbox. Use a runtime with an external isolation boundary for untrusted workloads. Runtime callers should use literal argv with exec, bounded byte-based I/O, and the scoped storage APIs rather than reaching around the adapter.

Development

Source: packages/agent-core in https://github.com/felan-ai/felan.

corepack enable
pnpm install --frozen-lockfile
pnpm --filter @felan-ai/agent-core build
pnpm --filter @felan-ai/agent-core type-check
pnpm --filter @felan-ai/agent-core test

Attribution

Agent Core composes the pinned MIT-licensed Pi packages listed in the package manifest. See NOTICE and LICENSE for the complete third-party attribution boundary.

Related documentation