@elaraai/e3-core 0.0.2-beta.3 → 0.0.2-beta.31

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.
Files changed (184) hide show
  1. package/README.md +25 -22
  2. package/dist/src/dataflow/api-compat.d.ts +90 -0
  3. package/dist/src/dataflow/api-compat.d.ts.map +1 -0
  4. package/dist/src/dataflow/api-compat.js +134 -0
  5. package/dist/src/dataflow/api-compat.js.map +1 -0
  6. package/dist/src/dataflow/index.d.ts +18 -0
  7. package/dist/src/dataflow/index.d.ts.map +1 -0
  8. package/dist/src/dataflow/index.js +23 -0
  9. package/dist/src/dataflow/index.js.map +1 -0
  10. package/dist/src/dataflow/orchestrator/LocalOrchestrator.d.ts +53 -0
  11. package/dist/src/dataflow/orchestrator/LocalOrchestrator.d.ts.map +1 -0
  12. package/dist/src/dataflow/orchestrator/LocalOrchestrator.js +416 -0
  13. package/dist/src/dataflow/orchestrator/LocalOrchestrator.js.map +1 -0
  14. package/dist/src/dataflow/orchestrator/index.d.ts +12 -0
  15. package/dist/src/dataflow/orchestrator/index.d.ts.map +1 -0
  16. package/dist/src/dataflow/orchestrator/index.js +12 -0
  17. package/dist/src/dataflow/orchestrator/index.js.map +1 -0
  18. package/dist/src/dataflow/orchestrator/interfaces.d.ts +157 -0
  19. package/dist/src/dataflow/orchestrator/interfaces.d.ts.map +1 -0
  20. package/dist/src/dataflow/orchestrator/interfaces.js +51 -0
  21. package/dist/src/dataflow/orchestrator/interfaces.js.map +1 -0
  22. package/dist/src/dataflow/state-store/FileStateStore.d.ts +67 -0
  23. package/dist/src/dataflow/state-store/FileStateStore.d.ts.map +1 -0
  24. package/dist/src/dataflow/state-store/FileStateStore.js +286 -0
  25. package/dist/src/dataflow/state-store/FileStateStore.js.map +1 -0
  26. package/dist/src/dataflow/state-store/InMemoryStateStore.d.ts +42 -0
  27. package/dist/src/dataflow/state-store/InMemoryStateStore.d.ts.map +1 -0
  28. package/dist/src/dataflow/state-store/InMemoryStateStore.js +214 -0
  29. package/dist/src/dataflow/state-store/InMemoryStateStore.js.map +1 -0
  30. package/dist/src/dataflow/state-store/index.d.ts +13 -0
  31. package/dist/src/dataflow/state-store/index.d.ts.map +1 -0
  32. package/dist/src/dataflow/state-store/index.js +13 -0
  33. package/dist/src/dataflow/state-store/index.js.map +1 -0
  34. package/dist/src/dataflow/state-store/interfaces.d.ts +159 -0
  35. package/dist/src/dataflow/state-store/interfaces.d.ts.map +1 -0
  36. package/dist/src/dataflow/state-store/interfaces.js +6 -0
  37. package/dist/src/dataflow/state-store/interfaces.js.map +1 -0
  38. package/dist/src/dataflow/steps.d.ts +176 -0
  39. package/dist/src/dataflow/steps.d.ts.map +1 -0
  40. package/dist/src/dataflow/steps.js +528 -0
  41. package/dist/src/dataflow/steps.js.map +1 -0
  42. package/dist/src/dataflow/types.d.ts +116 -0
  43. package/dist/src/dataflow/types.d.ts.map +1 -0
  44. package/dist/src/dataflow/types.js +7 -0
  45. package/dist/src/dataflow/types.js.map +1 -0
  46. package/dist/src/dataflow.d.ts +142 -9
  47. package/dist/src/dataflow.d.ts.map +1 -1
  48. package/dist/src/dataflow.js +427 -64
  49. package/dist/src/dataflow.js.map +1 -1
  50. package/dist/src/errors.d.ts +39 -9
  51. package/dist/src/errors.d.ts.map +1 -1
  52. package/dist/src/errors.js +51 -8
  53. package/dist/src/errors.js.map +1 -1
  54. package/dist/src/execution/LocalTaskRunner.d.ts +73 -0
  55. package/dist/src/execution/LocalTaskRunner.d.ts.map +1 -0
  56. package/dist/src/execution/LocalTaskRunner.js +399 -0
  57. package/dist/src/execution/LocalTaskRunner.js.map +1 -0
  58. package/dist/src/execution/MockTaskRunner.d.ts +49 -0
  59. package/dist/src/execution/MockTaskRunner.d.ts.map +1 -0
  60. package/dist/src/execution/MockTaskRunner.js +55 -0
  61. package/dist/src/execution/MockTaskRunner.js.map +1 -0
  62. package/dist/src/execution/index.d.ts +16 -0
  63. package/dist/src/execution/index.d.ts.map +1 -0
  64. package/dist/src/execution/index.js +8 -0
  65. package/dist/src/execution/index.js.map +1 -0
  66. package/dist/src/execution/interfaces.d.ts +246 -0
  67. package/dist/src/execution/interfaces.d.ts.map +1 -0
  68. package/dist/src/execution/interfaces.js +6 -0
  69. package/dist/src/execution/interfaces.js.map +1 -0
  70. package/dist/src/execution/processHelpers.d.ts +20 -0
  71. package/dist/src/execution/processHelpers.d.ts.map +1 -0
  72. package/dist/src/execution/processHelpers.js +62 -0
  73. package/dist/src/execution/processHelpers.js.map +1 -0
  74. package/dist/src/executions.d.ts +71 -104
  75. package/dist/src/executions.d.ts.map +1 -1
  76. package/dist/src/executions.js +110 -476
  77. package/dist/src/executions.js.map +1 -1
  78. package/dist/src/index.d.ts +17 -9
  79. package/dist/src/index.d.ts.map +1 -1
  80. package/dist/src/index.js +44 -18
  81. package/dist/src/index.js.map +1 -1
  82. package/dist/src/objects.d.ts +6 -53
  83. package/dist/src/objects.d.ts.map +1 -1
  84. package/dist/src/objects.js +11 -232
  85. package/dist/src/objects.js.map +1 -1
  86. package/dist/src/packages.d.ts +22 -14
  87. package/dist/src/packages.d.ts.map +1 -1
  88. package/dist/src/packages.js +116 -83
  89. package/dist/src/packages.js.map +1 -1
  90. package/dist/src/storage/in-memory/InMemoryRepoStore.d.ts +35 -0
  91. package/dist/src/storage/in-memory/InMemoryRepoStore.d.ts.map +1 -0
  92. package/dist/src/storage/in-memory/InMemoryRepoStore.js +107 -0
  93. package/dist/src/storage/in-memory/InMemoryRepoStore.js.map +1 -0
  94. package/dist/src/storage/in-memory/InMemoryStorage.d.ts +114 -0
  95. package/dist/src/storage/in-memory/InMemoryStorage.d.ts.map +1 -0
  96. package/dist/src/storage/in-memory/InMemoryStorage.js +349 -0
  97. package/dist/src/storage/in-memory/InMemoryStorage.js.map +1 -0
  98. package/dist/src/storage/in-memory/index.d.ts +12 -0
  99. package/dist/src/storage/in-memory/index.d.ts.map +1 -0
  100. package/dist/src/storage/in-memory/index.js +12 -0
  101. package/dist/src/storage/in-memory/index.js.map +1 -0
  102. package/dist/src/storage/index.d.ts +18 -0
  103. package/dist/src/storage/index.d.ts.map +1 -0
  104. package/dist/src/storage/index.js +10 -0
  105. package/dist/src/storage/index.js.map +1 -0
  106. package/dist/src/storage/interfaces.d.ts +520 -0
  107. package/dist/src/storage/interfaces.d.ts.map +1 -0
  108. package/dist/src/storage/interfaces.js +6 -0
  109. package/dist/src/storage/interfaces.js.map +1 -0
  110. package/dist/src/storage/local/LocalBackend.d.ts +54 -0
  111. package/dist/src/storage/local/LocalBackend.d.ts.map +1 -0
  112. package/dist/src/storage/local/LocalBackend.js +141 -0
  113. package/dist/src/storage/local/LocalBackend.js.map +1 -0
  114. package/dist/src/storage/local/LocalLockService.d.ts +105 -0
  115. package/dist/src/storage/local/LocalLockService.d.ts.map +1 -0
  116. package/dist/src/storage/local/LocalLockService.js +342 -0
  117. package/dist/src/storage/local/LocalLockService.js.map +1 -0
  118. package/dist/src/storage/local/LocalLogStore.d.ts +23 -0
  119. package/dist/src/storage/local/LocalLogStore.d.ts.map +1 -0
  120. package/dist/src/storage/local/LocalLogStore.js +66 -0
  121. package/dist/src/storage/local/LocalLogStore.js.map +1 -0
  122. package/dist/src/storage/local/LocalObjectStore.d.ts +52 -0
  123. package/dist/src/storage/local/LocalObjectStore.d.ts.map +1 -0
  124. package/dist/src/storage/local/LocalObjectStore.js +287 -0
  125. package/dist/src/storage/local/LocalObjectStore.js.map +1 -0
  126. package/dist/src/storage/local/LocalRefStore.d.ts +50 -0
  127. package/dist/src/storage/local/LocalRefStore.d.ts.map +1 -0
  128. package/dist/src/storage/local/LocalRefStore.js +337 -0
  129. package/dist/src/storage/local/LocalRefStore.js.map +1 -0
  130. package/dist/src/storage/local/LocalRepoStore.d.ts +53 -0
  131. package/dist/src/storage/local/LocalRepoStore.d.ts.map +1 -0
  132. package/dist/src/storage/local/LocalRepoStore.js +353 -0
  133. package/dist/src/storage/local/LocalRepoStore.js.map +1 -0
  134. package/dist/src/storage/local/gc.d.ts +92 -0
  135. package/dist/src/storage/local/gc.d.ts.map +1 -0
  136. package/dist/src/storage/local/gc.js +322 -0
  137. package/dist/src/storage/local/gc.js.map +1 -0
  138. package/dist/src/storage/local/index.d.ts +17 -0
  139. package/dist/src/storage/local/index.d.ts.map +1 -0
  140. package/dist/src/storage/local/index.js +17 -0
  141. package/dist/src/storage/local/index.js.map +1 -0
  142. package/dist/src/storage/local/localHelpers.d.ts +25 -0
  143. package/dist/src/storage/local/localHelpers.d.ts.map +1 -0
  144. package/dist/src/storage/local/localHelpers.js +69 -0
  145. package/dist/src/storage/local/localHelpers.js.map +1 -0
  146. package/dist/src/{repository.d.ts → storage/local/repository.d.ts} +8 -4
  147. package/dist/src/storage/local/repository.d.ts.map +1 -0
  148. package/dist/src/{repository.js → storage/local/repository.js} +31 -29
  149. package/dist/src/storage/local/repository.js.map +1 -0
  150. package/dist/src/tasks.d.ts +16 -10
  151. package/dist/src/tasks.d.ts.map +1 -1
  152. package/dist/src/tasks.js +35 -41
  153. package/dist/src/tasks.js.map +1 -1
  154. package/dist/src/test-helpers.d.ts +4 -4
  155. package/dist/src/test-helpers.d.ts.map +1 -1
  156. package/dist/src/test-helpers.js +7 -21
  157. package/dist/src/test-helpers.js.map +1 -1
  158. package/dist/src/trees.d.ts +89 -27
  159. package/dist/src/trees.d.ts.map +1 -1
  160. package/dist/src/trees.js +218 -100
  161. package/dist/src/trees.js.map +1 -1
  162. package/dist/src/uuid.d.ts +26 -0
  163. package/dist/src/uuid.d.ts.map +1 -0
  164. package/dist/src/uuid.js +80 -0
  165. package/dist/src/uuid.js.map +1 -0
  166. package/dist/src/workspaceStatus.d.ts +6 -4
  167. package/dist/src/workspaceStatus.d.ts.map +1 -1
  168. package/dist/src/workspaceStatus.js +43 -49
  169. package/dist/src/workspaceStatus.js.map +1 -1
  170. package/dist/src/workspaces.d.ts +35 -26
  171. package/dist/src/workspaces.d.ts.map +1 -1
  172. package/dist/src/workspaces.js +169 -118
  173. package/dist/src/workspaces.js.map +1 -1
  174. package/package.json +4 -4
  175. package/dist/src/gc.d.ts +0 -54
  176. package/dist/src/gc.d.ts.map +0 -1
  177. package/dist/src/gc.js +0 -233
  178. package/dist/src/gc.js.map +0 -1
  179. package/dist/src/repository.d.ts.map +0 -1
  180. package/dist/src/repository.js.map +0 -1
  181. package/dist/src/workspaceLock.d.ts +0 -67
  182. package/dist/src/workspaceLock.d.ts.map +0 -1
  183. package/dist/src/workspaceLock.js +0 -217
  184. package/dist/src/workspaceLock.js.map +0 -1
