---
title: '@runic-labs/cache'
description: 以签名为键的制品存储——内存与文件后端。
sidebar:
  order: 4
---
`@runic-labs/cache` 将规范化的决策签名映射到为其生成的制品。大多数集成不需要直接使用此包——`@runic-labs/sdk` 对其进行了封装——但它对自定义存储设置或检查缓存内部机制很有用。

```package-install
npm i @runic-labs/cache
```

## `signature(decision)`

对 `Decision` 进行规范化并返回其 SHA-256 签名。`params` 中的对象键会递归排序，因此键的顺序永远不会影响哈希值。完整算法请参阅[工作原理](/how-it-works)。

```ts
import { signature } from "@runic-labs/cache";

signature({ intent: "summarize_pr", params: { repo: "acme/widgets", pr: 482 } });
// => same hash regardless of param key order
```

## `createCache(store?)`

```ts
import { createCache, FileCacheStore, defaultCacheFilePath } from "@runic-labs/cache";

const cache = createCache(new FileCacheStore({ filePath: defaultCacheFilePath() }));
```

如果未传入存储，则默认使用 `.runic/cache.json`（或 `$RUNIC_HOME/cache.json`）下的 `FileCacheStore`。

| Prop | Type | Default | Description |
| - | - | - | - |
| `get(decision)?` | `CachedEntry \| null` | - | Looks up a decision. Bumps hit stats on a hit. |
| `set(decision, artifact, meta)?` | `CachedEntry` | - | Stores an artifact for a decision. meta = { tokensSpent }. |
| `list()?` | `CachedEntry[]` | - | All entries currently in the store. |
| `clear()?` | `void` | - | Removes all entries. |

## 存储后端

### `MemoryCacheStore`

仅存储在内存中，生命周期与进程一致。基准测试和测试都会使用它，因此运行是自包含且可重复的。

```ts
import { createCache, MemoryCacheStore } from "@runic-labs/cache";

const cache = createCache(new MemoryCacheStore({ staleAfterMs: 60_000 }));
```

### `FileCacheStore`

持久化到 JSON 文件，因此 CLI 进程和代理进程无需运行中的服务器即可读取同一份缓存。

```ts
import { createCache, FileCacheStore } from "@runic-labs/cache";

const cache = createCache(new FileCacheStore({ filePath: "./my-agent/.runic/cache.json" }));
```

损坏或部分写入的文件会被视为空，而不会抛出异常——写入过程中发生崩溃绝不应影响下一次读取。

## 实现自己的 `CacheStore`

两个内置存储都实现了相同的小型接口，因此由 Redis 或 SQLite 支持的存储可以直接替换：

```ts
interface CacheStore {
  get(signature: string): CachedEntry | null;
  set(signature: string, artifact: unknown, meta: { tokensSpent: number }): CachedEntry;
  touch(signature: string): CachedEntry | null;
  list(): CachedEntry[];
  clear(): void;
}
```

`touch` 会在每次缓存命中时于内部调用，以增加 `hitCount` 和 `lastUsedAt`——请针对你选择的任意后端存储，将其实现为读-修改-写操作。

## 下一步

- [账本](/ledger)——对应的已花费/节省核算层
- [SDK](/sdk)——大多数集成实际使用的双函数契约
