workflow-agent-vscode 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +172 -0
- package/dist/extension.js +486 -0
- package/dist/extension.js.map +1 -0
- package/package.json +129 -0
- package/src/commands.ts +204 -0
- package/src/config.ts +88 -0
- package/src/extension.ts +54 -0
- package/src/statusBar.ts +71 -0
- package/src/validation.ts +116 -0
- package/tsconfig.json +11 -0
- package/tsup.config.ts +12 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/extension.ts","../src/statusBar.ts","../src/validation.ts","../src/config.ts","../src/commands.ts"],"sourcesContent":["import * as vscode from \"vscode\";\nimport { StatusBarManager } from \"./statusBar\";\nimport { ValidationProvider } from \"./validation\";\nimport { ConfigManager } from \"./config\";\nimport { CommandRegistry } from \"./commands\";\n\nexport function activate(context: vscode.ExtensionContext) {\n console.log(\"Workflow Agent extension activating...\");\n\n // Initialize managers\n const configManager = new ConfigManager();\n const statusBar = new StatusBarManager();\n const validationProvider = new ValidationProvider(configManager);\n const commands = new CommandRegistry(\n configManager,\n statusBar,\n validationProvider,\n );\n\n // Register commands\n commands.registerAll(context);\n\n // Set up status bar\n statusBar.show();\n context.subscriptions.push(statusBar);\n\n // Set up validation\n validationProvider.activate(context);\n\n // Watch for configuration changes\n context.subscriptions.push(\n vscode.workspace.onDidChangeConfiguration((e) => {\n if (e.affectsConfiguration(\"workflow-agent\")) {\n configManager.reload();\n statusBar.update();\n }\n }),\n );\n\n // Watch for git changes\n context.subscriptions.push(\n vscode.workspace.onDidChangeTextDocument((e) => {\n if (e.document.fileName.includes(\".git/COMMIT_EDITMSG\")) {\n validationProvider.validateCommitMessage(e.document);\n }\n }),\n );\n\n console.log(\"Workflow Agent extension activated!\");\n}\n\nexport function deactivate() {\n console.log(\"Workflow Agent extension deactivating...\");\n}\n","import * as vscode from \"vscode\";\nimport { ConfigManager } from \"./config\";\n\nexport class StatusBarManager implements vscode.Disposable {\n private statusBarItem: vscode.StatusBarItem;\n\n constructor() {\n this.statusBarItem = vscode.window.createStatusBarItem(\n vscode.StatusBarAlignment.Left,\n 100,\n );\n this.statusBarItem.command = \"workflow-agent.showConfig\";\n }\n\n show(): void {\n this.statusBarItem.show();\n this.update();\n }\n\n hide(): void {\n this.statusBarItem.hide();\n }\n\n update(config?: ConfigManager): void {\n if (!config) {\n this.statusBarItem.text = \"$(workflow) Workflow\";\n this.statusBarItem.tooltip = \"Workflow Agent - Not configured\";\n return;\n }\n\n const branch = config.getCurrentBranch();\n const hasConfig = config.hasConfig();\n\n if (!hasConfig) {\n this.statusBarItem.text = \"$(workflow) Workflow: Not initialized\";\n this.statusBarItem.tooltip = \"Click to initialize Workflow Agent\";\n this.statusBarItem.command = \"workflow-agent.init\";\n this.statusBarItem.backgroundColor = new vscode.ThemeColor(\n \"statusBarItem.warningBackground\",\n );\n return;\n }\n\n const enforcement = config.getEnforcement();\n const icon = enforcement === \"strict\" ? \"$(shield)\" : \"$(check)\";\n\n this.statusBarItem.text = `${icon} Workflow: ${branch || \"Unknown\"}`;\n this.statusBarItem.tooltip = `Workflow Agent\\nBranch: ${branch}\\nEnforcement: ${enforcement}\\nClick for details`;\n this.statusBarItem.backgroundColor = undefined;\n }\n\n updateStatus(valid: boolean, message?: string): void {\n if (valid) {\n this.statusBarItem.backgroundColor = undefined;\n if (message) {\n this.statusBarItem.tooltip = message;\n }\n } else {\n this.statusBarItem.backgroundColor = new vscode.ThemeColor(\n \"statusBarItem.errorBackground\",\n );\n if (message) {\n this.statusBarItem.tooltip = `⚠ ${message}`;\n }\n }\n }\n\n dispose(): void {\n this.statusBarItem.dispose();\n }\n}\n","import * as vscode from \"vscode\";\nimport { ConfigManager } from \"./config\";\n\nexport class ValidationProvider {\n private diagnosticCollection: vscode.DiagnosticCollection;\n\n constructor(private configManager: ConfigManager) {\n this.diagnosticCollection =\n vscode.languages.createDiagnosticCollection(\"workflow-agent\");\n }\n\n activate(context: vscode.ExtensionContext): void {\n context.subscriptions.push(this.diagnosticCollection);\n\n // Validate on file open\n vscode.workspace.onDidOpenTextDocument((doc) => {\n if (doc.fileName.includes(\".git/COMMIT_EDITMSG\")) {\n this.validateCommitMessage(doc);\n }\n });\n\n // Validate on change\n vscode.workspace.onDidChangeTextDocument((e) => {\n if (\n this.configManager.shouldValidateOnType() &&\n e.document.fileName.includes(\".git/COMMIT_EDITMSG\")\n ) {\n this.validateCommitMessage(e.document);\n }\n });\n }\n\n validateCommitMessage(document: vscode.TextDocument): void {\n const text = document.getText();\n const firstLine = text.split(\"\\n\")[0];\n\n if (!firstLine || firstLine.startsWith(\"#\")) {\n return; // Empty or comment\n }\n\n const diagnostics: vscode.Diagnostic[] = [];\n\n // Check conventional commit format: type(scope): description\n const commitPattern =\n /^(feat|fix|refactor|chore|docs|test|perf|style|ci|build|revert)\\(([a-z0-9-]+)\\): .{10,}/;\n\n if (!commitPattern.test(firstLine)) {\n const diagnostic = new vscode.Diagnostic(\n new vscode.Range(0, 0, 0, firstLine.length),\n \"Commit message must follow format: type(scope): description\",\n vscode.DiagnosticSeverity.Error,\n );\n diagnostic.code = \"workflow-commit-format\";\n diagnostic.source = \"workflow-agent\";\n diagnostics.push(diagnostic);\n } else {\n // Validate scope\n const match = firstLine.match(/\\(([a-z0-9-]+)\\)/);\n if (match) {\n const scope = match[1];\n const validScopes = this.configManager.getScopes();\n\n if (validScopes.length > 0 && !validScopes.includes(scope)) {\n const diagnostic = new vscode.Diagnostic(\n new vscode.Range(\n 0,\n firstLine.indexOf(scope),\n 0,\n firstLine.indexOf(scope) + scope.length,\n ),\n `Invalid scope '${scope}'. Valid scopes: ${validScopes.join(\", \")}`,\n vscode.DiagnosticSeverity.Warning,\n );\n diagnostic.code = \"workflow-invalid-scope\";\n diagnostic.source = \"workflow-agent\";\n diagnostics.push(diagnostic);\n }\n }\n }\n\n this.diagnosticCollection.set(document.uri, diagnostics);\n }\n\n validateBranch(branchName: string): { valid: boolean; message?: string } {\n // Branch pattern: <type>/<scope>/<description>\n const branchPattern =\n /^(feature|bugfix|hotfix|chore|refactor|docs|test)\\/([a-z0-9-]+)\\/[a-z0-9-]+$/;\n\n if (!branchPattern.test(branchName)) {\n return {\n valid: false,\n message: \"Branch name must follow: <type>/<scope>/<description>\",\n };\n }\n\n // Extract and validate scope\n const parts = branchName.split(\"/\");\n if (parts.length >= 2) {\n const scope = parts[1];\n const validScopes = this.configManager.getScopes();\n\n if (validScopes.length > 0 && !validScopes.includes(scope)) {\n return {\n valid: false,\n message: `Invalid scope '${scope}'. Valid: ${validScopes.join(\", \")}`,\n };\n }\n }\n\n return { valid: true };\n }\n\n dispose(): void {\n this.diagnosticCollection.dispose();\n }\n}\n","import * as vscode from \"vscode\";\nimport { execSync } from \"child_process\";\nimport { join } from \"path\";\nimport { existsSync } from \"fs\";\n\nexport class ConfigManager {\n private workspaceConfig: any = null;\n private workspaceRoot: string | undefined;\n\n constructor() {\n this.workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;\n this.reload();\n }\n\n reload(): void {\n if (!this.workspaceRoot) {\n this.workspaceConfig = null;\n return;\n }\n\n const configPath = join(this.workspaceRoot, \"workflow.config.json\");\n\n if (existsSync(configPath)) {\n try {\n delete require.cache[require.resolve(configPath)];\n this.workspaceConfig = require(configPath);\n } catch (error) {\n console.error(\"Failed to load workflow config:\", error);\n this.workspaceConfig = null;\n }\n } else {\n this.workspaceConfig = null;\n }\n }\n\n hasConfig(): boolean {\n return this.workspaceConfig !== null;\n }\n\n getScopes(): string[] {\n if (!this.workspaceConfig?.scopes) {\n return [];\n }\n return this.workspaceConfig.scopes.map((s: any) => s.name);\n }\n\n getProjectName(): string | undefined {\n return this.workspaceConfig?.projectName;\n }\n\n getEnforcement(): string {\n return this.workspaceConfig?.enforcement || \"advisory\";\n }\n\n isEnabled(): boolean {\n const config = vscode.workspace.getConfiguration(\"workflow-agent\");\n return config.get<boolean>(\"enabled\", true);\n }\n\n shouldValidateOnType(): boolean {\n const config = vscode.workspace.getConfiguration(\"workflow-agent\");\n return config.get<boolean>(\"validateOnType\", true);\n }\n\n shouldShowStatusBar(): boolean {\n const config = vscode.workspace.getConfiguration(\"workflow-agent\");\n return config.get<boolean>(\"showStatusBar\", true);\n }\n\n isStrictMode(): boolean {\n const config = vscode.workspace.getConfiguration(\"workflow-agent\");\n return config.get<boolean>(\"strictMode\", false);\n }\n\n getCurrentBranch(): string | null {\n if (!this.workspaceRoot) return null;\n\n try {\n const branch = execSync(\"git rev-parse --abbrev-ref HEAD\", {\n cwd: this.workspaceRoot,\n encoding: \"utf-8\",\n }).trim();\n return branch;\n } catch {\n return null;\n }\n }\n}\n","import * as vscode from \"vscode\";\nimport { ConfigManager } from \"./config\";\nimport { StatusBarManager } from \"./statusBar\";\nimport { ValidationProvider } from \"./validation\";\n\nexport class CommandRegistry {\n constructor(\n private configManager: ConfigManager,\n private statusBar: StatusBarManager,\n private validation: ValidationProvider,\n ) {}\n\n registerAll(context: vscode.ExtensionContext): void {\n // Initialize command\n context.subscriptions.push(\n vscode.commands.registerCommand(\"workflow-agent.init\", () =>\n this.initCommand(),\n ),\n );\n\n // Validate command\n context.subscriptions.push(\n vscode.commands.registerCommand(\"workflow-agent.validate\", () =>\n this.validateCommand(),\n ),\n );\n\n // Suggest command\n context.subscriptions.push(\n vscode.commands.registerCommand(\"workflow-agent.suggest\", () =>\n this.suggestCommand(),\n ),\n );\n\n // Doctor command\n context.subscriptions.push(\n vscode.commands.registerCommand(\"workflow-agent.doctor\", () =>\n this.doctorCommand(),\n ),\n );\n\n // Show config command\n context.subscriptions.push(\n vscode.commands.registerCommand(\"workflow-agent.showConfig\", () =>\n this.showConfigCommand(),\n ),\n );\n }\n\n private async initCommand(): Promise<void> {\n const terminal = vscode.window.createTerminal(\"Workflow Agent\");\n terminal.show();\n terminal.sendText(\"workflow init\");\n }\n\n private async validateCommand(): Promise<void> {\n const branch = this.configManager.getCurrentBranch();\n\n if (!branch) {\n vscode.window.showErrorMessage(\"Not in a git repository\");\n return;\n }\n\n const result = this.validation.validateBranch(branch);\n\n if (result.valid) {\n vscode.window.showInformationMessage(`✓ Branch '${branch}' is valid`);\n this.statusBar.updateStatus(true, \"Branch is valid\");\n } else {\n vscode.window.showErrorMessage(`✗ Invalid branch: ${result.message}`);\n this.statusBar.updateStatus(false, result.message);\n }\n }\n\n private async suggestCommand(): Promise<void> {\n const feedback = await vscode.window.showInputBox({\n prompt: \"Enter your improvement suggestion\",\n placeHolder: \"e.g., Add support for GitLab repositories\",\n validateInput: (value) => {\n if (value.length < 10) {\n return \"Suggestion must be at least 10 characters\";\n }\n if (value.length > 1000) {\n return \"Suggestion must be less than 1000 characters\";\n }\n return null;\n },\n });\n\n if (!feedback) {\n return;\n }\n\n const category = await vscode.window.showQuickPick(\n [\n { label: \"✨ Feature Request\", value: \"feature\" },\n { label: \"🐛 Bug Report\", value: \"bug\" },\n { label: \"📚 Documentation\", value: \"documentation\" },\n { label: \"⚡ Performance\", value: \"performance\" },\n { label: \"💡 Other\", value: \"other\" },\n ],\n {\n placeHolder: \"Select suggestion category\",\n },\n );\n\n if (!category) {\n return;\n }\n\n const terminal = vscode.window.createTerminal(\"Workflow Agent\");\n terminal.show();\n terminal.sendText(\n `workflow suggest \"${feedback}\" --category ${category.value}`,\n );\n }\n\n private async doctorCommand(): Promise<void> {\n const terminal = vscode.window.createTerminal(\"Workflow Agent\");\n terminal.show();\n terminal.sendText(\"workflow doctor\");\n }\n\n private async showConfigCommand(): Promise<void> {\n if (!this.configManager.hasConfig()) {\n const action = await vscode.window.showInformationMessage(\n \"Workflow Agent is not initialized in this workspace\",\n \"Initialize Now\",\n );\n\n if (action === \"Initialize Now\") {\n this.initCommand();\n }\n return;\n }\n\n const projectName = this.configManager.getProjectName();\n const scopes = this.configManager.getScopes();\n const enforcement = this.configManager.getEnforcement();\n const branch = this.configManager.getCurrentBranch();\n\n const info = [\n `**Project:** ${projectName || \"Unknown\"}`,\n `**Branch:** ${branch || \"Unknown\"}`,\n `**Enforcement:** ${enforcement}`,\n `**Scopes (${scopes.length}):** ${scopes.join(\", \") || \"None\"}`,\n ].join(\"\\n\\n\");\n\n const panel = vscode.window.createWebviewPanel(\n \"workflowConfig\",\n \"Workflow Configuration\",\n vscode.ViewColumn.One,\n {},\n );\n\n panel.webview.html = `\n <!DOCTYPE html>\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <style>\n body {\n padding: 20px;\n font-family: var(--vscode-font-family);\n color: var(--vscode-foreground);\n }\n h1 {\n border-bottom: 1px solid var(--vscode-panel-border);\n padding-bottom: 10px;\n }\n .info {\n line-height: 1.8;\n }\n .scope-list {\n margin-top: 10px;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n }\n .scope {\n background: var(--vscode-badge-background);\n color: var(--vscode-badge-foreground);\n padding: 4px 12px;\n border-radius: 12px;\n font-size: 0.9em;\n }\n </style>\n </head>\n <body>\n <h1>🚀 Workflow Agent Configuration</h1>\n <div class=\"info\">\n <p><strong>Project:</strong> ${projectName || \"Unknown\"}</p>\n <p><strong>Current Branch:</strong> ${branch || \"Unknown\"}</p>\n <p><strong>Enforcement Mode:</strong> ${enforcement}</p>\n <p><strong>Available Scopes:</strong></p>\n <div class=\"scope-list\">\n ${scopes.map((s) => `<span class=\"scope\">${s}</span>`).join(\"\")}\n </div>\n </div>\n </body>\n </html>\n `;\n }\n}\n"],"mappings":"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","names":["vscode","vscode","vscode","vscode","commands"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "workflow-agent-vscode",
|
|
3
|
+
"displayName": "Workflow Agent",
|
|
4
|
+
"description": "Self-evolving workflow management with real-time validation",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"publisher": "workflow-agent",
|
|
7
|
+
"engines": {
|
|
8
|
+
"vscode": "^1.85.0"
|
|
9
|
+
},
|
|
10
|
+
"categories": [
|
|
11
|
+
"Other",
|
|
12
|
+
"Linters"
|
|
13
|
+
],
|
|
14
|
+
"keywords": [
|
|
15
|
+
"workflow",
|
|
16
|
+
"git",
|
|
17
|
+
"conventional-commits",
|
|
18
|
+
"branch-validation",
|
|
19
|
+
"scopes"
|
|
20
|
+
],
|
|
21
|
+
"activationEvents": [
|
|
22
|
+
"onStartupFinished"
|
|
23
|
+
],
|
|
24
|
+
"main": "./dist/extension.js",
|
|
25
|
+
"contributes": {
|
|
26
|
+
"commands": [
|
|
27
|
+
{
|
|
28
|
+
"command": "workflow-agent.init",
|
|
29
|
+
"title": "Workflow: Initialize Project"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"command": "workflow-agent.validate",
|
|
33
|
+
"title": "Workflow: Validate Current Branch"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"command": "workflow-agent.suggest",
|
|
37
|
+
"title": "Workflow: Submit Improvement Suggestion"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"command": "workflow-agent.doctor",
|
|
41
|
+
"title": "Workflow: Run Health Check"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"command": "workflow-agent.showConfig",
|
|
45
|
+
"title": "Workflow: Show Configuration"
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"configuration": {
|
|
49
|
+
"title": "Workflow Agent",
|
|
50
|
+
"properties": {
|
|
51
|
+
"workflow-agent.enabled": {
|
|
52
|
+
"type": "boolean",
|
|
53
|
+
"default": true,
|
|
54
|
+
"description": "Enable/disable Workflow Agent"
|
|
55
|
+
},
|
|
56
|
+
"workflow-agent.validateOnType": {
|
|
57
|
+
"type": "boolean",
|
|
58
|
+
"default": true,
|
|
59
|
+
"description": "Validate branch name and commit messages as you type"
|
|
60
|
+
},
|
|
61
|
+
"workflow-agent.showStatusBar": {
|
|
62
|
+
"type": "boolean",
|
|
63
|
+
"default": true,
|
|
64
|
+
"description": "Show workflow status in status bar"
|
|
65
|
+
},
|
|
66
|
+
"workflow-agent.autoSuggest": {
|
|
67
|
+
"type": "boolean",
|
|
68
|
+
"default": true,
|
|
69
|
+
"description": "Show IntelliSense suggestions for scopes"
|
|
70
|
+
},
|
|
71
|
+
"workflow-agent.strictMode": {
|
|
72
|
+
"type": "boolean",
|
|
73
|
+
"default": false,
|
|
74
|
+
"description": "Block commits that don't follow workflow patterns"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"keybindings": [
|
|
79
|
+
{
|
|
80
|
+
"command": "workflow-agent.validate",
|
|
81
|
+
"key": "ctrl+shift+w",
|
|
82
|
+
"mac": "cmd+shift+w",
|
|
83
|
+
"when": "editorTextFocus"
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
"menus": {
|
|
87
|
+
"commandPalette": [
|
|
88
|
+
{
|
|
89
|
+
"command": "workflow-agent.init",
|
|
90
|
+
"when": "workspaceFolderCount > 0"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"command": "workflow-agent.validate",
|
|
94
|
+
"when": "workspaceFolderCount > 0"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"command": "workflow-agent.suggest",
|
|
98
|
+
"when": "workspaceFolderCount > 0"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"command": "workflow-agent.doctor",
|
|
102
|
+
"when": "workspaceFolderCount > 0"
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"dependencies": {
|
|
108
|
+
"@hawkinside_out/workflow-agent": "^1.0.0"
|
|
109
|
+
},
|
|
110
|
+
"devDependencies": {
|
|
111
|
+
"@types/node": "^20.11.5",
|
|
112
|
+
"@types/vscode": "^1.85.0",
|
|
113
|
+
"@vscode/vsce": "^2.22.0",
|
|
114
|
+
"tsup": "^8.0.1",
|
|
115
|
+
"typescript": "^5.3.3"
|
|
116
|
+
},
|
|
117
|
+
"repository": {
|
|
118
|
+
"type": "git",
|
|
119
|
+
"url": "https://github.com/hawkinsideOut/workflow-agent.git",
|
|
120
|
+
"directory": "packages/vscode-extension"
|
|
121
|
+
},
|
|
122
|
+
"license": "MIT",
|
|
123
|
+
"scripts": {
|
|
124
|
+
"vscode:prepublish": "pnpm build",
|
|
125
|
+
"compile": "tsup --watch",
|
|
126
|
+
"build": "tsup",
|
|
127
|
+
"package": "vsce package"
|
|
128
|
+
}
|
|
129
|
+
}
|
package/src/commands.ts
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import * as vscode from "vscode";
|
|
2
|
+
import { ConfigManager } from "./config";
|
|
3
|
+
import { StatusBarManager } from "./statusBar";
|
|
4
|
+
import { ValidationProvider } from "./validation";
|
|
5
|
+
|
|
6
|
+
export class CommandRegistry {
|
|
7
|
+
constructor(
|
|
8
|
+
private configManager: ConfigManager,
|
|
9
|
+
private statusBar: StatusBarManager,
|
|
10
|
+
private validation: ValidationProvider,
|
|
11
|
+
) {}
|
|
12
|
+
|
|
13
|
+
registerAll(context: vscode.ExtensionContext): void {
|
|
14
|
+
// Initialize command
|
|
15
|
+
context.subscriptions.push(
|
|
16
|
+
vscode.commands.registerCommand("workflow-agent.init", () =>
|
|
17
|
+
this.initCommand(),
|
|
18
|
+
),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
// Validate command
|
|
22
|
+
context.subscriptions.push(
|
|
23
|
+
vscode.commands.registerCommand("workflow-agent.validate", () =>
|
|
24
|
+
this.validateCommand(),
|
|
25
|
+
),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// Suggest command
|
|
29
|
+
context.subscriptions.push(
|
|
30
|
+
vscode.commands.registerCommand("workflow-agent.suggest", () =>
|
|
31
|
+
this.suggestCommand(),
|
|
32
|
+
),
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
// Doctor command
|
|
36
|
+
context.subscriptions.push(
|
|
37
|
+
vscode.commands.registerCommand("workflow-agent.doctor", () =>
|
|
38
|
+
this.doctorCommand(),
|
|
39
|
+
),
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// Show config command
|
|
43
|
+
context.subscriptions.push(
|
|
44
|
+
vscode.commands.registerCommand("workflow-agent.showConfig", () =>
|
|
45
|
+
this.showConfigCommand(),
|
|
46
|
+
),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private async initCommand(): Promise<void> {
|
|
51
|
+
const terminal = vscode.window.createTerminal("Workflow Agent");
|
|
52
|
+
terminal.show();
|
|
53
|
+
terminal.sendText("workflow init");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private async validateCommand(): Promise<void> {
|
|
57
|
+
const branch = this.configManager.getCurrentBranch();
|
|
58
|
+
|
|
59
|
+
if (!branch) {
|
|
60
|
+
vscode.window.showErrorMessage("Not in a git repository");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const result = this.validation.validateBranch(branch);
|
|
65
|
+
|
|
66
|
+
if (result.valid) {
|
|
67
|
+
vscode.window.showInformationMessage(`✓ Branch '${branch}' is valid`);
|
|
68
|
+
this.statusBar.updateStatus(true, "Branch is valid");
|
|
69
|
+
} else {
|
|
70
|
+
vscode.window.showErrorMessage(`✗ Invalid branch: ${result.message}`);
|
|
71
|
+
this.statusBar.updateStatus(false, result.message);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private async suggestCommand(): Promise<void> {
|
|
76
|
+
const feedback = await vscode.window.showInputBox({
|
|
77
|
+
prompt: "Enter your improvement suggestion",
|
|
78
|
+
placeHolder: "e.g., Add support for GitLab repositories",
|
|
79
|
+
validateInput: (value) => {
|
|
80
|
+
if (value.length < 10) {
|
|
81
|
+
return "Suggestion must be at least 10 characters";
|
|
82
|
+
}
|
|
83
|
+
if (value.length > 1000) {
|
|
84
|
+
return "Suggestion must be less than 1000 characters";
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (!feedback) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const category = await vscode.window.showQuickPick(
|
|
95
|
+
[
|
|
96
|
+
{ label: "✨ Feature Request", value: "feature" },
|
|
97
|
+
{ label: "🐛 Bug Report", value: "bug" },
|
|
98
|
+
{ label: "📚 Documentation", value: "documentation" },
|
|
99
|
+
{ label: "⚡ Performance", value: "performance" },
|
|
100
|
+
{ label: "💡 Other", value: "other" },
|
|
101
|
+
],
|
|
102
|
+
{
|
|
103
|
+
placeHolder: "Select suggestion category",
|
|
104
|
+
},
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
if (!category) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const terminal = vscode.window.createTerminal("Workflow Agent");
|
|
112
|
+
terminal.show();
|
|
113
|
+
terminal.sendText(
|
|
114
|
+
`workflow suggest "${feedback}" --category ${category.value}`,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private async doctorCommand(): Promise<void> {
|
|
119
|
+
const terminal = vscode.window.createTerminal("Workflow Agent");
|
|
120
|
+
terminal.show();
|
|
121
|
+
terminal.sendText("workflow doctor");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private async showConfigCommand(): Promise<void> {
|
|
125
|
+
if (!this.configManager.hasConfig()) {
|
|
126
|
+
const action = await vscode.window.showInformationMessage(
|
|
127
|
+
"Workflow Agent is not initialized in this workspace",
|
|
128
|
+
"Initialize Now",
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
if (action === "Initialize Now") {
|
|
132
|
+
this.initCommand();
|
|
133
|
+
}
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const projectName = this.configManager.getProjectName();
|
|
138
|
+
const scopes = this.configManager.getScopes();
|
|
139
|
+
const enforcement = this.configManager.getEnforcement();
|
|
140
|
+
const branch = this.configManager.getCurrentBranch();
|
|
141
|
+
|
|
142
|
+
const info = [
|
|
143
|
+
`**Project:** ${projectName || "Unknown"}`,
|
|
144
|
+
`**Branch:** ${branch || "Unknown"}`,
|
|
145
|
+
`**Enforcement:** ${enforcement}`,
|
|
146
|
+
`**Scopes (${scopes.length}):** ${scopes.join(", ") || "None"}`,
|
|
147
|
+
].join("\n\n");
|
|
148
|
+
|
|
149
|
+
const panel = vscode.window.createWebviewPanel(
|
|
150
|
+
"workflowConfig",
|
|
151
|
+
"Workflow Configuration",
|
|
152
|
+
vscode.ViewColumn.One,
|
|
153
|
+
{},
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
panel.webview.html = `
|
|
157
|
+
<!DOCTYPE html>
|
|
158
|
+
<html>
|
|
159
|
+
<head>
|
|
160
|
+
<meta charset="UTF-8">
|
|
161
|
+
<style>
|
|
162
|
+
body {
|
|
163
|
+
padding: 20px;
|
|
164
|
+
font-family: var(--vscode-font-family);
|
|
165
|
+
color: var(--vscode-foreground);
|
|
166
|
+
}
|
|
167
|
+
h1 {
|
|
168
|
+
border-bottom: 1px solid var(--vscode-panel-border);
|
|
169
|
+
padding-bottom: 10px;
|
|
170
|
+
}
|
|
171
|
+
.info {
|
|
172
|
+
line-height: 1.8;
|
|
173
|
+
}
|
|
174
|
+
.scope-list {
|
|
175
|
+
margin-top: 10px;
|
|
176
|
+
display: flex;
|
|
177
|
+
flex-wrap: wrap;
|
|
178
|
+
gap: 8px;
|
|
179
|
+
}
|
|
180
|
+
.scope {
|
|
181
|
+
background: var(--vscode-badge-background);
|
|
182
|
+
color: var(--vscode-badge-foreground);
|
|
183
|
+
padding: 4px 12px;
|
|
184
|
+
border-radius: 12px;
|
|
185
|
+
font-size: 0.9em;
|
|
186
|
+
}
|
|
187
|
+
</style>
|
|
188
|
+
</head>
|
|
189
|
+
<body>
|
|
190
|
+
<h1>🚀 Workflow Agent Configuration</h1>
|
|
191
|
+
<div class="info">
|
|
192
|
+
<p><strong>Project:</strong> ${projectName || "Unknown"}</p>
|
|
193
|
+
<p><strong>Current Branch:</strong> ${branch || "Unknown"}</p>
|
|
194
|
+
<p><strong>Enforcement Mode:</strong> ${enforcement}</p>
|
|
195
|
+
<p><strong>Available Scopes:</strong></p>
|
|
196
|
+
<div class="scope-list">
|
|
197
|
+
${scopes.map((s) => `<span class="scope">${s}</span>`).join("")}
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
200
|
+
</body>
|
|
201
|
+
</html>
|
|
202
|
+
`;
|
|
203
|
+
}
|
|
204
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as vscode from "vscode";
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { existsSync } from "fs";
|
|
5
|
+
|
|
6
|
+
export class ConfigManager {
|
|
7
|
+
private workspaceConfig: any = null;
|
|
8
|
+
private workspaceRoot: string | undefined;
|
|
9
|
+
|
|
10
|
+
constructor() {
|
|
11
|
+
this.workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
|
|
12
|
+
this.reload();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
reload(): void {
|
|
16
|
+
if (!this.workspaceRoot) {
|
|
17
|
+
this.workspaceConfig = null;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const configPath = join(this.workspaceRoot, "workflow.config.json");
|
|
22
|
+
|
|
23
|
+
if (existsSync(configPath)) {
|
|
24
|
+
try {
|
|
25
|
+
delete require.cache[require.resolve(configPath)];
|
|
26
|
+
this.workspaceConfig = require(configPath);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error("Failed to load workflow config:", error);
|
|
29
|
+
this.workspaceConfig = null;
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
this.workspaceConfig = null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
hasConfig(): boolean {
|
|
37
|
+
return this.workspaceConfig !== null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
getScopes(): string[] {
|
|
41
|
+
if (!this.workspaceConfig?.scopes) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
return this.workspaceConfig.scopes.map((s: any) => s.name);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getProjectName(): string | undefined {
|
|
48
|
+
return this.workspaceConfig?.projectName;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
getEnforcement(): string {
|
|
52
|
+
return this.workspaceConfig?.enforcement || "advisory";
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
isEnabled(): boolean {
|
|
56
|
+
const config = vscode.workspace.getConfiguration("workflow-agent");
|
|
57
|
+
return config.get<boolean>("enabled", true);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
shouldValidateOnType(): boolean {
|
|
61
|
+
const config = vscode.workspace.getConfiguration("workflow-agent");
|
|
62
|
+
return config.get<boolean>("validateOnType", true);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
shouldShowStatusBar(): boolean {
|
|
66
|
+
const config = vscode.workspace.getConfiguration("workflow-agent");
|
|
67
|
+
return config.get<boolean>("showStatusBar", true);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
isStrictMode(): boolean {
|
|
71
|
+
const config = vscode.workspace.getConfiguration("workflow-agent");
|
|
72
|
+
return config.get<boolean>("strictMode", false);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
getCurrentBranch(): string | null {
|
|
76
|
+
if (!this.workspaceRoot) return null;
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const branch = execSync("git rev-parse --abbrev-ref HEAD", {
|
|
80
|
+
cwd: this.workspaceRoot,
|
|
81
|
+
encoding: "utf-8",
|
|
82
|
+
}).trim();
|
|
83
|
+
return branch;
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
package/src/extension.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as vscode from "vscode";
|
|
2
|
+
import { StatusBarManager } from "./statusBar";
|
|
3
|
+
import { ValidationProvider } from "./validation";
|
|
4
|
+
import { ConfigManager } from "./config";
|
|
5
|
+
import { CommandRegistry } from "./commands";
|
|
6
|
+
|
|
7
|
+
export function activate(context: vscode.ExtensionContext) {
|
|
8
|
+
console.log("Workflow Agent extension activating...");
|
|
9
|
+
|
|
10
|
+
// Initialize managers
|
|
11
|
+
const configManager = new ConfigManager();
|
|
12
|
+
const statusBar = new StatusBarManager();
|
|
13
|
+
const validationProvider = new ValidationProvider(configManager);
|
|
14
|
+
const commands = new CommandRegistry(
|
|
15
|
+
configManager,
|
|
16
|
+
statusBar,
|
|
17
|
+
validationProvider,
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
// Register commands
|
|
21
|
+
commands.registerAll(context);
|
|
22
|
+
|
|
23
|
+
// Set up status bar
|
|
24
|
+
statusBar.show();
|
|
25
|
+
context.subscriptions.push(statusBar);
|
|
26
|
+
|
|
27
|
+
// Set up validation
|
|
28
|
+
validationProvider.activate(context);
|
|
29
|
+
|
|
30
|
+
// Watch for configuration changes
|
|
31
|
+
context.subscriptions.push(
|
|
32
|
+
vscode.workspace.onDidChangeConfiguration((e) => {
|
|
33
|
+
if (e.affectsConfiguration("workflow-agent")) {
|
|
34
|
+
configManager.reload();
|
|
35
|
+
statusBar.update();
|
|
36
|
+
}
|
|
37
|
+
}),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Watch for git changes
|
|
41
|
+
context.subscriptions.push(
|
|
42
|
+
vscode.workspace.onDidChangeTextDocument((e) => {
|
|
43
|
+
if (e.document.fileName.includes(".git/COMMIT_EDITMSG")) {
|
|
44
|
+
validationProvider.validateCommitMessage(e.document);
|
|
45
|
+
}
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
console.log("Workflow Agent extension activated!");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function deactivate() {
|
|
53
|
+
console.log("Workflow Agent extension deactivating...");
|
|
54
|
+
}
|
package/src/statusBar.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as vscode from "vscode";
|
|
2
|
+
import { ConfigManager } from "./config";
|
|
3
|
+
|
|
4
|
+
export class StatusBarManager implements vscode.Disposable {
|
|
5
|
+
private statusBarItem: vscode.StatusBarItem;
|
|
6
|
+
|
|
7
|
+
constructor() {
|
|
8
|
+
this.statusBarItem = vscode.window.createStatusBarItem(
|
|
9
|
+
vscode.StatusBarAlignment.Left,
|
|
10
|
+
100,
|
|
11
|
+
);
|
|
12
|
+
this.statusBarItem.command = "workflow-agent.showConfig";
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
show(): void {
|
|
16
|
+
this.statusBarItem.show();
|
|
17
|
+
this.update();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
hide(): void {
|
|
21
|
+
this.statusBarItem.hide();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
update(config?: ConfigManager): void {
|
|
25
|
+
if (!config) {
|
|
26
|
+
this.statusBarItem.text = "$(workflow) Workflow";
|
|
27
|
+
this.statusBarItem.tooltip = "Workflow Agent - Not configured";
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const branch = config.getCurrentBranch();
|
|
32
|
+
const hasConfig = config.hasConfig();
|
|
33
|
+
|
|
34
|
+
if (!hasConfig) {
|
|
35
|
+
this.statusBarItem.text = "$(workflow) Workflow: Not initialized";
|
|
36
|
+
this.statusBarItem.tooltip = "Click to initialize Workflow Agent";
|
|
37
|
+
this.statusBarItem.command = "workflow-agent.init";
|
|
38
|
+
this.statusBarItem.backgroundColor = new vscode.ThemeColor(
|
|
39
|
+
"statusBarItem.warningBackground",
|
|
40
|
+
);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const enforcement = config.getEnforcement();
|
|
45
|
+
const icon = enforcement === "strict" ? "$(shield)" : "$(check)";
|
|
46
|
+
|
|
47
|
+
this.statusBarItem.text = `${icon} Workflow: ${branch || "Unknown"}`;
|
|
48
|
+
this.statusBarItem.tooltip = `Workflow Agent\nBranch: ${branch}\nEnforcement: ${enforcement}\nClick for details`;
|
|
49
|
+
this.statusBarItem.backgroundColor = undefined;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
updateStatus(valid: boolean, message?: string): void {
|
|
53
|
+
if (valid) {
|
|
54
|
+
this.statusBarItem.backgroundColor = undefined;
|
|
55
|
+
if (message) {
|
|
56
|
+
this.statusBarItem.tooltip = message;
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
this.statusBarItem.backgroundColor = new vscode.ThemeColor(
|
|
60
|
+
"statusBarItem.errorBackground",
|
|
61
|
+
);
|
|
62
|
+
if (message) {
|
|
63
|
+
this.statusBarItem.tooltip = `⚠ ${message}`;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
dispose(): void {
|
|
69
|
+
this.statusBarItem.dispose();
|
|
70
|
+
}
|
|
71
|
+
}
|