@@ -0,0 +1,322 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * Shared garbage collection algorithm for e3 repositories.
7
+ *
8
+ * Uses mark-and-sweep:
9
+ * 1. collectAllRoots: Collect root hashes from all root scan methods
10
+ * 2. markReachable: DFS through object graph via BEAST2 schema-aware traversal
11
+ * 3. sweepBatch: Pure decision function — identify unreachable objects to delete
12
+ * 4. repoGc: Driver that calls all phases in sequence
13
+ *
14
+ * These functions work with any StorageBackend — no instanceof checks.
15
+ * Cloud-specific concerns (S3 reachable set persistence, orphaned version cleanup)
16
+ * are handled in the cloud Lambda handlers.
17
+ */
18
+ import * as fs from 'fs/promises';
19
+ import * as path from 'path';
20
+ import { decodeBeast2 } from '@elaraai/east';
21
+ // =============================================================================
22
+ // Shared Algorithm Functions
23
+ // =============================================================================
24
+ /**
25
+ * Collect all root hashes from packages, workspaces, and executions.
26
+ *
27
+ * Calls each gcScan*Roots method with pagination support.
28
+ * Adding a new root scan method to RepoStore requires updating this function.
29
+ */
30
+ export async function collectAllRoots(store, repo) {
31
+ const roots = new Set();
32
+ const scanAll = async (scan) => {
33
+ let cursor;
34
+ do {
35
+ const result = await scan(repo, cursor);
36
+ for (const hash of result.roots) {
37
+ roots.add(hash);
38
+ }
39
+ cursor = result.cursor;
40
+ } while (cursor !== undefined);
41
+ };
42
+ await scanAll(store.gcScanPackageRoots.bind(store));
43
+ await scanAll(store.gcScanWorkspaceRoots.bind(store));
44
+ await scanAll(store.gcScanExecutionRoots.bind(store));
45
+ return roots;
46
+ }
47
+ /**
48
+ * Trace the object graph from roots using iterative DFS with schema-aware traversal.
49
+ *
50
+ * Decodes each object using BEAST2 self-describing format and extracts child
51
+ * hashes based on the detected object type (Package, Task, or Tree). Objects
52
+ * known to be leaves (values, IR blobs) are marked reachable without reading.
53
+ *
54
+ * @param readObject - Function to read an object by hash (returns null if missing)
55
+ * @param roots - Set of root hashes to start from
56
+ * @returns Set of all reachable hashes
57
+ */
58
+ export async function markReachable(readObject, roots) {
59
+ const reachable = new Set();
60
+ const stack = [...roots];
61
+ while (stack.length > 0) {
62
+ const hash = stack.pop();
63
+ if (reachable.has(hash))
64
+ continue;
65
+ const data = await readObject(hash);
66
+ if (!data)
67
+ continue;
68
+ reachable.add(hash);
69
+ // Schema-aware child extraction
70
+ let children;
71
+ try {
72
+ const decoded = decodeBeast2(Buffer.from(data));
73
+ children = extractChildren(decoded.type, decoded.value);
74
+ }
75
+ catch {
76
+ continue; // Not valid BEAST2 or unknown format — treat as leaf
77
+ }
78
+ for (const child of children) {
79
+ if (reachable.has(child.hash))
80
+ continue;
81
+ if (child.isLeaf) {
82
+ reachable.add(child.hash); // Mark without reading
83
+ }
84
+ else {
85
+ stack.push(child.hash);
86
+ }
87
+ }
88
+ }
89
+ return reachable;
90
+ }
91
+ // =============================================================================
92
+ // Type Detection Helpers
93
+ // =============================================================================
94
+ // EastTypeValue is a variant object: { type: string, value: any }
95
+ // For Struct: type.type === "Struct", type.value is Array<{ name: string, type: EastTypeValue }>
96
+ // For Variant: type.type === "Variant", type.value is Array<{ name: string, type: EastTypeValue }>
97
+ /**
98
+ * Check if a decoded EastTypeValue represents a PackageObject.
99
+ * PackageObject is a Struct with fields: tasks (Dict<String,String>), data (Struct)
100
+ */
101
+ function isPackageObjectShape(type) {
102
+ if (type.type !== 'Struct')
103
+ return false;
104
+ const fields = type.value;
105
+ const names = new Set(fields.map(f => f.name));
106
+ return names.has('tasks') && names.has('data');
107
+ }
108
+ /**
109
+ * Check if a decoded EastTypeValue represents a TaskObject.
110
+ * TaskObject is a Struct with fields: commandIr, inputs, output
111
+ */
112
+ function isTaskObjectShape(type) {
113
+ if (type.type !== 'Struct')
114
+ return false;
115
+ const fields = type.value;
116
+ const names = new Set(fields.map(f => f.name));
117
+ return names.has('commandIr') && names.has('inputs') && names.has('output');
118
+ }
119
+ /**
120
+ * Check if a field type is a DataRef (Variant with cases: unassigned, null, value, tree).
121
+ */
122
+ function isDataRefFieldType(fieldType) {
123
+ if (fieldType.type !== 'Variant')
124
+ return false;
125
+ const cases = fieldType.value;
126
+ const names = new Set(cases.map(c => c.name));
127
+ return names.has('tree') && names.has('value') && names.has('unassigned') && names.has('null');
128
+ }
129
+ /**
130
+ * Check if a decoded EastTypeValue represents a TreeObject.
131
+ * A tree is a Struct where every field is a DataRef variant.
132
+ */
133
+ function isTreeObjectShape(type) {
134
+ if (type.type !== 'Struct')
135
+ return false;
136
+ const fields = type.value;
137
+ return fields.length > 0 && fields.every(f => isDataRefFieldType(f.type));
138
+ }
139
+ /**
140
+ * Extract child hashes from a decoded BEAST2 object based on its type.
141
+ * Returns children with isLeaf flag to avoid reading leaf objects.
142
+ */
143
+ function extractChildren(type, value) {
144
+ const t = type;
145
+ const children = [];
146
+ if (isPackageObjectShape(t)) {
147
+ const pkg = value;
148
+ for (const taskHash of pkg.tasks.values()) {
149
+ children.push({ hash: taskHash, isLeaf: false });
150
+ }
151
+ children.push({ hash: pkg.data.value, isLeaf: false }); // root tree
152
+ return children;
153
+ }
154
+ if (isTaskObjectShape(t)) {
155
+ const task = value;
156
+ children.push({ hash: task.commandIr, isLeaf: true }); // IR is a leaf
157
+ return children;
158
+ }
159
+ if (isTreeObjectShape(t)) {
160
+ const tree = value;
161
+ for (const ref of Object.values(tree)) {
162
+ if (ref.type === 'tree') {
163
+ children.push({ hash: ref.value, isLeaf: false }); // subtree needs traversal
164
+ }
165
+ else if (ref.type === 'value') {
166
+ children.push({ hash: ref.value, isLeaf: true }); // value is a leaf
167
+ }
168
+ // 'unassigned' and 'null': no hash to follow
169
+ }
170
+ return children;
171
+ }
172
+ return []; // Unknown type: leaf, no children
173
+ }
174
+ /**
175
+ * Pure decision function: determine which objects to delete.
176
+ *
177
+ * No side effects — trivially testable. Caller decides whether to
178
+ * actually delete (supports dry-run by skipping gcDeleteObjects).
179
+ *
180
+ * @param objects - Object entries from gcScanObjects
181
+ * @param reachable - Set of reachable hashes from markReachable
182
+ * @param minAge - Minimum age in ms; objects younger than this are skipped
183
+ * @returns Decision result with toDelete list and stats
184
+ */
185
+ export function sweepBatch(objects, reachable, minAge) {
186
+ const now = Date.now();
187
+ const toDelete = [];
188
+ let retained = 0;
189
+ let skippedYoung = 0;
190
+ let bytesFreed = 0;
191
+ for (const obj of objects) {
192
+ if (reachable.has(obj.hash)) {
193
+ retained++;
194
+ continue;
195
+ }
196
+ const age = now - obj.lastModified;
197
+ if (minAge > 0 && age < minAge) {
198
+ skippedYoung++;
199
+ continue;
200
+ }
201
+ toDelete.push(obj.hash);
202
+ bytesFreed += obj.size;
203
+ }
204
+ return { toDelete, retained, skippedYoung, bytesFreed };
205
+ }
206
+ // =============================================================================
207
+ // Local Driver
208
+ // =============================================================================
209
+ /**
210
+ * Run garbage collection on an e3 repository.
211
+ *
212
+ * Works with any StorageBackend — no instanceof checks.
213
+ *
214
+ * @param storage - Storage backend
215
+ * @param repo - Repository identifier
216
+ * @param options - GC options
217
+ * @returns GC result with statistics
218
+ */
219
+ export async function repoGc(storage, repo, options = {}) {
220
+ const minAge = options.minAge ?? 60000;
221
+ const dryRun = options.dryRun ?? false;
222
+ // Step 1: Collect all root hashes
223
+ const roots = await collectAllRoots(storage.repos, repo);
224
+ // Step 2: Mark all reachable objects
225
+ const readObject = async (hash) => {
226
+ try {
227
+ return await storage.objects.read(repo, hash);
228
+ }
229
+ catch {
230
+ return null;
231
+ }
232
+ };
233
+ const reachable = await markReachable(readObject, roots);
234
+ // Step 3: Scan and sweep objects
235
+ let totalDeleted = 0;
236
+ let totalRetained = 0;
237
+ let totalSkippedYoung = 0;
238
+ let totalBytesFreed = 0;
239
+ let cursor;
240
+ do {
241
+ const scan = await storage.repos.gcScanObjects(repo, cursor);
242
+ const result = sweepBatch(scan.objects, reachable, minAge);
243
+ totalRetained += result.retained;
244
+ totalSkippedYoung += result.skippedYoung;
245
+ totalBytesFreed += result.bytesFreed;
246
+ if (!dryRun && result.toDelete.length > 0) {
247
+ await storage.repos.gcDeleteObjects(repo, result.toDelete);
248
+ }
249
+ totalDeleted += result.toDelete.length;
250
+ cursor = scan.cursor;
251
+ } while (cursor !== undefined);
252
+ // Step 4: Clean up orphaned .partial files (local-only concern)
253
+ let deletedPartials = 0;
254
+ let partialSkippedYoung = 0;
255
+ try {
256
+ const partialResult = await cleanupPartials(repo, minAge, dryRun);
257
+ deletedPartials = partialResult.deleted;
258
+ partialSkippedYoung = partialResult.skippedYoung;
259
+ }
260
+ catch {
261
+ // Not a fatal error
262
+ }
263
+ return {
264
+ deletedObjects: totalDeleted,
265
+ deletedPartials,
266
+ retainedObjects: totalRetained,
267
+ skippedYoung: totalSkippedYoung + partialSkippedYoung,
268
+ bytesFreed: totalBytesFreed,
269
+ };
270
+ }
271
+ /**
272
+ * Clean up orphaned .partial staging files in the objects directory.
273
+ * This is a local-only concern — cloud storage doesn't use .partial files.
274
+ */
275
+ async function cleanupPartials(repoPath, minAge, dryRun) {
276
+ const objectsDir = path.join(repoPath, 'objects');
277
+ const now = Date.now();
278
+ let deleted = 0;
279
+ let skippedYoung = 0;
280
+ try {
281
+ const subdirs = await fs.readdir(objectsDir);
282
+ for (const subdir of subdirs) {
283
+ if (!/^[a-f0-9]{2}$/.test(subdir))
284
+ continue;
285
+ const subdirPath = path.join(objectsDir, subdir);
286
+ try {
287
+ const stat = await fs.stat(subdirPath);
288
+ if (!stat.isDirectory())
289
+ continue;
290
+ }
291
+ catch {
292
+ continue;
293
+ }
294
+ const files = await fs.readdir(subdirPath);
295
+ for (const file of files) {
296
+ if (!file.endsWith('.partial'))
297
+ continue;
298
+ const filePath = path.join(subdirPath, file);
299
+ try {
300
+ const fileStat = await fs.stat(filePath);
301
+ const age = now - fileStat.mtimeMs;
302
+ if (minAge > 0 && age < minAge) {
303
+ skippedYoung++;
304
+ continue;
305
+ }
306
+ if (!dryRun) {
307
+ await fs.unlink(filePath);
308
+ }
309
+ deleted++;
310
+ }
311
+ catch {
312
+ // Skip files we can't stat or delete
313
+ }
314
+ }
315
+ }
316
+ }
317
+ catch {
318
+ // Objects directory doesn't exist
319
+ }
320
+ return { deleted, skippedYoung };
321
+ }
322
+ //# sourceMappingURL=gc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gc.js","sourceRoot":"","sources":["../../../../src/storage/local/gc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * Local filesystem implementation of StorageBackend.
7
+ *
8
+ * This wraps the existing e3-core filesystem functions to provide a
9
+ * StorageBackend that works with local repositories.
10
+ */
11
+ export { LocalStorage, LocalBackend } from './LocalBackend.js';
12
+ export { LocalObjectStore } from './LocalObjectStore.js';
13
+ export { LocalRefStore } from './LocalRefStore.js';
14
+ export { LocalLockService } from './LocalLockService.js';
15
+ export { LocalLogStore } from './LocalLogStore.js';
16
+ export { LocalRepoStore } from './LocalRepoStore.js';
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/storage/local/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * Local filesystem implementation of StorageBackend.
7
+ *
8
+ * This wraps the existing e3-core filesystem functions to provide a
9
+ * StorageBackend that works with local repositories.
10
+ */
11
+ export { LocalStorage, LocalBackend } from './LocalBackend.js';
12
+ export { LocalObjectStore } from './LocalObjectStore.js';
13
+ export { LocalRefStore } from './LocalRefStore.js';
14
+ export { LocalLockService } from './LocalLockService.js';
15
+ export { LocalLogStore } from './LocalLogStore.js';
16
+ export { LocalRepoStore } from './LocalRepoStore.js';
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/storage/local/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * Get the filesystem path for an object.
7
+ *
8
+ * @param repoPath - Path to e3 repository
9
+ * @param hash - SHA256 hash of the object
10
+ * @returns Filesystem path: objects/<hash[0..2]>/<hash[2..]>.beast2
11
+ */
12
+ export declare function objectPath(repoPath: string, hash: string): string;
13
+ /**
14
+ * Get the minimum unambiguous prefix length for an object hash.
15
+ *
16
+ * Scans the object store to find the shortest prefix of the given hash
17
+ * that uniquely identifies it among all stored objects.
18
+ *
19
+ * @param repoPath - Path to e3 repository
20
+ * @param hash - Full SHA256 hash of the object
21
+ * @param minLength - Minimum prefix length to return (default: 4)
22
+ * @returns Minimum unambiguous prefix length
23
+ */
24
+ export declare function objectAbbrev(repoPath: string, hash: string, minLength?: number): Promise<number>;
25
+ //# sourceMappingURL=localHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localHelpers.d.ts","sourceRoot":"","sources":["../../../../src/storage/local/localHelpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIjE;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,MAAU,GACpB,OAAO,CAAC,MAAM,CAAC,CAwCjB"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * Local filesystem helpers for e3 object storage.
7
+ *
8
+ * These functions are local-specific utilities for working with
9
+ * the filesystem-based object store. They are used by LocalObjectStore
10
+ * and other local storage components.
11
+ */
12
+ import * as fs from 'fs/promises';
13
+ import * as path from 'path';
14
+ /**
15
+ * Get the filesystem path for an object.
16
+ *
17
+ * @param repoPath - Path to e3 repository
18
+ * @param hash - SHA256 hash of the object
19
+ * @returns Filesystem path: objects/<hash[0..2]>/<hash[2..]>.beast2
20
+ */
21
+ export function objectPath(repoPath, hash) {
22
+ const dirName = hash.slice(0, 2);
23
+ const fileName = hash.slice(2) + '.beast2';
24
+ return path.join(repoPath, 'objects', dirName, fileName);
25
+ }
26
+ /**
27
+ * Get the minimum unambiguous prefix length for an object hash.
28
+ *
29
+ * Scans the object store to find the shortest prefix of the given hash
30
+ * that uniquely identifies it among all stored objects.
31
+ *
32
+ * @param repoPath - Path to e3 repository
33
+ * @param hash - Full SHA256 hash of the object
34
+ * @param minLength - Minimum prefix length to return (default: 4)
35
+ * @returns Minimum unambiguous prefix length
36
+ */
37
+ export async function objectAbbrev(repoPath, hash, minLength = 4) {
38
+ const objectsDir = path.join(repoPath, 'objects');
39
+ const targetPrefix = hash.slice(0, 2);
40
+ // Collect all hashes that share the same 2-char prefix directory
41
+ const hashes = [];
42
+ try {
43
+ const dirPath = path.join(objectsDir, targetPrefix);
44
+ const entries = await fs.readdir(dirPath);
45
+ for (const entry of entries) {
46
+ if (entry.endsWith('.beast2') && !entry.includes('.partial')) {
47
+ // Reconstruct full hash: dir prefix + filename without extension
48
+ const fullHash = targetPrefix + entry.slice(0, -7); // remove '.beast2'
49
+ hashes.push(fullHash);
50
+ }
51
+ }
52
+ }
53
+ catch {
54
+ // Directory doesn't exist - hash is unique at minimum length
55
+ return minLength;
56
+ }
57
+ // Find minimum length that disambiguates from all other hashes
58
+ let length = minLength;
59
+ while (length < hash.length) {
60
+ const prefix = hash.slice(0, length);
61
+ const conflicts = hashes.filter((h) => h !== hash && h.startsWith(prefix));
62
+ if (conflicts.length === 0) {
63
+ return length;
64
+ }
65
+ length++;
66
+ }
67
+ return hash.length;
68
+ }
69
+ //# sourceMappingURL=localHelpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localHelpers.js","sourceRoot":"","sources":["../../../../src/storage/local/localHelpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,IAAY;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAgB,EAChB,IAAY,EACZ,YAAoB,CAAC;IAErB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEtC,iEAAiE;IACjE,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAE1C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC7D,iEAAiE;gBACjE,MAAM,QAAQ,GAAG,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB;gBACvE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;QAC7D,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,+DAA+D;IAC/D,IAAI,MAAM,GAAG,SAAS,CAAC;IAEvB,OAAO,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACrC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAC1C,CAAC;QAEF,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,EAAE,CAAC;IACX,CAAC;IAED,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC"}
@@ -7,28 +7,32 @@
7
7
  */
