Co-mate is an AI-powered software architecture copilot, design and governance tools.
Project Kanban: https://github.com/orgs/archguard/projects/5/views/1
Supported languages by ArchGuard and Chapi: Java, Kotlin, TypeScript/JavaScript, Golang, Python
- DSL as Ubiquitous Language: Empower efficient communication between humans and machines by employing a Domain-Specific Language (DSL).
- Atomic LLM for Orchestration: Harness the atomic capabilities of a Language Model (LLM) to construct intricate behaviors within the DSL.
- Dynamic Context by Layered: Divide the context into layers to handle complexities effectively through the LLM.
- download the latest release from release page
- please put
OPENAI_API_KEY=xxx
in~/.comate/.env
- run
java -jar comate-cli-*-all.jar
replace*
with the version number
.env
file example:
OPENAI_API_KEY=xxx
OPENAI_API_PROXY=xxxx (optional, if you had a OpenAI proxy server)
Prerequisites: Node.js 16+, Java 11+
- Clone
git clone https://github.com/archguard/co-mate
- Setup backend server
./gradlew :comate-server:run
- Setup frontend GUI
cd comate-gui
pnpm install
pnpm dev
comate-server
: server side which provide REST APIcomate-gui
: web GUIcomate-cli
: command line interface [todo]
Core modules:
comate-core
: core logic, handle ArchGuard API, LLM logic, etc.- LLM modules:
llm-core
: large language model core, like OpenAI call, Token calculate, Tokenizer, Embedding, Similarity for Embedding, etc.
- Architecture Spec
spec-lang
: the Kotlin DSL for architecture's specification, like: Domain Driven Design, RESTful API, etc.spec-runtime
: the Kotlin REPL/Interpreter for Architecture Spec DSLspec-partitioner
: the partitioner for partitioning the architecture spec document
- Architecture Define
architecture
: architecture model
- GUI: Next.js + React + AI.js
- Server: Kotlin + Ktor
- DSL: Kotlin Type-Safe DSL
- Code Engine: ArchGuard & ArchGuard CodeDB
domain {
context_map("TicketBooking") {
context("Reservation") {}
context("Ticket") {}
mapping {
context("Reservation") dependedOn context("Ticket")
context("Reservation") dependedOn context("Movie")
}
}
}
caseflow("MovieTicketBooking", defaultActor = "User") {
// activity's should consider all user activities
activity("AccountManage") {
// task part should include all user tasks under the activity
task("UserRegistration") {
// you should list key steps in the story
stories = listOf("Register with email", "Register with phone")
}
task("UserLogin") {
stories += "Login to the website"
}
}
activity("MovieSelection") {}
// ...
activity("PaymentCancel") {
task("ConfirmCancel") {
actor = "Admin" // if some task is role-specific, you can specify it here
//...
}
}
}
concepts {
val customer = Concept("Customer") {
behavior("Place Order", "Place an order for a coffee")
behaviors = listOf(
"View Menu",
"Add to Cart",
"Remove from Cart",
"Place Order",
"Pay",
"View Order Status",
"View Order History",
"Customize Order"
)
}
val barista = Concept("Barista") {
behavior("Make Coffee")
}
val deliveryPerson = Concept("Delivery Person") {
behavior("Deliver Order")
}
val shoppingCart = Concept("Shopping Cart") {
behavior("Add to Cart", "Add a coffee to the shopping cart")
behavior("Remove from Cart", "Remove a coffee from the shopping cart")
behavior("View Cart", "View the contents of the shopping cart")
behavior("Checkout", "Proceed to checkout and place the order")
}
relations {
customer["View Menu"] perform barista
customer["View Order History"] perform barista
customer["Add to Cart"] perform shoppingCart
customer["Remove from Cart"] perform shoppingCart
customer["View Cart"] perform shoppingCart
customer["Checkout"] perform barista
customer["Place Order"] perform barista
customer["Pay"] perform deliveryPerson
customer["View Order Status"] perform deliveryPerson
customer["Customize Order"].perform(barista) {
// condition("").action("") // when need
}
}
}
foundation {
project_name {
pattern("^([a-z0-9-]+)-([a-z0-9-]+)-([a-z0-9-]+)(-common)?\$")
example("system1-servicecenter1-microservice1")
}
layered {
layer("interface") {
pattern(".*\\.interface") { name shouldBe endsWith("Controller", "Service") }
}
layer("application") {
pattern(".*\\.application") {
name shouldBe endsWith("DTO", "Request", "Response", "Factory", "Service")
}
}
layer("domain") {
pattern(".*\\.domain") { name shouldBe endsWith("Entity") }
}
layer("infrastructure") {
pattern(".*\\.infrastructure") { name shouldBe endsWith("Repository", "Mapper") }
}
dependency {
"interface" dependedOn "domain"
"interface" dependedOn "application"
"interface" dependedOn "infrastructure"
"application" dependedOn "domain"
"application" dependedOn "infrastructure"
"domain" dependedOn "infrastructure"
}
}
naming {
class_level {
style("CamelCase")
pattern(".*") { name shouldNotBe contains("$") }
}
function_level {
style("CamelCase")
pattern(".*") { name shouldNotBe contains("$") }
}
}
}
for MVC:
foundation {
project_name {
pattern("^([a-z0-9-]+)-([a-z0-9-]+)(-common)?\$")
example("system1-webapp1")
}
layered {
layer("controller") {
pattern(".*\\.controller") { name shouldBe endsWith("Controller") }
}
layer("service") {
pattern(".*\\.service") {
name shouldBe endsWith("DTO", "Request", "Response", "Factory", "Service")
}
}
layer("repository") {
pattern(".*\\.repository") { name shouldBe endsWith("Entity", "Repository", "Mapper") }
}
dependency {
"controller" dependedOn "service"
"controller" dependedOn "repository"
"service" dependedOn "repository"
}
}
naming {
class_level {
style("CamelCase")
pattern(".*") { name shouldNotBe contains("$") }
}
function_level {
style("CamelCase")
pattern(".*") { name shouldNotBe contains("$") }
}
}
}
rest_api {
uri_construction {
pattern("/api\\/[a-zA-Z0-9]+\\/v[0-9]+\\/[a-zA-Z0-9\\/\\-]+")
example("/api/petstore/v1/pets/dogs")
}
http_action("GET", "POST", "PUT", "DELETE")
status_code(200, 201, 202, 204, 400, 401, 403, 404, 500, 502, 503, 504)
security(
"""
Token Based Authentication (Recommended) Ideally, microservices should be stateless so the service instances can be scaled out easily and the client requests can be routed to multiple independent service providers. A token based authentication mechanism should be used instead of session based authentication
""".trimIndent()
)
misc("""""")
}
Similar Project:
- AutoDoc. Autodoc is an experimental toolkit for auto-generating codebase documentation for git repositories using Large Language Models, like GPT-4 or Alpaca. Autodoc can be installed in your repo in about 5 minutes. It indexes your codebase through a depth-first traversal of all repository contents and calls an LLM to write documentation for each file and folder. These documents can be combined to describe the different components of your system and how they work together.
This code is distributed under the MPL license. See LICENSE
in this directory.