@kb-labs/adapters-snapshot-localfs 2.6.0 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/manifest.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { AdapterManifest } from '@kb-labs/core-platform';\n\nexport const manifest: AdapterManifest = {\n manifestVersion: '1.0.0',\n id: 'localfs-snapshot-provider',\n name: 'LocalFS Snapshot Provider',\n version: '0.1.0',\n description: 'Snapshot provider on local filesystem',\n author: 'KB Labs Team',\n license: 'KBPL-1.1',\n type: 'core',\n implements: 'ISnapshotProvider',\n contexts: ['workspace'],\n capabilities: {\n custom: {\n provider: 'localfs',\n workspaceRegistry: true,\n },\n },\n configSchema: {\n storageDir: {\n type: 'string',\n default: '.kb/runtime/snapshots',\n description: 'Root directory where snapshots are stored',\n },\n workspaceRegistryDir: {\n type: 'string',\n default: '.kb/runtime/workspace-registry',\n description: 'Directory with workspace metadata for source path resolution',\n },\n },\n};\n","import { mkdir, readFile, rm, writeFile, access, cp, readdir, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport type {\n ISnapshotProvider,\n CaptureSnapshotRequest,\n SnapshotDescriptor,\n RestoreSnapshotRequest,\n RestoreSnapshotResult,\n SnapshotStatusResult,\n SnapshotGarbageCollectRequest,\n SnapshotGarbageCollectResult,\n SnapshotProviderCapabilities,\n SnapshotStatus,\n} from '@kb-labs/core-platform';\n\nexport { manifest } from './manifest.js';\n\ninterface WorkspaceContext {\n cwd?: string;\n}\n\nexport interface LocalFsSnapshotAdapterConfig {\n storageDir?: string;\n workspaceRegistryDir?: string;\n workspace?: WorkspaceContext;\n}\n\ninterface SnapshotRecord {\n snapshotId: string;\n status: SnapshotStatus;\n createdAt: string;\n updatedAt: string;\n workspaceId?: string;\n environmentId?: string;\n sourcePath: string;\n payloadPath: string;\n namespace?: string;\n}\n\ninterface WorkspaceRecord {\n workspaceId: string;\n rootPath?: string;\n}\n\nexport class LocalFsSnapshotAdapter implements ISnapshotProvider {\n private readonly cwd: string;\n private readonly storageDir: string;\n private readonly workspaceRegistryDir: string;\n private readonly records = new Map<string, SnapshotRecord>();\n\n constructor(private readonly config: LocalFsSnapshotAdapterConfig = {}) {\n this.cwd = path.resolve(config.workspace?.cwd ?? process.cwd());\n this.storageDir = path.resolve(this.cwd, config.storageDir ?? '.kb/runtime/snapshots');\n this.workspaceRegistryDir = path.resolve(\n this.cwd,\n config.workspaceRegistryDir ?? '.kb/runtime/workspace-registry'\n );\n }\n\n async capture(request: CaptureSnapshotRequest): Promise<SnapshotDescriptor> {\n const snapshotId = request.snapshotId ?? `snap_${randomUUID()}`;\n const now = new Date().toISOString();\n const sourcePath = await this.resolveSourcePath(request);\n const namespace = request.namespace ?? 'default';\n const payloadPath = path.join(this.storageDir, namespace, snapshotId);\n\n await mkdir(path.dirname(payloadPath), { recursive: true });\n await rm(payloadPath, { recursive: true, force: true });\n await cp(sourcePath, payloadPath, { recursive: true, force: true });\n\n const record: SnapshotRecord = {\n snapshotId,\n status: 'ready',\n createdAt: now,\n updatedAt: now,\n workspaceId: request.workspaceId,\n environmentId: request.environmentId,\n sourcePath,\n payloadPath,\n namespace,\n };\n\n await this.persistRecord(record);\n\n return {\n snapshotId,\n provider: 'snapshot-localfs',\n status: 'ready',\n createdAt: now,\n updatedAt: now,\n workspaceId: request.workspaceId,\n environmentId: request.environmentId,\n metadata: {\n namespace,\n payloadPath,\n },\n };\n }\n\n async restore(request: RestoreSnapshotRequest): Promise<RestoreSnapshotResult> {\n const record = await this.getRecordOrThrow(request.snapshotId);\n const now = new Date().toISOString();\n\n const targetPath = request.targetPath\n ? path.resolve(this.cwd, request.targetPath)\n : await this.resolveRestoreTargetPath(request.workspaceId, record.workspaceId);\n\n if (!request.overwrite) {\n try {\n await access(targetPath);\n throw new Error(`Restore target already exists: ${targetPath}. Use overwrite=true.`);\n } catch (error) {\n if (error instanceof Error && error.message.startsWith('Restore target already exists')) {\n throw error;\n }\n // path missing, continue\n }\n }\n\n if (request.overwrite) {\n await rm(targetPath, { recursive: true, force: true });\n }\n\n await mkdir(path.dirname(targetPath), { recursive: true });\n await cp(record.payloadPath, targetPath, { recursive: true, force: true });\n\n record.status = 'ready';\n record.updatedAt = now;\n await this.persistRecord(record);\n\n return {\n snapshotId: request.snapshotId,\n restoredAt: now,\n workspaceId: request.workspaceId,\n environmentId: request.environmentId,\n targetPath,\n };\n }\n\n async getStatus(snapshotId: string): Promise<SnapshotStatusResult> {\n const record = await this.getRecordOrThrow(snapshotId);\n return {\n snapshotId,\n status: record.status,\n updatedAt: record.updatedAt,\n };\n }\n\n async delete(snapshotId: string): Promise<void> {\n const record = await this.getRecordOrThrow(snapshotId);\n await rm(record.payloadPath, { recursive: true, force: true });\n this.records.delete(snapshotId);\n await rm(this.getRecordPath(snapshotId), { force: true });\n }\n\n async garbageCollect(\n request: SnapshotGarbageCollectRequest = {}\n ): Promise<SnapshotGarbageCollectResult> {\n const beforeTs = request.before ? new Date(request.before).getTime() : Number.POSITIVE_INFINITY;\n const limit = request.limit ?? Number.POSITIVE_INFINITY;\n const dryRun = request.dryRun ?? false;\n let scanned = 0;\n let deleted = 0;\n\n for (const record of await this.loadAllRecords()) {\n scanned += 1;\n const createdTs = new Date(record.createdAt).getTime();\n if (createdTs >= beforeTs) {\n continue;\n }\n if (request.namespace && record.namespace !== request.namespace) {\n continue;\n }\n if (deleted >= limit) {\n break;\n }\n\n if (!dryRun) {\n await this.delete(record.snapshotId);\n }\n deleted += 1;\n }\n\n return { scanned, deleted, dryRun };\n }\n\n getCapabilities(): SnapshotProviderCapabilities {\n return {\n supportsWorkspaceSnapshots: true,\n supportsEnvironmentSnapshots: false,\n supportsGarbageCollection: true,\n supportsIncrementalSnapshots: false,\n custom: {\n provider: 'localfs',\n },\n };\n }\n\n private async resolveSourcePath(request: CaptureSnapshotRequest): Promise<string> {\n if (request.sourcePath) {\n return path.resolve(this.cwd, request.sourcePath);\n }\n\n if (request.workspaceId) {\n const workspace = await this.readWorkspaceRecord(request.workspaceId);\n if (workspace.rootPath) {\n return workspace.rootPath;\n }\n }\n\n throw new Error('Snapshot capture requires sourcePath or resolvable workspaceId');\n }\n\n private async resolveRestoreTargetPath(\n requestedWorkspaceId?: string,\n recordWorkspaceId?: string\n ): Promise<string> {\n const workspaceId = requestedWorkspaceId ?? recordWorkspaceId;\n if (!workspaceId) {\n throw new Error('Snapshot restore requires targetPath or workspaceId');\n }\n const workspace = await this.readWorkspaceRecord(workspaceId);\n if (!workspace.rootPath) {\n throw new Error(`Workspace rootPath not found for workspaceId=${workspaceId}`);\n }\n return workspace.rootPath;\n }\n\n private getRecordPath(snapshotId: string): string {\n return path.join(this.storageDir, '.records', `${snapshotId}.json`);\n }\n\n private async persistRecord(record: SnapshotRecord): Promise<void> {\n this.records.set(record.snapshotId, record);\n const recordPath = this.getRecordPath(record.snapshotId);\n await mkdir(path.dirname(recordPath), { recursive: true });\n await writeFile(recordPath, JSON.stringify(record, null, 2), 'utf8');\n }\n\n private async getRecordOrThrow(snapshotId: string): Promise<SnapshotRecord> {\n const inMemory = this.records.get(snapshotId);\n if (inMemory) {\n return inMemory;\n }\n\n const recordPath = this.getRecordPath(snapshotId);\n try {\n const raw = await readFile(recordPath, 'utf8');\n const parsed = JSON.parse(raw) as SnapshotRecord;\n this.records.set(snapshotId, parsed);\n return parsed;\n } catch {\n throw new Error(`Snapshot not found: ${snapshotId}`);\n }\n }\n\n private async readWorkspaceRecord(workspaceId: string): Promise<WorkspaceRecord> {\n const filePath = path.join(this.workspaceRegistryDir, `${workspaceId}.json`);\n const raw = await readFile(filePath, 'utf8');\n return JSON.parse(raw) as WorkspaceRecord;\n }\n\n private async loadAllRecords(): Promise<SnapshotRecord[]> {\n const recordsDir = path.join(this.storageDir, '.records');\n try {\n const entries = await readdir(recordsDir);\n const loaded: SnapshotRecord[] = [];\n for (const entry of entries) {\n if (!entry.endsWith('.json')) {\n continue;\n }\n const filePath = path.join(recordsDir, entry);\n const fileStat = await stat(filePath);\n if (!fileStat.isFile()) {\n continue;\n }\n const raw = await readFile(filePath, 'utf8');\n loaded.push(JSON.parse(raw) as SnapshotRecord);\n }\n return loaded;\n } catch {\n return [];\n }\n }\n}\n\nexport function createAdapter(config?: LocalFsSnapshotAdapterConfig): LocalFsSnapshotAdapter {\n return new LocalFsSnapshotAdapter(config);\n}\n\nexport default createAdapter;\n"]}
1
+ {"version":3,"sources":["../../../../../../Users/kirillbaranov/Desktop/kb-labs-workspace/adapters/snapshot-localfs/src/manifest.ts","../../../../../../Users/kirillbaranov/Desktop/kb-labs-workspace/adapters/snapshot-localfs/src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { AdapterManifest } from '@kb-labs/core-platform';\n\nexport const manifest: AdapterManifest = {\n manifestVersion: '1.0.0',\n id: 'localfs-snapshot-provider',\n name: 'LocalFS Snapshot Provider',\n version: '0.1.0',\n description: 'Snapshot provider on local filesystem',\n author: 'KB Labs Team',\n license: 'KBPL-1.1',\n type: 'core',\n implements: 'ISnapshotProvider',\n contexts: ['workspace'],\n capabilities: {\n custom: {\n provider: 'localfs',\n workspaceRegistry: true,\n },\n },\n configSchema: {\n storageDir: {\n type: 'string',\n default: '.kb/runtime/snapshots',\n description: 'Root directory where snapshots are stored',\n },\n workspaceRegistryDir: {\n type: 'string',\n default: '.kb/runtime/workspace-registry',\n description: 'Directory with workspace metadata for source path resolution',\n },\n },\n};\n","import { mkdir, readFile, rm, writeFile, access, cp, readdir, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport type {\n ISnapshotProvider,\n CaptureSnapshotRequest,\n SnapshotDescriptor,\n RestoreSnapshotRequest,\n RestoreSnapshotResult,\n SnapshotStatusResult,\n SnapshotGarbageCollectRequest,\n SnapshotGarbageCollectResult,\n SnapshotProviderCapabilities,\n SnapshotStatus,\n} from '@kb-labs/core-platform';\n\nexport { manifest } from './manifest.js';\n\ninterface WorkspaceContext {\n cwd?: string;\n}\n\nexport interface LocalFsSnapshotAdapterConfig {\n storageDir?: string;\n workspaceRegistryDir?: string;\n workspace?: WorkspaceContext;\n}\n\ninterface SnapshotRecord {\n snapshotId: string;\n status: SnapshotStatus;\n createdAt: string;\n updatedAt: string;\n workspaceId?: string;\n environmentId?: string;\n sourcePath: string;\n payloadPath: string;\n namespace?: string;\n}\n\ninterface WorkspaceRecord {\n workspaceId: string;\n rootPath?: string;\n}\n\nexport class LocalFsSnapshotAdapter implements ISnapshotProvider {\n private readonly cwd: string;\n private readonly storageDir: string;\n private readonly workspaceRegistryDir: string;\n private readonly records = new Map<string, SnapshotRecord>();\n\n constructor(private readonly config: LocalFsSnapshotAdapterConfig = {}) {\n this.cwd = path.resolve(config.workspace?.cwd ?? process.cwd());\n this.storageDir = path.resolve(this.cwd, config.storageDir ?? '.kb/runtime/snapshots');\n this.workspaceRegistryDir = path.resolve(\n this.cwd,\n config.workspaceRegistryDir ?? '.kb/runtime/workspace-registry'\n );\n }\n\n async capture(request: CaptureSnapshotRequest): Promise<SnapshotDescriptor> {\n const snapshotId = request.snapshotId ?? `snap_${randomUUID()}`;\n const now = new Date().toISOString();\n const sourcePath = await this.resolveSourcePath(request);\n const namespace = request.namespace ?? 'default';\n const payloadPath = path.join(this.storageDir, namespace, snapshotId);\n\n await mkdir(path.dirname(payloadPath), { recursive: true });\n await rm(payloadPath, { recursive: true, force: true });\n await cp(sourcePath, payloadPath, { recursive: true, force: true });\n\n const record: SnapshotRecord = {\n snapshotId,\n status: 'ready',\n createdAt: now,\n updatedAt: now,\n workspaceId: request.workspaceId,\n environmentId: request.environmentId,\n sourcePath,\n payloadPath,\n namespace,\n };\n\n await this.persistRecord(record);\n\n return {\n snapshotId,\n provider: 'snapshot-localfs',\n status: 'ready',\n createdAt: now,\n updatedAt: now,\n workspaceId: request.workspaceId,\n environmentId: request.environmentId,\n metadata: {\n namespace,\n payloadPath,\n },\n };\n }\n\n async restore(request: RestoreSnapshotRequest): Promise<RestoreSnapshotResult> {\n const record = await this.getRecordOrThrow(request.snapshotId);\n const now = new Date().toISOString();\n\n const targetPath = request.targetPath\n ? path.resolve(this.cwd, request.targetPath)\n : await this.resolveRestoreTargetPath(request.workspaceId, record.workspaceId);\n\n if (!request.overwrite) {\n try {\n await access(targetPath);\n throw new Error(`Restore target already exists: ${targetPath}. Use overwrite=true.`);\n } catch (error) {\n if (error instanceof Error && error.message.startsWith('Restore target already exists')) {\n throw error;\n }\n // path missing, continue\n }\n }\n\n if (request.overwrite) {\n await rm(targetPath, { recursive: true, force: true });\n }\n\n await mkdir(path.dirname(targetPath), { recursive: true });\n await cp(record.payloadPath, targetPath, { recursive: true, force: true });\n\n record.status = 'ready';\n record.updatedAt = now;\n await this.persistRecord(record);\n\n return {\n snapshotId: request.snapshotId,\n restoredAt: now,\n workspaceId: request.workspaceId,\n environmentId: request.environmentId,\n targetPath,\n };\n }\n\n async getStatus(snapshotId: string): Promise<SnapshotStatusResult> {\n const record = await this.getRecordOrThrow(snapshotId);\n return {\n snapshotId,\n status: record.status,\n updatedAt: record.updatedAt,\n };\n }\n\n async delete(snapshotId: string): Promise<void> {\n const record = await this.getRecordOrThrow(snapshotId);\n await rm(record.payloadPath, { recursive: true, force: true });\n this.records.delete(snapshotId);\n await rm(this.getRecordPath(snapshotId), { force: true });\n }\n\n async garbageCollect(\n request: SnapshotGarbageCollectRequest = {}\n ): Promise<SnapshotGarbageCollectResult> {\n const beforeTs = request.before ? new Date(request.before).getTime() : Number.POSITIVE_INFINITY;\n const limit = request.limit ?? Number.POSITIVE_INFINITY;\n const dryRun = request.dryRun ?? false;\n let scanned = 0;\n let deleted = 0;\n\n for (const record of await this.loadAllRecords()) {\n scanned += 1;\n const createdTs = new Date(record.createdAt).getTime();\n if (createdTs >= beforeTs) {\n continue;\n }\n if (request.namespace && record.namespace !== request.namespace) {\n continue;\n }\n if (deleted >= limit) {\n break;\n }\n\n if (!dryRun) {\n await this.delete(record.snapshotId);\n }\n deleted += 1;\n }\n\n return { scanned, deleted, dryRun };\n }\n\n getCapabilities(): SnapshotProviderCapabilities {\n return {\n supportsWorkspaceSnapshots: true,\n supportsEnvironmentSnapshots: false,\n supportsGarbageCollection: true,\n supportsIncrementalSnapshots: false,\n custom: {\n provider: 'localfs',\n },\n };\n }\n\n private async resolveSourcePath(request: CaptureSnapshotRequest): Promise<string> {\n if (request.sourcePath) {\n return path.resolve(this.cwd, request.sourcePath);\n }\n\n if (request.workspaceId) {\n const workspace = await this.readWorkspaceRecord(request.workspaceId);\n if (workspace.rootPath) {\n return workspace.rootPath;\n }\n }\n\n throw new Error('Snapshot capture requires sourcePath or resolvable workspaceId');\n }\n\n private async resolveRestoreTargetPath(\n requestedWorkspaceId?: string,\n recordWorkspaceId?: string\n ): Promise<string> {\n const workspaceId = requestedWorkspaceId ?? recordWorkspaceId;\n if (!workspaceId) {\n throw new Error('Snapshot restore requires targetPath or workspaceId');\n }\n const workspace = await this.readWorkspaceRecord(workspaceId);\n if (!workspace.rootPath) {\n throw new Error(`Workspace rootPath not found for workspaceId=${workspaceId}`);\n }\n return workspace.rootPath;\n }\n\n private getRecordPath(snapshotId: string): string {\n return path.join(this.storageDir, '.records', `${snapshotId}.json`);\n }\n\n private async persistRecord(record: SnapshotRecord): Promise<void> {\n this.records.set(record.snapshotId, record);\n const recordPath = this.getRecordPath(record.snapshotId);\n await mkdir(path.dirname(recordPath), { recursive: true });\n await writeFile(recordPath, JSON.stringify(record, null, 2), 'utf8');\n }\n\n private async getRecordOrThrow(snapshotId: string): Promise<SnapshotRecord> {\n const inMemory = this.records.get(snapshotId);\n if (inMemory) {\n return inMemory;\n }\n\n const recordPath = this.getRecordPath(snapshotId);\n try {\n const raw = await readFile(recordPath, 'utf8');\n const parsed = JSON.parse(raw) as SnapshotRecord;\n this.records.set(snapshotId, parsed);\n return parsed;\n } catch {\n throw new Error(`Snapshot not found: ${snapshotId}`);\n }\n }\n\n private async readWorkspaceRecord(workspaceId: string): Promise<WorkspaceRecord> {\n const filePath = path.join(this.workspaceRegistryDir, `${workspaceId}.json`);\n const raw = await readFile(filePath, 'utf8');\n return JSON.parse(raw) as WorkspaceRecord;\n }\n\n private async loadAllRecords(): Promise<SnapshotRecord[]> {\n const recordsDir = path.join(this.storageDir, '.records');\n try {\n const entries = await readdir(recordsDir);\n const loaded: SnapshotRecord[] = [];\n for (const entry of entries) {\n if (!entry.endsWith('.json')) {\n continue;\n }\n const filePath = path.join(recordsDir, entry);\n const fileStat = await stat(filePath);\n if (!fileStat.isFile()) {\n continue;\n }\n const raw = await readFile(filePath, 'utf8');\n loaded.push(JSON.parse(raw) as SnapshotRecord);\n }\n return loaded;\n } catch {\n return [];\n }\n }\n}\n\nexport function createAdapter(config?: LocalFsSnapshotAdapterConfig): LocalFsSnapshotAdapter {\n return new LocalFsSnapshotAdapter(config);\n}\n\nexport default createAdapter;\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/manifest.ts"],"names":[],"mappings":";AAEO,IAAM,QAAA,GAA4B;AAAA,EACvC,eAAA,EAAiB,OAAA;AAAA,EACjB,EAAA,EAAI,2BAAA;AAAA,EACJ,IAAA,EAAM,2BAAA;AAAA,EACN,OAAA,EAAS,OAAA;AAAA,EACT,WAAA,EAAa,uCAAA;AAAA,EACb,MAAA,EAAQ,cAAA;AAAA,EACR,OAAA,EAAS,UAAA;AAAA,EACT,IAAA,EAAM,MAAA;AAAA,EACN,UAAA,EAAY,mBAAA;AAAA,EACZ,QAAA,EAAU,CAAC,WAAW,CAAA;AAAA,EACtB,YAAA,EAAc;AAAA,IACZ,MAAA,EAAQ;AAAA,MACN,QAAA,EAAU,SAAA;AAAA,MACV,iBAAA,EAAmB;AAAA;AACrB,GACF;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,UAAA,EAAY;AAAA,MACV,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,uBAAA;AAAA,MACT,WAAA,EAAa;AAAA,KACf;AAAA,IACA,oBAAA,EAAsB;AAAA,MACpB,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,gCAAA;AAAA,MACT,WAAA,EAAa;AAAA;AACf;AAEJ","file":"manifest.js","sourcesContent":["import type { AdapterManifest } from '@kb-labs/core-platform';\n\nexport const manifest: AdapterManifest = {\n manifestVersion: '1.0.0',\n id: 'localfs-snapshot-provider',\n name: 'LocalFS Snapshot Provider',\n version: '0.1.0',\n description: 'Snapshot provider on local filesystem',\n author: 'KB Labs Team',\n license: 'KBPL-1.1',\n type: 'core',\n implements: 'ISnapshotProvider',\n contexts: ['workspace'],\n capabilities: {\n custom: {\n provider: 'localfs',\n workspaceRegistry: true,\n },\n },\n configSchema: {\n storageDir: {\n type: 'string',\n default: '.kb/runtime/snapshots',\n description: 'Root directory where snapshots are stored',\n },\n workspaceRegistryDir: {\n type: 'string',\n default: '.kb/runtime/workspace-registry',\n description: 'Directory with workspace metadata for source path resolution',\n },\n },\n};\n"]}
1
+ {"version":3,"sources":["../../../../../../Users/kirillbaranov/Desktop/kb-labs-workspace/adapters/snapshot-localfs/src/manifest.ts"],"names":[],"mappings":";AAEO,IAAM,QAAA,GAA4B;AAAA,EACvC,eAAA,EAAiB,OAAA;AAAA,EACjB,EAAA,EAAI,2BAAA;AAAA,EACJ,IAAA,EAAM,2BAAA;AAAA,EACN,OAAA,EAAS,OAAA;AAAA,EACT,WAAA,EAAa,uCAAA;AAAA,EACb,MAAA,EAAQ,cAAA;AAAA,EACR,OAAA,EAAS,UAAA;AAAA,EACT,IAAA,EAAM,MAAA;AAAA,EACN,UAAA,EAAY,mBAAA;AAAA,EACZ,QAAA,EAAU,CAAC,WAAW,CAAA;AAAA,EACtB,YAAA,EAAc;AAAA,IACZ,MAAA,EAAQ;AAAA,MACN,QAAA,EAAU,SAAA;AAAA,MACV,iBAAA,EAAmB;AAAA;AACrB,GACF;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,UAAA,EAAY;AAAA,MACV,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,uBAAA;AAAA,MACT,WAAA,EAAa;AAAA,KACf;AAAA,IACA,oBAAA,EAAsB;AAAA,MACpB,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,gCAAA;AAAA,MACT,WAAA,EAAa;AAAA;AACf;AAEJ","file":"manifest.js","sourcesContent":["import type { AdapterManifest } from '@kb-labs/core-platform';\n\nexport const manifest: AdapterManifest = {\n manifestVersion: '1.0.0',\n id: 'localfs-snapshot-provider',\n name: 'LocalFS Snapshot Provider',\n version: '0.1.0',\n description: 'Snapshot provider on local filesystem',\n author: 'KB Labs Team',\n license: 'KBPL-1.1',\n type: 'core',\n implements: 'ISnapshotProvider',\n contexts: ['workspace'],\n capabilities: {\n custom: {\n provider: 'localfs',\n workspaceRegistry: true,\n },\n },\n configSchema: {\n storageDir: {\n type: 'string',\n default: '.kb/runtime/snapshots',\n description: 'Root directory where snapshots are stored',\n },\n workspaceRegistryDir: {\n type: 'string',\n default: '.kb/runtime/workspace-registry',\n description: 'Directory with workspace metadata for source path resolution',\n },\n },\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kb-labs/adapters-snapshot-localfs",
3
- "version": "2.6.0",
3
+ "version": "2.9.0",
4
4
  "description": "Local filesystem adapter implementing ISnapshotProvider",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -20,28 +20,18 @@
20
20
  "README.md"
21
21
  ],
22
22
  "sideEffects": false,
23
- "scripts": {
24
- "clean": "rimraf dist",
25
- "build": "tsup",
26
- "dev": "tsup --watch",
27
- "type-check": "tsc --noEmit",
28
- "test": "vitest run --passWithNoTests",
29
- "test:watch": "vitest",
30
- "lint": "eslint src --ext .ts",
31
- "lint:fix": "eslint . --fix"
32
- },
33
23
  "peerDependencies": {
34
- "@kb-labs/core-platform": "^2.6.0"
24
+ "@kb-labs/core-platform": "2.9.0"
35
25
  },
36
26
  "devDependencies": {
37
- "@kb-labs/core-platform": "workspace:*",
38
27
  "@types/node": "^24.3.3",
39
28
  "eslint": "^9",
40
29
  "tsup": "^8.5.0",
41
30
  "typescript": "^5.6.3",
42
31
  "vitest": "^3.2.4",
43
- "@kb-labs/devkit": "workspace:*",
44
- "rimraf": "^6.0.1"
32
+ "rimraf": "^6.0.1",
33
+ "@kb-labs/core-platform": "2.9.0",
34
+ "@kb-labs/devkit": "2.9.0"
45
35
  },
46
36
  "engines": {
47
37
  "node": ">=20.0.0",
@@ -49,5 +39,15 @@
49
39
  },
50
40
  "kb": {
51
41
  "manifest": "./dist/manifest.js"
42
+ },
43
+ "scripts": {
44
+ "clean": "rimraf dist",
45
+ "build": "tsup",
46
+ "dev": "tsup --watch",
47
+ "type-check": "tsc --noEmit",
48
+ "test": "vitest run --passWithNoTests",
49
+ "test:watch": "vitest",
50
+ "lint": "eslint src --ext .ts",
51
+ "lint:fix": "eslint . --fix"
52
52
  }
53
- }
53
+ }