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

@xpert-ai/plugin-file-memory

v0.1.4

Published

`@xpert-ai/plugin-file-memory` is a sandbox-only durable memory middleware for XpertAI agents.

Readme

XpertAI Plugin: File Memory Middleware

@xpert-ai/plugin-file-memory is a sandbox-only durable memory middleware for XpertAI agents.

It stores memories as Markdown files, injects lightweight memory context during runtime, exposes explicit read/write tools, and performs optional asynchronous writeback after the agent finishes.

For a Chinese implementation guide, see README_zh.md.

Current Runtime Model

  • The middleware requires the Xpert sandbox feature.
  • There is no host-path fallback and no path-related user config.
  • The memory root is always the current workspace dir under ./.xpert/memory.
  • The plugin isolates memories by xpertId.
  • The old users/<userId> directory layer is removed.
  • Private memories are stored under private/ and filtered by frontmatter ownerUserId.

What Users Configure

There are no enabled flags anymore.

  • Recall is part of the middleware runtime.
  • Explicit write_memory is always available when the middleware is mounted.
  • Automatic writeback becomes active when writeback.model is configured.

Config Schema

The public config schema has two optional top-level blocks:

  • recall
  • writeback

Recall

| Field | Type | Default | Usage | | --- | --- | --- | --- | | recall.mode | hybrid_async \| legacy_blocking | hybrid_async | Controls whether detailed recall is prefetched asynchronously or blocks the current model call. Keep hybrid_async unless you explicitly want the reply to wait for detail recall. | | recall.model | ICopilotModel | none | Optional selector model for choosing the most useful memories from scanned headers. If omitted, recall falls back to local ranking. | | recall.timeoutMs | number | 1500 | Wait budget for the detached selector path. Increase for better selection quality; decrease for lower latency. | | recall.maxSelected | number | 5 | Maximum number of full memory bodies surfaced in one turn. Keep this small to control context size. | | recall.prompt | string | built-in prompt | Optional override for selector policy. Use only when you intentionally want custom recall behavior. |

Writeback

| Field | Type | Default | Usage | | --- | --- | --- | --- | | writeback.waitPolicy | never_wait \| soft_drain | never_wait | Whether afterAgent should briefly wait for the background writeback queue. never_wait is the normal interactive default. | | writeback.model | ICopilotModel | none | Enables automatic writeback. Without this field, background writeback is skipped. | | writeback.qaPrompt | string | built-in prompt | Optional override for non-user memories such as feedback, project, and reference. | | writeback.profilePrompt | string | built-in prompt | Optional override for user profile/preference writeback decisions. |

Tools

The middleware provides two tools:

  • search_recall_memories Reads durable memory by query, exact memoryId, or exact relativePath.
  • write_memory Creates or updates a durable memory file.

search_recall_memories and runtime digest results now return layer-aware relativePath values:

  • private/<semanticDir>/<filename>.md
  • shared/<semanticDir>/<filename>.md

This removes ambiguity between private and shared files with the same semantic path.

How Files Are Written

All writes eventually go through the same service path:

  1. Resolve scope from the current xpertId.
  2. Resolve target layer from audience.
  3. Resolve semanticKind and its directory name.
  4. Reuse the existing file path when updating by memoryId; otherwise create a new filename as <slug(title)>-<memoryId>.md.
  5. Serialize frontmatter + Markdown body.
  6. Write the file through sandbox upload APIs.
  7. Rebuild the layer-level MEMORY.md.

There are two write entry points:

  • explicit write_memory
  • background FileMemoryWritebackRunner

How File Locations Are Decided

The path decision is now fully internal to the plugin and independent of host-side path configuration.

Root

The memory root is fixed to:

./.xpert/memory

This path is interpreted inside the current workspace dir, so the effective physical location is:

<workspace dir>/.xpert/memory

The workspace dir comes from the Xpert runtime:

  • project runs use the shared project root
  • non-project runs use the shared user root

The middleware does not create a default thread-specific subdirectory. If you need special per-thread isolation in prompts, use sys.thread_id to derive your own path logic.

Scope

The plugin keeps xpert isolation:

xperts/<xpertId>

This remains necessary because one workspace dir can still be shared by multiple xperts in project-style scenarios.

Layer

Each xpert has two layers:

  • private
  • shared

The full layer roots are:

./.xpert/memory/xperts/<xpertId>/private
./.xpert/memory/xperts/<xpertId>/shared

Semantic Directory

Within each layer, files are grouped by semantic directory:

  • user
  • feedback
  • project
  • reference

Legacy kinds still map into the semantic model:

  • profile -> user
  • qa -> reference by default, unless a more specific semantic kind is resolved

Filename

New files use:

<slug(title)>-<memoryId>.md

Updates reuse the original file path instead of renaming the file.

Final Storage Layout

Typical memory files now look like:

./.xpert/memory/xperts/<xpertId>/private/<semanticDir>/<slug>-<memoryId>.md
./.xpert/memory/xperts/<xpertId>/shared/<semanticDir>/<slug>-<memoryId>.md

Layer indexes live at:

./.xpert/memory/xperts/<xpertId>/private/MEMORY.md
./.xpert/memory/xperts/<xpertId>/shared/MEMORY.md

Inside MEMORY.md, links stay relative to the current layer root, for example:

  • user/alice-style-123.md
  • reference/release-dashboard-456.md

Private vs Shared Semantics

shared memories are visible to all sessions under the current xpert.

private memories still preserve per-user behavior, but isolation is no longer represented in the directory tree. Instead:

  • files live under the shared private/ layer directory
  • each private file keeps ownerUserId in frontmatter
  • recall and exact lookup filter private files by the current user

This keeps the on-disk layout simpler while preserving private visibility rules.

Runtime Recall Flow

First model call

  • read MEMORY.md entrypoints from visible layers
  • scan headers
  • build a lightweight summary digest
  • inject only lightweight context

Later model calls

  • detached recall may select full memory bodies in the background
  • the next model call consumes the ready detail once
  • if model selection is unavailable, recall falls back to local ranking

Sandbox Storage Layer

The middleware uses an internal SandboxMemoryStore.

It reads and writes only through sandbox backend APIs:

  • raw file read: downloadFiles()
  • overwrite/new write: uploadFiles()
  • markdown enumeration: globInfo()
  • file mtime lookup: lsInfo()

This avoids host-path coupling and keeps all file IO inside the active workspace dir.

Development

Install dependencies from the xpertai/ workspace root:

pnpm install

Run focused tests:

pnpm exec jest --config middlewares/file-memory/jest.config.cjs --runInBand --watchman=false

Run a type check:

pnpm exec tsc -p middlewares/file-memory/tsconfig.json --noEmit

License

This project follows the AGPL-3.0 License at the repository root.