8
8
  export interface InitRepositoryResult {
9
9
  success: boolean;
10
- e3Dir: string;
10
+ repoPath: string;
11
11
  error?: Error;
12
12
  alreadyExists?: boolean;
13
13
  }
14
14
  /**
15
15
  * Initialize a new e3 repository
16
16
  *
17
- * Creates:
17
+ * Creates the repository directory structure:
18
18
  * - objects/
19
19
  * - packages/
20
20
  * - executions/
21
21
  * - workspaces/
22
22
  *
23
+ * The repository IS the specified directory - subdirectories are created directly within it.
24
+ *
23
25
  * Pure business logic - no UI dependencies
24
26
  */
25
27
  export declare function repoInit(repoPath: string): InitRepositoryResult;
26
28
  /**
27
29
  * Find the e3 repository directory
28
30
  *
29
- * Searches:
31
+ * Checks:
30
32
  * 1. E3_REPO environment variable
31
- * 2. Current directory and parents (like git)
33
+ * 2. The provided startPath (if given)
34
+ *
35
+ * Returns null if no valid repository is found.
32
36
  */
33
37
  export declare function repoFind(startPath?: string): string | null;
34
38
  /**
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../../src/storage/local/repository.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,oBAAoB,CAwC/D;AAYD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkB1D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAQjD"}
@@ -2,51 +2,58 @@
2
2
  * Copyright (c) 2025 Elara AI Pty Ltd
3
3
  * Licensed under BSL 1.1. See LICENSE for details.
4
4
  */
