delimit-cli 1.0.0 → 2.1.1

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.
Files changed (95) hide show
  1. package/.github/workflows/api-governance.yml +43 -0
  2. package/README.md +70 -113
  3. package/adapters/codex-skill.js +87 -0
  4. package/adapters/cursor-extension.js +190 -0
  5. package/adapters/gemini-action.js +93 -0
  6. package/adapters/openai-function.js +112 -0
  7. package/adapters/xai-plugin.js +151 -0
  8. package/bin/delimit-cli.js +921 -0
  9. package/bin/delimit.js +237 -1
  10. package/delimit.yml +19 -0
  11. package/hooks/evidence-status.sh +12 -0
  12. package/hooks/git/commit-msg +4 -0
  13. package/hooks/git/pre-commit +4 -0
  14. package/hooks/git/pre-push +4 -0
  15. package/hooks/install-hooks.sh +583 -0
  16. package/hooks/message-auth-hook.js +9 -0
  17. package/hooks/message-governance-hook.js +9 -0
  18. package/hooks/models/claude-post.js +4 -0
  19. package/hooks/models/claude-pre.js +4 -0
  20. package/hooks/models/codex-post.js +4 -0
  21. package/hooks/models/codex-pre.js +4 -0
  22. package/hooks/models/cursor-post.js +4 -0
  23. package/hooks/models/cursor-pre.js +4 -0
  24. package/hooks/models/gemini-post.js +4 -0
  25. package/hooks/models/gemini-pre.js +4 -0
  26. package/hooks/models/openai-post.js +4 -0
  27. package/hooks/models/openai-pre.js +4 -0
  28. package/hooks/models/windsurf-post.js +4 -0
  29. package/hooks/models/windsurf-pre.js +4 -0
  30. package/hooks/models/xai-post.js +4 -0
  31. package/hooks/models/xai-pre.js +4 -0
  32. package/hooks/post-bash-hook.js +13 -0
  33. package/hooks/post-mcp-hook.js +13 -0
  34. package/hooks/post-response-hook.js +4 -0
  35. package/hooks/post-tool-hook.js +126 -0
  36. package/hooks/post-write-hook.js +13 -0
  37. package/hooks/pre-bash-hook.js +30 -0
  38. package/hooks/pre-mcp-hook.js +13 -0
  39. package/hooks/pre-read-hook.js +13 -0
  40. package/hooks/pre-search-hook.js +13 -0
  41. package/hooks/pre-submit-hook.js +4 -0
  42. package/hooks/pre-task-hook.js +13 -0
  43. package/hooks/pre-tool-hook.js +121 -0
  44. package/hooks/pre-web-hook.js +13 -0
  45. package/hooks/pre-write-hook.js +31 -0
  46. package/hooks/test-hooks.sh +12 -0
  47. package/hooks/update-delimit.sh +6 -0
  48. package/lib/agent.js +509 -0
  49. package/lib/api-engine.js +156 -0
  50. package/lib/auth-setup.js +891 -0
  51. package/lib/decision-engine.js +474 -0
  52. package/lib/hooks-installer.js +416 -0
  53. package/lib/platform-adapters.js +353 -0
  54. package/lib/proxy-handler.js +114 -0
  55. package/package.json +38 -30
  56. package/scripts/infect.js +128 -0
  57. package/test-decision-engine.js +181 -0
  58. package/test-hook.js +27 -0
  59. package/dist/commands/validate.d.ts +0 -2
  60. package/dist/commands/validate.d.ts.map +0 -1
  61. package/dist/commands/validate.js +0 -106
  62. package/dist/commands/validate.js.map +0 -1
  63. package/dist/index.d.ts +0 -3
  64. package/dist/index.d.ts.map +0 -1
  65. package/dist/index.js +0 -71
  66. package/dist/index.js.map +0 -1
  67. package/dist/types/index.d.ts +0 -39
  68. package/dist/types/index.d.ts.map +0 -1
  69. package/dist/types/index.js +0 -3
  70. package/dist/types/index.js.map +0 -1
  71. package/dist/utils/api.d.ts +0 -3
  72. package/dist/utils/api.d.ts.map +0 -1
  73. package/dist/utils/api.js +0 -64
  74. package/dist/utils/api.js.map +0 -1
  75. package/dist/utils/file.d.ts +0 -7
  76. package/dist/utils/file.d.ts.map +0 -1
  77. package/dist/utils/file.js +0 -69
  78. package/dist/utils/file.js.map +0 -1
  79. package/dist/utils/logger.d.ts +0 -14
  80. package/dist/utils/logger.d.ts.map +0 -1
  81. package/dist/utils/logger.js +0 -28
  82. package/dist/utils/logger.js.map +0 -1
  83. package/dist/utils/masker.d.ts +0 -14
  84. package/dist/utils/masker.d.ts.map +0 -1
  85. package/dist/utils/masker.js +0 -89
  86. package/dist/utils/masker.js.map +0 -1
  87. package/src/commands/validate.ts +0 -150
  88. package/src/index.ts +0 -80
  89. package/src/types/index.ts +0 -41
  90. package/src/utils/api.ts +0 -68
  91. package/src/utils/file.ts +0 -71
  92. package/src/utils/logger.ts +0 -27
  93. package/src/utils/masker.ts +0 -101
  94. package/test-sensitive.yaml +0 -109
  95. package/tsconfig.json +0 -23
