Claude 24f816b6a3
Consolidate 22 sibling repos into layered organism structure
Place useful parts of the surrounding repos into sica-fondt by layer, per the
body model (Ada = membrane; brain/endocrine/capabilities/knowledge non-Ada):

- brain/        LLM reasoning + providers (dapr, hermes, MoMoA)
- capabilities/ REPRAG sidecars: hermes tools/skills, dapr tools, parallel
                dispatch, A51 channels, and the OSINT cluster
- knowledge/    LORAG corpus: 754 cyber-skills, agency personas, secure-coding,
                MITRE ATT&CK data
- reference/    defensive threat-reference (C3, shhbruh doc) + AdaYaml parser

License handling: AGPL sources (worldosint, advanced_evolution, mercury,
Reticulum) and GPL DeTTECT are SPEC-only clean-room/port descriptions — no
copyleft code copied. MIT/Apache/data parts copied as working trees.

Safety: shhbruh escape/persistence material and C3 covert-C2 kept as reference
only, not wired into the running organism. See CONSOLIDATION.md.

https://claude.ai/code/session_01UehUqEXXJJCsHoA4voCU5c
2026-06-10 06:53:01 +00:00

200 lines
8.0 KiB
TypeScript

/**
* Copyright 2026 Reto Meier
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { MultiAgentTool } from '../multiAgentTool.js';
import { MultiAgentToolContext, MultiAgentToolResult, ToolParsingResult } from '../../momoa_core/types.js';
import { fileNameLookup } from '../../utils/fileNameLookup.js';
import { generateDiffString, isLockFile, getLockFileHiddenPlaceholder } from '../../utils/diffGenerator.js';
import { getAssetString } from '../../services/promptManager.js';
import { updateFileEntry } from '../../utils/fileAnalysis.js';
/**
* Regenerates the project diff and updates the diff block in all
* transcripts that are registered in the context.
*/
export async function updateDiffInAllTranscripts(context: MultiAgentToolContext) {
const docId = PROJECT_DIFF_ID;
if (!docId || !context.transcriptsToUpdate) {
return;
}
const newDiffBlock = generateDiffString(context);
context.transcriptsToUpdate.forEach(transcript => {
transcript.replaceEntry(docId, newDiffBlock);
});
console.log(`Updated diff block '${docId}' in all registered transcripts.`);
}
export const PROJECT_DIFF_ID = "PROJECT_DIFF_ID";
export const revertFileTool: MultiAgentTool = {
displayName: "Revert File",
name: 'DOC/REVERT{',
endToken: '}',
async execute(params: Record<string, string>, context: MultiAgentToolContext): Promise<MultiAgentToolResult> {
const providedFilename = params.filename;
if (!providedFilename) {
return { result: "Error: 'filename' parameter is missing." };
}
if (!context.originalFileMap || !context.originalBinaryFileMap) {
return { result: "Error: Orchestrator did not provide original file maps to context." };
}
// Use fileNameLookup to find the precise file name
const allFilesMap = new Map<string, string>([
...context.fileMap,
...Array.from(context.binaryFileMap.keys()).map(key => [key, ''] as [string, string])
]);
const filename = await fileNameLookup(providedFilename, allFilesMap, context.multiAgentGeminiClient);
const originalExisted = context.originalFileMap.has(filename) || context.originalBinaryFileMap.has(filename);
const currentExisted = context.fileMap.has(filename) || context.binaryFileMap.has(filename);
let revertMessage = `---Error: Could not revert '${filename}'. It was not found in the current project state.---`;
let revertSucceeded = false;
let finalContent: string | null | undefined = undefined;
let isBinary = false;
// Case 1: Revert text file (it existed originally)
if (context.originalFileMap.has(filename)) {
const originalContent = context.originalFileMap.get(filename)!;
context.fileMap.set(filename, originalContent);
context.binaryFileMap.delete(filename); // Clean up just in case
// We will remove from editedFilesSet *after* updating transcripts
revertMessage = `---File '${filename}' has been successfully reverted to its original state.---`;
revertSucceeded = true;
finalContent = originalContent;
isBinary = false;
}
// Case 2: Revert binary file (it existed originally)
else if (context.originalBinaryFileMap.has(filename)) {
const originalContent = context.originalBinaryFileMap.get(filename)!;
context.binaryFileMap.set(filename, originalContent);
context.fileMap.delete(filename); // Clean up just in case
// We will remove from editedFilesSet *after* updating transcripts
revertMessage = `---File '${filename}' has been successfully reverted to its original state.---`;
revertSucceeded = true;
finalContent = null;
isBinary = true;
}
// Case 3: File was created (didn't exist originally), so "reverting" means deleting it.
else if (!originalExisted && currentExisted) {
context.fileMap.delete(filename);
context.binaryFileMap.delete(filename);
// We will remove from editedFilesSet *after* updating transcripts
revertMessage = `---File '${filename}' was created during this run and has been successfully deleted (reverted).---`;
revertSucceeded = true;
finalContent = undefined; // Flag for deleted
isBinary = false;
}
// Case 4: File doesn't exist now and didn't exist originally
else if (!originalExisted && !currentExisted) {
revertMessage = `---Error: Could not revert '${filename}'. It was not found in the current project or the original project state.---`;
}
// If a revert or deletion succeeded, update all transcripts
if (revertSucceeded) {
context.sendMessage({
type: 'PROGRESS_UPDATE',
message: `Undoing changes to \`${filename}\`, and reverting it to its original content.`,
});
// If the file was not deleted, force a re-analysis
// to update its description and remove any "---DELETED---" markers.
if (finalContent !== undefined) { // undefined means it was deleted
try {
if (!context.binaryFileMap.has(filename)) {
await updateFileEntry(filename, context.fileMap, context.multiAgentGeminiClient);
} else {
await updateFileEntry(filename, context.fileMap, undefined,
{
filename: filename,
description: "[Binary File]"
},
true);
}
} catch (e: any) {
console.warn(`Failed to re-analyze reverted file ${filename}: ${e.message}`);
}
}
// Immediately supersede this file's entry in all transcripts
// (WorkPhase experts + Orchestrator) *before* removing from the set.
context.transcriptsToUpdate?.forEach(transcript => {
transcript.supersedeEntry(filename);
});
// Now that transcripts are updated, remove it from the set.
context.editedFilesSet.delete(filename);
}
// Always update the diff block in all transcripts
await updateDiffInAllTranscripts(context);
// --- Format Return Value ---
const prefix = await getAssetString('file-content-prefix');
const suffix = await getAssetString('file-content-suffix');
const replacementString = await getAssetString('file-content-removed');
if (!revertSucceeded) {
// Return the error message, but still provide the ID/replacement
// so the WorkPhase supersedes any *previous* read of this file.
return {
result: revertMessage,
transcriptReplacementID: filename,
transcriptReplacementString: `${prefix}\n${replacementString}\n${suffix}`
};
}
// Build the final result string
let finalResultString = revertMessage;
if (finalContent !== undefined) { // File exists post-revert
if (isBinary) {
finalResultString += `\nFile '${filename}' is a binary file.`;
} else if (isLockFile(filename)) {
finalResultString += `\n${getLockFileHiddenPlaceholder(filename)}`;
} else if (finalContent !== null) {
finalResultString += `\n${prefix}\n${finalContent}\n${suffix}`;
}
}
return {
result: finalResultString,
transcriptReplacementID: filename,
transcriptReplacementString: `${prefix}\n${replacementString}\n${suffix}`
};
},
async extractParameters(invocation: string, _context: MultiAgentToolContext): Promise<ToolParsingResult> {
if (invocation.trim().endsWith("}")) {
const filename = invocation.trim().slice(0, -1).trim();
return {
success: true,
params: { filename }
};
} else {
return {
success: false,
error: `Invalid syntax for ${this.displayName}. Expected DOC/REVERT{filename.txt}`
};
}
}
};