5
+ /**
6
+ * Local filesystem repository initialization and discovery.
7
+ *
8
+ * This module handles creating and finding e3 repositories on the local
9
+ * filesystem. It is used by the CLI and local development tools.
10
+ */
5
11
  import * as fs from 'fs';
6
12
  import * as path from 'path';
7
13
  /**
8
14
  * Initialize a new e3 repository
9
15
  *
10
- * Creates:
16
+ * Creates the repository directory structure:
11
17
  * - objects/
12
18
  * - packages/
13
19
  * - executions/
14
20
  * - workspaces/
15
21
  *
22
+ * The repository IS the specified directory - subdirectories are created directly within it.
23
+ *
16
24
  * Pure business logic - no UI dependencies
17
25
  */
18
26
  export function repoInit(repoPath) {
19
27
  const targetPath = path.resolve(repoPath);
20
- const e3Dir = path.join(targetPath, '.e3');
21
- // Check if .e3 already exists
22
- if (fs.existsSync(e3Dir)) {
28
+ // Check if directory already is a valid repository
29
+ if (isValidRepository(targetPath)) {
23
30
  return {
24
31
  success: false,
25
- e3Dir,
32
+ repoPath: targetPath,
26
33
  alreadyExists: true,
27
- error: new Error(`e3 repository already exists at ${e3Dir}`),
34
+ error: new Error(`e3 repository already exists at ${targetPath}`),
28
35
  };
29
36
  }
30
37
  try {
31
- // Create main .e3 directory
32
- fs.mkdirSync(e3Dir, { recursive: true });
38
+ // Create the repository directory if it doesn't exist
39
+ fs.mkdirSync(targetPath, { recursive: true });
33
40
  // Create objects directory (content-addressed storage)
34
- fs.mkdirSync(path.join(e3Dir, 'objects'), { recursive: true });
41
+ fs.mkdirSync(path.join(targetPath, 'objects'), { recursive: true });
35
42
  // Create packages directory (package refs: packages/<name>/<version> -> hash)
36
- fs.mkdirSync(path.join(e3Dir, 'packages'), { recursive: true });
43
+ fs.mkdirSync(path.join(targetPath, 'packages'), { recursive: true });
37
44
  // Create executions directory (execution cache: executions/<hash>/output -> hash)
38
- fs.mkdirSync(path.join(e3Dir, 'executions'), { recursive: true });
45
+ fs.mkdirSync(path.join(targetPath, 'executions'), { recursive: true });
39
46
  // Create workspaces directory (workspace state)
40
- fs.mkdirSync(path.join(e3Dir, 'workspaces'), { recursive: true });
47
+ fs.mkdirSync(path.join(targetPath, 'workspaces'), { recursive: true });
41
48
  return {
42
49
  success: true,
43
- e3Dir,
50
+ repoPath: targetPath,
44
51
  };
45
52
  }
46
53
  catch (error) {
47
54
  return {
48
55
  success: false,
49
- e3Dir,
56
+ repoPath: targetPath,
50
57
  error: error instanceof Error ? error : new Error(String(error)),
51
58
  };
52
59
  }
@@ -62,9 +69,11 @@ function isValidRepository(repoPath) {
62
69
  /**
63
70
  * Find the e3 repository directory
64
71
  *
65
- * Searches:
72
+ * Checks:
66
73
  * 1. E3_REPO environment variable
67
- * 2. Current directory and parents (like git)
74
+ * 2. The provided startPath (if given)
75
+ *
76
+ * Returns null if no valid repository is found.
68
77
  */
69
78
  export function repoFind(startPath) {
70
79
  // 1. Check E3_REPO environment variable
@@ -74,19 +83,12 @@ export function repoFind(startPath) {
74
83
  return repoPath;
75
84
  }
76
85
  }
77
- // 2. Check current directory and parents
78
- let currentDir = startPath !== undefined ? path.resolve(startPath) : process.cwd();
79
- while (true) {
80
- const e3Dir = path.join(currentDir, '.e3');
81
- if (fs.existsSync(e3Dir) && isValidRepository(e3Dir)) {
82
- return e3Dir;
83
- }
84
- const parentDir = path.dirname(currentDir);
85
- if (parentDir === currentDir) {
86
- // Reached root
87
- break;
86
+ // 2. Check the provided path
87
+ if (startPath !== undefined) {
88
+ const repoPath = path.resolve(startPath);
89
+ if (fs.existsSync(repoPath) && isValidRepository(repoPath)) {
90
+ return repoPath;
88
91
  }
89
- currentDir = parentDir;
90
92
  }
91
93
  return null;
92
94
  }
@@ -96,7 +98,7 @@ export function repoFind(startPath) {
96
98
  export function repoGet(repoPath) {
97
99
  const repo = repoFind(repoPath);
98
100
  if (!repo) {
99
- throw new Error('e3 repository not found. Run `e3 init` to create one.');
101
+ throw new Error('e3 repository not found. Run `e3 repo create` to create one.');
100
102
  }
101
103
  return repo;
102
104
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.js","sourceRoot":"","sources":["../../../../src/storage/local/repository.ts"],"names":[],"mappings":"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"}