genesis-ai-cli 7.4.5

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 (227) hide show
  1. package/.env.example +78 -0
  2. package/README.md +282 -0
  3. package/dist/src/active-inference/actions.d.ts +75 -0
  4. package/dist/src/active-inference/actions.js +250 -0
  5. package/dist/src/active-inference/autonomous-loop.d.ts +103 -0
  6. package/dist/src/active-inference/autonomous-loop.js +289 -0
  7. package/dist/src/active-inference/core.d.ts +85 -0
  8. package/dist/src/active-inference/core.js +555 -0
  9. package/dist/src/active-inference/demo-autonomous-loop.d.ts +8 -0
  10. package/dist/src/active-inference/demo-autonomous-loop.js +338 -0
  11. package/dist/src/active-inference/demo-value-integration.d.ts +8 -0
  12. package/dist/src/active-inference/demo-value-integration.js +174 -0
  13. package/dist/src/active-inference/index.d.ts +32 -0
  14. package/dist/src/active-inference/index.js +88 -0
  15. package/dist/src/active-inference/integration.d.ts +114 -0
  16. package/dist/src/active-inference/integration.js +698 -0
  17. package/dist/src/active-inference/memory-integration.d.ts +51 -0
  18. package/dist/src/active-inference/memory-integration.js +232 -0
  19. package/dist/src/active-inference/observations.d.ts +67 -0
  20. package/dist/src/active-inference/observations.js +147 -0
  21. package/dist/src/active-inference/test-active-inference.d.ts +8 -0
  22. package/dist/src/active-inference/test-active-inference.js +320 -0
  23. package/dist/src/active-inference/test-value-integration.d.ts +6 -0
  24. package/dist/src/active-inference/test-value-integration.js +168 -0
  25. package/dist/src/active-inference/types.d.ts +150 -0
  26. package/dist/src/active-inference/types.js +59 -0
  27. package/dist/src/active-inference/value-integration.d.ts +164 -0
  28. package/dist/src/active-inference/value-integration.js +459 -0
  29. package/dist/src/agents/base-agent.d.ts +53 -0
  30. package/dist/src/agents/base-agent.js +178 -0
  31. package/dist/src/agents/builder.d.ts +67 -0
  32. package/dist/src/agents/builder.js +537 -0
  33. package/dist/src/agents/critic.d.ts +35 -0
  34. package/dist/src/agents/critic.js +322 -0
  35. package/dist/src/agents/ethicist.d.ts +54 -0
  36. package/dist/src/agents/ethicist.js +393 -0
  37. package/dist/src/agents/explorer.d.ts +26 -0
  38. package/dist/src/agents/explorer.js +216 -0
  39. package/dist/src/agents/feeling.d.ts +41 -0
  40. package/dist/src/agents/feeling.js +320 -0
  41. package/dist/src/agents/index.d.ts +111 -0
  42. package/dist/src/agents/index.js +222 -0
  43. package/dist/src/agents/memory.d.ts +69 -0
  44. package/dist/src/agents/memory.js +404 -0
  45. package/dist/src/agents/message-bus.d.ts +88 -0
  46. package/dist/src/agents/message-bus.js +267 -0
  47. package/dist/src/agents/narrator.d.ts +90 -0
  48. package/dist/src/agents/narrator.js +473 -0
  49. package/dist/src/agents/planner.d.ts +38 -0
  50. package/dist/src/agents/planner.js +341 -0
  51. package/dist/src/agents/predictor.d.ts +73 -0
  52. package/dist/src/agents/predictor.js +506 -0
  53. package/dist/src/agents/sensor.d.ts +88 -0
  54. package/dist/src/agents/sensor.js +377 -0
  55. package/dist/src/agents/test-agents.d.ts +6 -0
  56. package/dist/src/agents/test-agents.js +73 -0
  57. package/dist/src/agents/types.d.ts +194 -0
  58. package/dist/src/agents/types.js +7 -0
  59. package/dist/src/brain/index.d.ts +185 -0
  60. package/dist/src/brain/index.js +843 -0
  61. package/dist/src/brain/trace.d.ts +91 -0
  62. package/dist/src/brain/trace.js +327 -0
  63. package/dist/src/brain/types.d.ts +165 -0
  64. package/dist/src/brain/types.js +51 -0
  65. package/dist/src/cli/chat.d.ts +237 -0
  66. package/dist/src/cli/chat.js +1959 -0
  67. package/dist/src/cli/dispatcher.d.ts +182 -0
  68. package/dist/src/cli/dispatcher.js +718 -0
  69. package/dist/src/cli/human-loop.d.ts +170 -0
  70. package/dist/src/cli/human-loop.js +543 -0
  71. package/dist/src/cli/index.d.ts +12 -0
  72. package/dist/src/cli/index.js +28 -0
  73. package/dist/src/cli/interactive.d.ts +141 -0
  74. package/dist/src/cli/interactive.js +757 -0
  75. package/dist/src/cli/ui.d.ts +205 -0
  76. package/dist/src/cli/ui.js +632 -0
  77. package/dist/src/consciousness/attention-schema.d.ts +154 -0
  78. package/dist/src/consciousness/attention-schema.js +432 -0
  79. package/dist/src/consciousness/global-workspace.d.ts +149 -0
  80. package/dist/src/consciousness/global-workspace.js +422 -0
  81. package/dist/src/consciousness/index.d.ts +186 -0
  82. package/dist/src/consciousness/index.js +476 -0
  83. package/dist/src/consciousness/phi-calculator.d.ts +119 -0
  84. package/dist/src/consciousness/phi-calculator.js +445 -0
  85. package/dist/src/consciousness/phi-decisions.d.ts +169 -0
  86. package/dist/src/consciousness/phi-decisions.js +383 -0
  87. package/dist/src/consciousness/phi-monitor.d.ts +153 -0
  88. package/dist/src/consciousness/phi-monitor.js +465 -0
  89. package/dist/src/consciousness/types.d.ts +260 -0
  90. package/dist/src/consciousness/types.js +44 -0
  91. package/dist/src/daemon/dream-mode.d.ts +115 -0
  92. package/dist/src/daemon/dream-mode.js +470 -0
  93. package/dist/src/daemon/index.d.ts +162 -0
  94. package/dist/src/daemon/index.js +542 -0
  95. package/dist/src/daemon/maintenance.d.ts +139 -0
  96. package/dist/src/daemon/maintenance.js +549 -0
  97. package/dist/src/daemon/process.d.ts +82 -0
  98. package/dist/src/daemon/process.js +442 -0
  99. package/dist/src/daemon/scheduler.d.ts +90 -0
  100. package/dist/src/daemon/scheduler.js +494 -0
  101. package/dist/src/daemon/types.d.ts +213 -0
  102. package/dist/src/daemon/types.js +50 -0
  103. package/dist/src/epistemic/index.d.ts +74 -0
  104. package/dist/src/epistemic/index.js +225 -0
  105. package/dist/src/grounding/epistemic-stack.d.ts +100 -0
  106. package/dist/src/grounding/epistemic-stack.js +408 -0
  107. package/dist/src/grounding/feedback.d.ts +98 -0
  108. package/dist/src/grounding/feedback.js +276 -0
  109. package/dist/src/grounding/index.d.ts +123 -0
  110. package/dist/src/grounding/index.js +224 -0
  111. package/dist/src/grounding/verifier.d.ts +149 -0
  112. package/dist/src/grounding/verifier.js +484 -0
  113. package/dist/src/healing/detector.d.ts +110 -0
  114. package/dist/src/healing/detector.js +436 -0
  115. package/dist/src/healing/fixer.d.ts +138 -0
  116. package/dist/src/healing/fixer.js +572 -0
  117. package/dist/src/healing/index.d.ts +23 -0
  118. package/dist/src/healing/index.js +43 -0
  119. package/dist/src/hooks/index.d.ts +135 -0
  120. package/dist/src/hooks/index.js +317 -0
  121. package/dist/src/index.d.ts +23 -0
  122. package/dist/src/index.js +1266 -0
  123. package/dist/src/kernel/index.d.ts +155 -0
  124. package/dist/src/kernel/index.js +795 -0
  125. package/dist/src/kernel/invariants.d.ts +153 -0
  126. package/dist/src/kernel/invariants.js +355 -0
  127. package/dist/src/kernel/test-kernel.d.ts +6 -0
  128. package/dist/src/kernel/test-kernel.js +108 -0
  129. package/dist/src/kernel/test-real-mcp.d.ts +10 -0
  130. package/dist/src/kernel/test-real-mcp.js +295 -0
  131. package/dist/src/llm/index.d.ts +146 -0
  132. package/dist/src/llm/index.js +428 -0
  133. package/dist/src/llm/router.d.ts +136 -0
  134. package/dist/src/llm/router.js +510 -0
  135. package/dist/src/mcp/index.d.ts +85 -0
  136. package/dist/src/mcp/index.js +657 -0
  137. package/dist/src/mcp/resilient.d.ts +139 -0
  138. package/dist/src/mcp/resilient.js +417 -0
  139. package/dist/src/memory/cache.d.ts +118 -0
  140. package/dist/src/memory/cache.js +356 -0
  141. package/dist/src/memory/cognitive-workspace.d.ts +231 -0
  142. package/dist/src/memory/cognitive-workspace.js +521 -0
  143. package/dist/src/memory/consolidation.d.ts +99 -0
  144. package/dist/src/memory/consolidation.js +443 -0
  145. package/dist/src/memory/episodic.d.ts +114 -0
  146. package/dist/src/memory/episodic.js +394 -0
  147. package/dist/src/memory/forgetting.d.ts +134 -0
  148. package/dist/src/memory/forgetting.js +324 -0
  149. package/dist/src/memory/index.d.ts +211 -0
  150. package/dist/src/memory/index.js +367 -0
  151. package/dist/src/memory/indexer.d.ts +123 -0
  152. package/dist/src/memory/indexer.js +479 -0
  153. package/dist/src/memory/procedural.d.ts +136 -0
  154. package/dist/src/memory/procedural.js +479 -0
  155. package/dist/src/memory/semantic.d.ts +132 -0
  156. package/dist/src/memory/semantic.js +497 -0
  157. package/dist/src/memory/types.d.ts +193 -0
  158. package/dist/src/memory/types.js +15 -0
  159. package/dist/src/orchestrator.d.ts +65 -0
  160. package/dist/src/orchestrator.js +317 -0
  161. package/dist/src/persistence/index.d.ts +257 -0
  162. package/dist/src/persistence/index.js +763 -0
  163. package/dist/src/pipeline/executor.d.ts +51 -0
  164. package/dist/src/pipeline/executor.js +695 -0
  165. package/dist/src/pipeline/index.d.ts +7 -0
  166. package/dist/src/pipeline/index.js +11 -0
  167. package/dist/src/self-production.d.ts +67 -0
  168. package/dist/src/self-production.js +205 -0
  169. package/dist/src/subagents/executor.d.ts +58 -0
  170. package/dist/src/subagents/executor.js +283 -0
  171. package/dist/src/subagents/index.d.ts +37 -0
  172. package/dist/src/subagents/index.js +53 -0
  173. package/dist/src/subagents/registry.d.ts +23 -0
  174. package/dist/src/subagents/registry.js +167 -0
  175. package/dist/src/subagents/types.d.ts +79 -0
  176. package/dist/src/subagents/types.js +14 -0
  177. package/dist/src/tools/bash.d.ts +139 -0
  178. package/dist/src/tools/bash.js +583 -0
  179. package/dist/src/tools/edit.d.ts +125 -0
  180. package/dist/src/tools/edit.js +424 -0
  181. package/dist/src/tools/git.d.ts +179 -0
  182. package/dist/src/tools/git.js +504 -0
  183. package/dist/src/tools/index.d.ts +21 -0
  184. package/dist/src/tools/index.js +163 -0
  185. package/dist/src/types.d.ts +145 -0
  186. package/dist/src/types.js +7 -0
  187. package/dist/src/world-model/decoder.d.ts +163 -0
  188. package/dist/src/world-model/decoder.js +517 -0
  189. package/dist/src/world-model/digital-twin.d.ts +219 -0
  190. package/dist/src/world-model/digital-twin.js +695 -0
  191. package/dist/src/world-model/encoder.d.ts +141 -0
  192. package/dist/src/world-model/encoder.js +564 -0
  193. package/dist/src/world-model/index.d.ts +221 -0
  194. package/dist/src/world-model/index.js +772 -0
  195. package/dist/src/world-model/predictor.d.ts +161 -0
  196. package/dist/src/world-model/predictor.js +681 -0
  197. package/dist/src/world-model/test-value-jepa.d.ts +8 -0
  198. package/dist/src/world-model/test-value-jepa.js +430 -0
  199. package/dist/src/world-model/types.d.ts +341 -0
  200. package/dist/src/world-model/types.js +69 -0
  201. package/dist/src/world-model/value-jepa.d.ts +247 -0
  202. package/dist/src/world-model/value-jepa.js +622 -0
  203. package/dist/test/brain.test.d.ts +11 -0
  204. package/dist/test/brain.test.js +358 -0
  205. package/dist/test/cli/dispatcher.test.d.ts +4 -0
  206. package/dist/test/cli/dispatcher.test.js +332 -0
  207. package/dist/test/cli/human-loop.test.d.ts +4 -0
  208. package/dist/test/cli/human-loop.test.js +270 -0
  209. package/dist/test/grounding/feedback.test.d.ts +4 -0
  210. package/dist/test/grounding/feedback.test.js +462 -0
  211. package/dist/test/grounding/verifier.test.d.ts +4 -0
  212. package/dist/test/grounding/verifier.test.js +442 -0
  213. package/dist/test/grounding.test.d.ts +6 -0
  214. package/dist/test/grounding.test.js +246 -0
  215. package/dist/test/healing/detector.test.d.ts +4 -0
  216. package/dist/test/healing/detector.test.js +266 -0
  217. package/dist/test/healing/fixer.test.d.ts +4 -0
  218. package/dist/test/healing/fixer.test.js +369 -0
  219. package/dist/test/integration.test.d.ts +5 -0
  220. package/dist/test/integration.test.js +290 -0
  221. package/dist/test/tools/bash.test.d.ts +4 -0
  222. package/dist/test/tools/bash.test.js +348 -0
  223. package/dist/test/tools/edit.test.d.ts +4 -0
  224. package/dist/test/tools/edit.test.js +350 -0
  225. package/dist/test/tools/git.test.d.ts +4 -0
  226. package/dist/test/tools/git.test.js +350 -0
  227. package/package.json +60 -0
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Genesis Diff-Based File Editor
3
+ *
4
+ * File editing capabilities:
5
+ * - old_string -> new_string replacement
6
+ * - Unique match verification
7
+ * - replace_all for global replacements
8
+ * - Atomic writes with backup
9
+ * - Indentation preservation
10
+ */
11
+ export interface EditParams {
12
+ /** Absolute path to the file */
13
+ file_path: string;
14
+ /** Text to find and replace */
15
+ old_string: string;
16
+ /** Text to replace with */
17
+ new_string: string;
18
+ /** Replace all occurrences (default: false) */
19
+ replace_all?: boolean;
20
+ }
21
+ export interface EditResult {
22
+ success: boolean;
23
+ /** Number of replacements made */
24
+ replacements: number;
25
+ /** Error message if failed */
26
+ error?: string;
27
+ /** Diff preview (before/after context) */
28
+ diff?: string;
29
+ /** Backup file path if created */
30
+ backup?: string;
31
+ }
32
+ export interface WriteParams {
33
+ /** Absolute path to the file */
34
+ file_path: string;
35
+ /** Content to write */
36
+ content: string;
37
+ /** Create backup of existing file */
38
+ backup?: boolean;
39
+ }
40
+ export interface WriteResult {
41
+ success: boolean;
42
+ error?: string;
43
+ backup?: string;
44
+ bytes_written: number;
45
+ }
46
+ export interface EditToolConfig {
47
+ /** Create backups before editing */
48
+ createBackups: boolean;
49
+ /** Backup file suffix */
50
+ backupSuffix: string;
51
+ /** Maximum file size to edit (bytes) */
52
+ maxFileSize: number;
53
+ /** Allowed file extensions (empty = all) */
54
+ allowedExtensions: string[];
55
+ /** Blocked paths */
56
+ blockedPaths: RegExp[];
57
+ }
58
+ export declare const DEFAULT_EDIT_CONFIG: EditToolConfig;
59
+ export declare class EditTool {
60
+ private config;
61
+ constructor(config?: Partial<EditToolConfig>);
62
+ /**
63
+ * Validate file path for editing
64
+ */
65
+ validatePath(filePath: string): {
66
+ valid: boolean;
67
+ reason?: string;
68
+ };
69
+ /**
70
+ * Edit a file by replacing old_string with new_string
71
+ */
72
+ edit(params: EditParams): Promise<EditResult>;
73
+ /**
74
+ * Write content to a file
75
+ */
76
+ write(params: WriteParams): Promise<WriteResult>;
77
+ /**
78
+ * Count occurrences of a string in content
79
+ */
80
+ private countOccurrences;
81
+ /**
82
+ * Generate a simple diff preview
83
+ */
84
+ private generateDiff;
85
+ /**
86
+ * Check if a string occurs exactly once in content
87
+ */
88
+ isUnique(content: string, search: string): boolean;
89
+ /**
90
+ * Find all occurrences with line numbers
91
+ */
92
+ findOccurrences(content: string, search: string): Array<{
93
+ line: number;
94
+ column: number;
95
+ }>;
96
+ /**
97
+ * Get configuration
98
+ */
99
+ getConfig(): EditToolConfig;
100
+ /**
101
+ * Update configuration
102
+ */
103
+ updateConfig(config: Partial<EditToolConfig>): void;
104
+ }
105
+ export declare function getEditTool(config?: Partial<EditToolConfig>): EditTool;
106
+ export declare function resetEditTool(): void;
107
+ /**
108
+ * Edit a file with default settings
109
+ */
110
+ export declare function edit(params: EditParams): Promise<EditResult>;
111
+ /**
112
+ * Write a file with default settings
113
+ */
114
+ export declare function writeFile(params: WriteParams): Promise<WriteResult>;
115
+ /**
116
+ * Check if old_string is unique in file
117
+ */
118
+ export declare function isUnique(filePath: string, search: string): boolean;
119
+ /**
120
+ * Validate a file path for editing
121
+ */
122
+ export declare function validatePath(filePath: string): {
123
+ valid: boolean;
124
+ reason?: string;
125
+ };
@@ -0,0 +1,424 @@
1
+ "use strict";
2
+ /**
3
+ * Genesis Diff-Based File Editor
4
+ *
5
+ * File editing capabilities:
6
+ * - old_string -> new_string replacement
7
+ * - Unique match verification
8
+ * - replace_all for global replacements
9
+ * - Atomic writes with backup
10
+ * - Indentation preservation
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.EditTool = exports.DEFAULT_EDIT_CONFIG = void 0;
47
+ exports.getEditTool = getEditTool;
48
+ exports.resetEditTool = resetEditTool;
49
+ exports.edit = edit;
50
+ exports.writeFile = writeFile;
51
+ exports.isUnique = isUnique;
52
+ exports.validatePath = validatePath;
53
+ const fs = __importStar(require("fs"));
54
+ const path = __importStar(require("path"));
55
+ // ============================================================================
56
+ // Default Configuration
57
+ // ============================================================================
58
+ exports.DEFAULT_EDIT_CONFIG = {
59
+ createBackups: true,
60
+ backupSuffix: '.bak',
61
+ maxFileSize: 10 * 1024 * 1024, // 10MB
62
+ allowedExtensions: [], // All extensions allowed
63
+ blockedPaths: [
64
+ /\/\.git\//, // .git directory
65
+ /\/node_modules\//, // node_modules
66
+ /\/\.env$/, // .env files (exact match)
67
+ /\/\.env\.[^/]+$/, // .env.* files
68
+ /\/secrets?\./i, // secrets files
69
+ /\/credentials?\./i, // credentials files
70
+ /\/\.ssh\//, // SSH directory
71
+ /\/\.aws\//, // AWS directory
72
+ ],
73
+ };
74
+ // ============================================================================
75
+ // Edit Tool Class
76
+ // ============================================================================
77
+ class EditTool {
78
+ config;
79
+ constructor(config) {
80
+ this.config = { ...exports.DEFAULT_EDIT_CONFIG, ...config };
81
+ }
82
+ // --------------------------------------------------------------------------
83
+ // Validation
84
+ // --------------------------------------------------------------------------
85
+ /**
86
+ * Validate file path for editing
87
+ */
88
+ validatePath(filePath) {
89
+ // Must be absolute path
90
+ if (!path.isAbsolute(filePath)) {
91
+ return { valid: false, reason: 'Path must be absolute' };
92
+ }
93
+ // Check blocked paths
94
+ for (const pattern of this.config.blockedPaths) {
95
+ if (pattern.test(filePath)) {
96
+ return { valid: false, reason: `Path matches blocked pattern: ${pattern.toString()}` };
97
+ }
98
+ }
99
+ // Check file extension if restricted
100
+ if (this.config.allowedExtensions.length > 0) {
101
+ const ext = path.extname(filePath).toLowerCase();
102
+ if (!this.config.allowedExtensions.includes(ext)) {
103
+ return { valid: false, reason: `Extension not allowed: ${ext}` };
104
+ }
105
+ }
106
+ return { valid: true };
107
+ }
108
+ // --------------------------------------------------------------------------
109
+ // Edit Operations
110
+ // --------------------------------------------------------------------------
111
+ /**
112
+ * Edit a file by replacing old_string with new_string
113
+ */
114
+ async edit(params) {
115
+ const { file_path, old_string, new_string, replace_all = false } = params;
116
+ // Validate path
117
+ const pathValidation = this.validatePath(file_path);
118
+ if (!pathValidation.valid) {
119
+ return {
120
+ success: false,
121
+ replacements: 0,
122
+ error: pathValidation.reason,
123
+ };
124
+ }
125
+ // Check file exists
126
+ if (!fs.existsSync(file_path)) {
127
+ return {
128
+ success: false,
129
+ replacements: 0,
130
+ error: `File not found: ${file_path}`,
131
+ };
132
+ }
133
+ // Check file size
134
+ const stats = fs.statSync(file_path);
135
+ if (stats.size > this.config.maxFileSize) {
136
+ return {
137
+ success: false,
138
+ replacements: 0,
139
+ error: `File too large: ${stats.size} bytes (max: ${this.config.maxFileSize})`,
140
+ };
141
+ }
142
+ // Read file content
143
+ let content;
144
+ try {
145
+ content = fs.readFileSync(file_path, 'utf-8');
146
+ }
147
+ catch (err) {
148
+ return {
149
+ success: false,
150
+ replacements: 0,
151
+ error: `Failed to read file: ${err.message}`,
152
+ };
153
+ }
154
+ // Validate old_string and new_string are different
155
+ if (old_string === new_string) {
156
+ return {
157
+ success: false,
158
+ replacements: 0,
159
+ error: 'old_string and new_string must be different',
160
+ };
161
+ }
162
+ // Find occurrences
163
+ const occurrences = this.countOccurrences(content, old_string);
164
+ if (occurrences === 0) {
165
+ return {
166
+ success: false,
167
+ replacements: 0,
168
+ error: `old_string not found in file`,
169
+ };
170
+ }
171
+ // If not replace_all, ensure unique match
172
+ if (!replace_all && occurrences > 1) {
173
+ return {
174
+ success: false,
175
+ replacements: 0,
176
+ error: `old_string found ${occurrences} times. Use replace_all=true or provide more context to make it unique.`,
177
+ };
178
+ }
179
+ // Create backup if configured
180
+ let backupPath;
181
+ if (this.config.createBackups) {
182
+ backupPath = file_path + this.config.backupSuffix;
183
+ try {
184
+ fs.copyFileSync(file_path, backupPath);
185
+ }
186
+ catch (err) {
187
+ return {
188
+ success: false,
189
+ replacements: 0,
190
+ error: `Failed to create backup: ${err.message}`,
191
+ };
192
+ }
193
+ }
194
+ // Perform replacement
195
+ let newContent;
196
+ let replacements;
197
+ if (replace_all) {
198
+ newContent = content.split(old_string).join(new_string);
199
+ replacements = occurrences;
200
+ }
201
+ else {
202
+ // Replace only first occurrence
203
+ const index = content.indexOf(old_string);
204
+ newContent = content.slice(0, index) + new_string + content.slice(index + old_string.length);
205
+ replacements = 1;
206
+ }
207
+ // Write atomically
208
+ try {
209
+ const tempPath = file_path + '.tmp.' + Date.now();
210
+ fs.writeFileSync(tempPath, newContent, 'utf-8');
211
+ fs.renameSync(tempPath, file_path);
212
+ }
213
+ catch (err) {
214
+ // Restore from backup if available
215
+ if (backupPath && fs.existsSync(backupPath)) {
216
+ fs.copyFileSync(backupPath, file_path);
217
+ }
218
+ return {
219
+ success: false,
220
+ replacements: 0,
221
+ error: `Failed to write file: ${err.message}`,
222
+ };
223
+ }
224
+ // Generate diff preview
225
+ const diff = this.generateDiff(old_string, new_string, content);
226
+ return {
227
+ success: true,
228
+ replacements,
229
+ diff,
230
+ backup: backupPath,
231
+ };
232
+ }
233
+ /**
234
+ * Write content to a file
235
+ */
236
+ async write(params) {
237
+ const { file_path, content, backup = true } = params;
238
+ // Validate path
239
+ const pathValidation = this.validatePath(file_path);
240
+ if (!pathValidation.valid) {
241
+ return {
242
+ success: false,
243
+ error: pathValidation.reason,
244
+ bytes_written: 0,
245
+ };
246
+ }
247
+ // Create backup if file exists
248
+ let backupPath;
249
+ if (backup && fs.existsSync(file_path)) {
250
+ backupPath = file_path + this.config.backupSuffix;
251
+ try {
252
+ fs.copyFileSync(file_path, backupPath);
253
+ }
254
+ catch (err) {
255
+ return {
256
+ success: false,
257
+ error: `Failed to create backup: ${err.message}`,
258
+ bytes_written: 0,
259
+ };
260
+ }
261
+ }
262
+ // Ensure parent directory exists
263
+ const dir = path.dirname(file_path);
264
+ if (!fs.existsSync(dir)) {
265
+ try {
266
+ fs.mkdirSync(dir, { recursive: true });
267
+ }
268
+ catch (err) {
269
+ return {
270
+ success: false,
271
+ error: `Failed to create directory: ${err.message}`,
272
+ bytes_written: 0,
273
+ };
274
+ }
275
+ }
276
+ // Write atomically
277
+ try {
278
+ const tempPath = file_path + '.tmp.' + Date.now();
279
+ fs.writeFileSync(tempPath, content, 'utf-8');
280
+ fs.renameSync(tempPath, file_path);
281
+ }
282
+ catch (err) {
283
+ return {
284
+ success: false,
285
+ error: `Failed to write file: ${err.message}`,
286
+ bytes_written: 0,
287
+ };
288
+ }
289
+ return {
290
+ success: true,
291
+ bytes_written: Buffer.byteLength(content, 'utf-8'),
292
+ backup: backupPath,
293
+ };
294
+ }
295
+ // --------------------------------------------------------------------------
296
+ // Helper Methods
297
+ // --------------------------------------------------------------------------
298
+ /**
299
+ * Count occurrences of a string in content
300
+ */
301
+ countOccurrences(content, search) {
302
+ let count = 0;
303
+ let pos = 0;
304
+ while ((pos = content.indexOf(search, pos)) !== -1) {
305
+ count++;
306
+ pos += search.length;
307
+ }
308
+ return count;
309
+ }
310
+ /**
311
+ * Generate a simple diff preview
312
+ */
313
+ generateDiff(old_string, new_string, context) {
314
+ const lines = [];
315
+ const oldLines = old_string.split('\n');
316
+ const newLines = new_string.split('\n');
317
+ // Find line number in context
318
+ const beforeMatch = context.split(old_string)[0];
319
+ const lineNumber = beforeMatch.split('\n').length;
320
+ lines.push(`@@ -${lineNumber},${oldLines.length} +${lineNumber},${newLines.length} @@`);
321
+ for (const line of oldLines) {
322
+ lines.push(`- ${line}`);
323
+ }
324
+ for (const line of newLines) {
325
+ lines.push(`+ ${line}`);
326
+ }
327
+ return lines.join('\n');
328
+ }
329
+ /**
330
+ * Check if a string occurs exactly once in content
331
+ */
332
+ isUnique(content, search) {
333
+ return this.countOccurrences(content, search) === 1;
334
+ }
335
+ /**
336
+ * Find all occurrences with line numbers
337
+ */
338
+ findOccurrences(content, search) {
339
+ const results = [];
340
+ const lines = content.split('\n');
341
+ for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
342
+ const line = lines[lineIdx];
343
+ let pos = 0;
344
+ while ((pos = line.indexOf(search, pos)) !== -1) {
345
+ results.push({ line: lineIdx + 1, column: pos + 1 });
346
+ pos += search.length;
347
+ }
348
+ }
349
+ // Also check for multi-line matches
350
+ let globalPos = 0;
351
+ while ((globalPos = content.indexOf(search, globalPos)) !== -1) {
352
+ const beforeMatch = content.slice(0, globalPos);
353
+ const lineNumber = beforeMatch.split('\n').length;
354
+ const lastNewline = beforeMatch.lastIndexOf('\n');
355
+ const column = globalPos - lastNewline;
356
+ // Add if not already in results (multi-line match)
357
+ const exists = results.some(r => r.line === lineNumber && r.column === column);
358
+ if (!exists) {
359
+ results.push({ line: lineNumber, column });
360
+ }
361
+ globalPos += search.length;
362
+ }
363
+ return results;
364
+ }
365
+ /**
366
+ * Get configuration
367
+ */
368
+ getConfig() {
369
+ return { ...this.config };
370
+ }
371
+ /**
372
+ * Update configuration
373
+ */
374
+ updateConfig(config) {
375
+ this.config = { ...this.config, ...config };
376
+ }
377
+ }
378
+ exports.EditTool = EditTool;
379
+ // ============================================================================
380
+ // Singleton Instance
381
+ // ============================================================================
382
+ let editToolInstance = null;
383
+ function getEditTool(config) {
384
+ if (!editToolInstance) {
385
+ editToolInstance = new EditTool(config);
386
+ }
387
+ else if (config) {
388
+ editToolInstance.updateConfig(config);
389
+ }
390
+ return editToolInstance;
391
+ }
392
+ function resetEditTool() {
393
+ editToolInstance = null;
394
+ }
395
+ // ============================================================================
396
+ // Convenience Functions
397
+ // ============================================================================
398
+ /**
399
+ * Edit a file with default settings
400
+ */
401
+ async function edit(params) {
402
+ return getEditTool().edit(params);
403
+ }
404
+ /**
405
+ * Write a file with default settings
406
+ */
407
+ async function writeFile(params) {
408
+ return getEditTool().write(params);
409
+ }
410
+ /**
411
+ * Check if old_string is unique in file
412
+ */
413
+ function isUnique(filePath, search) {
414
+ if (!fs.existsSync(filePath))
415
+ return false;
416
+ const content = fs.readFileSync(filePath, 'utf-8');
417
+ return getEditTool().isUnique(content, search);
418
+ }
419
+ /**
420
+ * Validate a file path for editing
421
+ */
422
+ function validatePath(filePath) {
423
+ return getEditTool().validatePath(filePath);
424
+ }