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.
- package/.env.example +78 -0
- package/README.md +282 -0
- package/dist/src/active-inference/actions.d.ts +75 -0
- package/dist/src/active-inference/actions.js +250 -0
- package/dist/src/active-inference/autonomous-loop.d.ts +103 -0
- package/dist/src/active-inference/autonomous-loop.js +289 -0
- package/dist/src/active-inference/core.d.ts +85 -0
- package/dist/src/active-inference/core.js +555 -0
- package/dist/src/active-inference/demo-autonomous-loop.d.ts +8 -0
- package/dist/src/active-inference/demo-autonomous-loop.js +338 -0
- package/dist/src/active-inference/demo-value-integration.d.ts +8 -0
- package/dist/src/active-inference/demo-value-integration.js +174 -0
- package/dist/src/active-inference/index.d.ts +32 -0
- package/dist/src/active-inference/index.js +88 -0
- package/dist/src/active-inference/integration.d.ts +114 -0
- package/dist/src/active-inference/integration.js +698 -0
- package/dist/src/active-inference/memory-integration.d.ts +51 -0
- package/dist/src/active-inference/memory-integration.js +232 -0
- package/dist/src/active-inference/observations.d.ts +67 -0
- package/dist/src/active-inference/observations.js +147 -0
- package/dist/src/active-inference/test-active-inference.d.ts +8 -0
- package/dist/src/active-inference/test-active-inference.js +320 -0
- package/dist/src/active-inference/test-value-integration.d.ts +6 -0
- package/dist/src/active-inference/test-value-integration.js +168 -0
- package/dist/src/active-inference/types.d.ts +150 -0
- package/dist/src/active-inference/types.js +59 -0
- package/dist/src/active-inference/value-integration.d.ts +164 -0
- package/dist/src/active-inference/value-integration.js +459 -0
- package/dist/src/agents/base-agent.d.ts +53 -0
- package/dist/src/agents/base-agent.js +178 -0
- package/dist/src/agents/builder.d.ts +67 -0
- package/dist/src/agents/builder.js +537 -0
- package/dist/src/agents/critic.d.ts +35 -0
- package/dist/src/agents/critic.js +322 -0
- package/dist/src/agents/ethicist.d.ts +54 -0
- package/dist/src/agents/ethicist.js +393 -0
- package/dist/src/agents/explorer.d.ts +26 -0
- package/dist/src/agents/explorer.js +216 -0
- package/dist/src/agents/feeling.d.ts +41 -0
- package/dist/src/agents/feeling.js +320 -0
- package/dist/src/agents/index.d.ts +111 -0
- package/dist/src/agents/index.js +222 -0
- package/dist/src/agents/memory.d.ts +69 -0
- package/dist/src/agents/memory.js +404 -0
- package/dist/src/agents/message-bus.d.ts +88 -0
- package/dist/src/agents/message-bus.js +267 -0
- package/dist/src/agents/narrator.d.ts +90 -0
- package/dist/src/agents/narrator.js +473 -0
- package/dist/src/agents/planner.d.ts +38 -0
- package/dist/src/agents/planner.js +341 -0
- package/dist/src/agents/predictor.d.ts +73 -0
- package/dist/src/agents/predictor.js +506 -0
- package/dist/src/agents/sensor.d.ts +88 -0
- package/dist/src/agents/sensor.js +377 -0
- package/dist/src/agents/test-agents.d.ts +6 -0
- package/dist/src/agents/test-agents.js +73 -0
- package/dist/src/agents/types.d.ts +194 -0
- package/dist/src/agents/types.js +7 -0
- package/dist/src/brain/index.d.ts +185 -0
- package/dist/src/brain/index.js +843 -0
- package/dist/src/brain/trace.d.ts +91 -0
- package/dist/src/brain/trace.js +327 -0
- package/dist/src/brain/types.d.ts +165 -0
- package/dist/src/brain/types.js +51 -0
- package/dist/src/cli/chat.d.ts +237 -0
- package/dist/src/cli/chat.js +1959 -0
- package/dist/src/cli/dispatcher.d.ts +182 -0
- package/dist/src/cli/dispatcher.js +718 -0
- package/dist/src/cli/human-loop.d.ts +170 -0
- package/dist/src/cli/human-loop.js +543 -0
- package/dist/src/cli/index.d.ts +12 -0
- package/dist/src/cli/index.js +28 -0
- package/dist/src/cli/interactive.d.ts +141 -0
- package/dist/src/cli/interactive.js +757 -0
- package/dist/src/cli/ui.d.ts +205 -0
- package/dist/src/cli/ui.js +632 -0
- package/dist/src/consciousness/attention-schema.d.ts +154 -0
- package/dist/src/consciousness/attention-schema.js +432 -0
- package/dist/src/consciousness/global-workspace.d.ts +149 -0
- package/dist/src/consciousness/global-workspace.js +422 -0
- package/dist/src/consciousness/index.d.ts +186 -0
- package/dist/src/consciousness/index.js +476 -0
- package/dist/src/consciousness/phi-calculator.d.ts +119 -0
- package/dist/src/consciousness/phi-calculator.js +445 -0
- package/dist/src/consciousness/phi-decisions.d.ts +169 -0
- package/dist/src/consciousness/phi-decisions.js +383 -0
- package/dist/src/consciousness/phi-monitor.d.ts +153 -0
- package/dist/src/consciousness/phi-monitor.js +465 -0
- package/dist/src/consciousness/types.d.ts +260 -0
- package/dist/src/consciousness/types.js +44 -0
- package/dist/src/daemon/dream-mode.d.ts +115 -0
- package/dist/src/daemon/dream-mode.js +470 -0
- package/dist/src/daemon/index.d.ts +162 -0
- package/dist/src/daemon/index.js +542 -0
- package/dist/src/daemon/maintenance.d.ts +139 -0
- package/dist/src/daemon/maintenance.js +549 -0
- package/dist/src/daemon/process.d.ts +82 -0
- package/dist/src/daemon/process.js +442 -0
- package/dist/src/daemon/scheduler.d.ts +90 -0
- package/dist/src/daemon/scheduler.js +494 -0
- package/dist/src/daemon/types.d.ts +213 -0
- package/dist/src/daemon/types.js +50 -0
- package/dist/src/epistemic/index.d.ts +74 -0
- package/dist/src/epistemic/index.js +225 -0
- package/dist/src/grounding/epistemic-stack.d.ts +100 -0
- package/dist/src/grounding/epistemic-stack.js +408 -0
- package/dist/src/grounding/feedback.d.ts +98 -0
- package/dist/src/grounding/feedback.js +276 -0
- package/dist/src/grounding/index.d.ts +123 -0
- package/dist/src/grounding/index.js +224 -0
- package/dist/src/grounding/verifier.d.ts +149 -0
- package/dist/src/grounding/verifier.js +484 -0
- package/dist/src/healing/detector.d.ts +110 -0
- package/dist/src/healing/detector.js +436 -0
- package/dist/src/healing/fixer.d.ts +138 -0
- package/dist/src/healing/fixer.js +572 -0
- package/dist/src/healing/index.d.ts +23 -0
- package/dist/src/healing/index.js +43 -0
- package/dist/src/hooks/index.d.ts +135 -0
- package/dist/src/hooks/index.js +317 -0
- package/dist/src/index.d.ts +23 -0
- package/dist/src/index.js +1266 -0
- package/dist/src/kernel/index.d.ts +155 -0
- package/dist/src/kernel/index.js +795 -0
- package/dist/src/kernel/invariants.d.ts +153 -0
- package/dist/src/kernel/invariants.js +355 -0
- package/dist/src/kernel/test-kernel.d.ts +6 -0
- package/dist/src/kernel/test-kernel.js +108 -0
- package/dist/src/kernel/test-real-mcp.d.ts +10 -0
- package/dist/src/kernel/test-real-mcp.js +295 -0
- package/dist/src/llm/index.d.ts +146 -0
- package/dist/src/llm/index.js +428 -0
- package/dist/src/llm/router.d.ts +136 -0
- package/dist/src/llm/router.js +510 -0
- package/dist/src/mcp/index.d.ts +85 -0
- package/dist/src/mcp/index.js +657 -0
- package/dist/src/mcp/resilient.d.ts +139 -0
- package/dist/src/mcp/resilient.js +417 -0
- package/dist/src/memory/cache.d.ts +118 -0
- package/dist/src/memory/cache.js +356 -0
- package/dist/src/memory/cognitive-workspace.d.ts +231 -0
- package/dist/src/memory/cognitive-workspace.js +521 -0
- package/dist/src/memory/consolidation.d.ts +99 -0
- package/dist/src/memory/consolidation.js +443 -0
- package/dist/src/memory/episodic.d.ts +114 -0
- package/dist/src/memory/episodic.js +394 -0
- package/dist/src/memory/forgetting.d.ts +134 -0
- package/dist/src/memory/forgetting.js +324 -0
- package/dist/src/memory/index.d.ts +211 -0
- package/dist/src/memory/index.js +367 -0
- package/dist/src/memory/indexer.d.ts +123 -0
- package/dist/src/memory/indexer.js +479 -0
- package/dist/src/memory/procedural.d.ts +136 -0
- package/dist/src/memory/procedural.js +479 -0
- package/dist/src/memory/semantic.d.ts +132 -0
- package/dist/src/memory/semantic.js +497 -0
- package/dist/src/memory/types.d.ts +193 -0
- package/dist/src/memory/types.js +15 -0
- package/dist/src/orchestrator.d.ts +65 -0
- package/dist/src/orchestrator.js +317 -0
- package/dist/src/persistence/index.d.ts +257 -0
- package/dist/src/persistence/index.js +763 -0
- package/dist/src/pipeline/executor.d.ts +51 -0
- package/dist/src/pipeline/executor.js +695 -0
- package/dist/src/pipeline/index.d.ts +7 -0
- package/dist/src/pipeline/index.js +11 -0
- package/dist/src/self-production.d.ts +67 -0
- package/dist/src/self-production.js +205 -0
- package/dist/src/subagents/executor.d.ts +58 -0
- package/dist/src/subagents/executor.js +283 -0
- package/dist/src/subagents/index.d.ts +37 -0
- package/dist/src/subagents/index.js +53 -0
- package/dist/src/subagents/registry.d.ts +23 -0
- package/dist/src/subagents/registry.js +167 -0
- package/dist/src/subagents/types.d.ts +79 -0
- package/dist/src/subagents/types.js +14 -0
- package/dist/src/tools/bash.d.ts +139 -0
- package/dist/src/tools/bash.js +583 -0
- package/dist/src/tools/edit.d.ts +125 -0
- package/dist/src/tools/edit.js +424 -0
- package/dist/src/tools/git.d.ts +179 -0
- package/dist/src/tools/git.js +504 -0
- package/dist/src/tools/index.d.ts +21 -0
- package/dist/src/tools/index.js +163 -0
- package/dist/src/types.d.ts +145 -0
- package/dist/src/types.js +7 -0
- package/dist/src/world-model/decoder.d.ts +163 -0
- package/dist/src/world-model/decoder.js +517 -0
- package/dist/src/world-model/digital-twin.d.ts +219 -0
- package/dist/src/world-model/digital-twin.js +695 -0
- package/dist/src/world-model/encoder.d.ts +141 -0
- package/dist/src/world-model/encoder.js +564 -0
- package/dist/src/world-model/index.d.ts +221 -0
- package/dist/src/world-model/index.js +772 -0
- package/dist/src/world-model/predictor.d.ts +161 -0
- package/dist/src/world-model/predictor.js +681 -0
- package/dist/src/world-model/test-value-jepa.d.ts +8 -0
- package/dist/src/world-model/test-value-jepa.js +430 -0
- package/dist/src/world-model/types.d.ts +341 -0
- package/dist/src/world-model/types.js +69 -0
- package/dist/src/world-model/value-jepa.d.ts +247 -0
- package/dist/src/world-model/value-jepa.js +622 -0
- package/dist/test/brain.test.d.ts +11 -0
- package/dist/test/brain.test.js +358 -0
- package/dist/test/cli/dispatcher.test.d.ts +4 -0
- package/dist/test/cli/dispatcher.test.js +332 -0
- package/dist/test/cli/human-loop.test.d.ts +4 -0
- package/dist/test/cli/human-loop.test.js +270 -0
- package/dist/test/grounding/feedback.test.d.ts +4 -0
- package/dist/test/grounding/feedback.test.js +462 -0
- package/dist/test/grounding/verifier.test.d.ts +4 -0
- package/dist/test/grounding/verifier.test.js +442 -0
- package/dist/test/grounding.test.d.ts +6 -0
- package/dist/test/grounding.test.js +246 -0
- package/dist/test/healing/detector.test.d.ts +4 -0
- package/dist/test/healing/detector.test.js +266 -0
- package/dist/test/healing/fixer.test.d.ts +4 -0
- package/dist/test/healing/fixer.test.js +369 -0
- package/dist/test/integration.test.d.ts +5 -0
- package/dist/test/integration.test.js +290 -0
- package/dist/test/tools/bash.test.d.ts +4 -0
- package/dist/test/tools/bash.test.js +348 -0
- package/dist/test/tools/edit.test.d.ts +4 -0
- package/dist/test/tools/edit.test.js +350 -0
- package/dist/test/tools/git.test.d.ts +4 -0
- package/dist/test/tools/git.test.js +350 -0
- 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
|
+
}
|