Token导航 LogoToken导航

Agent Skill · 研究检索

resilient-storage(弹性存储)

resilient-storage 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

resilient-storage 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 55,343。

总安装 485周安装 20GitHub Stars 777下载 158核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:resilient-storage(弹性存储)
来源仓库:https://github.com/dadbodgeoff/drift
仓库路径:skills/resilient-storage
安装命令:
npx skills add https://github.com/dadbodgeoff/drift --skill resilient-storage
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/dadbodgeoff/drift --skill resilient-storage

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

用于查找、检索和筛选相关信息。适合在 Codex、Claude、Cursor、Gemini CLI 中根据关键词或任务场景快速定位候选结果。通过 npx skills add 命令从指定 GitHub 仓库安装,需确认权限与联网能力。建议结合原始 README 核验具体用法,注意维护状态和功能边界。

使用前请检查是否会触发文件读写或命令执行,确保环境安全。

来源仓库内路径:skills/resilient-storage

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/dadbodgeoff/drift --skill resilient-storage;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

resilient-storage 怎么安装?

在终端执行 npx skills add https://github.com/dadbodgeoff/drift --skill resilient-storage。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

resilient-storage 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

resilient-storage 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

resilient-storage 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

resilient-storage 用的人多吗?

公开数据是累计安装 485 次,近一周安装 20 次,下载 158 次,GitHub 777 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

resilient-storage 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
resilient-storage

弹性存储 · 本页

485777需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Resilient Storage Layer

Multi-backend storage with automatic failover. Redis primary, database secondary, memory fallback. Circuit breakers per backend. Health-aware routing.

When to Use This Skill

  • Building systems that can't afford storage downtime
  • Need graceful degradation when Redis or database is unavailable
  • Implementing distributed locks that must work even during partial outages
  • Any caching layer that needs high availability

Core Concepts

The resilient storage layer provides:

  • Multiple storage backends with priority ordering
  • Automatic failover when a backend fails
  • Circuit breakers to prevent cascading failures
  • Health checks to detect and recover from outages
  • Memory fallback that's always available

Architecture:

Backend Selection (FAILOVER | ROUND_ROBIN | PRIORITY)
         │
    ┌────┼────┐
    ▼    ▼    ▼
  Redis  DB  Memory
  (P:1) (P:2) (P:999)
    │    │    │
    └────┴────┘
         │
   Health Monitor

Implementation

TypeScript

export enum StorageBackendType {
  REDIS = 'redis',
  SUPABASE = 'supabase',
  MEMORY = 'memory',
}

export enum BackendHealth {
  HEALTHY = 'healthy',
  DEGRADED = 'degraded',
  UNHEALTHY = 'unhealthy',
}

export interface IStorageBackend {
  name: string;
  type: StorageBackendType;

  initialize(): Promise<void>;
  shutdown(): Promise<void>;
  healthCheck(): Promise<BackendHealth>;

  get(key: string): Promise<string | null>;
  set(key: string, value: string, ttlSeconds?: number): Promise<boolean>;
  delete(key: string): Promise<boolean>;

  acquireLock(name: string, holderId: string, ttlSeconds: number): Promise<LockResult>;
  releaseLock(name: string, holderId: string): Promise<boolean>;
}

interface BackendState {
  backend: IStorageBackend;
  priority: number;
  health: BackendHealth;
  circuitOpen: boolean;
  circuitOpenedAt?: Date;
  consecutiveFailures: number;
}

export class ResilientStorage {
  private backends: BackendState[] = [];
  private healthCheckInterval: NodeJS.Timeout | null = null;

  constructor(
    private config: {
      healthCheckIntervalMs: number;
      circuitBreakerThreshold: number;
      circuitBreakerResetMs: number;
    }
  ) {}

