@skillbolt/sync
v1.0.1
Published
Cross-device Skill synchronization with cloud backends for Skillbolt
Downloads
7
Maintainers
Readme
@skillbolt/sync
技能同步工具,支持将技能同步到云端存储,实现跨设备共享和备份。
功能特性
- 多云后端: 支持 GitHub Gist、Supabase 等多种存储后端
- 自动同步: 可配置自动同步策略
- 冲突解决: 智能检测和解决同步冲突
- 离线队列: 支持离线操作,网络恢复后自动同步
- 增量同步: 仅同步变更的技能,提高效率
- 版本历史: 保留技能的版本历史
- 网络监控: 自动检测网络状态
基本使用
CLI 使用
# 推送技能到云端
skill sync push
# 从云端拉取技能
skill sync pull
# 查看同步状态
skill sync status
# 强制推送(覆盖远程)
skill sync push --force
# 强制拉取(覆盖本地)
skill sync pull --forceAPI 使用
import { SyncEngine, push, pull, syncStatus } from '@skillbolt/sync';
// 创建同步引擎
const syncEngine = new SyncEngine({
backend: {
type: 'github-gist',
credentials: {
token: 'your-github-token',
gistId: 'your-gist-id'
}
}
});
// 推送技能
const pushResult = await syncEngine.push();
console.log(`Pushed ${pushResult.pushed} skills`);
// 拉取技能
const pullResult = await syncEngine.pull();
console.log(`Pulled ${pullResult.pulled} skills`);
// 查看状态
const status = await syncEngine.getStatus();
console.log(`Local: ${status.local.length}, Remote: ${status.remote.length}`);后端配置
GitHub Gist
import { SyncEngine } from '@skillbolt/sync';
const syncEngine = new SyncEngine({
backend: {
type: 'github-gist',
credentials: {
token: process.env.GITHUB_TOKEN,
gistId: process.env.GIST_ID
}
}
});Supabase
import { SyncEngine } from '@skillbolt/sync';
const syncEngine = new SyncEngine({
backend: {
type: 'supabase',
credentials: {
url: 'https://your-project.supabase.co',
anonKey: 'your-anon-key'
}
}
});自定义后端
import { BaseBackend, SyncEngine } from '@skillbolt/sync';
class CustomBackend extends BaseBackend {
async upload(skill: LocalSkill): Promise<UploadResult> {
// 自定义上传逻辑
}
async download(skillId: string): Promise<RemoteSkill> {
// 自定义下载逻辑
}
async delete(skillId: string): Promise<DeleteResult> {
// 自定义删除逻辑
}
async list(): Promise<RemoteSkill[]> {
// 自定义列出逻辑
}
}
const syncEngine = new SyncEngine({
backend: new CustomBackend()
});同步操作
推送 (Push)
import { push } from '@skillbolt/sync';
const result = await push({
backend: 'github-gist',
credentials: { token: 'xxx', gistId: 'yyy' },
skills: ['skill-1', 'skill-2'], // 特定技能,不指定则全部
force: false
});
console.log(result.pushed); // 推送的数量
console.log(result.skipped); // 跳过的数量
console.log(result.failed); // 失败的数量拉取 (Pull)
import { pull } from '@skillbolt/sync';
const result = await pull({
backend: 'supabase',
credentials: { url: 'xxx', anonKey: 'yyy' },
force: false
});
console.log(result.pulled); // 拉取的数量
console.log(result.skipped); // 跳过的数量
console.log(result.failed); // 失败的数量状态检查
import { syncStatus } from '@skillbolt/sync';
const status = await syncStatus();
status.skills.forEach(skill => {
console.log(`${skill.name}: ${skill.status}`);
// 'synced', 'local-only', 'remote-only', 'conflict'
});
console.log(`Overall: ${status.overallStatus}`);
// 'synced', 'needs-sync', 'has-conflicts'冲突解决
检测冲突
import { detectConflicts } from '@skillbolt/sync';
const conflicts = await detectConflicts(localSkills, remoteSkills);
conflicts.forEach(conflict => {
console.log(`Conflict in ${conflict.skillName}`);
console.log(`Local version: ${conflict.localVersion}`);
console.log(`Remote version: ${conflict.remoteVersion}`);
});解决冲突
import { resolveConflict, resolveConflictWithBackup } from '@skillbolt/sync';
// 策略: 使用本地版本
await resolveConflict(conflict, 'local');
// 策略: 使用远程版本
await resolveConflict(conflict, 'remote');
// 策略: 创建备份后使用本地
await resolveConflictWithBackup(conflict, 'local');
// 策略: 手动解决
const resolved = {
name: conflict.skillName,
content: 'merged content',
version: '1.0.0'
};
await resolveConflict(conflict, 'manual', resolved);离线队列
使用离线队列
import { OfflineQueue } from '@skillbolt/sync';
const queue = new OfflineQueue({
storagePath: './.skillbolt/queue.json'
});
// 网络可用时,自动同步队列中的操作
queue.on('network:available', async () => {
await queue.flush();
});
// 添加操作到队列
await queue.add({
type: 'push',
skillId: 'my-skill',
timestamp: Date.now()
});
// 手动刷新队列
await queue.flush();队列状态
const status = await queue.getStatus();
console.log(`Pending: ${status.pending}`);
console.log(`Failed: ${status.failed}`);
console.log(`Total: ${status.total}`);自动同步
配置自动同步
import { SyncEngine } from '@skillbolt/sync';
const syncEngine = new SyncEngine({
backend: {
type: 'github-gist',
credentials: { token: 'xxx', gistId: 'yyy' }
},
autoSync: {
enabled: true,
interval: 60000, // 每 60 秒
onConflict: 'local', // 冲突时使用本地版本
syncOnStartup: true // 启动时同步
}
});
// 手动触发自动同步
await syncEngine.autoSync();事件监听
syncEngine.on('sync:start', () => {
console.log('Sync started');
});
syncEngine.on('sync:complete', (result) => {
console.log('Sync completed', result);
});
syncEngine.on('sync:error', (error) => {
console.error('Sync error', error);
});
syncEngine.on('conflict', (conflict) => {
console.log('Conflict detected', conflict);
});使用示例
示例 1: 基本同步
import { SyncEngine } from '@skillbolt/sync';
async function basicSync() {
const syncEngine = new SyncEngine({
backend: {
type: 'github-gist',
credentials: {
token: process.env.GITHUB_TOKEN,
gistId: process.env.GIST_ID
}
}
});
// 检查状态
const status = await syncEngine.getStatus();
console.log(`Local skills: ${status.local.length}`);
console.log(`Remote skills: ${status.remote.length}`);
// 如果需要同步
if (status.overallStatus !== 'synced') {
await syncEngine.push();
await syncEngine.pull();
}
}示例 2: 处理冲突
import { SyncEngine, resolveConflict } from '@skillbolt/sync';
async function syncWithConflictHandling() {
const syncEngine = new SyncEngine({
backend: {
type: 'github-gist',
credentials: { token: 'xxx', gistId: 'yyy' }
}
});
// 检测冲突
const conflicts = await syncEngine.detectConflicts();
// 解决冲突
for (const conflict of conflicts) {
console.log(`Resolving conflict for ${conflict.skillName}`);
// 简单策略: 使用最新修改的版本
if (conflict.localModifiedAt > conflict.remoteModifiedAt) {
await resolveConflict(conflict, 'local');
} else {
await resolveConflict(conflict, 'remote');
}
}
// 继续同步
await syncEngine.push();
}示例 3: 网络监控
import { SyncEngine, createNetworkMonitor } from '@skillbolt/sync';
async function syncWithNetworkMonitoring() {
const syncEngine = new SyncEngine({
backend: {
type: 'supabase',
credentials: { url: 'xxx', anonKey: 'yyy' }
}
});
// 创建网络监控器
const monitor = createNetworkMonitor({
checkInterval: 5000, // 每 5 秒检查一次
pingUrl: 'https://www.google.com'
});
// 网络可用时同步
monitor.on('online', async () => {
console.log('Network available, syncing...');
await syncEngine.pull();
await syncEngine.push();
});
// 网络不可用时记录
monitor.on('offline', () => {
console.log('Network unavailable');
});
// 启动监控
monitor.start();
}示例 4: 备份和恢复
import { SyncEngine } from '@skillbolt/sync';
async function backupSkills() {
const syncEngine = new SyncEngine({
backend: {
type: 'github-gist',
credentials: { token: 'xxx', gistId: 'yyy' }
}
});
// 推送所有技能作为备份
const result = await syncEngine.push({
all: true,
force: true // 覆盖远程
});
console.log(`Backed up ${result.pushed} skills`);
}类型定义
interface SyncEngineOptions {
backend: BackendConfig;
autoSync?: AutoSyncConfig;
queue?: QueueConfig;
backup?: BackupSettings;
}
interface BackendConfig {
type: BackendType;
credentials: Credentials;
}
interface PushOptions {
skills?: string[];
force?: boolean;
dryRun?: boolean;
}
interface PullOptions {
skills?: string[];
force?: boolean;
dryRun?: boolean;
}
interface PushResult {
pushed: number;
skipped: number;
failed: number;
errors: Error[];
}
interface PullResult {
pulled: number;
skipped: number;
failed: number;
errors: Error[];
}
interface StatusResult {
local: SkillStatus[];
remote: SkillStatus[];
overallStatus: OverallStatus;
}
interface SkillStatus {
name: string;
status: 'synced' | 'local-only' | 'remote-only' | 'conflict';
localVersion?: string;
remoteVersion?: string;
localModifiedAt?: Date;
remoteModifiedAt?: Date;
}
interface Conflict {
skillName: string;
local: LocalSkill;
remote: RemoteSkill;
}
type BackendType = 'github-gist' | 'supabase' | 'custom';
type ConflictStrategy = 'local' | 'remote' | 'manual';
type OverallStatus = 'synced' | 'needs-sync' | 'has-conflicts';CLI 命令
push
skill sync push
# 选项
skill sync push --force
skill sync push --skills skill-1,skill-2
skill sync push --dry-runpull
skill sync pull
# 选项
skill sync pull --force
skill sync pull --skills skill-1,skill-2
skill sync pull --dry-runstatus
skill sync status
# 选项
skill sync status --detailed
skill sync status --json最佳实践
- 定期同步: 设置自动同步确保数据安全
- 冲突处理: 建立明确的冲突解决策略
- 网络监控: 在网络不稳定时使用离线队列
- 备份策略: 定期备份重要技能
- 版本控制: 保留技能的版本历史
故障排除
同步失败
如果同步失败:
- 检查网络连接
- 验证后端凭证
- 查看详细的错误日志
- 检查磁盘空间
冲突频繁
如果频繁出现冲突:
- 检查自动同步配置
- 调整同步间隔
- 审查多设备使用情况
- 建立明确的使用规范
性能问题
如果同步速度慢:
- 检查技能数量和大小
- 考虑增量同步
- 优化网络连接
- 使用更快的后端
API 参考
主要导出
// 核心
export { SyncEngine, computeSyncDiff, getSyncSummary };
// 冲突处理
export {
detectConflicts,
resolveConflict,
resolveConflictWithBackup,
createConflictBackup
};
// 后端
export {
BaseBackend,
SupabaseBackend,
GitHubGistBackend,
createBackend,
getSupportedBackends
};
// 队列
export { OfflineQueue, QueueStorage };
// 命令
export { push, pull, syncStatus, formatStatus };
// 工具
export {
computeHashFromString,
computeHashFromFile,
hashesMatch,
checkNetworkConnectivity,
createNetworkMonitor,
scanLocalSkills,
filterSkills
};贡献
欢迎贡献!请查看 CONTRIBUTING.md 了解详细信息。
许可证
MIT