@@ -0,0 +1,43 @@
1
+ name: API Governance
2
+
3
+ on:
4
+ pull_request:
5
+ paths:
6
+ - '**/*.yaml'
7
+ - '**/*.yml'
8
+ - '**/*.json'
9
+ - 'lib/**'
10
+
11
+ jobs:
12
+ api-check:
13
+ name: Delimit API Check
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ pull-requests: write
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - uses: actions/checkout@v4
21
+ with:
22
+ ref: ${{ github.event.pull_request.base.sha }}
23
+ path: base
24
+
25
+ - name: Check for spec changes
26
+ id: spec-check
27
+ run: |
28
+ # Find any OpenAPI/Swagger specs in the repo
29
+ SPECS=$(find . -path ./base -prune -o \( -name "openapi*.yaml" -o -name "openapi*.yml" -o -name "openapi*.json" -o -name "swagger*.yaml" -o -name "swagger*.json" \) -print | head -1)
30
+ if [ -n "$SPECS" ]; then
31
+ echo "spec_found=true" >> $GITHUB_OUTPUT
32
+ echo "spec_path=$SPECS" >> $GITHUB_OUTPUT
33
+ else
34
+ echo "spec_found=false" >> $GITHUB_OUTPUT
35
+ fi
36
+
37
+ - name: Run Delimit
38
+ if: steps.spec-check.outputs.spec_found == 'true'
39
+ uses: delimit-ai/delimit-action@v1
40
+ with:
41
+ old_spec: base/${{ steps.spec-check.outputs.spec_path }}
42
+ new_spec: ${{ steps.spec-check.outputs.spec_path }}
43
+ mode: advisory
package/README.md CHANGED
@@ -1,157 +1,114 @@
1
1
  # delimit-cli
2
2
 
