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.
- package/.github/workflows/api-governance.yml +43 -0
- package/README.md +70 -113
- package/adapters/codex-skill.js +87 -0
- package/adapters/cursor-extension.js +190 -0
- package/adapters/gemini-action.js +93 -0
- package/adapters/openai-function.js +112 -0
- package/adapters/xai-plugin.js +151 -0
- package/bin/delimit-cli.js +921 -0
- package/bin/delimit.js +237 -1
- package/delimit.yml +19 -0
- package/hooks/evidence-status.sh +12 -0
- package/hooks/git/commit-msg +4 -0
- package/hooks/git/pre-commit +4 -0
- package/hooks/git/pre-push +4 -0
- package/hooks/install-hooks.sh +583 -0
- package/hooks/message-auth-hook.js +9 -0
- package/hooks/message-governance-hook.js +9 -0
- package/hooks/models/claude-post.js +4 -0
- package/hooks/models/claude-pre.js +4 -0
- package/hooks/models/codex-post.js +4 -0
- package/hooks/models/codex-pre.js +4 -0
- package/hooks/models/cursor-post.js +4 -0
- package/hooks/models/cursor-pre.js +4 -0
- package/hooks/models/gemini-post.js +4 -0
- package/hooks/models/gemini-pre.js +4 -0
- package/hooks/models/openai-post.js +4 -0
- package/hooks/models/openai-pre.js +4 -0
- package/hooks/models/windsurf-post.js +4 -0
- package/hooks/models/windsurf-pre.js +4 -0
- package/hooks/models/xai-post.js +4 -0
- package/hooks/models/xai-pre.js +4 -0
- package/hooks/post-bash-hook.js +13 -0
- package/hooks/post-mcp-hook.js +13 -0
- package/hooks/post-response-hook.js +4 -0
- package/hooks/post-tool-hook.js +126 -0
- package/hooks/post-write-hook.js +13 -0
- package/hooks/pre-bash-hook.js +30 -0
- package/hooks/pre-mcp-hook.js +13 -0
- package/hooks/pre-read-hook.js +13 -0
- package/hooks/pre-search-hook.js +13 -0
- package/hooks/pre-submit-hook.js +4 -0
- package/hooks/pre-task-hook.js +13 -0
- package/hooks/pre-tool-hook.js +121 -0
- package/hooks/pre-web-hook.js +13 -0
- package/hooks/pre-write-hook.js +31 -0
- package/hooks/test-hooks.sh +12 -0
- package/hooks/update-delimit.sh +6 -0
- package/lib/agent.js +509 -0
- package/lib/api-engine.js +156 -0
- package/lib/auth-setup.js +891 -0
- package/lib/decision-engine.js +474 -0
- package/lib/hooks-installer.js +416 -0
- package/lib/platform-adapters.js +353 -0
- package/lib/proxy-handler.js +114 -0
- package/package.json +38 -30
- package/scripts/infect.js +128 -0
- package/test-decision-engine.js +181 -0
- package/test-hook.js +27 -0
- package/dist/commands/validate.d.ts +0 -2
- package/dist/commands/validate.d.ts.map +0 -1
- package/dist/commands/validate.js +0 -106
- package/dist/commands/validate.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -71
- package/dist/index.js.map +0 -1
- package/dist/types/index.d.ts +0 -39
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -3
- package/dist/types/index.js.map +0 -1
- package/dist/utils/api.d.ts +0 -3
- package/dist/utils/api.d.ts.map +0 -1
- package/dist/utils/api.js +0 -64
- package/dist/utils/api.js.map +0 -1
- package/dist/utils/file.d.ts +0 -7
- package/dist/utils/file.d.ts.map +0 -1
- package/dist/utils/file.js +0 -69
- package/dist/utils/file.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -14
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -28
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/masker.d.ts +0 -14
- package/dist/utils/masker.d.ts.map +0 -1
- package/dist/utils/masker.js +0 -89
- package/dist/utils/masker.js.map +0 -1
- package/src/commands/validate.ts +0 -150
- package/src/index.ts +0 -80
- package/src/types/index.ts +0 -41
- package/src/utils/api.ts +0 -68
- package/src/utils/file.ts +0 -71
- package/src/utils/logger.ts +0 -27
- package/src/utils/masker.ts +0 -101
- package/test-sensitive.yaml +0 -109
- 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
|
-
|
|
3
|
+
**ESLint for API contracts** — detect breaking changes, enforce semver, and generate migration guides for OpenAPI specs.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/delimit-cli)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
7
|
|
|
7
|
-
|
|
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
|
-
|
|
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
|
-
|
|
32
|
-
|
|
19
|
+
# Initialize a policy file in your repo
|
|
20
|
+
delimit init
|
|
33
21
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
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
|
-
|
|
41
|
+
### Options
|
|
44
42
|
|
|
45
43
|
```bash
|
|
46
|
-
|
|
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
|
-
|
|
50
|
-
|
|
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
|
-
|
|
54
|
-
|
|
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
|
-
###
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
70
|
+
For automated PR checks, use the GitHub Action:
|
|
94
71
|
|
|
95
72
|
```yaml
|
|
96
|
-
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
|
|
83
|
+
Create `.delimit/policies.yml`:
|
|
118
84
|
|
|
119
85
|
```yaml
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
##
|
|
128
|
-
|
|
129
|
-
- `0` - Validation passed
|
|
130
|
-
- `1` - Validation failed or error occurred
|
|
100
|
+
## Supported Specs
|
|
131
101
|
|
|
132
|
-
|
|
102
|
+
- OpenAPI 3.0.x and 3.1.x
|
|
103
|
+
- Swagger 2.0
|
|
104
|
+
- YAML and JSON formats
|
|
133
105
|
|
|
134
|
-
|
|
135
|
-
- `DELIMIT_API_URL` - Override API URL (optional, for testing)
|
|
106
|
+
## Links
|
|
136
107
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
-
|
|
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
|
|
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
|
+
}
|