  async initialize(backendConfigs: Array<{
    backend: IStorageBackend;
    priority: number;
    enabled: boolean;
  }>): Promise<void> {
    for (const config of backendConfigs) {
      if (!config.enabled) continue;

      try {
        await config.backend.initialize();
        this.backends.push({
          backend: config.backend,
          priority: config.priority,
          health: BackendHealth.HEALTHY,
          circuitOpen: false,
          consecutiveFailures: 0,
        });
      } catch (error) {
        console.warn(`Failed to initialize ${config.backend.name}:`, error);
      }
    }

    // Always add memory fallback
    if (!this.backends.some(b => b.backend.type === StorageBackendType.MEMORY)) {
      const memoryBackend = new MemoryBackend();
      await memoryBackend.initialize();
      this.backends.push({
        backend: memoryBackend,
        priority: 999,
        health: BackendHealth.HEALTHY,
        circuitOpen: false,
        consecutiveFailures: 0,
      });
    }

    // Sort by priority
    this.backends.sort((a, b) => a.priority - b.priority);

    // Start health checks
    this.healthCheckInterval = setInterval(
      () => this.runHealthChecks(),
      this.config.healthCheckIntervalMs
    );
  }

  private async executeWithFailover<T>(
    operation: string,
    fn: (backend: IStorageBackend) => Promise<T>,
    isSuccess: (result: T) => boolean = () => true
  ): Promise<T> {
    const triedBackends = new Set<string>();

    while (triedBackends.size < this.backends.length) {
      const state = this.selectBackend(triedBackends);
      if (!state) break;

      triedBackends.add(state.backend.name);

      try {
        const result = await fn(state.backend);
        if (isSuccess(result)) {
          this.recordSuccess(state);
          return result;
        }
        this.recordFailure(state);
      } catch (error) {
        console.warn(`${operation} failed on ${state.backend.name}:`, error);
        this.recordFailure(state);
      }
    }

    throw new Error(`All backends failed for: ${operation}`);
  }

  private selectBackend(exclude: Set<string>): BackendState | null {
    const available = this.backends.filter(
      b => !exclude.has(b.backend.name) &&
           b.health !== BackendHealth.UNHEALTHY &&
           !b.circuitOpen
    );

    if (available.length === 0) {
      // Try memory fallback even if excluded
      return this.backends.find(
        b => b.backend.type === StorageBackendType.MEMORY
      ) || null;
    }

    return available[0];
  }

  private recordSuccess(state: BackendState): void {
    state.consecutiveFailures = 0;
    if (state.circuitOpen) {
      state.circuitOpen = false;
      console.log(`Circuit closed for ${state.backend.name}`);
    }
  }

  private recordFailure(state: BackendState): void {
    state.consecutiveFailures++;

    if (state.consecutiveFailures >= this.config.circuitBreakerThreshold) {
      if (!state.circuitOpen) {
        state.circuitOpen = true;
        state.circuitOpenedAt = new Date();
        console.warn(`Circuit opened for ${state.backend.name}`);
      }
    }
  }

  // Public API
  async get(key: string): Promise<string | null> {
    return this.executeWithFailover('get', b => b.get(key));
  }

  async set(key: string, value: string, ttlSeconds?: number): Promise<boolean> {
    return this.executeWithFailover('set', b => b.set(key, value, ttlSeconds), r => r);
  }

  async acquireLock(
    name: string,
    holderId: string,
    ttlSeconds: number
  ): Promise<LockResult> {
    return this.executeWithFailover(
      'acquireLock',
      b => b.acquireLock(name, holderId, ttlSeconds),
      r => r.acquired || !r.error
    );
  }
}

Memory Backend (Fallback)

export class MemoryBackend implements IStorageBackend {
  name = 'memory';
  type = StorageBackendType.MEMORY;

  private store = new Map<string, { value: string; expiresAt?: number }>();
  private locks = new Map<string, { holderId: string; expiresAt: number }>();

  async initialize(): Promise<void> {
    setInterval(() => this.cleanup(), 60000);
  }

  async shutdown(): Promise<void> {
    this.store.clear();
    this.locks.clear();
  }

  async healthCheck(): Promise<BackendHealth> {
    return BackendHealth.HEALTHY; // Memory is always healthy
  }

