boxsafe 1.0.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.
Files changed (118) hide show
  1. package/.directory +2 -0
  2. package/.env.example +3 -0
  3. package/AUDIT_LANG.md +45 -0
  4. package/BOXSAFE_VERSION_NOTES.md +14 -0
  5. package/README.md +4 -0
  6. package/TODO.md +130 -0
  7. package/adapters/index.ts +27 -0
  8. package/adapters/primary/cli-adapter.ts +56 -0
  9. package/adapters/secondary/filesystem/node-filesystem.ts +307 -0
  10. package/adapters/secondary/system/configuration.ts +147 -0
  11. package/ai/caller.ts +42 -0
  12. package/ai/label.ts +33 -0
  13. package/ai/modelConfig.ts +236 -0
  14. package/ai/provider.ts +111 -0
  15. package/boxsafe.config.json +68 -0
  16. package/core/auth/dasktop/cred/CRED.md +112 -0
  17. package/core/auth/dasktop/cred/credLinux.ts +82 -0
  18. package/core/auth/dasktop/cred/credWin.ts +2 -0
  19. package/core/config/defaults/boxsafeDefaults.ts +67 -0
  20. package/core/config/defaults/index.ts +1 -0
  21. package/core/config/loadConfig.ts +133 -0
  22. package/core/loop/about.md +13 -0
  23. package/core/loop/boxConfig.ts +20 -0
  24. package/core/loop/buildExecCommand.ts +76 -0
  25. package/core/loop/cmd/execode.ts +121 -0
  26. package/core/loop/cmd/test.js +3 -0
  27. package/core/loop/execLoop.ts +341 -0
  28. package/core/loop/git/VERSIONING.md +17 -0
  29. package/core/loop/git/commands.ts +11 -0
  30. package/core/loop/git/gitClient.ts +78 -0
  31. package/core/loop/git/index.ts +99 -0
  32. package/core/loop/git/runVersionControlRunner.ts +33 -0
  33. package/core/loop/initNavigator.ts +44 -0
  34. package/core/loop/initTasksManager.ts +35 -0
  35. package/core/loop/runValidation.ts +25 -0
  36. package/core/loop/tasks/AGENT-TASKS.md +36 -0
  37. package/core/loop/tasks/index.ts +96 -0
  38. package/core/loop/toolCalls.ts +168 -0
  39. package/core/loop/toolDispatcher.ts +146 -0
  40. package/core/loop/traceLogger.ts +106 -0
  41. package/core/loop/types.ts +26 -0
  42. package/core/loop/versionControlAdapter.ts +36 -0
  43. package/core/loop/waterfall.ts +404 -0
  44. package/core/loop/writeArtifactAtomically.ts +13 -0
  45. package/core/navigate/NAVIGATE.md +186 -0
  46. package/core/navigate/about.md +128 -0
  47. package/core/navigate/examples.ts +367 -0
  48. package/core/navigate/handler.ts +148 -0
  49. package/core/navigate/index.ts +32 -0
  50. package/core/navigate/navigate.test.ts +372 -0
  51. package/core/navigate/navigator.ts +437 -0
  52. package/core/navigate/types.ts +132 -0
  53. package/core/navigate/utils.ts +146 -0
  54. package/core/paths/paths.ts +33 -0
  55. package/core/ports/index.ts +271 -0
  56. package/core/segments/CONVENTIONS.md +30 -0
  57. package/core/segments/loop/index.ts +18 -0
  58. package/core/segments/map.ts +56 -0
  59. package/core/segments/navigate/index.ts +20 -0
  60. package/core/segments/versionControl/index.ts +18 -0
  61. package/core/util/logger.ts +128 -0
  62. package/docs/AGENT-TASKS.md +36 -0
  63. package/docs/ARQUITETURA_CORRECAO.md +121 -0
  64. package/docs/CONVENTIONS.md +30 -0
  65. package/docs/CRED.md +112 -0
  66. package/docs/L_RAG.md +567 -0
  67. package/docs/NAVIGATE.md +186 -0
  68. package/docs/PRIMARY_ACTORS.md +78 -0
  69. package/docs/SECONDARY_ACTORS.md +174 -0
  70. package/docs/VERSIONING.md +17 -0
  71. package/docs/boxsafe.config.md +472 -0
  72. package/eslint.config.mts +15 -0
  73. package/main.ts +53 -0
  74. package/memo/generated/codelog.md +13 -0
  75. package/memo/state/tasks/state.json +6 -0
  76. package/memo/state/tasks/tasks/task_001.md +2 -0
  77. package/memo/states-logs/logs.txt +7 -0
  78. package/memo/states-logs/trace-mljvrxvi-9g0k4q.jsonl +11 -0
  79. package/memo/states-logs/trace-mljvvc9j-pe9ekj.jsonl +11 -0
  80. package/memo/states-logs/trace-mljvvm1c-wbnqzp.jsonl +11 -0
  81. package/memo/states-logs/trace-mljxecwn-9xh3nw.jsonl +11 -0
  82. package/memo/states-logs/trace-mljxqkfm-ipijik.jsonl +11 -0
  83. package/memo/states-logs/trace-mljxwtrw-3fanky.jsonl +11 -0
  84. package/memo/states-logs/trace-mljxzen3-m8iinh.jsonl +11 -0
  85. package/memo/states-logs/trace-mljyucef-td6odn.jsonl +11 -0
  86. package/memo/states-logs/trace-mljyuprw-b1a6f4.jsonl +11 -0
  87. package/memo/states-logs/trace-mljyvefl-b6yoce.jsonl +11 -0
  88. package/memo/states-logs/trace-mljyxjo4-n7ibj2.jsonl +13 -0
  89. package/memo/states-logs/trace-mljziez5-8drqtn.jsonl +13 -0
  90. package/memo/states-logs/trace-mljziulp-dtd03z.jsonl +13 -0
  91. package/memo/states-logs/trace-mljzjwrq-1p2krb.jsonl +13 -0
  92. package/memo/states-logs/trace-mljzl0i7-b1cqa6.jsonl +13 -0
  93. package/memo/states-logs/trace-mljzmlk6-7kdyls.jsonl +13 -0
  94. package/memo/states-logs/trace-mlk0oj25-xa3dcu.jsonl +13 -0
  95. package/memo/states-logs/trace-mlk1x59q-713huj.jsonl +14 -0
  96. package/memo/states-logs/trace-mlk22dz8-7fd6hq.jsonl +14 -0
  97. package/memo/states-logs/trace-mlk241uy-wmx907.jsonl +14 -0
  98. package/memo/states-logs/trace-mlk2bf5r-yoh1vg.jsonl +15 -0
  99. package/package.json +44 -0
  100. package/pnpm-workspace.yaml +4 -0
  101. package/prompt_improvement_example.md +55 -0
  102. package/remove.txt +1 -0
  103. package/tests/adapters.test.ts +128 -0
  104. package/tests/extractCode.test.ts +26 -0
  105. package/tests/integration.test.ts +83 -0
  106. package/tests/loadConfig.test.ts +25 -0
  107. package/tests/navigatorBoundary.test.ts +17 -0
  108. package/tests/ports.test.ts +84 -0
  109. package/tests/runAllTests.ts +49 -0
  110. package/tests/toolCalls.test.ts +149 -0
  111. package/tests/waterfall.test.ts +52 -0
  112. package/tsconfig.json +32 -0
  113. package/tsup.config.ts +17 -0
  114. package/types.d.ts +96 -0
  115. package/util/ANSI.ts +29 -0
  116. package/util/extractCode.ts +217 -0
  117. package/util/extractToolCalls.ts +80 -0
  118. package/util/logger.ts +125 -0
@@ -0,0 +1,128 @@
1
+ # Navigate Module
2
+
3
+ File system navigation system with safety boundaries for LLM-driven operations.
4
+
5
+ ## Purpose
6
+
7
+ Provides a robust, type-safe interface for an LLM to:
8
+ - List directory contents
9
+ - Read file contents
10
+ - Write/create files
11
+ - Create directories
12
+ - Delete files and directories
13
+ - Get file/directory metadata
14
+
15
+ All operations are confined to a workspace boundary and validated.
16
+
17
+ ## Architecture
18
+
19
+ ```
20
+ navigator.ts (main class)
21
+ ├─ listDirectory()
22
+ ├─ readFile()
23
+ ├─ writeFile()
24
+ ├─ createDirectory()
25
+ ├─ delete()
26
+ └─ getMetadata()
27
+
28
+ handler.ts (sgmnt integration)
29
+ └─ NavigatorHandler.execute(params)
30
+
31
+ utils.ts (security & validation)
32
+ ├─ isWithinWorkspace()
33
+ ├─ resolvePath()
34
+ ├─ checkFileSize()
35
+ └─ isReadable/isWritable()
36
+
37
+ types.ts (exported interfaces)
38
+ ├─ NavigatorConfig
39
+ ├─ NavigatorResult
40
+ └─ FileSystemEntry
41
+ ```
42
+
43
+ ## Quick Start
44
+
45
+ ```typescript
46
+ import { createNavigator } from '@core/navigate';
47
+
48
+ const nav = createNavigator({ workspace: '/app' });
49
+
50
+ // List files
51
+ const dir = await nav.listDirectory('src');
52
+ if (dir.ok) {
53
+ console.log(dir.entries);
54
+ }
55
+
56
+ // Read file
57
+ const file = await nav.readFile('src/main.ts');
58
+ if (file.ok) {
59
+ console.log(file.content);
60
+ }
61
+
62
+ // Write file
63
+ const write = await nav.writeFile('src/out.ts', 'export const x = 1;', {
64
+ createDirs: true,
65
+ });
66
+
67
+ // Create directory
68
+ const mkdir = await nav.createDirectory('src/utils');
69
+
70
+ // Get metadata
71
+ const stat = await nav.getMetadata('src/main.ts');
72
+
73
+ // Delete
74
+ const del = await nav.delete('src/temp', { recursive: true });
75
+ ```
76
+
77
+ ## Integration with sgmnt
78
+
79
+ Can be integrated into the segmentation map for unified command routing:
80
+
81
+ ```typescript
82
+ const handler = createNavigatorHandler(workspace);
83
+
84
+ await handler.execute({
85
+ op: 'write',
86
+ path: 'src/file.ts',
87
+ content: '...',
88
+ writeOptions: { createDirs: true }
89
+ });
90
+ ```
91
+
92
+ ## Safety Features
93
+
94
+ 1. **Workspace Boundary** - All paths validated to stay within workspace
95
+ 2. **Size Limits** - File reads limited to 10MB default (configurable)
96
+ 3. **Permission Checks** - Validates read/write permissions before operations
97
+ 4. **Path Validation** - Prevents directory traversal attacks
98
+ 5. **Structured Errors** - Clear, machine-readable error results
99
+
100
+ ## Error Handling
101
+
102
+ All operations return `NavigatorResult` - either success or error:
103
+
104
+ ```typescript
105
+ type NavigatorResult =
106
+ | DirectoryListing
107
+ | FileReadResult
108
+ | FileWriteResult
109
+ | DirectoryCreateResult
110
+ | DeleteResult
111
+ | MetadataResult
112
+ | OperationError;
113
+
114
+ if (result.ok) {
115
+ // Success - type is narrowed to specific result type
116
+ } else {
117
+ // Error
118
+ console.error(result.error);
119
+ }
120
+ ```
121
+
122
+ ## Performance Notes
123
+
124
+ - No blocking operations
125
+ - Async/await throughout
126
+ - Efficient directory sorting (dirs first, then alphabetical)
127
+ - Metadata included with directory listings for smart filtering
128
+ - File read limited by configurable size limit
@@ -0,0 +1,367 @@
1
+ /**
2
+ * @fileoverview
3
+ * Practical examples of using the Navigator module.
4
+ * These examples show common use cases for LLM-driven file operations.
5
+ *
6
+ * @module core/navigate/examples
7
+ */
8
+
9
+ import { createNavigator, createNavigatorHandler } from '@core/navigate';
10
+ import type { DirectoryListing, FileReadResult, FileWriteResult, MetadataResult } from '@core/navigate';
11
+ import { Logger } from '@core/util/logger';
12
+
13
+ // Type guards for proper narrowing
14
+ const isDirectory = (result: any): result is DirectoryListing => result.ok && 'entries' in result;
15
+ const isFileRead = (result: any): result is FileReadResult => result.ok && 'content' in result;
16
+ const isFileWrite = (result: any): result is FileWriteResult => result.ok && 'created' in result;
17
+ const isMetadata = (result: any): result is MetadataResult => result.ok && 'stat' in result;
18
+ const isError = (result: any): result is { ok: false; error: string } => !result.ok;
19
+
20
+ const logger = Logger.createModuleLogger('NavigateExamples');
21
+
22
+ // Example 1: Basic Setup and Directory Listing
23
+
24
+ async function example1_BasicListingAndExploration() {
25
+ const nav = createNavigator({
26
+ workspace: '/home/inky/Development/boxsafe',
27
+ });
28
+
29
+ // List root workspace
30
+ const root = await nav.listDirectory('.');
31
+ if (isDirectory(root)) {
32
+ logger.info(`Workspace has ${root.total} items:`);
33
+ root.entries.forEach((entry) => {
34
+ const icon = entry.type === 'directory' ? '📁' : '📄';
35
+ const size = entry.size ? ` (${entry.size} bytes)` : '';
36
+ logger.info(` ${icon} ${entry.name}${size}`);
37
+ });
38
+ }
39
+
40
+ // Navigate to specific directory
41
+ const srcDir = await nav.listDirectory('src');
42
+ if (isDirectory(srcDir)) {
43
+ logger.info(`Found ${srcDir.total} items in src/`);
44
+ }
45
+ }
46
+
47
+ // ============================================================================
48
+ // Example 2: Reading Multiple Files for Analysis
49
+ // ============================================================================
50
+
51
+ async function example2_ReadMultipleFilesForLLMAnalysis() {
52
+ const nav = createNavigator({
53
+ workspace: '/home/inky/Development/boxsafe',
54
+ });
55
+
56
+ // Read several related files
57
+ const files = ['main.ts', 'types.d.ts', 'package.json'];
58
+ const contents: Record<string, string> = {};
59
+
60
+ for (const file of files) {
61
+ const result = await nav.readFile(file);
62
+ if (isFileRead(result)) {
63
+ contents[file] = result.content;
64
+ logger.info(`Loaded ${file} (${result.size} bytes)`);
65
+ } else if (!result.ok) {
66
+ logger.error(`Failed to read ${file}: ${result.error}`);
67
+ }
68
+ }
69
+
70
+ // Now LLM can analyze all files together
71
+ logger.info(`All files loaded for analysis`);
72
+ return contents;
73
+ }
74
+
75
+ // ============================================================================
76
+ // Example 3: Creating Project Structure
77
+ // ============================================================================
78
+
79
+ async function example3_CreateProjectStructure() {
80
+ const nav = createNavigator({
81
+ workspace: '/home/inky/Development/boxsafe',
82
+ });
83
+
84
+ // Create directory structure
85
+ const dirs = [
86
+ 'output',
87
+ 'output/generated',
88
+ 'output/reports',
89
+ 'output/logs',
90
+ ];
91
+
92
+ for (const dir of dirs) {
93
+ const result = await nav.createDirectory(dir, { recursive: true });
94
+ if (isError(result)) {
95
+ logger.error(`Failed: ${result.error}`);
96
+ } else {
97
+ logger.info(`Created: ${result.path}`);
98
+ }
99
+ }
100
+ }
101
+
102
+ // ============================================================================
103
+ // Example 4: Generate Multiple Code Files
104
+ // ============================================================================
105
+
106
+ async function example4_GenerateCodeFiles() {
107
+ const nav = createNavigator({
108
+ workspace: '/home/inky/Development/boxsafe',
109
+ });
110
+
111
+ const files = [
112
+ {
113
+ path: 'generated/types.ts',
114
+ content: `export interface User { id: string; name: string; }`,
115
+ },
116
+ {
117
+ path: 'generated/utils.ts',
118
+ content: `export function formatName(name: string): string { return name.trim(); }`,
119
+ },
120
+ {
121
+ path: 'generated/index.ts',
122
+ content: `export * from './types';\nexport * from './utils';`,
123
+ },
124
+ ];
125
+
126
+ for (const file of files) {
127
+ const result = await nav.writeFile(file.path, file.content, {
128
+ createDirs: true,
129
+ });
130
+
131
+ if (isError(result)) {
132
+ logger.error(`✗ Failed: ${result.error}`);
133
+ } else {
134
+ logger.info(`✓ Created ${result.path}`);
135
+ }
136
+ }
137
+ }
138
+
139
+ // ============================================================================
140
+ // Example 5: Iterate and Update Files
141
+ // ============================================================================
142
+
143
+ async function example5_IterativeFileUpdates() {
144
+ const nav = createNavigator({
145
+ workspace: '/home/inky/Development/boxsafe',
146
+ });
147
+
148
+ // Read existing file
149
+ const result = await nav.readFile('src/main.ts');
150
+ if (!isFileRead(result)) {
151
+ logger.error(`Cannot read: ${isError(result) ? result.error : 'unknown'}`);
152
+ return;
153
+ }
154
+ let content = result.content;
155
+ const hasExport = content.includes('export');
156
+ if (!hasExport) {
157
+ // Add export if missing
158
+ content = `export ${content}`;
159
+ }
160
+
161
+ // Write back with updated content
162
+ const writeResult = await nav.writeFile('src/main.ts', content);
163
+ if (isFileWrite(writeResult)) {
164
+ logger.info(`Updated ${writeResult.path} (${writeResult.size} bytes)`);
165
+ } else if (isError(writeResult)) {
166
+ logger.error(`Write failed: ${writeResult.error}`);
167
+ }
168
+ }
169
+
170
+ // ============================================================================
171
+ // Example 6: Check File Metadata Before Operations
172
+ // ============================================================================
173
+
174
+ async function example6_ValidateBeforeOperation() {
175
+ const nav = createNavigator({
176
+ workspace: '/home/inky/Development/boxsafe',
177
+ maxFileSize: 5 * 1024 * 1024, // 5MB limit
178
+ });
179
+
180
+ const filePath = 'src/large.json';
181
+
182
+ // Check metadata first
183
+ const stat = await nav.getMetadata(filePath);
184
+ if (!isMetadata(stat)) {
185
+ logger.error(`File not found: ${isError(stat) ? stat.error : 'unknown'}`);
186
+ return;
187
+ }
188
+ if (stat.stat.size > 1024 * 1024) {
189
+ logger.warn(`File is ${stat.stat.size} bytes - may be too large`);
190
+ }
191
+ if (!stat.stat.isReadable) {
192
+ logger.error(`File is not readable`);
193
+ return;
194
+ }
195
+
196
+ // Now safe to read
197
+ const content = await nav.readFile(filePath);
198
+ if (isFileRead(content)) {
199
+ logger.info(`File content loaded: ${content.content.slice(0, 100)}`);
200
+ }
201
+ }
202
+
203
+ // ============================================================================
204
+ // Example 7: LLM-Friendly Handler Integration
205
+ // ============================================================================
206
+
207
+ async function example7_HandlerIntegration() {
208
+ const handler = createNavigatorHandler('/home/inky/Development/boxsafe');
209
+
210
+ // Simple operations through handler
211
+ const list = await handler.execute({
212
+ op: 'list',
213
+ path: 'src',
214
+ });
215
+ logger.info(`Directory listing result:`);
216
+ logger.debug(JSON.stringify(list, null, 2));
217
+
218
+ // Write with structured params
219
+ const write = await handler.execute({
220
+ op: 'write',
221
+ path: 'output/result.ts',
222
+ content: 'export const result = "success";',
223
+ writeOptions: { createDirs: true },
224
+ });
225
+ logger.info(`Write result:`);
226
+ logger.debug(JSON.stringify(write, null, 2));
227
+
228
+ // Read with error handling
229
+ const read = await handler.execute({
230
+ op: 'read',
231
+ path: 'output/result.ts',
232
+ });
233
+ if (isError(read)) {
234
+ logger.error(`Read error: ${read.error}`);
235
+ } else if (isFileRead(read)) {
236
+ logger.info(`Content: ${read.content}`);
237
+ }
238
+
239
+ // Delete operation
240
+ const del = await handler.execute({
241
+ op: 'delete',
242
+ path: 'output/temp',
243
+ deleteOptions: { recursive: true },
244
+ });
245
+ logger.info(`Delete result:`);
246
+ logger.debug(JSON.stringify(del, null, 2));
247
+ }
248
+
249
+ // ============================================================================
250
+ // Example 8: Batch Operations with Error Recovery
251
+ // ============================================================================
252
+
253
+ async function example8_BatchOperationsWithRecovery() {
254
+ const nav = createNavigator({
255
+ workspace: '/home/inky/Development/boxsafe',
256
+ });
257
+
258
+ const operations = [
259
+ { type: 'mkdir' as const, path: 'batch/level1' },
260
+ { type: 'mkdir' as const, path: 'batch/level1/level2' },
261
+ { type: 'write' as const, path: 'batch/file1.txt', content: 'content1' },
262
+ { type: 'write' as const, path: 'batch/level1/file2.txt', content: 'content2' },
263
+ ];
264
+
265
+ const results = [];
266
+ for (const op of operations) {
267
+ try {
268
+ let result;
269
+ if (op.type === 'mkdir') {
270
+ result = await nav.createDirectory(op.path, { recursive: true });
271
+ } else if (op.type === 'write') {
272
+ result = await nav.writeFile(op.path, op.content, { createDirs: true });
273
+ }
274
+
275
+ if (result?.ok) {
276
+ results.push({ status: 'ok', op, result });
277
+ } else if (isError(result)) {
278
+ results.push({ status: 'error', op, error: result });
279
+ }
280
+ } catch (err) {
281
+ results.push({ status: 'exception', op, error: err });
282
+ }
283
+ }
284
+
285
+ logger.info(`Batch results:`);
286
+ logger.debug(JSON.stringify(results, null, 2));
287
+ return results;
288
+ }
289
+
290
+ // ============================================================================
291
+ // Example 9: Explore Directory Tree
292
+ // ============================================================================
293
+
294
+ async function example9_ExploreDirectoryTree() {
295
+ const nav = createNavigator({
296
+ workspace: '/home/inky/Development/boxsafe',
297
+ });
298
+
299
+ async function exploreTree(dirPath: string, depth: number = 0): Promise<void> {
300
+ const indent = ' '.repeat(depth);
301
+
302
+ const listing = await nav.listDirectory(dirPath);
303
+ if (!isDirectory(listing)) {
304
+ logger.error(`${indent}ERROR: ${isError(listing) ? listing.error : 'unknown'}`);
305
+ return;
306
+ }
307
+
308
+ for (const entry of listing.entries) {
309
+ if (entry.type === 'directory') {
310
+ logger.info(`${indent}📁 ${entry.name}/`);
311
+ if (depth < 2) await exploreTree(entry.path, depth + 1);
312
+ } else {
313
+ logger.info(`${indent}📄 ${entry.name} (${entry.size ?? 0} bytes)`);
314
+ }
315
+ }
316
+ }
317
+
318
+ await exploreTree('.');
319
+ }
320
+
321
+ // ============================================================================
322
+ // Example 10: Validate Workspace Before Starting
323
+ // ============================================================================
324
+
325
+ async function example10_ValidateWorkspace() {
326
+ const nav = createNavigator({
327
+ workspace: '/home/inky/Development/boxsafe',
328
+ });
329
+
330
+ const requiredFiles = [
331
+ 'package.json',
332
+ 'tsconfig.json',
333
+ 'types.d.ts',
334
+ ];
335
+
336
+ const required = [];
337
+ for (const file of requiredFiles) {
338
+ const stat = await nav.getMetadata(file);
339
+ const exists = isMetadata(stat);
340
+ const writable = exists ? stat.stat.isWritable : false;
341
+
342
+ required.push({ file, exists, writable });
343
+ }
344
+
345
+ logger.info(`Workspace validation:`);
346
+ logger.debug(JSON.stringify(required, null, 2));
347
+ const allReady = required.every((r) => r.exists && r.writable);
348
+ logger.info(`Workspace ready: ${allReady}`);
349
+ return allReady;
350
+ }
351
+
352
+ // ============================================================================
353
+ // Export all examples for testing
354
+ // ============================================================================
355
+
356
+ export const examples = {
357
+ basicListing: example1_BasicListingAndExploration,
358
+ readMultiple: example2_ReadMultipleFilesForLLMAnalysis,
359
+ createStructure: example3_CreateProjectStructure,
360
+ generateFiles: example4_GenerateCodeFiles,
361
+ iterateUpdate: example5_IterativeFileUpdates,
362
+ validateMetadata: example6_ValidateBeforeOperation,
363
+ handlerIntegration: example7_HandlerIntegration,
364
+ batchOperations: example8_BatchOperationsWithRecovery,
365
+ exploreTree: example9_ExploreDirectoryTree,
366
+ validateWorkspace: example10_ValidateWorkspace,
367
+ };
@@ -0,0 +1,148 @@
1
+ /**
2
+ * @fileoverview
3
+ * Handler for file system navigation operations.
4
+ * Integrates with the sgmnt (segmentation) system for unified LLM command routing.
5
+ *
6
+ * @module core/navigate/handler
7
+ */
8
+
9
+ import type { NavigatorResult } from '@core/navigate/types';
10
+ import { createNavigator, Navigator } from '@core/navigate/navigator';
11
+
12
+ /**
13
+ * Parameters for navigator operations.
14
+ */
15
+ export interface NavigatorOperationParams {
16
+ /** Operation type: 'list', 'read', 'write', 'mkdir', 'delete', 'stat' */
17
+ op: 'list' | 'read' | 'write' | 'mkdir' | 'delete' | 'stat';
18
+
19
+ /** File or directory path (required for all except 'list' with default) */
20
+ path?: string;
21
+
22
+ /** Content to write (required for 'write') */
23
+ content?: string;
24
+
25
+ /** Write options */
26
+ writeOptions?: {
27
+ append?: boolean;
28
+ createDirs?: boolean;
29
+ };
30
+
31
+ /** Directory creation options */
32
+ mkdirOptions?: {
33
+ recursive?: boolean;
34
+ };
35
+
36
+ /** Delete options */
37
+ deleteOptions?: {
38
+ recursive?: boolean;
39
+ };
40
+ }
41
+
42
+ /**
43
+ * Handler for all navigation operations.
44
+ * Provides a unified interface for LLM-driven file system access.
45
+ */
46
+ export class NavigatorHandler {
47
+ private navigator: Navigator;
48
+
49
+ /**
50
+ * Creates a handler instance.
51
+ *
52
+ * @param workspace - Workspace root path for all operations
53
+ */
54
+ constructor(workspace: string) {
55
+ this.navigator = createNavigator({
56
+ workspace,
57
+ followSymlinks: false,
58
+ maxFileSize: 10 * 1024 * 1024, // 10MB default
59
+ });
60
+ }
61
+
62
+ /**
63
+ * Executes a navigation operation.
64
+ *
65
+ * @param params - Operation parameters
66
+ * @returns Promise resolving to operation result
67
+ */
68
+ async execute(params: NavigatorOperationParams): Promise<NavigatorResult> {
69
+ switch (params.op) {
70
+ case 'list':
71
+ return this.navigator.listDirectory(params.path || '.');
72
+
73
+ case 'read':
74
+ if (!params.path) {
75
+ return {
76
+ ok: false,
77
+ operation: 'read',
78
+ error: 'path is required for read operation',
79
+ };
80
+ }
81
+ return this.navigator.readFile(params.path);
82
+
83
+ case 'write':
84
+ if (!params.path) {
85
+ return {
86
+ ok: false,
87
+ operation: 'write',
88
+ error: 'path is required for write operation',
89
+ };
90
+ }
91
+ if (params.content === undefined) {
92
+ return {
93
+ ok: false,
94
+ operation: 'write',
95
+ error: 'content is required for write operation',
96
+ };
97
+ }
98
+ return this.navigator.writeFile(params.path, params.content, params.writeOptions);
99
+
100
+ case 'mkdir':
101
+ if (!params.path) {
102
+ return {
103
+ ok: false,
104
+ operation: 'mkdir',
105
+ error: 'path is required for mkdir operation',
106
+ };
107
+ }
108
+ return this.navigator.createDirectory(params.path, params.mkdirOptions);
109
+
110
+ case 'delete':
111
+ if (!params.path) {
112
+ return {
113
+ ok: false,
114
+ operation: 'delete',
115
+ error: 'path is required for delete operation',
116
+ };
117
+ }
118
+ return this.navigator.delete(params.path, params.deleteOptions);
119
+
120
+ case 'stat':
121
+ if (!params.path) {
122
+ return {
123
+ ok: false,
124
+ operation: 'stat',
125
+ error: 'path is required for stat operation',
126
+ };
127
+ }
128
+ return this.navigator.getMetadata(params.path);
129
+
130
+ default:
131
+ return {
132
+ ok: false,
133
+ operation: 'unknown',
134
+ error: `unknown operation: ${(params as any).op}`,
135
+ };
136
+ }
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Creates a handler instance bound to a workspace.
142
+ *
143
+ * @param workspace - Workspace root path
144
+ * @returns NavigatorHandler instance
145
+ */
146
+ export function createNavigatorHandler(workspace: string): NavigatorHandler {
147
+ return new NavigatorHandler(workspace);
148
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @fileoverview
3
+ * File system navigation module - public API exports.
4
+ *
5
+ * Provides LLM-safe file and directory operations with workspace boundary enforcement.
6
+ *
7
+ * @module core/navigate
8
+ * @example
9
+ * ```typescript
10
+ * import { createNavigator } from '@core/navigate';
11
+ *
12
+ * const nav = createNavigator({ workspace: '/app' });
13
+ * const result = await nav.listDirectory('src');
14
+ * ```
15
+ */
16
+
17
+ export { Navigator, createNavigator } from '@core/navigate/navigator';
18
+ export { NavigatorHandler, createNavigatorHandler } from '@core/navigate/handler';
19
+ export type {
20
+ NavigatorConfig,
21
+ NavigatorResult,
22
+ OperationResult,
23
+ OperationError,
24
+ DirectoryListing,
25
+ FileReadResult,
26
+ FileWriteResult,
27
+ DirectoryCreateResult,
28
+ DeleteResult,
29
+ MetadataResult,
30
+ FileSystemEntry,
31
+ } from '@core/navigate/types';
32
+ export type { NavigatorOperationParams } from '@core/navigate/handler';