mirror of
https://github.com/SHOGGOTH-SECTOR/sica-fondt.git
synced 2026-08-01 08:30:20 +00:00
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
200 lines
8.0 KiB
TypeScript
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}`
|
|
};
|
|
}
|
|
}
|
|
}; |