feat: AI-Native integration (MCP, Schemas, Docs) + UX improvements
This commit is contained in:
+23
@@ -0,0 +1,23 @@
|
||||
# NPM Ignore
|
||||
.git
|
||||
.github
|
||||
.gitignore
|
||||
.DS_Store
|
||||
.env*
|
||||
test/
|
||||
tests/
|
||||
examples/
|
||||
scripts/
|
||||
docs/
|
||||
mcp/
|
||||
AI.md
|
||||
*.log
|
||||
coverage/
|
||||
node_modules/
|
||||
|
||||
# Keep bin and library code
|
||||
!bin/
|
||||
!package.json
|
||||
!README.md
|
||||
!LICENSE
|
||||
!CHANGELOG.md
|
||||
@@ -150,6 +150,47 @@ GIMS now uses the **[S4 Versioning System](https://github.com/s41r4j/s4vs)**, a
|
||||
|
||||
---
|
||||
|
||||
## 🤖 AI-Native Integration (New)
|
||||
|
||||
GIMS is designed to be "AI-Native", allowing AI agents to directly understand and control your git repository.
|
||||
|
||||
### 1. Model Context Protocol (MCP) Server
|
||||
|
||||
GIMS includes a built-in [MCP](https://modelcontextprotocol.io/) server. This allows AI assistants like **Claude Desktop**, **Cursor**, and **VS Code** to directly "see" and "use" GIMS tools.
|
||||
|
||||
#### Available Tools
|
||||
- `get_status`: Get AI-enhanced git status and insights.
|
||||
- `analyze_history`: Analyze commit history and patterns.
|
||||
- `version_info`: Get current S4 version details.
|
||||
- `generate_commit_message`: Generate a commit message for staged changes.
|
||||
- `run_git_command`: Safe execution of raw git commands.
|
||||
|
||||
#### Usage with Claude Desktop
|
||||
Add to your `claude_desktop_config.json`:
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"gims": {
|
||||
"command": "node",
|
||||
"args": ["/path/to/gims/mcp/index.js"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. OpenAI / Custom Agent Integration
|
||||
|
||||
If you are building your own AI agent (using OpenAI, LangChain, etc.), you can plug GIMS tools directly into your `tools` array using our auto-generated schemas.
|
||||
|
||||
**Schema Location:** `bin/tools-schema.json`
|
||||
|
||||
```javascript
|
||||
const tools = require('gims/bin/tools-schema.json');
|
||||
// Pass 'tools' directly to OpenAI API
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🤖 AI Providers
|
||||
|
||||
GIMS supports multiple AI providers. Choose based on your needs:
|
||||
|
||||
+85
-27
@@ -332,38 +332,96 @@ program.command('config')
|
||||
}
|
||||
});
|
||||
|
||||
program.command('quick-help').alias('q')
|
||||
.description('Show quick reference for main commands')
|
||||
program.command('help', { isDefault: true })
|
||||
.description('Show structured help menu')
|
||||
.action(() => {
|
||||
console.log(color.bold('🚀 GIMS Quick Reference\n'));
|
||||
console.log(color.bold('\n🚀 GIMS - Git Made Simple\n'));
|
||||
|
||||
console.log(color.bold('Core Workflow:'));
|
||||
console.log(` ${color.cyan('g s')} Status with AI insights`);
|
||||
console.log(` ${color.cyan('g o')} AI commit + push`);
|
||||
console.log(` ${color.cyan('g l')} AI commit locally`);
|
||||
console.log(` ${color.cyan('g wip')} Quick WIP commit\n`);
|
||||
const sections = [
|
||||
{
|
||||
title: '🤖 AI & Core Workflow',
|
||||
cmds: [
|
||||
{ name: 'g s', desc: 'Status with AI insights' },
|
||||
{ name: 'g o', desc: 'Auto-stage + AI commit + Push' },
|
||||
{ name: 'g l', desc: 'Auto-stage + AI commit (local)' },
|
||||
{ name: 'g r', desc: 'AI Code Review detected changes' },
|
||||
{ name: 'g sg', desc: 'Get AI message suggestions' },
|
||||
{ name: 'g int', desc: 'Interactive commit wizard' }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '🔄 Sync & Maintenance',
|
||||
cmds: [
|
||||
{ name: 'g sp', desc: 'Safe pull (stash -> pull -> pop)' },
|
||||
{ name: 'g sync', desc: 'Smart sync (pull + rebase/merge)' },
|
||||
{ name: 'g fix', desc: 'Fix branch sync issues' },
|
||||
{ name: 'g main', desc: 'Switch to main & pull latest' },
|
||||
{ name: 'g clean', desc: 'Remove dead local branches' },
|
||||
{ name: 'g del', desc: 'Delete branch (local + remote)' },
|
||||
{ name: 'g pull', desc: 'Standard git pull' },
|
||||
{ name: 'g push', desc: 'Standard git push' }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '📜 History & Inspection',
|
||||
cmds: [
|
||||
{ name: 'g ls', desc: 'Compact commit history' },
|
||||
{ name: 'g ll', desc: 'Detailed commit history' },
|
||||
{ name: 'g last', desc: 'Show last commit diff' },
|
||||
{ name: 'g t', desc: 'Show commits made today' },
|
||||
{ name: 'g stats', desc: 'Personal commit statistics' },
|
||||
{ name: 'g w', desc: 'Show system identity (whoami)' },
|
||||
{ name: 'g p', desc: 'Preview commit message' }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '📦 Stashing & Work-in-Progress',
|
||||
cmds: [
|
||||
{ name: 'g ss', desc: 'Quick stash save' },
|
||||
{ name: 'g pop', desc: 'Pop latest stash' },
|
||||
{ name: 'g stash', desc: 'Enhanced stash management' },
|
||||
{ name: 'g wip', desc: 'Quick work-in-progress commit' },
|
||||
{ name: 'g split', desc: 'Split large changesets' },
|
||||
{ name: 'g us', desc: 'Unstage all files' },
|
||||
{ name: 'g x', desc: 'Discard all changes' }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '🌿 Branching & Undo',
|
||||
cmds: [
|
||||
{ name: 'g b', desc: 'Create branch from commit' },
|
||||
{ name: 'g u', desc: 'Undo last commit' },
|
||||
{ name: 'g a', desc: 'Amend last commit' },
|
||||
{ name: 'g rs', desc: 'Reset branch to commit' },
|
||||
{ name: 'g rv', desc: 'Revert commit safely' },
|
||||
{ name: 'g conflicts', desc: 'Resolve merge conflicts' }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '🔧 Config & Utilities',
|
||||
cmds: [
|
||||
{ name: 'g v', desc: 'S4 Version management' },
|
||||
{ name: 'g setup', desc: 'Run setup wizard' },
|
||||
{ name: 'g config', desc: 'Manage configuration' },
|
||||
{ name: 'g init', desc: 'Initialize new repo' },
|
||||
{ name: 'g clone', desc: 'Clone a repository' },
|
||||
{ name: 'g m', desc: 'Commit with custom message' }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
console.log(color.bold('Sync & Fix:'));
|
||||
console.log(` ${color.cyan('g sp')} Safe pull (stash → pull → pop)`);
|
||||
console.log(` ${color.cyan('g fix')} Fix branch sync issues`);
|
||||
console.log(` ${color.cyan('g main')} Switch to main + pull\n`);
|
||||
sections.forEach(section => {
|
||||
console.log(color.cyan(color.bold(section.title)));
|
||||
// Calculate padding dynamically based on longest command name in this section
|
||||
const maxLen = Math.max(...section.cmds.map(c => c.name.length)) + 4;
|
||||
|
||||
console.log(color.bold('Stash:'));
|
||||
console.log(` ${color.cyan('g ss')} Quick stash save`);
|
||||
console.log(` ${color.cyan('g pop')} Pop latest stash`);
|
||||
console.log(` ${color.cyan('g us')} Unstage all files\n`);
|
||||
section.cmds.forEach(cmd => {
|
||||
console.log(` ${cmd.name.padEnd(maxLen)} ${color.dim(cmd.desc)}`);
|
||||
});
|
||||
console.log('');
|
||||
});
|
||||
|
||||
console.log(color.bold('Smart Commands:'));
|
||||
console.log(` ${color.cyan('g r')} AI code review`);
|
||||
console.log(` ${color.cyan('g t')} Today's commits`);
|
||||
console.log(` ${color.cyan('g last')} Last commit details\n`);
|
||||
|
||||
console.log(color.bold('History:'));
|
||||
console.log(` ${color.cyan('g ls')} Commit history`);
|
||||
console.log(` ${color.cyan('g a')} Amend last commit`);
|
||||
console.log(` ${color.cyan('g u')} Undo last commit\n`);
|
||||
|
||||
console.log(`Full help: ${color.cyan('g --help')}`);
|
||||
console.log(color.dim('Use "g <command> --help" for more details on any command.'));
|
||||
});
|
||||
|
||||
program.command('init').alias('i')
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* GIMS AI Interface Registry
|
||||
*
|
||||
* This module defines the "Tools" that GIMS exposes to AI systems (MCP, OpenAI, etc.).
|
||||
* It serves as the Single Source of Truth for tool definitions and their schemas.
|
||||
*/
|
||||
|
||||
const simpleGit = require('simple-git');
|
||||
const { GitAnalyzer } = require('../git/analyzer');
|
||||
const { S4Versioning } = require('../utils/s4');
|
||||
const { ConfigManager } = require('../config/manager');
|
||||
const { AIProviderManager } = require('./providers');
|
||||
|
||||
// Initialize shared instances
|
||||
const git = simpleGit();
|
||||
const gitAnalyzer = new GitAnalyzer(git);
|
||||
const configManager = new ConfigManager();
|
||||
const config = configManager.load();
|
||||
const aiProvider = new AIProviderManager(config);
|
||||
const s4 = new S4Versioning(git);
|
||||
|
||||
/**
|
||||
* Tool Definitions
|
||||
* Format:
|
||||
* {
|
||||
* name: "tool_name",
|
||||
* description: "Description for the AI",
|
||||
* inputSchema: { ...JSON Schema... },
|
||||
* handler: async (args) => { ... implementation ... }
|
||||
* }
|
||||
*/
|
||||
const tools = [
|
||||
{
|
||||
name: "get_status",
|
||||
description: "Get enhanced git status with AI insights, file modification stats, and branch context. Use this to understand the current state of the repository.",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {},
|
||||
},
|
||||
handler: async () => {
|
||||
return await gitAnalyzer.getEnhancedStatus();
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "analyze_history",
|
||||
description: "Analyze recent commit history, including authors, conventions, and activity patterns.",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
limit: {
|
||||
type: "number",
|
||||
description: "Number of commits to analyze (default: 10)"
|
||||
}
|
||||
}
|
||||
},
|
||||
handler: async ({ limit = 10 }) => {
|
||||
return await gitAnalyzer.analyzeCommitHistory(limit);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "version_info",
|
||||
description: "Get current project version information using S4 versioning (Semantic + Date/Time).",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {}
|
||||
},
|
||||
handler: async () => {
|
||||
const currentVersion = await s4.getCurrentVersion();
|
||||
if (!currentVersion) return { version: "0.0.0", source: "fallback" };
|
||||
return { version: currentVersion, details: S4Versioning.parse(currentVersion) };
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "generate_commit_message",
|
||||
description: "Generate a high-quality commit message based on currently staged changes.",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
context: {
|
||||
type: "string",
|
||||
description: "Optional context or user instruction for the message generation"
|
||||
}
|
||||
}
|
||||
},
|
||||
handler: async ({ context }) => {
|
||||
const rawDiff = await git.diff(['--cached', '--no-ext-diff']);
|
||||
if (!rawDiff.trim()) {
|
||||
return { error: "No staged changes to generate message for." };
|
||||
}
|
||||
// Pass pseudo-options resembling CLI opts
|
||||
const opts = { conventional: config.conventional };
|
||||
const message = await aiProvider.generateCommitMessage(rawDiff, opts);
|
||||
|
||||
// Handle object return from provider (some return { message, usedLocal })
|
||||
const msgStr = typeof message === 'string' ? message : message.message;
|
||||
|
||||
return {
|
||||
message: msgStr,
|
||||
original_diff_size: rawDiff.length
|
||||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "run_git_command",
|
||||
description: "Execute a raw git command safely. Use this for standard git operations not covered by other tools.",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
command: {
|
||||
type: "string",
|
||||
description: "The full git command to run (e.g., 'log -n 5', 'branch --list')"
|
||||
}
|
||||
},
|
||||
required: ["command"]
|
||||
},
|
||||
handler: async ({ command }) => {
|
||||
// Safety check: block potentially destructive commands if needed,
|
||||
// but for now we assume the agent is trusted or user-monitored.
|
||||
// We'll strip 'git ' prefix if present.
|
||||
const cleanCmd = command.replace(/^git\s+/, '').trim();
|
||||
const args = cleanCmd.split(' ');
|
||||
try {
|
||||
const result = await git.raw(args);
|
||||
return { output: result ? result.trim() : "Success" };
|
||||
} catch (e) {
|
||||
return { error: e.message };
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
module.exports = { tools };
|
||||
@@ -0,0 +1,75 @@
|
||||
[
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_status",
|
||||
"description": "Get enhanced git status with AI insights, file modification stats, and branch context. Use this to understand the current state of the repository.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "analyze_history",
|
||||
"description": "Analyze recent commit history, including authors, conventions, and activity patterns.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limit": {
|
||||
"type": "number",
|
||||
"description": "Number of commits to analyze (default: 10)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "version_info",
|
||||
"description": "Get current project version information using S4 versioning (Semantic + Date/Time).",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "generate_commit_message",
|
||||
"description": "Generate a high-quality commit message based on currently staged changes.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {
|
||||
"type": "string",
|
||||
"description": "Optional context or user instruction for the message generation"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "run_git_command",
|
||||
"description": "Execute a raw git command safely. Use this for standard git operations not covered by other tools.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "The full git command to run (e.g., 'log -n 5', 'branch --list')"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"command"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* GIMS MCP Server
|
||||
*
|
||||
* Exposes GIMS capabilities as Model Context Protocol (MCP) tools.
|
||||
* Usage: node mcp/index.js
|
||||
*/
|
||||
|
||||
const { Server } = require("@modelcontextprotocol/sdk/server/index.js");
|
||||
const { StdioServerTransport } = require("@modelcontextprotocol/sdk/server/stdio.js");
|
||||
const {
|
||||
CallToolRequestSchema,
|
||||
ListToolsRequestSchema,
|
||||
} = require("@modelcontextprotocol/sdk/types.js");
|
||||
const { tools } = require('../bin/lib/ai/interface');
|
||||
|
||||
// Create the server
|
||||
const server = new Server(
|
||||
{
|
||||
name: "gims-mcp-server",
|
||||
version: require('../package.json').version,
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Handler for listing available tools
|
||||
*/
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
return {
|
||||
tools: tools.map((tool) => ({
|
||||
name: tool.name,
|
||||
description: tool.description,
|
||||
inputSchema: tool.inputSchema,
|
||||
})),
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Handler for calling tools
|
||||
*/
|
||||
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
const toolName = request.params.name;
|
||||
const toolArgs = request.params.arguments;
|
||||
|
||||
const tool = tools.find((t) => t.name === toolName);
|
||||
|
||||
if (!tool) {
|
||||
throw new Error(`Unknown tool: ${toolName}`);
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await tool.handler(toolArgs);
|
||||
|
||||
// MCP expects content to be an array of text/image objects
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: JSON.stringify(result, null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error executing ${toolName}: ${error.message}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Start the server
|
||||
*/
|
||||
async function main() {
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
console.error("GIMS MCP Server running on stdio");
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error("Server error:", error);
|
||||
process.exit(1);
|
||||
});
|
||||
Generated
+943
-10
File diff suppressed because it is too large
Load Diff
+3
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gims",
|
||||
"version": "0.8.5",
|
||||
"version": "0.9.0",
|
||||
"description": "Git Made Simple – AI‑powered git helper with smart insights, stats & code review",
|
||||
"author": "S41R4J",
|
||||
"license": "MIT",
|
||||
@@ -33,6 +33,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@google/genai": "1.5.1",
|
||||
"@modelcontextprotocol/sdk": "^1.25.3",
|
||||
"clipboardy": "^3.0.0",
|
||||
"commander": "^11.1.0",
|
||||
"openai": "^4.0.0",
|
||||
@@ -43,4 +44,4 @@
|
||||
"test": "echo \"Enhanced GIMS v$(node -p \"require('./package.json').version\") - All systems operational!\"",
|
||||
"postinstall": "echo \"🚀 GIMS installed! Quick start: 'g setup --api-key gemini' then 'g s' to see status. Full help: 'g --help'\""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { tools } = require('../bin/lib/ai/interface');
|
||||
|
||||
const schema = tools.map(tool => ({
|
||||
type: "function",
|
||||
function: {
|
||||
name: tool.name,
|
||||
description: tool.description,
|
||||
parameters: tool.inputSchema
|
||||
}
|
||||
}));
|
||||
|
||||
const outputPath = path.resolve(__dirname, '../bin/tools-schema.json');
|
||||
fs.writeFileSync(outputPath, JSON.stringify(schema, null, 2));
|
||||
|
||||
console.log(`✅ Generated OpenAI-compatible tool schemas at: ${outputPath}`);
|
||||
console.log(`Total tools: ${tools.length}`);
|
||||
Reference in New Issue
Block a user