  async get(key: string): Promise<string | null> {
    const entry = this.store.get(key);
    if (!entry) return null;
    if (entry.expiresAt && Date.now() > entry.expiresAt) {
      this.store.delete(key);
      return null;
    }
    return entry.value;
  }

  async set(key: string, value: string, ttlSeconds?: number): Promise<boolean> {
    this.store.set(key, {
      value,
      expiresAt: ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined,
    });
    return true;
  }

  async delete(key: string): Promise<boolean> {
    return this.store.delete(key);
  }

  async acquireLock(
    name: string,
    holderId: string,
    ttlSeconds: number
  ): Promise<LockResult> {
    const existing = this.locks.get(name);
    const now = Date.now();

    if (existing && existing.expiresAt > now && existing.holderId !== holderId) {
      return { acquired: false, error: 'Lock held by another process' };
    }

    this.locks.set(name, {
      holderId,
      expiresAt: now + ttlSeconds * 1000,
    });

    return { acquired: true };
  }

  async releaseLock(name: string, holderId: string): Promise<boolean> {
    const lock = this.locks.get(name);
    if (!lock || lock.holderId !== holderId) return false;
    this.locks.delete(name);
    return true;
  }

  private cleanup(): void {
    const now = Date.now();
    for (const [key, entry] of this.store) {
      if (entry.expiresAt && entry.expiresAt < now) {
        this.store.delete(key);
      }
    }
    for (const [name, lock] of this.locks) {
      if (lock.expiresAt < now) {
        this.locks.delete(name);
      }
    }
  }
}

Usage Examples

Initialization

const storage = new ResilientStorage({
  healthCheckIntervalMs: 30000,
  circuitBreakerThreshold: 5,
  circuitBreakerResetMs: 60000,
});

await storage.initialize([
  { backend: new RedisBackend(process.env.REDIS_URL), priority: 1, enabled: true },
  { backend: new SupabaseBackend(), priority: 2, enabled: true },
  { backend: new MemoryBackend(), priority: 999, enabled: true },
]);

// Operations automatically failover
await storage.set('key', 'value', 3600);
const value = await storage.get('key');

// Locks work across backends
const lock = await storage.acquireLock('job:123', 'worker-1', 30);

Health Endpoint

// GET /api/health/storage
export async function GET() {
  const status = storage.getHealthStatus();

  const allHealthy = Object.values(status).every(
    s => s.health === 'healthy' && !s.circuitOpen
  );

  return Response.json({
    status: allHealthy ? 'healthy' : 'degraded',
    activeBackend: storage.getActiveBackend(),
    backends: status,
  }, {
    status: allHealthy ? 200 : 503,
  });
}

Best Practices

  1. Always include memory fallback - it's your last line of defense
  2. Set appropriate circuit breaker thresholds based on your SLAs
  3. Monitor backend switches - frequent switches indicate instability
  4. Use health checks to detect issues before they cause failures
  5. Log all failover events for debugging and alerting

Common Mistakes

  • Not including a memory fallback backend
  • Setting circuit breaker thresholds too low (causes flapping)
  • Forgetting to handle the case where all backends fail
  • Not monitoring health check results
  • Using the same TTL for all backends (memory may need shorter TTLs)

Related Patterns

  • circuit-breaker - Prevent cascading failures
  • distributed-lock - Distributed locking implementation
  • leader-election - Leader election using locks
  • graceful-degradation - Graceful degradation strategies

适合场景

01

研究助手

02

事实核查

03

知识库问答

04

带来源的搜索总结

能力概览

能力 1

组合搜索和大模型调用

能力 2

支持多来源检索和总结

能力 3

强调引用来源和事实核查

能力 4

适合研究型 Agent 流程

平台分布

Codex

33.15%
按下载量换算52

Claude

28.28%
按下载量换算45

Cursor

19.96%
按下载量换算32

Gemini CLI

8.71%
按下载量换算14

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills