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
package/.directory ADDED
@@ -0,0 +1,2 @@
1
+ [Desktop Entry]
2
+ Icon=folder-cyan
package/.env.example ADDED
@@ -0,0 +1,3 @@
1
+ GOOGLE_GENERATIVE_AI_API_KEY=
2
+ EMAIL_GIT=
3
+ PASSWORD_GIT=
package/AUDIT_LANG.md ADDED
@@ -0,0 +1,45 @@
1
+ # Language Audit - BoxSafe Project
2
+
3
+ ## Objective
4
+ Ensure all code files use English for comments and documentation to maintain consistency across the project.
5
+
6
+ ## Files Checked & Fixed
7
+
8
+ ### ✅ Fixed
9
+ - [x] `/home/inky/Development/boxsafe/ai/modelConfig.ts` - Portuguese comments → English
10
+ - [x] `/home/inky/Development/boxsafe/prompt_improvement_example.md` - Portuguese content → English
11
+ - [x] `/home/inky/Development/boxsafe/util/logger.ts` - Portuguese comments → English
12
+ - [x] `/home/inky/Development/boxsafe/core/segments/map.ts` - Portuguese comments → English
13
+ - [x] `/home/inky/Development/boxsafe/core/auth/dasktop/cred/credWin.ts` - Portuguese comments → English
14
+ - [x] `/home/inky/Development/boxsafe/core/ports/index.ts` - Portuguese comments → English (COMPLETED)
15
+ - [x] `/home/inky/Development/boxsafe/core/config/loadConfig.ts` - Portuguese comments → English
16
+ - [x] `/home/inky/Development/boxsafe/core/config/defaults/boxsafeDefaults.ts` - Portuguese comments → English
17
+ - [x] `/home/inky/Development/boxsafe/core/navigate/handler.ts` - Portuguese comments → English
18
+ - [x] `/home/inky/Development/boxsafe/core/navigate/navigator.ts` - Portuguese comments → English (COMPLETED)
19
+
20
+ ### 🔄 Already in English
21
+ - [x] `/home/inky/Development/boxsafe/core/loop/toolCalls.ts` - Comments already in English
22
+ - [x] `/home/inky/Development/boxsafe/core/loop/execLoop.ts` - Comments already in English
23
+ - [x] `/home/inky/Development/boxsafe/core/loop/waterfall.ts` - Comments already in English
24
+ - [x] `/home/inky/Development/boxsafe/tests/integration.test.ts` - Comments already in English
25
+ - [x] `/home/inky/Development/boxsafe/tests/waterfall.test.ts` - Comments already in English
26
+ - [x] `/home/inky/Development/boxsafe/tests/ports.test.ts` - Comments already in English
27
+ - [x] `/home/inky/Development/boxsafe/tests/adapters.test.ts` - Comments already in English
28
+
29
+ ### 📝 Notes
30
+ - Documentation files in `/docs/` can remain in Portuguese as they are user-facing
31
+ - `/util/` and `/root/` directories are excluded from this audit
32
+ - Focus on core functionality files only
33
+
34
+ ## Standards
35
+ - All code comments: English
36
+ - All variable/function names: English (already standard)
37
+ - All documentation in code: English
38
+ - User-facing docs: Can be multilingual
39
+
40
+ ## 🎯 AUDIT COMPLETE
41
+ **Status: 100% COMPLETE**
42
+ - All core code files have been audited
43
+ - All Portuguese comments have been converted to English
44
+ - All files now follow the language standards
45
+ - Project consistency achieved
@@ -0,0 +1,14 @@
1
+ # BOXSAFE Versioning Notes
2
+
3
+ Commit message:
4
+
5
+ save agent
6
+
7
+ Summary:
8
+
9
+ save agent
10
+
11
+ LOG_AUDIT.md
12
+ memo/states-logs/trace-mljvfahg-t4zc18.jsonl
13
+ memo/states-logs/trace-mljyuprw-b1a6f4.jsonl
14
+ memo/states-logs/trace-mljyvefl-b6yoce.jsonl
package/README.md ADDED
@@ -0,0 +1,4 @@
1
+ core → can call everyone
2
+ pack → can call everyone except core
3
+ memo → can only call util
4
+ util → cannot call anyone
package/TODO.md ADDED
@@ -0,0 +1,130 @@
1
+ # BoxSafe TODO - Sistema Inteligente de Prompts
2
+
3
+ ## Status Atual
4
+ - ✅ Sistema de tools 100% funcional
5
+ - ✅ Parsing de json-tool perfeito
6
+ - ✅ Logging consistente implementado
7
+ - ❌ Prompt atual incompleto (falta parâmetro `content`)
8
+ - ❌ Sistema de prompts hardcoded (gambiarra funcional)
9
+
10
+ ---
11
+
12
+ ## 🎯 Objetivo Principal
13
+ Implementar um sistema inteligente de gerenciamento de prompts que:
14
+ - Categorize modelos por capacidade (LOW/MEDIUM/HIGH/EXCELLENT)
15
+ - Otimize frequência de lembretes baseada no modelo
16
+ - Reduza custos com providers
17
+ - Melhore a experiência do usuário
18
+
19
+ ---
20
+
21
+ ## 📋 Tasks Organizadas
22
+
23
+ ### Phase 1: Fundação (Crítica)
24
+ **1. Criar Sistema de Configuração de Modelos**
25
+ - [ ] Criar arquivo `ai/modelConfig.ts` com perfis de modelos
26
+ - [ ] Definir categorias: LOW (<8k), MEDIUM (8k-32k), HIGH (32k-128k), EXCELLENT (>128k)
27
+ - [ ] Configurar frequências de lembrete por categoria
28
+ - [ ] Adicionar metadados de custo por token
29
+
30
+ **2. Implementar Estratégias de Prompt**
31
+ - [ ] Criar prompts específicos por capacidade do modelo
32
+ - [ ] Incluir exemplos completos com parâmetro `content`
33
+ - [ ] Sistema de lembretes inteligentes
34
+ - [ ] Validação de prompts
35
+
36
+ **3. Integrar com Loop Principal**
37
+ - [ ] Substituir prompt hardcoded pelo PromptManager
38
+ - [ ] Detectar modelo automaticamente da configuração
39
+ - [ ] Implementar sistema de contexto/usage tracking
40
+ - [ ] Testar integração completa
41
+
42
+ ### Phase 2: Inteligência (Otimização)
43
+ **4. Sistema de Context Awareness**
44
+ - [ ] Monitorar uso de contexto em tempo real
45
+ - [ ] Trigger de lembretes baseado em threshold
46
+ - [ ] Otimização de tokens por interação
47
+ - [ ] Sistema de recuperação de erros
48
+
49
+ **5. Otimização de Custos**
50
+ - [ ] Calcular custo por interação
51
+ - [ ] Estratégias para reduzir tokens desnecessários
52
+ - [ ] Balance entre qualidade e custo
53
+ - [ ] Relatórios de uso
54
+
55
+ **6. Sistema de Aprendizado**
56
+ - [ ] Detectar padrões de erros do modelo
57
+ - [ ] Adaptar prompts baseado no histórico
58
+ - [ ] Sistema de feedback automático
59
+ - [ ] Melhoria contínua
60
+
61
+ ### Phase 3: Avançado (Futuro)
62
+ **7. Interface de Configuração**
63
+ - [ ] CLI para gerenciar modelos
64
+ - [ ] Configuração via arquivo YAML/JSON
65
+ - [ ] Validação de configurações
66
+ - [ ] Documentação interativa
67
+
68
+ **8. Monitoramento e Analytics**
69
+ - [ ] Dashboard de uso de prompts
70
+ - [ ] Métricas de performance
71
+ - [ ] Alertas de anomalias
72
+ - [ ] Sistema de logging avançado
73
+
74
+ ---
75
+
76
+ ## 🔧 Detalhes Técnicos
77
+
78
+ ### Arquivos a Criar:
79
+ - `ai/modelConfig.ts` - Configurações dos modelos
80
+ - `ai/promptManager.ts` - Sistema inteligente de prompts
81
+ - `ai/promptStrategies.ts` - Estratégias por capacidade
82
+ - `ai/contextTracker.ts` - Monitoramento de contexto
83
+ - `ai/costOptimizer.ts` - Otimização de custos
84
+
85
+ ### Arquivos a Modificar:
86
+ - `core/loop/execLoop.ts` - Integrar PromptManager
87
+ - `boxsafe.config.json` - Adicionar configurações de modelo
88
+ - `ai/prompts.ts` - Migrar para sistema estruturado
89
+
90
+ ### Critérios de Sucesso:
91
+ - [ ] Prompt completo com parâmetro `content`
92
+ - [ ] Sistema adaptável a diferentes modelos
93
+ - [ ] Redução de 30% nos custos de API
94
+ - [ ] Zero erros de json-tool incompleto
95
+ - [ ] Documentação completa e testada
96
+
97
+ ---
98
+
99
+ ## 🚀 Próximos Passos Imediatos
100
+
101
+ 1. **Discussão**: Validar arquitetura proposta
102
+ 2. **Prioridade**: Phase 1 (fundação crítica)
103
+ 3. **Execução**: Implementar task por task com validação
104
+ 4. **Testes**: Garantir funcionamento em todos os modelos
105
+ 5. **Deploy**: Substituir sistema atual
106
+
107
+ ---
108
+
109
+ ## 📝 Notas
110
+ - Manter compatibilidade com sistema atual
111
+ - Implementar fallbacks para modelos desconhecidos
112
+ - Considerar modelos locais vs API
113
+ - Performance crítica para não impactar o loop
114
+
115
+ Dynamic Tool Loading: Só injete as tools relevantes ao contexto atual
116
+ Schema Compression: Para modelos fracos, use schemas simplificados
117
+ 1. Início: Ensina TUDO (full system prompt + todas as tools)
118
+ 2. Durante: Relembra periodicamente baseado em:
119
+ • Qualidade do modelo (tier)
120
+ • Frequência de uso das tools
121
+ 3. Otimização: Prompts compactos para modelos fracos
122
+ 2. uso eficiente ded sistema de caching dos provaders integrar todas os plugs para economizar tokes oferecido pelo provider
123
+
124
+ 3. criação de (RAG)
125
+
126
+
127
+ 16. tool para busca inteligente, o modelo não sabe aonde um metodo ou função em expecifica ou qualquer coisa dentro do de um codigo esta mas ele consegue de forma inteligente so por um trecho do codigo achar
128
+ sem indicação externa
129
+
130
+ 17. usar script sheel para comandos fixo do projeto para ter menos codigo com comandos misturados
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @fileoverview
3
+ * Hexagonal architecture adapters - Concrete implementations of ports
4
+ *
5
+ * Each adapter connects BoxSafe core with a specific Secondary Actor.
6
+ *
7
+ * @module adapters/index
8
+ */
9
+
10
+ // Secondary Adapters
11
+ export { SystemConfigurationAdapter } from '@adapters/secondary/system/configuration';
12
+ export { FileSystemAdapter } from '@adapters/secondary/filesystem/node-filesystem';
13
+
14
+ // Primary Adapters
15
+ export { CLIAdapter } from '@adapters/primary/cli-adapter';
16
+
17
+ // Factory functions
18
+ export { createSystemConfigurationAdapter } from '@adapters/secondary/system/configuration';
19
+ export { createFileSystemAdapter } from '@adapters/secondary/filesystem/node-filesystem';
20
+ export { createCLIAdapter } from '@adapters/primary/cli-adapter';
21
+
22
+ // Re-export ports for convenience
23
+ export type {
24
+ ISystemConfigurationPort,
25
+ IFileSystemPort,
26
+ ISystemExecutionPort
27
+ } from '../core/ports';
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @fileoverview
3
+ * Primary Adapters - Implement ports for primary actors
4
+ *
5
+ * Connect Primary Actors (CLI, Web, IDE) with system core
6
+ *
7
+ * @module adapters/primary/index
8
+ */
9
+
10
+ import type { ISystemExecutionPort } from '@core/ports';
11
+ import { initSegments } from '@core/segments/map';
12
+
13
+ /**
14
+ * CLI Adapter - implements ISystemExecutionPort for command line interface
15
+ */
16
+ export class CLIAdapter implements ISystemExecutionPort {
17
+ private segments: any;
18
+
19
+ constructor() {
20
+ this.init();
21
+ }
22
+
23
+ private async init() {
24
+ const { runSegment, BSConfig } = await initSegments();
25
+ this.segments = { runSegment, BSConfig };
26
+ }
27
+
28
+ /**
29
+ * Execute a specific system segment
30
+ */
31
+ async executeSegment(segmentName: string, args?: any): Promise<any> {
32
+ if (!this.segments?.runSegment) {
33
+ throw new Error('Segments not initialized');
34
+ }
35
+ return this.segments.runSegment(segmentName, args);
36
+ }
37
+
38
+ /**
39
+ * List all available segments
40
+ */
41
+ listSegments(): Record<string, any> {
42
+ // TODO: Implement segment listing
43
+ return {
44
+ loop: { description: 'Iterative LLM -> code -> exec loop', implemented: true },
45
+ navigate: { description: 'File system navigation with workspace boundary', implemented: true },
46
+ versionControl: { description: 'Git version control operations', implemented: true }
47
+ };
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Factory function to create CLI adapter
53
+ */
54
+ export function createCLIAdapter(): CLIAdapter {
55
+ return new CLIAdapter();
56
+ }
@@ -0,0 +1,307 @@
1
+ /**
2
+ * @fileoverview
3
+ * Adapter for IFileSystemPort
4
+ * Implementation based on existing navigate module
5
+ *
6
+ * @module adapters/secondary/filesystem/node-filesystem
7
+ */
8
+
9
+ import fs from 'node:fs/promises';
10
+ import path from 'node:path';
11
+ import type {
12
+ IFileSystemPort,
13
+ NavigatorResult,
14
+ DirectoryListing,
15
+ FileReadResult,
16
+ FileWriteResult,
17
+ DirectoryCreateResult,
18
+ DeleteResult,
19
+ MetadataResult,
20
+ OperationError
21
+ } from '@core/ports';
22
+ import type {
23
+ FileSystemEntry,
24
+ NavigatorConfig
25
+ } from '@core/navigate/types';
26
+
27
+ /**
28
+ * File system adapter using Node.js fs module
29
+ */
30
+ export class FileSystemAdapter implements IFileSystemPort {
31
+ private workspace: string;
32
+ private followSymlinks: boolean;
33
+ private maxFileSize: number;
34
+
35
+ constructor(config: NavigatorConfig) {
36
+ this.workspace = config.workspace;
37
+ this.followSymlinks = config.followSymlinks ?? false;
38
+ this.maxFileSize = config.maxFileSize ?? 10 * 1024 * 1024; // 10MB
39
+ }
40
+
41
+ /**
42
+ * Lista conteúdo de um diretório
43
+ */
44
+ async listDirectory(dirPath: string): Promise<NavigatorResult> {
45
+ try {
46
+ const resolvedPath = this.resolvePath(dirPath);
47
+ const entries = await fs.readdir(resolvedPath, { withFileTypes: true });
48
+
49
+ const fileSystemEntries: FileSystemEntry[] = [];
50
+
51
+ for (const entry of entries) {
52
+ const fullPath = path.join(resolvedPath, entry.name);
53
+ const relativePath = path.relative(this.workspace, fullPath);
54
+
55
+ try {
56
+ const stats = await fs.stat(fullPath);
57
+
58
+ fileSystemEntries.push({
59
+ path: relativePath,
60
+ name: entry.name,
61
+ type: entry.isDirectory() ? 'directory' : 'file',
62
+ size: entry.isFile() ? stats.size : undefined,
63
+ mtime: stats.mtime.getTime(),
64
+ readable: await this.isReadable(fullPath),
65
+ writable: await this.isWritable(fullPath)
66
+ } as FileSystemEntry);
67
+ } catch {
68
+ // If stat fails, add basic entry
69
+ fileSystemEntries.push({
70
+ path: relativePath,
71
+ name: entry.name,
72
+ type: entry.isDirectory() ? 'directory' : 'file',
73
+ readable: false,
74
+ writable: false
75
+ } as FileSystemEntry);
76
+ }
77
+ }
78
+
79
+ // Sort: directories first, then files, both alphabetically
80
+ fileSystemEntries.sort((a, b) => {
81
+ if (a.type !== b.type) {
82
+ return a.type === 'directory' ? -1 : 1;
83
+ }
84
+ return a.name.localeCompare(b.name);
85
+ });
86
+
87
+ const result: DirectoryListing = {
88
+ ok: true,
89
+ path: dirPath,
90
+ entries: fileSystemEntries,
91
+ total: fileSystemEntries.length
92
+ };
93
+
94
+ return result;
95
+ } catch (error) {
96
+ return this.createOperationError('listDirectory', error as Error);
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Lê conteúdo de um arquivo
102
+ */
103
+ async readFile(filePath: string): Promise<NavigatorResult> {
104
+ try {
105
+ const resolvedPath = this.resolvePath(filePath);
106
+
107
+ // Verificar tamanho do arquivo
108
+ const stats = await fs.stat(resolvedPath);
109
+ if (stats.size > this.maxFileSize) {
110
+ throw new Error(`File too large: ${stats.size} bytes (max: ${this.maxFileSize})`);
111
+ }
112
+
113
+ const content = await fs.readFile(resolvedPath, 'utf-8');
114
+
115
+ const result: FileReadResult = {
116
+ ok: true,
117
+ path: filePath,
118
+ content,
119
+ size: stats.size,
120
+ encoding: 'utf-8'
121
+ };
122
+
123
+ return result;
124
+ } catch (error) {
125
+ return this.createOperationError('readFile', error as Error);
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Write content to a file
131
+ */
132
+ async writeFile(filePath: string, content: string, options?: { append?: boolean; createDirs?: boolean }): Promise<NavigatorResult> {
133
+ try {
134
+ const resolvedPath = this.resolvePath(filePath);
135
+ const dir = path.dirname(resolvedPath);
136
+
137
+ // Create directories if necessary
138
+ if (options?.createDirs) {
139
+ await fs.mkdir(dir, { recursive: true });
140
+ }
141
+
142
+ // Check if directory exists
143
+ try {
144
+ await fs.access(dir);
145
+ } catch {
146
+ throw new Error(`Directory does not exist: ${dir}`);
147
+ }
148
+
149
+ // Write file
150
+ if (options?.append) {
151
+ await fs.appendFile(resolvedPath, content, 'utf-8');
152
+ } else {
153
+ await fs.writeFile(resolvedPath, content, 'utf-8');
154
+ }
155
+
156
+ const stats = await fs.stat(resolvedPath);
157
+ const created = !options?.append;
158
+
159
+ const result: FileWriteResult = {
160
+ ok: true,
161
+ path: filePath,
162
+ size: stats.size,
163
+ created
164
+ };
165
+
166
+ return result;
167
+ } catch (error) {
168
+ return this.createOperationError('writeFile', error as Error);
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Create a directory
174
+ */
175
+ async createDirectory(dirPath: string, options?: { recursive?: boolean }): Promise<NavigatorResult> {
176
+ try {
177
+ const resolvedPath = this.resolvePath(dirPath);
178
+
179
+ await fs.mkdir(resolvedPath, { recursive: options?.recursive ?? false });
180
+
181
+ const stats = await fs.stat(resolvedPath);
182
+ const created = true; // mkdir always creates or throws error
183
+
184
+ const result: DirectoryCreateResult = {
185
+ ok: true,
186
+ path: dirPath,
187
+ created
188
+ };
189
+
190
+ return result;
191
+ } catch (error) {
192
+ return this.createOperationError('createDirectory', error as Error);
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Remove arquivo ou diretório
198
+ */
199
+ async delete(targetPath: string, options?: { recursive?: boolean }): Promise<NavigatorResult> {
200
+ try {
201
+ const resolvedPath = this.resolvePath(targetPath);
202
+ const stats = await fs.stat(resolvedPath);
203
+ const type = stats.isDirectory() ? 'directory' : 'file';
204
+
205
+ if (type === 'directory' && options?.recursive) {
206
+ await fs.rm(resolvedPath, { recursive: true, force: true });
207
+ } else if (type === 'directory') {
208
+ await fs.rmdir(resolvedPath);
209
+ } else {
210
+ await fs.unlink(resolvedPath);
211
+ }
212
+
213
+ const result: DeleteResult = {
214
+ ok: true,
215
+ path: targetPath,
216
+ type,
217
+ deletedAt: Date.now()
218
+ };
219
+
220
+ return result;
221
+ } catch (error) {
222
+ return this.createOperationError('delete', error as Error);
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Obtém metadados de um arquivo/diretório
228
+ */
229
+ async getMetadata(targetPath: string): Promise<NavigatorResult> {
230
+ try {
231
+ const resolvedPath = this.resolvePath(targetPath);
232
+ const stats = await fs.stat(resolvedPath);
233
+
234
+ const result: MetadataResult = {
235
+ ok: true,
236
+ path: targetPath,
237
+ stat: {
238
+ type: stats.isDirectory() ? 'directory' : 'file',
239
+ size: stats.size,
240
+ mtime: stats.mtime.getTime(),
241
+ isReadable: await this.isReadable(resolvedPath),
242
+ isWritable: await this.isWritable(resolvedPath)
243
+ }
244
+ };
245
+
246
+ return result;
247
+ } catch (error) {
248
+ return this.createOperationError('getMetadata', error as Error);
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Helper to resolve path within workspace
254
+ */
255
+ private resolvePath(targetPath: string): string {
256
+ const resolved = path.resolve(this.workspace, targetPath);
257
+
258
+ // Check if inside workspace (security)
259
+ if (!resolved.startsWith(path.resolve(this.workspace))) {
260
+ throw new Error('Path outside workspace is not allowed');
261
+ }
262
+
263
+ return resolved;
264
+ }
265
+
266
+ /**
267
+ * Helper to check if path is readable
268
+ */
269
+ private async isReadable(filePath: string): Promise<boolean> {
270
+ try {
271
+ await fs.access(filePath, fs.constants.R_OK);
272
+ return true;
273
+ } catch {
274
+ return false;
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Helper to check if path is writable
280
+ */
281
+ private async isWritable(filePath: string): Promise<boolean> {
282
+ try {
283
+ await fs.access(filePath, fs.constants.W_OK);
284
+ return true;
285
+ } catch {
286
+ return false;
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Helper to create OperationError
292
+ */
293
+ private createOperationError(operation: string, error: Error): OperationError {
294
+ return {
295
+ ok: false,
296
+ operation,
297
+ error: error.message
298
+ };
299
+ }
300
+ }
301
+
302
+ /**
303
+ * Factory function para criar o adapter
304
+ */
305
+ export function createFileSystemAdapter(config: NavigatorConfig): FileSystemAdapter {
306
+ return new FileSystemAdapter(config);
307
+ }