@soulcraft/brainy 6.2.2 → 6.2.3
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/augmentations/KnowledgeAugmentation.d.ts +40 -0
- package/dist/augmentations/KnowledgeAugmentation.js +251 -0
- package/dist/importManager.d.ts +78 -0
- package/dist/importManager.js +267 -0
- package/dist/query/typeInference.d.ts +158 -0
- package/dist/query/typeInference.js +760 -0
- package/dist/storage/adapters/typeAwareStorageAdapter.d.ts +252 -0
- package/dist/storage/adapters/typeAwareStorageAdapter.js +814 -0
- package/dist/storage/baseStorage.d.ts +12 -0
- package/dist/storage/baseStorage.js +16 -0
- package/dist/types/brainyDataInterface.d.ts +52 -0
- package/dist/types/brainyDataInterface.js +10 -0
- package/dist/utils/metadataIndex.d.ts +6 -2
- package/dist/utils/metadataIndex.js +31 -14
- package/dist/vfs/ConceptSystem.d.ts +203 -0
- package/dist/vfs/ConceptSystem.js +545 -0
- package/dist/vfs/EntityManager.d.ts +75 -0
- package/dist/vfs/EntityManager.js +216 -0
- package/dist/vfs/EventRecorder.d.ts +84 -0
- package/dist/vfs/EventRecorder.js +269 -0
- package/dist/vfs/GitBridge.d.ts +167 -0
- package/dist/vfs/GitBridge.js +537 -0
- package/dist/vfs/KnowledgeLayer.d.ts +35 -0
- package/dist/vfs/KnowledgeLayer.js +443 -0
- package/dist/vfs/PersistentEntitySystem.d.ts +165 -0
- package/dist/vfs/PersistentEntitySystem.js +503 -0
- package/dist/vfs/SemanticVersioning.d.ts +105 -0
- package/dist/vfs/SemanticVersioning.js +309 -0
- package/package.json +1 -1
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Bridge for VFS
|
|
3
|
+
*
|
|
4
|
+
* Provides Git import/export capabilities without Git dependencies
|
|
5
|
+
* Enables migration to/from Git repositories while preserving VFS intelligence
|
|
6
|
+
* PRODUCTION-READY: Real implementation using filesystem operations
|
|
7
|
+
*/
|
|
8
|
+
import { VirtualFileSystem } from './VirtualFileSystem.js';
|
|
9
|
+
import { Brainy } from '../brainy.js';
|
|
10
|
+
/**
|
|
11
|
+
* Git repository representation
|
|
12
|
+
*/
|
|
13
|
+
export interface GitRepository {
|
|
14
|
+
path: string;
|
|
15
|
+
branches: GitBranch[];
|
|
16
|
+
commits: GitCommit[];
|
|
17
|
+
files: GitFile[];
|
|
18
|
+
metadata: {
|
|
19
|
+
name: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
origin?: string;
|
|
22
|
+
lastImported?: number;
|
|
23
|
+
vfsMetadata?: Record<string, any>;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Git branch information
|
|
28
|
+
*/
|
|
29
|
+
export interface GitBranch {
|
|
30
|
+
name: string;
|
|
31
|
+
commitHash: string;
|
|
32
|
+
isActive: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Git commit information
|
|
36
|
+
*/
|
|
37
|
+
export interface GitCommit {
|
|
38
|
+
hash: string;
|
|
39
|
+
message: string;
|
|
40
|
+
author: string;
|
|
41
|
+
email: string;
|
|
42
|
+
timestamp: number;
|
|
43
|
+
parent?: string;
|
|
44
|
+
files: string[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Git file representation
|
|
48
|
+
*/
|
|
49
|
+
export interface GitFile {
|
|
50
|
+
path: string;
|
|
51
|
+
content: Buffer;
|
|
52
|
+
hash: string;
|
|
53
|
+
mode: string;
|
|
54
|
+
size: number;
|
|
55
|
+
lastModified: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Export options
|
|
59
|
+
*/
|
|
60
|
+
export interface ExportOptions {
|
|
61
|
+
preserveMetadata?: boolean;
|
|
62
|
+
preserveRelationships?: boolean;
|
|
63
|
+
preserveHistory?: boolean;
|
|
64
|
+
branch?: string;
|
|
65
|
+
commitMessage?: string;
|
|
66
|
+
author?: {
|
|
67
|
+
name: string;
|
|
68
|
+
email: string;
|
|
69
|
+
};
|
|
70
|
+
includeSystemFiles?: boolean;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Import options
|
|
74
|
+
*/
|
|
75
|
+
export interface ImportOptions {
|
|
76
|
+
preserveGitHistory?: boolean;
|
|
77
|
+
extractMetadata?: boolean;
|
|
78
|
+
restoreRelationships?: boolean;
|
|
79
|
+
includeSystemFiles?: boolean;
|
|
80
|
+
branch?: string;
|
|
81
|
+
since?: number;
|
|
82
|
+
author?: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Git Bridge - Import/Export between VFS and Git repositories
|
|
86
|
+
*
|
|
87
|
+
* Capabilities:
|
|
88
|
+
* - Export VFS to standard Git repository structure
|
|
89
|
+
* - Import Git repository into VFS with intelligence
|
|
90
|
+
* - Preserve VFS metadata and relationships
|
|
91
|
+
* - Convert Git history to VFS events
|
|
92
|
+
* - No Git dependencies - pure filesystem operations
|
|
93
|
+
*/
|
|
94
|
+
export declare class GitBridge {
|
|
95
|
+
private vfs;
|
|
96
|
+
private brain;
|
|
97
|
+
constructor(vfs: VirtualFileSystem, brain: Brainy);
|
|
98
|
+
/**
|
|
99
|
+
* Export VFS to Git repository structure
|
|
100
|
+
*/
|
|
101
|
+
exportToGit(vfsPath: string, gitRepoPath: string, options?: ExportOptions): Promise<GitRepository>;
|
|
102
|
+
/**
|
|
103
|
+
* Import Git repository into VFS
|
|
104
|
+
*/
|
|
105
|
+
importFromGit(gitRepoPath: string, vfsPath: string, options?: ImportOptions): Promise<{
|
|
106
|
+
filesImported: number;
|
|
107
|
+
eventsCreated: number;
|
|
108
|
+
entitiesCreated: number;
|
|
109
|
+
relationshipsCreated: number;
|
|
110
|
+
}>;
|
|
111
|
+
/**
|
|
112
|
+
* Export directory recursively
|
|
113
|
+
*/
|
|
114
|
+
private exportDirectory;
|
|
115
|
+
/**
|
|
116
|
+
* Export VFS metadata to .vfs-metadata.json
|
|
117
|
+
*/
|
|
118
|
+
private exportMetadata;
|
|
119
|
+
/**
|
|
120
|
+
* Export relationships to .vfs-relationships.json
|
|
121
|
+
*/
|
|
122
|
+
private exportRelationships;
|
|
123
|
+
/**
|
|
124
|
+
* Export history to .vfs-history.json
|
|
125
|
+
*/
|
|
126
|
+
private exportHistory;
|
|
127
|
+
/**
|
|
128
|
+
* Collect metadata recursively
|
|
129
|
+
*/
|
|
130
|
+
private collectFileMetadata;
|
|
131
|
+
/**
|
|
132
|
+
* Read Git repository structure
|
|
133
|
+
*/
|
|
134
|
+
private readGitRepository;
|
|
135
|
+
/**
|
|
136
|
+
* Scan Git files recursively
|
|
137
|
+
*/
|
|
138
|
+
private scanGitFiles;
|
|
139
|
+
/**
|
|
140
|
+
* Import metadata from exported data
|
|
141
|
+
*/
|
|
142
|
+
private importMetadata;
|
|
143
|
+
/**
|
|
144
|
+
* Import relationships
|
|
145
|
+
*/
|
|
146
|
+
private importRelationships;
|
|
147
|
+
/**
|
|
148
|
+
* Import history from exported data
|
|
149
|
+
*/
|
|
150
|
+
private importHistory;
|
|
151
|
+
/**
|
|
152
|
+
* Convert Git commits to VFS events
|
|
153
|
+
*/
|
|
154
|
+
private convertCommitsToEvents;
|
|
155
|
+
/**
|
|
156
|
+
* Generate commit hash
|
|
157
|
+
*/
|
|
158
|
+
private generateCommitHash;
|
|
159
|
+
/**
|
|
160
|
+
* Write repository metadata
|
|
161
|
+
*/
|
|
162
|
+
private writeRepoMetadata;
|
|
163
|
+
/**
|
|
164
|
+
* Record Git bridge event
|
|
165
|
+
*/
|
|
166
|
+
private recordGitEvent;
|
|
167
|
+
}
|
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Bridge for VFS
|
|
3
|
+
*
|
|
4
|
+
* Provides Git import/export capabilities without Git dependencies
|
|
5
|
+
* Enables migration to/from Git repositories while preserving VFS intelligence
|
|
6
|
+
* PRODUCTION-READY: Real implementation using filesystem operations
|
|
7
|
+
*/
|
|
8
|
+
import { NounType } from '../types/graphTypes.js';
|
|
9
|
+
import { v4 as uuidv4 } from '../universal/uuid.js';
|
|
10
|
+
import { createHash } from 'crypto';
|
|
11
|
+
import { promises as fs } from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
/**
|
|
14
|
+
* Git Bridge - Import/Export between VFS and Git repositories
|
|
15
|
+
*
|
|
16
|
+
* Capabilities:
|
|
17
|
+
* - Export VFS to standard Git repository structure
|
|
18
|
+
* - Import Git repository into VFS with intelligence
|
|
19
|
+
* - Preserve VFS metadata and relationships
|
|
20
|
+
* - Convert Git history to VFS events
|
|
21
|
+
* - No Git dependencies - pure filesystem operations
|
|
22
|
+
*/
|
|
23
|
+
export class GitBridge {
|
|
24
|
+
constructor(vfs, brain) {
|
|
25
|
+
this.vfs = vfs;
|
|
26
|
+
this.brain = brain;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Export VFS to Git repository structure
|
|
30
|
+
*/
|
|
31
|
+
async exportToGit(vfsPath, gitRepoPath, options) {
|
|
32
|
+
// Ensure target directory exists
|
|
33
|
+
await fs.mkdir(gitRepoPath, { recursive: true });
|
|
34
|
+
const exportId = uuidv4();
|
|
35
|
+
const timestamp = Date.now();
|
|
36
|
+
const files = [];
|
|
37
|
+
// Initialize Git repository metadata
|
|
38
|
+
const gitRepo = {
|
|
39
|
+
path: gitRepoPath,
|
|
40
|
+
branches: [{ name: options?.branch || 'main', commitHash: '', isActive: true }],
|
|
41
|
+
commits: [],
|
|
42
|
+
files: [],
|
|
43
|
+
metadata: {
|
|
44
|
+
name: path.basename(gitRepoPath),
|
|
45
|
+
description: `Exported from Brainy VFS on ${new Date().toISOString()}`,
|
|
46
|
+
lastImported: timestamp,
|
|
47
|
+
vfsMetadata: {
|
|
48
|
+
exportId,
|
|
49
|
+
sourcePath: vfsPath,
|
|
50
|
+
options
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
// Export files recursively
|
|
55
|
+
await this.exportDirectory(vfsPath, gitRepoPath, '', files, options);
|
|
56
|
+
// Create .vfs-metadata file if preserving metadata
|
|
57
|
+
if (options?.preserveMetadata) {
|
|
58
|
+
await this.exportMetadata(vfsPath, gitRepoPath, options);
|
|
59
|
+
}
|
|
60
|
+
// Create .vfs-relationships file if preserving relationships
|
|
61
|
+
if (options?.preserveRelationships) {
|
|
62
|
+
await this.exportRelationships(vfsPath, gitRepoPath, options);
|
|
63
|
+
}
|
|
64
|
+
// Create .vfs-history file if preserving history
|
|
65
|
+
if (options?.preserveHistory) {
|
|
66
|
+
await this.exportHistory(vfsPath, gitRepoPath, options);
|
|
67
|
+
}
|
|
68
|
+
// Create initial commit metadata
|
|
69
|
+
const commitHash = this.generateCommitHash(files);
|
|
70
|
+
const commit = {
|
|
71
|
+
hash: commitHash,
|
|
72
|
+
message: options?.commitMessage || `Export from Brainy VFS: ${vfsPath}`,
|
|
73
|
+
author: options?.author?.name || 'VFS Export',
|
|
74
|
+
email: options?.author?.email || 'vfs@brainy.local',
|
|
75
|
+
timestamp,
|
|
76
|
+
files: files.map(f => f.path)
|
|
77
|
+
};
|
|
78
|
+
gitRepo.commits = [commit];
|
|
79
|
+
gitRepo.branches[0].commitHash = commitHash;
|
|
80
|
+
gitRepo.files = files;
|
|
81
|
+
// Write repository metadata
|
|
82
|
+
await this.writeRepoMetadata(gitRepoPath, gitRepo);
|
|
83
|
+
// Record export event
|
|
84
|
+
await this.recordGitEvent('export', {
|
|
85
|
+
vfsPath,
|
|
86
|
+
gitRepoPath,
|
|
87
|
+
commitHash,
|
|
88
|
+
fileCount: files.length,
|
|
89
|
+
options
|
|
90
|
+
});
|
|
91
|
+
return gitRepo;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Import Git repository into VFS
|
|
95
|
+
*/
|
|
96
|
+
async importFromGit(gitRepoPath, vfsPath, options) {
|
|
97
|
+
const stats = {
|
|
98
|
+
filesImported: 0,
|
|
99
|
+
eventsCreated: 0,
|
|
100
|
+
entitiesCreated: 0,
|
|
101
|
+
relationshipsCreated: 0
|
|
102
|
+
};
|
|
103
|
+
// Read repository structure
|
|
104
|
+
const gitRepo = await this.readGitRepository(gitRepoPath);
|
|
105
|
+
// Import files
|
|
106
|
+
for (const gitFile of gitRepo.files) {
|
|
107
|
+
// Skip system files unless requested
|
|
108
|
+
if (!options?.includeSystemFiles && gitFile.path.startsWith('.vfs-')) {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const targetPath = path.join(vfsPath, gitFile.path);
|
|
112
|
+
// Create directory structure
|
|
113
|
+
const dirPath = path.dirname(targetPath);
|
|
114
|
+
if (dirPath !== vfsPath) {
|
|
115
|
+
try {
|
|
116
|
+
await this.vfs.mkdir(dirPath, { recursive: true });
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
// Directory might already exist
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Write file
|
|
123
|
+
await this.vfs.writeFile(targetPath, gitFile.content, {
|
|
124
|
+
metadata: {
|
|
125
|
+
gitHash: gitFile.hash,
|
|
126
|
+
gitMode: gitFile.mode,
|
|
127
|
+
importedFrom: gitRepoPath,
|
|
128
|
+
importedAt: Date.now()
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
stats.filesImported++;
|
|
132
|
+
}
|
|
133
|
+
// Import metadata if available and requested
|
|
134
|
+
if (options?.extractMetadata) {
|
|
135
|
+
const metadataFile = path.join(gitRepoPath, '.vfs-metadata.json');
|
|
136
|
+
try {
|
|
137
|
+
const metadataContent = await fs.readFile(metadataFile, 'utf8');
|
|
138
|
+
const metadata = JSON.parse(metadataContent);
|
|
139
|
+
await this.importMetadata(vfsPath, metadata);
|
|
140
|
+
stats.entitiesCreated += Object.keys(metadata.entities || {}).length;
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
// No metadata file or invalid format
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Import relationships if available and requested
|
|
147
|
+
if (options?.restoreRelationships) {
|
|
148
|
+
const relationshipsFile = path.join(gitRepoPath, '.vfs-relationships.json');
|
|
149
|
+
try {
|
|
150
|
+
const relationshipsContent = await fs.readFile(relationshipsFile, 'utf8');
|
|
151
|
+
const relationships = JSON.parse(relationshipsContent);
|
|
152
|
+
await this.importRelationships(relationships);
|
|
153
|
+
stats.relationshipsCreated += relationships.length || 0;
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
// No relationships file or invalid format
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Import Git history as VFS events if requested
|
|
160
|
+
if (options?.preserveGitHistory) {
|
|
161
|
+
const historyFile = path.join(gitRepoPath, '.vfs-history.json');
|
|
162
|
+
try {
|
|
163
|
+
const historyContent = await fs.readFile(historyFile, 'utf8');
|
|
164
|
+
const history = JSON.parse(historyContent);
|
|
165
|
+
stats.eventsCreated = await this.importHistory(vfsPath, history);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
// Convert Git commits to VFS events
|
|
169
|
+
stats.eventsCreated = await this.convertCommitsToEvents(vfsPath, gitRepo.commits);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Record import event
|
|
173
|
+
await this.recordGitEvent('import', {
|
|
174
|
+
gitRepoPath,
|
|
175
|
+
vfsPath,
|
|
176
|
+
stats,
|
|
177
|
+
options
|
|
178
|
+
});
|
|
179
|
+
return stats;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Export directory recursively
|
|
183
|
+
*/
|
|
184
|
+
async exportDirectory(vfsPath, gitRepoPath, relativePath, files, options) {
|
|
185
|
+
const currentPath = relativePath ? path.join(vfsPath, relativePath) : vfsPath;
|
|
186
|
+
try {
|
|
187
|
+
// Check if path exists in VFS
|
|
188
|
+
const exists = await this.vfs.exists(currentPath);
|
|
189
|
+
if (!exists)
|
|
190
|
+
return;
|
|
191
|
+
// Get directory contents
|
|
192
|
+
const entries = await this.vfs.readdir(currentPath, { withFileTypes: true });
|
|
193
|
+
for (const entry of entries) {
|
|
194
|
+
const entryVfsPath = path.join(currentPath, entry.name);
|
|
195
|
+
const entryRelativePath = relativePath ? path.join(relativePath, entry.name) : entry.name;
|
|
196
|
+
const entryGitPath = path.join(gitRepoPath, entryRelativePath);
|
|
197
|
+
if (entry.type === 'directory') {
|
|
198
|
+
// Create directory in Git repo
|
|
199
|
+
await fs.mkdir(entryGitPath, { recursive: true });
|
|
200
|
+
// Recurse into subdirectory
|
|
201
|
+
await this.exportDirectory(vfsPath, gitRepoPath, entryRelativePath, files, options);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
// Export file
|
|
205
|
+
const content = await this.vfs.readFile(entryVfsPath);
|
|
206
|
+
const stats = await this.vfs.stat(entryVfsPath);
|
|
207
|
+
// Write file to Git repo
|
|
208
|
+
await fs.writeFile(entryGitPath, content);
|
|
209
|
+
// Add to files list
|
|
210
|
+
const gitFile = {
|
|
211
|
+
path: entryRelativePath,
|
|
212
|
+
content,
|
|
213
|
+
hash: createHash('sha1').update(content).digest('hex'),
|
|
214
|
+
mode: stats.mode?.toString(8) || '100644',
|
|
215
|
+
size: content.length,
|
|
216
|
+
lastModified: stats.mtime?.getTime() || Date.now()
|
|
217
|
+
};
|
|
218
|
+
files.push(gitFile);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
console.warn(`Failed to export directory ${currentPath}:`, error);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Export VFS metadata to .vfs-metadata.json
|
|
228
|
+
*/
|
|
229
|
+
async exportMetadata(vfsPath, gitRepoPath, options) {
|
|
230
|
+
const metadata = {
|
|
231
|
+
exportedAt: Date.now(),
|
|
232
|
+
vfsPath,
|
|
233
|
+
version: '1.0',
|
|
234
|
+
entities: {},
|
|
235
|
+
files: {}
|
|
236
|
+
};
|
|
237
|
+
// Collect metadata for all files
|
|
238
|
+
await this.collectFileMetadata(vfsPath, '', metadata);
|
|
239
|
+
// Write metadata file
|
|
240
|
+
const metadataPath = path.join(gitRepoPath, '.vfs-metadata.json');
|
|
241
|
+
await fs.writeFile(metadataPath, JSON.stringify(metadata, null, 2));
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Export relationships to .vfs-relationships.json
|
|
245
|
+
*/
|
|
246
|
+
async exportRelationships(vfsPath, gitRepoPath, options) {
|
|
247
|
+
// Get all relationships for files in the VFS path
|
|
248
|
+
const relationships = [];
|
|
249
|
+
try {
|
|
250
|
+
// Get relationships for the specified path and its children
|
|
251
|
+
const related = await this.vfs.getRelated(vfsPath);
|
|
252
|
+
if (related && related.length > 0) {
|
|
253
|
+
relationships.push({
|
|
254
|
+
path: vfsPath,
|
|
255
|
+
relationships: related
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
// If it's a directory, get relationships for all files within
|
|
259
|
+
const stats = await this.vfs.stat(vfsPath);
|
|
260
|
+
if (stats.isDirectory()) {
|
|
261
|
+
const files = await this.vfs.readdir(vfsPath, { recursive: true });
|
|
262
|
+
for (const file of files) {
|
|
263
|
+
const fileName = typeof file === 'string' ? file : file.name;
|
|
264
|
+
const fullPath = path.join(vfsPath, fileName);
|
|
265
|
+
try {
|
|
266
|
+
const fileRelated = await this.vfs.getRelated(fullPath);
|
|
267
|
+
if (fileRelated && fileRelated.length > 0) {
|
|
268
|
+
relationships.push({
|
|
269
|
+
path: fullPath,
|
|
270
|
+
relationships: fileRelated
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
catch (err) {
|
|
275
|
+
// Skip files without relationships
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
catch (err) {
|
|
281
|
+
// Path might not have relationships
|
|
282
|
+
}
|
|
283
|
+
// Write relationships file
|
|
284
|
+
const relationshipsPath = path.join(gitRepoPath, '.vfs-relationships.json');
|
|
285
|
+
await fs.writeFile(relationshipsPath, JSON.stringify(relationships, null, 2));
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Export history to .vfs-history.json
|
|
289
|
+
*/
|
|
290
|
+
async exportHistory(vfsPath, gitRepoPath, options) {
|
|
291
|
+
// Get event history for the VFS path
|
|
292
|
+
const history = {
|
|
293
|
+
exportedAt: Date.now(),
|
|
294
|
+
vfsPath,
|
|
295
|
+
events: []
|
|
296
|
+
};
|
|
297
|
+
// Get history if Knowledge Layer is enabled
|
|
298
|
+
if ('getHistory' in this.vfs && typeof this.vfs.getHistory === 'function') {
|
|
299
|
+
try {
|
|
300
|
+
const events = await this.vfs.getHistory(vfsPath);
|
|
301
|
+
if (events) {
|
|
302
|
+
history.events = events;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
catch (err) {
|
|
306
|
+
// Knowledge Layer might not be enabled
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// Write history file
|
|
310
|
+
const historyPath = path.join(gitRepoPath, '.vfs-history.json');
|
|
311
|
+
await fs.writeFile(historyPath, JSON.stringify(history, null, 2));
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Collect metadata recursively
|
|
315
|
+
*/
|
|
316
|
+
async collectFileMetadata(vfsPath, relativePath, metadata) {
|
|
317
|
+
const currentPath = relativePath ? path.join(vfsPath, relativePath) : vfsPath;
|
|
318
|
+
try {
|
|
319
|
+
const entries = await this.vfs.readdir(currentPath, { withFileTypes: true });
|
|
320
|
+
for (const entry of entries) {
|
|
321
|
+
const entryPath = path.join(currentPath, entry.name);
|
|
322
|
+
const entryRelativePath = relativePath ? path.join(relativePath, entry.name) : entry.name;
|
|
323
|
+
if (entry.type === 'directory') {
|
|
324
|
+
await this.collectFileMetadata(vfsPath, entryRelativePath, metadata);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
const stats = await this.vfs.stat(entryPath);
|
|
328
|
+
metadata.files[entryRelativePath] = {
|
|
329
|
+
size: stats.size,
|
|
330
|
+
mtime: stats.mtime,
|
|
331
|
+
ctime: stats.ctime,
|
|
332
|
+
mode: stats.mode,
|
|
333
|
+
metadata: stats.metadata || {}
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
console.warn(`Failed to collect metadata for ${currentPath}:`, error);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Read Git repository structure
|
|
344
|
+
*/
|
|
345
|
+
async readGitRepository(gitRepoPath) {
|
|
346
|
+
// Read repository metadata if available
|
|
347
|
+
const metadataPath = path.join(gitRepoPath, '.vfs-repo-metadata.json');
|
|
348
|
+
let metadata = {
|
|
349
|
+
name: path.basename(gitRepoPath),
|
|
350
|
+
description: 'Imported Git repository',
|
|
351
|
+
branches: [{ name: 'main', commitHash: '', isActive: true }],
|
|
352
|
+
commits: []
|
|
353
|
+
};
|
|
354
|
+
try {
|
|
355
|
+
const metadataContent = await fs.readFile(metadataPath, 'utf8');
|
|
356
|
+
metadata = { ...metadata, ...JSON.parse(metadataContent) };
|
|
357
|
+
}
|
|
358
|
+
catch (error) {
|
|
359
|
+
// No metadata file available
|
|
360
|
+
}
|
|
361
|
+
// Scan directory for files
|
|
362
|
+
const files = await this.scanGitFiles(gitRepoPath, '');
|
|
363
|
+
const gitRepo = {
|
|
364
|
+
path: gitRepoPath,
|
|
365
|
+
branches: metadata.branches,
|
|
366
|
+
commits: metadata.commits,
|
|
367
|
+
files,
|
|
368
|
+
metadata
|
|
369
|
+
};
|
|
370
|
+
return gitRepo;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Scan Git files recursively
|
|
374
|
+
*/
|
|
375
|
+
async scanGitFiles(gitRepoPath, relativePath) {
|
|
376
|
+
const files = [];
|
|
377
|
+
const currentPath = relativePath ? path.join(gitRepoPath, relativePath) : gitRepoPath;
|
|
378
|
+
try {
|
|
379
|
+
const entries = await fs.readdir(currentPath, { withFileTypes: true });
|
|
380
|
+
for (const entry of entries) {
|
|
381
|
+
// Skip Git metadata directories
|
|
382
|
+
if (entry.name === '.git')
|
|
383
|
+
continue;
|
|
384
|
+
const entryPath = path.join(currentPath, entry.name);
|
|
385
|
+
const entryRelativePath = relativePath ? path.join(relativePath, entry.name) : entry.name;
|
|
386
|
+
if (entry.isDirectory()) {
|
|
387
|
+
const subFiles = await this.scanGitFiles(gitRepoPath, entryRelativePath);
|
|
388
|
+
files.push(...subFiles);
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
const content = await fs.readFile(entryPath);
|
|
392
|
+
const stats = await fs.stat(entryPath);
|
|
393
|
+
const gitFile = {
|
|
394
|
+
path: entryRelativePath,
|
|
395
|
+
content,
|
|
396
|
+
hash: createHash('sha1').update(content).digest('hex'),
|
|
397
|
+
mode: stats.mode.toString(8),
|
|
398
|
+
size: content.length,
|
|
399
|
+
lastModified: stats.mtime.getTime()
|
|
400
|
+
};
|
|
401
|
+
files.push(gitFile);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
console.warn(`Failed to scan Git files in ${currentPath}:`, error);
|
|
407
|
+
}
|
|
408
|
+
return files;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Import metadata from exported data
|
|
412
|
+
*/
|
|
413
|
+
async importMetadata(vfsPath, metadata) {
|
|
414
|
+
// Apply metadata to imported files
|
|
415
|
+
for (const [filePath, fileMetadata] of Object.entries(metadata.files || {})) {
|
|
416
|
+
const fullPath = path.join(vfsPath, filePath);
|
|
417
|
+
try {
|
|
418
|
+
// Update file metadata if it exists
|
|
419
|
+
const exists = await this.vfs.exists(fullPath);
|
|
420
|
+
if (exists) {
|
|
421
|
+
// Would update file metadata in VFS
|
|
422
|
+
// This depends on VFS implementation supporting metadata updates
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
console.warn(`Failed to import metadata for ${fullPath}:`, error);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Import relationships
|
|
432
|
+
*/
|
|
433
|
+
async importRelationships(relationships) {
|
|
434
|
+
for (const relationship of relationships) {
|
|
435
|
+
try {
|
|
436
|
+
await this.brain.relate({
|
|
437
|
+
from: relationship.from,
|
|
438
|
+
to: relationship.to,
|
|
439
|
+
type: relationship.type,
|
|
440
|
+
metadata: relationship.metadata
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
catch (error) {
|
|
444
|
+
console.warn('Failed to import relationship:', error);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Import history from exported data
|
|
450
|
+
*/
|
|
451
|
+
async importHistory(vfsPath, history) {
|
|
452
|
+
let eventsCreated = 0;
|
|
453
|
+
for (const event of history.events || []) {
|
|
454
|
+
try {
|
|
455
|
+
await this.brain.add({
|
|
456
|
+
type: NounType.Event,
|
|
457
|
+
data: Buffer.from(JSON.stringify(event)),
|
|
458
|
+
metadata: {
|
|
459
|
+
...event,
|
|
460
|
+
importedFrom: 'git',
|
|
461
|
+
importedAt: Date.now()
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
eventsCreated++;
|
|
465
|
+
}
|
|
466
|
+
catch (error) {
|
|
467
|
+
console.warn('Failed to import history event:', error);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return eventsCreated;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Convert Git commits to VFS events
|
|
474
|
+
*/
|
|
475
|
+
async convertCommitsToEvents(vfsPath, commits) {
|
|
476
|
+
let eventsCreated = 0;
|
|
477
|
+
for (const commit of commits) {
|
|
478
|
+
try {
|
|
479
|
+
await this.brain.add({
|
|
480
|
+
type: NounType.Event,
|
|
481
|
+
data: Buffer.from(commit.message),
|
|
482
|
+
metadata: {
|
|
483
|
+
eventType: 'git-commit',
|
|
484
|
+
gitHash: commit.hash,
|
|
485
|
+
author: commit.author,
|
|
486
|
+
email: commit.email,
|
|
487
|
+
timestamp: commit.timestamp,
|
|
488
|
+
files: commit.files,
|
|
489
|
+
vfsPath,
|
|
490
|
+
system: 'git-bridge'
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
eventsCreated++;
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
console.warn('Failed to convert commit to event:', error);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return eventsCreated;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Generate commit hash
|
|
503
|
+
*/
|
|
504
|
+
generateCommitHash(files) {
|
|
505
|
+
const content = files.map(f => f.path + ':' + f.hash).join('\n');
|
|
506
|
+
return createHash('sha1').update(content).digest('hex');
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Write repository metadata
|
|
510
|
+
*/
|
|
511
|
+
async writeRepoMetadata(gitRepoPath, gitRepo) {
|
|
512
|
+
const metadataPath = path.join(gitRepoPath, '.vfs-repo-metadata.json');
|
|
513
|
+
await fs.writeFile(metadataPath, JSON.stringify(gitRepo.metadata, null, 2));
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Record Git bridge event
|
|
517
|
+
*/
|
|
518
|
+
async recordGitEvent(operation, details) {
|
|
519
|
+
try {
|
|
520
|
+
await this.brain.add({
|
|
521
|
+
type: NounType.Event,
|
|
522
|
+
data: Buffer.from(JSON.stringify(details)),
|
|
523
|
+
metadata: {
|
|
524
|
+
eventType: 'git-bridge',
|
|
525
|
+
operation,
|
|
526
|
+
timestamp: Date.now(),
|
|
527
|
+
system: 'git-bridge',
|
|
528
|
+
...details
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
catch (error) {
|
|
533
|
+
console.warn('Failed to record Git bridge event:', error);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
//# sourceMappingURL=GitBridge.js.map
|