3
- Official CLI tool for [Delimit API Governance Platform](https://delimit.ai) with built-in Privacy Shield™ technology.
3
+ **ESLint for API contracts** detect breaking changes, enforce semver, and generate migration guides for OpenAPI specs.
4
4
 
5
- ## Features
5
+ [![npm](https://img.shields.io/npm/v/delimit-cli)](https://www.npmjs.com/package/delimit-cli)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
7
 
7
- - 🛡️ **Privacy Shield™**: Automatically masks sensitive data before sending to API
8
- - ✅ **OpenAPI Validation**: Validate specs against governance rules
9
- - 🎨 **Beautiful Output**: Color-coded terminal output for easy reading
10
- - 🚀 **Fast & Lightweight**: Built with TypeScript for performance
11
- - 🔒 **Secure by Design**: Your sensitive API data never leaves your machine
12
-
13
- ## Installation
8
+ ## Install
14
9
 
15
10
  ```bash
16
11
  npm install -g delimit-cli
17
12
  ```
18
13
 
19
- Or with yarn:
20
-
21
- ```bash
22
- yarn global add delimit-cli
23
- ```
14
+ This installs the `delimit` command globally.
24
15
 
25
16
  ## Quick Start
26
17
 
27
- 1. Get your API key from [RapidAPI](https://rapidapi.com/delimit/api/openapi-diff-api)
28
-
29
- 2. Set your API key as an environment variable:
30
18
  ```bash
31
- export DELIMIT_API_KEY="your-api-key-here"
32
- ```
19
+ # Initialize a policy file in your repo
20
+ delimit init
33
21
 
34
- 3. Validate your OpenAPI specification:
35
- ```bash
36
- delimit validate api-spec.yaml
22
+ # Detect breaking changes between two specs
23
+ delimit lint api/openapi-old.yaml api/openapi-new.yaml
24
+
25
+ # See raw diff output
26
+ delimit diff api/openapi-old.yaml api/openapi-new.yaml
27
+
28
+ # Generate a human-readable explanation
29
+ delimit explain api/openapi-old.yaml api/openapi-new.yaml
37
30
  ```
38
31
 
39
32
  ## Commands
40
33
 
41
- ### `validate`
34
+ | Command | Description |
35
+ |---------|-------------|
36
+ | `delimit init` | Create `.delimit/policies.yml` with default rules |
37
+ | `delimit lint <old> <new>` | Diff + policy check with semver badge and violations |
38
+ | `delimit diff <old> <new>` | Raw diff with `[BREAKING]`/`[safe]` tags |
39
+ | `delimit explain <old> <new>` | Human-readable change explanation |
42
40
 
43
- Validate an OpenAPI specification against governance rules.
41
+ ### Options
44
42
 
45
43
  ```bash
46
- delimit validate <filepath>
47
- ```
44
+ # Specify explainer template (default: developer)
45
+ delimit explain old.yaml new.yaml -t migration
46
+ delimit explain old.yaml new.yaml -t pr_comment
47
+ delimit explain old.yaml new.yaml -t changelog
48
48
 
49
- **Options:**
50
- - `--verbose` - Show detailed validation output
51
- - `--output <format>` - Output format: `text` (default) or `json`
49
+ # Include semver classification
50
+ delimit lint old.yaml new.yaml --current-version 1.0.0
52
51
 
53
- **Example:**
54
- ```bash
55
- # Validate a YAML spec
56
- delimit validate openapi.yaml
57
-
58
- # Validate a JSON spec with verbose output
59
- delimit validate api.json --verbose
60
-
61
- # Get JSON output for CI/CD integration
62
- delimit validate spec.yaml --output json
52
+ # Use custom policy file
53
+ delimit lint old.yaml new.yaml -p .delimit/policies.yml
63
54
  ```
64
55
 
65
- ### Coming Soon
66
-
67
- - `diff` - Compare two API versions for breaking changes
68
- - `analyze` - Analyze API changes for risks and soft breaks
69
- - `recommend` - Get version recommendations based on changes
70
- - `gate` - CI/CD release gate checks
56
+ ### Explainer Templates
71
57
 
72
- ## Privacy Shield™
73
-
74
- The CLI includes built-in Privacy Shield technology that automatically removes sensitive information from your OpenAPI specifications before sending them for validation:
75
-
76
- **What gets masked:**
77
- - API descriptions and summaries
78
- - Example values and responses
79
- - Server URLs
80
- - Contact information
81
- - License and terms of service
82
-
83
- **What stays intact:**
84
- - API structure and schemas
85
- - Endpoints and methods
86
- - Parameters and types
87
- - Required fields and validations
88
-
89
- This ensures your proprietary business logic and sensitive documentation never leave your local environment.
58
+ | Template | Audience |
59
+ |----------|----------|
60
+ | `developer` | Technical details for engineers |
61
+ | `team_lead` | Summary for engineering managers |
62
+ | `product` | Non-technical overview for PMs |
63
+ | `migration` | Step-by-step migration guide |
64
+ | `changelog` | Ready-to-paste changelog entry |
65
+ | `pr_comment` | GitHub PR comment format |
66
+ | `slack` | Slack message format |
90
67
 
91
68
  ## CI/CD Integration
92
69
 
93
- ### GitHub Actions
70
+ For automated PR checks, use the GitHub Action:
94
71
 
95
72
  ```yaml
96
- - name: Validate API Spec
97
- run: |
98
- npm install -g delimit-cli
99
- export DELIMIT_API_KEY=${{ secrets.DELIMIT_API_KEY }}
100
- delimit validate openapi.yaml
73
+ - uses: delimit-ai/delimit-action@v1
74
+ with:
75
+ old_spec: base/api/openapi.yaml
76
+ new_spec: api/openapi.yaml
101
77
  ```
102
78
 
103
- ### Jenkins
104
-
105
- ```groovy
106
- stage('API Validation') {
107
- steps {
108
- sh '''
109
- npm install -g delimit-cli
110
- export DELIMIT_API_KEY=${DELIMIT_API_KEY}
111
- delimit validate openapi.yaml
112
- '''
113
- }
114
- }
115
- ```
79
+ See [Delimit API Governance](https://github.com/marketplace/actions/delimit-api-governance) on the GitHub Marketplace.
80
+
81
+ ## Custom Policies
116
82
 
117
- ### GitLab CI
83
+ Create `.delimit/policies.yml`:
118
84
 
119
85
  ```yaml
120
- validate-api:
121
- script:
122
- - npm install -g delimit-cli
123
- - export DELIMIT_API_KEY=$DELIMIT_API_KEY
124
- - delimit validate openapi.yaml
86
+ rules:
87
+ - id: no_endpoint_removal
88
+ change_types: [endpoint_removed]
89
+ severity: error
90
+ action: forbid
91
+ message: "Endpoints cannot be removed without deprecation"
92
+
93
+ - id: warn_type_change
94
+ change_types: [type_changed]
95
+ severity: warning
96
+ action: warn
97
+ message: "Type change may break clients"
125
98
  ```
126
99
 
127
- ## Exit Codes
128
-
129
- - `0` - Validation passed
130
- - `1` - Validation failed or error occurred
100
+ ## Supported Specs
131
101
 
132
- ## Environment Variables
102
+ - OpenAPI 3.0.x and 3.1.x
103
+ - Swagger 2.0
104
+ - YAML and JSON formats
133
105
 
134
- - `DELIMIT_API_KEY` - Your RapidAPI key (required)
135
- - `DELIMIT_API_URL` - Override API URL (optional, for testing)
106
+ ## Links
136
107
 
137
- ## Support
138
-
139
- - **Documentation**: https://api.delimit.ai/docs
140
- - **Issues**: https://github.com/delimit-ai/delimit-cli/issues
141
- - **Email**: support@delimit.ai
108
+ - [GitHub Action](https://github.com/marketplace/actions/delimit-api-governance) — CI/CD integration
109
+ - [GitHub](https://github.com/delimit-ai/delimit) — Source code
110
+ - [Issues](https://github.com/delimit-ai/delimit/issues) — Bug reports and feature requests
142
111
 
143
112
  ## License
144
113
 
145
- MIT © Delimit.ai
146
-
147
- ## Contributing
148
-
149
- We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
150
-
151
- ## Security
152
-
153
- Found a security issue? Please email security@delimit.ai directly.
154
-
155
- ---
156
-
157
- Built with ❤️ by the Delimit team
114
+ MIT
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Delimit™ Codex Skill Adapter
4
+ * Implements GitHub Codex "Skills" interface
5
+ */
6
+
7
+ const axios = require('axios');
8
+ const AGENT_URL = `http://127.0.0.1:${process.env.DELIMIT_AGENT_PORT || 7823}`;
9
+
10
+ class DelimitCodexSkill {
11
+ constructor() {
12
+ this.name = 'delimit-governance';
13
+ this.version = '2.0.0';
14
+ }
15
+
16
+ /**
17
+ * Codex Skills use onBeforeSuggestion and onAfterAccept events
18
+ */
19
+ async onBeforeSuggestion(context) {
20
+ console.log('[DELIMIT CODEX] Validating code suggestion...');
21
+
22
+ try {
23
+ const { code, language, file } = context;
24
+
25
+ // Check governance rules
26
+ const response = await axios.post(`${AGENT_URL}/evaluate`, {
27
+ action: 'codex_suggestion',
28
+ code: code,
29
+ language: language,
30
+ file: file,
31
+ tool: 'codex'
32
+ });
33
+
34
+ if (response.data.action === 'block') {
35
+ return {
36
+ allow: false,
37
+ message: `[DELIMIT] Code blocked: ${response.data.reason}`
38
+ };
39
+ }
40
+
41
+ if (response.data.action === 'prompt') {
42
+ return {
43
+ allow: true,
44
+ warning: response.data.message
45
+ };
46
+ }
47
+
48
+ return { allow: true };
49
+ } catch (error) {
50
+ console.warn('[DELIMIT CODEX] Governance check failed:', error.message);
51
+ return { allow: true }; // Fail open
52
+ }
53
+ }
54
+
55
+ async onAfterAccept(context) {
56
+ console.log('[DELIMIT CODEX] Recording accepted suggestion...');
57
+
58
+ try {
59
+ // Collect evidence
60
+ await axios.post(`${AGENT_URL}/audit`, {
61
+ action: 'codex_accept',
62
+ context: context,
63
+ timestamp: new Date().toISOString()
64
+ });
65
+ } catch (error) {
66
+ // Silent fail for audit
67
+ }
68
+ }
69
+
70
+ // Codex-specific command handler
71
+ async handleCommand(command, args) {
72
+ if (command === 'governance') {
73
+ const { execSync } = require('child_process');
74
+ return execSync('delimit status --verbose').toString();
75
+ }
76
+ }
77
+ }
78
+
79
+ // Export for Codex
80
+ if (typeof module !== 'undefined' && module.exports) {
81
+ module.exports = new DelimitCodexSkill();
82
+ }
83
+
84
+ // Codex registration
85
+ if (typeof registerSkill === 'function') {
86
+ registerSkill(new DelimitCodexSkill());
87
+ }
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Delimit™ Cursor Extension Adapter
4
+ * Implements VSCode-style extension for Cursor
5
+ */
6
+
7
+ const vscode = typeof acquireVsCodeApi !== 'undefined' ? acquireVsCodeApi() : null;
8
+ const axios = require('axios');
9
+ const AGENT_URL = `http://127.0.0.1:${process.env.DELIMIT_AGENT_PORT || 7823}`;
10
+
11
+ class DelimitCursorExtension {
12
+ constructor() {
13
+ this.extensionId = 'delimit.governance';
14
+ this.version = '2.0.0';
15
+ }
16
+
17
+ /**
18
+ * Extension activation
19
+ */
20
+ async activate(context) {
21
+ console.log('[DELIMIT CURSOR] Extension activated');
22
+
23
+ // Register commands
24
+ this.registerCommands(context);
25
+
26
+ // Register code action provider
27
+ this.registerCodeActions(context);
28
+
29
+ // Register diagnostics
30
+ this.registerDiagnostics(context);
31
+
32
+ return {
33
+ extendMarkdownIt: (md) => this.extendMarkdown(md)
34
+ };
35
+ }
36
+
37
+ registerCommands(context) {
38
+ const commands = {
39
+ 'delimit.checkGovernance': async () => {
40
+ const { execSync } = require('child_process');
41
+ const result = execSync('delimit status --verbose').toString();
42
+ this.showMessage(result);
43
+ },
44
+ 'delimit.switchMode': async () => {
45
+ const mode = await this.showQuickPick(['advisory', 'guarded', 'enforce']);
46
+ if (mode) {
47
+ const { execSync } = require('child_process');
48
+ execSync(`delimit mode ${mode}`);
49
+ this.showMessage(`Switched to ${mode} mode`);
50
+ }
51
+ },
52
+ 'delimit.viewAudit': async () => {
53
+ const { execSync } = require('child_process');
54
+ const audit = execSync('delimit audit --tail 20').toString();
55
+ this.showMessage(audit, 'Audit Log');
56
+ }
57
+ };
58
+
59
+ Object.entries(commands).forEach(([cmd, handler]) => {
60
+ if (vscode) {
61
+ context.subscriptions.push(
62
+ vscode.commands.registerCommand(cmd, handler)
63
+ );
64
+ }
65
+ });
66
+ }
67
+
68
+ registerCodeActions(context) {
69
+ // Register code action provider for all languages
70
+ const provider = {
71
+ provideCodeActions: async (document, range, context) => {
72
+ const actions = [];
73
+
74
+ // Check if there are any governance issues
75
+ const text = document.getText(range);
76
+ const issues = await this.checkGovernance(text, document.languageId);
77
+
78
+ if (issues.length > 0) {
79
+ actions.push({
80
+ title: '🛡️ Fix Governance Issues',
81
+ command: 'delimit.fixIssues',
82
+ arguments: [issues]
83
+ });
84
+ }
85
+
86
+ return actions;
87
+ }
88
+ };
89
+
90
+ if (vscode) {
91
+ context.subscriptions.push(
92
+ vscode.languages.registerCodeActionsProvider('*', provider)
93
+ );
94
+ }
95
+ }
96
+
97
+ registerDiagnostics(context) {
98
+ const diagnosticCollection = vscode ?
99
+ vscode.languages.createDiagnosticCollection('delimit') : null;
100
+
101
+ // Watch for document changes
102
+ if (vscode) {
103
+ vscode.workspace.onDidChangeTextDocument(async (event) => {
104
+ const document = event.document;
105
+ const diagnostics = [];
106
+
107
+ // Check governance
108
+ const text = document.getText();
109
+ const issues = await this.checkGovernance(text, document.languageId);
110
+
111
+ issues.forEach(issue => {
112
+ diagnostics.push({
113
+ range: new vscode.Range(
114
+ issue.line || 0,
115
+ issue.column || 0,
116
+ issue.line || 0,
117
+ issue.columnEnd || 100
118
+ ),
119
+ message: issue.message,
120
+ severity: issue.severity === 'error' ?
121
+ vscode.DiagnosticSeverity.Error :
122
+ vscode.DiagnosticSeverity.Warning
123
+ });
124
+ });
125
+
126
+ diagnosticCollection.set(document.uri, diagnostics);
127
+ });
128
+ }
129
+
130
+ context.subscriptions.push(diagnosticCollection);
131
+ }
132
+
133
+ async checkGovernance(code, language) {
134
+ try {
135
+ const response = await axios.post(`${AGENT_URL}/evaluate`, {
136
+ action: 'cursor_validation',
137
+ code: code,
138
+ language: language,
139
+ tool: 'cursor'
140
+ });
141
+
142
+ if (response.data.issues) {
143
+ return response.data.issues;
144
+ }
145
+
146
+ return [];
147
+ } catch (error) {
148
+ return [];
149
+ }
150
+ }
151
+
152
+ showMessage(message, title = 'Delimit') {
153
+ if (vscode) {
154
+ vscode.window.showInformationMessage(`${title}: ${message}`);
155
+ } else {
156
+ console.log(`[${title}] ${message}`);
157
+ }
158
+ }
159
+
160
+ async showQuickPick(items) {
161
+ if (vscode) {
162
+ return await vscode.window.showQuickPick(items);
163
+ }
164
+ return items[0];
165
+ }
166
+
167
+ extendMarkdown(md) {
168
+ // Add custom markdown rendering for governance info
169
+ return md.use((md) => {
170
+ md.renderer.rules.delimit_governance = (tokens, idx) => {
171
+ return `<div class="delimit-governance">${tokens[idx].content}</div>`;
172
+ };
173
+ });
174
+ }
175
+
176
+ deactivate() {
177
+ console.log('[DELIMIT CURSOR] Extension deactivated');
178
+ }
179
+ }
180
+
181
+ // Export for Cursor/VSCode
182
+ if (typeof module !== 'undefined' && module.exports) {
183
+ module.exports = new DelimitCursorExtension();
184
+ }
185
+
186
+ // VSCode activation
187
+ if (vscode) {
188
+ exports.activate = (context) => new DelimitCursorExtension().activate(context);
189
+ exports.deactivate = () => new DelimitCursorExtension().deactivate();
190
+ }
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Delimit™ Gemini Action Adapter
4
+ * Implements Google Gemini Extensions interface
5
+ */
6
+
7
+ const axios = require('axios');
8
+ const AGENT_URL = `http://127.0.0.1:${process.env.DELIMIT_AGENT_PORT || 7823}`;
9
+
10
+ class DelimitGeminiAction {
11
+ constructor() {
12
+ this.id = 'delimit-governance';
13
+ this.version = '2.0.0';
14
+ }
15
+
16
+ /**
17
+ * Gemini uses action handlers for extension points
18
+ */
19
+ async beforeCodeGeneration(request) {
20
+ console.log('[DELIMIT GEMINI] Pre-generation validation...');
21
+
22
+ try {
23
+ const { prompt, context, model } = request;
24
+
25
+ // Check if the request involves sensitive operations
26
+ const response = await axios.post(`${AGENT_URL}/evaluate`, {
27
+ action: 'gemini_generation',
28
+ prompt: prompt,
29
+ context: context,
30
+ model: model || 'gemini-pro',
31
+ tool: 'gemini'
32
+ });
33
+
34
+ if (response.data.action === 'block') {
35
+ throw new Error(`[DELIMIT] Generation blocked: ${response.data.reason}`);
36
+ }
37
+
38
+ if (response.data.action === 'prompt') {
39
+ console.warn(`[DELIMIT] Warning: ${response.data.message}`);
40
+ }
41
+
42
+ return request; // Pass through
43
+ } catch (error) {
44
+ if (error.message.includes('[DELIMIT]')) {
45
+ throw error; // Re-throw governance blocks
46
+ }
47
+ console.warn('[DELIMIT GEMINI] Governance check failed:', error.message);
48
+ return request; // Fail open
49
+ }
50
+ }
51
+
52
+ async afterResponse(response) {
53
+ console.log('[DELIMIT GEMINI] Processing response...');
54
+
55
+ try {
56
+ // Collect evidence
57
+ await axios.post(`${AGENT_URL}/audit`, {
58
+ action: 'gemini_response',
59
+ response: {
60
+ model: response.model,
61
+ tokens: response.usage,
62
+ timestamp: new Date().toISOString()
63
+ }
64
+ });
65
+ } catch (error) {
66
+ // Silent fail for audit
67
+ }
68
+
69
+ return response;
70
+ }
71
+
72
+ // Gemini command handler (uses @ prefix)
73
+ async handleCommand(command, args) {
74
+ const commands = {
75
+ '@governance': 'delimit status',
76
+ '@audit': 'delimit audit',
77
+ '@mode': 'delimit mode'
78
+ };
79
+
80
+ if (commands[command]) {
81
+ const { execSync } = require('child_process');
82
+ return execSync(commands[command]).toString();
83
+ }
84
+ }
85
+ }
86
+
87
+ // Export for Gemini
88
+ module.exports = new DelimitGeminiAction();
89
+
90
+ // Gemini registration (if available)
91
+ if (typeof registerExtension === 'function') {
92
+ registerExtension(new DelimitGeminiAction());
93
+ }