Skip to content

Instantly share code, notes, and snippets.

@smileham
Last active July 12, 2025 10:11
Show Gist options
  • Save smileham/8cbb3116db7f0ee80bcab4f1a57d14a8 to your computer and use it in GitHub Desktop.
Save smileham/8cbb3116db7f0ee80bcab4f1a57d14a8 to your computer and use it in GitHub Desktop.
A suite of scripts for jArchi and the Archi modelling tool to enable integration between the tool and LLM such as Gemini from Google
/*
* Generate AI Analysis (Requires AI-Gemini.js and Export To Markdown.ajs)
*
* Requires:
* * jArchi - https://www.archimatetool.com/blog/2018/07/02/jarchi/
* * AI-Gemini.js -
* * Export to Markdown.ajs - https://gist.github.com/smileham/578bbbb88dc0ed5a1403f3b98711ec25
*
* Version 1: Gemini API
*
* (c) 2025 Steven Mileham
*
*/
console.show();
console.clear();
console.log("Generate AI Summary");
const library = true;
const promptTemplate = "As a friendly Enterprise Architect trained in TOGAF and ArchiMate, using language which can be understood by the business in British English, analyse the following component. Do not greet the user, the summary will be stored against the component for future users, summarise the analysis in no more than two paragraphs";
const md = require('../Export To MarkDown.ajs');
const ai = require('./AI-REST.js');
const theComponents = $(selection);
function buttonDialog(message,options) {
var dialog = new org.eclipse.jface.dialogs.MessageDialog(shell,"Archi",null,message,3,options.concat(["Cancel"]),0);
var result=dialog.open();
return result==options.length?null:(result+1).toString();
}
const theView = theComponents.parents("archimate-diagram-model")
console.log(theView);
let markdownContent = md(theView, false,false, false);
theComponents.forEach(theComponent => {
console.log(`Generating Summary for component:${theComponent.name}`);
summary = generateAnalysis (theComponent,markdownContent);
var updateDocumentation = buttonDialog(`Component:${theComponent.name}\nAnalysis:\n${summary}`, ["Replace Documentation", "Append to Documentation", "Create Assessment"]);
if (updateDocumentation=="3") {
let theAnalysis = model.createElement("assessment", `Analysis for ${theComponent.name}`);
theAnalysis.documentation = summary;
let theRelationship = model.createRelationship("association-relationship", "", theComponent.concept, theAnalysis);
}
else if (updateDocumentation=="2") {
theComponent.documentation += `\n${summary}`;
}
else if (updateDocumentation=="1") {
theComponent.documentation = summary;
}
});
function generateAnalysis (theComponent,theContext) {
let componentPrompt = `Component Name: \"${theComponent.name}\", Component Type: \"${theComponent.type}\"${(theComponent.specialization!=null?", Component Specialisation: \""+theComponent.specialization+"\"":"")}${(theComponent.documentation!=""&&theComponent.documentation!=null)?", Current Documentation: \""+theComponent.documentation+"\"":""}`
theComponent.prop().forEach(function (prop) {
componentPrompt+=` Property: "${prop}" = "${theComponent.prop(prop)}",`;
})
return ai(`${promptTemplate}, analyse ${componentPrompt} in the context of:\n ${theContext}`);
}
/*
* Generate AI Critique (Requires AI-Gemini.js and Export To Markdown.ajs)
*
* Requires:
* * jArchi - https://www.archimatetool.com/blog/2018/07/02/jarchi/
* * AI-Gemini.js -
* * Export to Markdown.ajs - https://gist.github.com/smileham/578bbbb88dc0ed5a1403f3b98711ec25
*
* Version 1: Gemini API
*
* (c) 2025 Steven Mileham
*
*/
console.show();
console.clear();
console.log("Generate AI Summary");
const library = true;
const md = require('../Export To MarkDown.ajs');
const ai = require('./AI-REST.js');
const promptTemplate = "You are three Enterprise Architects trained in TOGAF and ArchiMate, one critical, one friendly and one neutral, using language which can be understood by the business in British English, critique the following architecture, highlight areas for improvement, missed opportunities and any gaps. Do not greet the user, summarise your output into no more than three paragraphs:\n";
const theViews = $(selection).filter("archimate-diagram-model");
function buttonDialog(message,options) {
var dialog = new org.eclipse.jface.dialogs.MessageDialog(shell,"Archi",null,message,3,options.concat(["Cancel"]),0);
var result=dialog.open();
return result==options.length?null:(result+1).toString();
}
if (!theViews || theViews.length==0) {
console.log("> Please Select a View");
}
const theIndexMap = new Map();
theViews.each(function(theView){
console.log(`Generating Critique for view:${theView}`);
theDocument = "";
let markdownContent = md(theView, false,false, false);
summary = generateCritique (markdownContent);
var updateDocumentation = buttonDialog(`View:${theView.name}\nCritique:\n${summary}`, ["Replace Documentation", "Append to Documentation", "Create Assessment"]);
if (updateDocumentation=="3") {
let theAnalysis = model.createElement("assessment", `Critique for ${theView.name}`);
theAnalysis.documentation = summary;
theView.add(theAnalysis, 10, 200, -1, -1, true);
}
else if (updateDocumentation=="2") {
theView.documentation += `\n${summary}`;
}
else if (updateDocumentation=="1") {
theView.documentation = summary;
}
});
function generateCritique (markdownContent) {
return ai(promptTemplate+markdownContent);
}
/*
* Generate AI Documentation (Requires AI-Gemini.js and Export To Markdown.ajs)
*
* Requires:
* * jArchi - https://www.archimatetool.com/blog/2018/07/02/jarchi/
* * AI-Gemini.js -
* * Export to Markdown.ajs - https://gist.github.com/smileham/578bbbb88dc0ed5a1403f3b98711ec25
*
*
* Version 1: Gemini API
*
* (c) 2025 Steven Mileham
*
*/
console.show();
console.clear();
console.log("Generate AI Summary");
const library = true;
const md = require('../Export To MarkDown.ajs');
const ai = require('./AI-REST.js');
const persona = `As a friendly Enterprise Architect trained in TOGAF and ArchiMate`;
const viewPromptTemplate = `${persona}, using language which can be understood by the business in British English, summarise the following documentation into no more than two paragraphs. Do not greet the user, the summary will be stored against the document for future users:\n`;
const componentPromptTemplate = `${persona}, using language which can be understood by the business in British English, summarise the following component into no one sentence, include product details if this is a application, service or device. Do not greet the user, the summary will be stored against the component for future users`;
const theComponents = $(selection);
const theViews = theComponents.filter("archimate-diagram-model");
function buttonDialog(message,options) {
var dialog = new org.eclipse.jface.dialogs.MessageDialog(shell,"Archi",null,message,3,options.concat(["Cancel"]),0);
var result=dialog.open();
return result==options.length?null:(result+1).toString();
}
if (theViews && theViews.length>0) {
theViews.each(function(theView){
console.log(`Generating Summary for view:${theView}`);
theDocument = "";
let markdownContent = md(theView, false,false, false);
summary = summariseMarkdownToAI (markdownContent);
var updateDocumentation = buttonDialog(`View:${theView.name}\nNew Documentation:\n${summary}`, ["Replace Documentation", "Append Documentation"]);
if (updateDocumentation=="2") {
theView.documentation += `\n${summary}`;
}
else if (updateDocumentation=="1") {
theView.documentation = summary;
}
});
}
else {
theComponents.forEach(theComponent => {
console.log(`Generating Summary for component:${theComponent.name}`);
summary = generateDocumentation (theComponent);
var updateDocumentation = buttonDialog(`Component:${theComponent.name}\nNew Documentation:\n${summary}`, ["Replace Documentation", "Append Documentation"]);
if (updateDocumentation=="2") {
theComponent.documentation += `\n${summary}`;
}
else if (updateDocumentation=="1") {
theComponent.documentation = summary;
}
});
}
function generateDocumentation (theComponent) {
let componentPrompt = `Component Name: \"${theComponent.name}\", Component Type: \"${theComponent.type}\"${(theComponent.specialization!=null?", Component Specialisation: \""+theComponent.specialization+"\"":"")}${(theComponent.documentation!=""&&theComponent.documentation!=null)?", Current Documentation: \""+theComponent.documentation+"\"":""}`
theComponent.prop().forEach(function (prop) {
componentPrompt+=` Property: "${prop}" = "${theComponent.prop(prop)}",`;
})
return ai(`${componentPromptTemplate}:\n ${componentPrompt}`);
}
function summariseMarkdownToAI (markdownContent) {
return ai(viewPromptTemplate+markdownContent)
}
/*
* AI Support package
*
* Requires:
* * jArchi - https://www.archimatetool.com/blog/2018/07/02/jarchi/
*
* Gemini API Key - https://ai.google.dev/gemini-api/docs/api-key
* ChatGPT Key - https://platform.openai.com/docs/overview
*
* Version 1: Gemini API
* Version 2: Chat GPT + REST API usage
*
* (c) 2025 Steven Mileham
*
*/
const gptKey = "{{INSERT KEY HERE}}";
const gptEndpoint = "https://api.openai.com/v1/responses";
const geminiKey = "{{INSERT KEY HERE}}";
const geminiEndpoint = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent";
const engine = "Gemini"; // "Gemini" or "GPT"
console.log("Loaded AI REST Package");
function callApi(url, payload) {
var imports = new JavaImporter(java.net, java.util, java.lang, java.io);
var apiResult = "";
let result= {};
with (imports) {
var urlObj = new URL(url);
var hcon = urlObj.openConnection();
hcon.setRequestMethod("POST");
hcon.setDoOutput(true);
// Set request headers
hcon.setRequestProperty("Content-Type", "application/json");
hcon.setRequestProperty("Accept", "application/json");
hcon.setRequestProperty("Accept-Charset", "UTF-8");
if (engine == "Gemini") {
hcon.setRequestProperty("x-goog-api-key", geminiKey);
}
else if (engine == "GPT") {
hcon.setRequestProperty("Authorization", `Bearer ${gptKey}`);
}
try {
var output = new OutputStreamWriter(hcon.getOutputStream());
output.write(JSON.stringify(payload));
output.flush();
output.close();
} catch(e) {
console.setTextColor(255,0,0);
console.log("Error writing POST data:");
console.log(e);
exit();
}
try {
var reader = new BufferedReader(new InputStreamReader(hcon.getInputStream()));
var line = reader.readLine();
while (line != null) {
apiResult += line + "\n";
line = reader.readLine();
}
reader.close();
result = JSON.parse(apiResult);
if (!result.candidates && !result.output[0]) {
console.log ("Error");
}
} catch (e) {
console.setTextColor(255, 0, 0);
console.log("HTTPS error:");
console.log(e);
console.log(hcon.getHeaderFields());
exit();
}
}
console.setDefaultTextColor();
return result;
}
const sendToAI = (thePrompt) => {
if (engine == "Gemini") {
console.log("Asking Gemini");
let data = {
"contents" : {
"parts" : [
{
"text": thePrompt
}
]
}
};
let aiOutput = callApi(geminiEndpoint,data).candidates[0].content.parts[0].text;
return `${aiOutput}\n\nGenerated by Gemini ${new Date().toLocaleString()}`;
}
else if (engine == "GPT") {
console.log("Asking ChatGPT");
let data = {
"model": "gpt-4.1",
"input": thePrompt
};
let aiOutput = callApi(gptEndpoint,data).output[0].content[0].text;
return `${aiOutput}\n\nGenerated by ChatGPT ${new Date().toLocaleString()}`;
}
}
module.exports=sendToAI;
/*
* AI Support package
*
* WARNING: Use the new one below!
* An alternative file below "AI-REST.js", enables both Gemini or Chat GPT via REST API's without the Java jar packages being loaded.
*
* Requires:
* * jArchi - https://www.archimatetool.com/blog/2018/07/02/jarchi/
* * Gemini API Java Libraries:
* * https://repo1.maven.org/maven2/commons-logging/commons-logging/1.3.5/commons-logging-1.3.5.jar
* * https://repo1.maven.org/maven2/com/google/auth/google-auth-library-credentials/1.37.1/google-auth-library-credentials-1.37.1.jar
* * https://repo1.maven.org/maven2/com/google/auth/google-auth-library-oauth2-http/1.37.1/google-auth-library-oauth2-http-1.37.1.jar
* * https://repo1.maven.org/maven2/com/google/genai/google-genai/1.5.0/google-genai-1.5.0.jar
* * https://repo1.maven.org/maven2/com/google/guava/guava/33.4.8-jre/guava-33.4.8-jre.jar
* * https://repo1.maven.org/maven2/org/apache/httpcomponents/httpclient/4.5/httpclient-4.5.jar
* * https://repo1.maven.org/maven2/org/apache/httpcomponents/client5/httpclient5/5.5/httpclient5-5.5.jar
* * https://repo1.maven.org/maven2/org/apache/httpcomponents/httpcore/4.4.16/httpcore-4.4.16.jar
* * https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.19.1/jackson-annotations-2.19.1.jar
* * https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.19.1/jackson-core-2.19.1.jar
* * https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.19.1/jackson-databind-2.19.1.jar
* * https://repo1.maven.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.19.1/jackson-datatype-jdk8-2.19.1.jar
* * https://repo1.maven.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.19.1/jackson-datatype-jsr310-2.19.1.jar
*
* Gemini API Key - https://ai.google.dev/gemini-api/docs/api-key
*
* Version 1: Gemini API
*
* (c) 2025 Steven Mileham
*
*/
const geminiKey = "{{INSERT KEY HERE}}";
Java.addToClasspath(__DIR__ +"/jars/google-genai-1.5.0.jar");
Java.addToClasspath(__DIR__ +"/jars/jackson-core-2.19.1.jar");
Java.addToClasspath(__DIR__ +"/jars/jackson-databind-2.19.1.jar");
Java.addToClasspath(__DIR__ +"/jars/guava-33.4.8-jre.jar");
Java.addToClasspath(__DIR__ +"/jars/httpclient-4.5.14.jar");
Java.addToClasspath(__DIR__ +"/jars/httpcore-4.4.16.jar");
Java.addToClasspath(__DIR__ +"/jars/google-auth-library-credentials-1.37.1.jar");
Java.addToClasspath(__DIR__ +"/jars/google-auth-library-oauth2-http-1.37.1.jar");
Java.addToClasspath(__DIR__ +"/jars/jackson-datatype-jdk8-2.19.1.jar");
Java.addToClasspath(__DIR__ +"/jars/jackson-datatype-jsr310-2.19.1.jar");
Java.addToClasspath(__DIR__ +"/jars/jackson-annotations-2.19.1.jar");
Java.addToClasspath(__DIR__ +"/jars/commons-logging-1.3.5.jar");
console.log("Loaded Gemini Package")
const sendToAI = (thePrompt) => {
var client = Java.type("com.google.genai.Client");
let theclient = client.builder().apiKey(geminiKey).build();
let response =
theclient.models.generateContent(
"gemini-2.5-flash",
`${thePrompt}`,
null);
let aiOutput = response.text();
return `${aiOutput}\n\nGenerated by Gemini ${new Date().toLocaleString()}`;
}
module.exports=sendToAI;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment