@aakrit512/gatekeep 1.0.0 → 1.0.2
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/README.md +56 -56
- package/dist/functions/toolExecutor.js +11 -7
- package/dist/ui/server.js +2 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,46 +1,70 @@
|
|
|
1
1
|
# Gatekeep
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Gatekeep is a local web app for reviewing codebases with an OpenAI-compatible model.
|
|
4
|
+
It runs on your machine, keeps project/chat history locally, and helps you initialize and inspect repositories safely.
|
|
4
5
|
|
|
5
|
-
## What
|
|
6
|
+
## What You Get
|
|
6
7
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
- Supports OpenAI-compatible providers through `AI_API_KEY`, `AI_BASE_URL`, and `MODEL_NAME`.
|
|
8
|
+
- Local browser UI for project setup and chat-based review.
|
|
9
|
+
- One-click project initialization that creates `docs/intro.md` in the selected repo.
|
|
10
|
+
- Built-in Doctor checks for Node runtime, API config, and project path readiness.
|
|
11
|
+
- Local storage for project history, tool traces, token usage, and estimated cost.
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- Node.js `20+`
|
|
16
|
+
- An OpenAI-compatible API key
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
Install from npm (recommended):
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
npm install --global @aakrit512/gatekeep
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Or run from source:
|
|
14
27
|
|
|
15
28
|
```sh
|
|
16
29
|
pnpm install
|
|
17
30
|
pnpm run build
|
|
18
31
|
pnpm link --global
|
|
19
|
-
gatekeep start --project /path/to/repo
|
|
20
32
|
```
|
|
21
33
|
|
|
22
|
-
|
|
34
|
+
## Start Gatekeep
|
|
23
35
|
|
|
24
|
-
```
|
|
25
|
-
|
|
36
|
+
```sh
|
|
37
|
+
gatekeep start --project /path/to/repo
|
|
26
38
|
```
|
|
27
39
|
|
|
28
|
-
|
|
40
|
+
Defaults:
|
|
41
|
+
|
|
42
|
+
- Host: `127.0.0.1`
|
|
43
|
+
- Port: `9808`
|
|
44
|
+
|
|
45
|
+
You can also run:
|
|
29
46
|
|
|
30
47
|
```sh
|
|
31
48
|
gatekeep start --project .
|
|
49
|
+
gatekeep start --port 9809 --host 0.0.0.0
|
|
32
50
|
```
|
|
33
51
|
|
|
34
|
-
|
|
52
|
+
Then open `http://127.0.0.1:9808`.
|
|
35
53
|
|
|
36
|
-
|
|
37
|
-
npm install --global @aakrit512/gatekeep
|
|
38
|
-
gatekeep start
|
|
39
|
-
```
|
|
54
|
+
## First-Run Setup (In the UI)
|
|
40
55
|
|
|
41
|
-
|
|
56
|
+
1. Choose a project directory.
|
|
57
|
+
2. Open **Config** and set:
|
|
58
|
+
- `AI_API_KEY`
|
|
59
|
+
- `AI_BASE_URL` (for example `https://api.openai.com/v1`)
|
|
60
|
+
- `MODEL_NAME` (for example `gpt-4o`)
|
|
61
|
+
3. Run **Doctor** and fix any reported issues.
|
|
62
|
+
4. Click **Initialize** to generate `docs/intro.md`.
|
|
63
|
+
5. Start chatting in the review panel.
|
|
42
64
|
|
|
43
|
-
|
|
65
|
+
## Environment Variables
|
|
66
|
+
|
|
67
|
+
You can set config through `.env` (or UI settings):
|
|
44
68
|
|
|
45
69
|
```sh
|
|
46
70
|
AI_API_KEY=your_api_key
|
|
@@ -48,44 +72,20 @@ AI_BASE_URL=https://api.openai.com/v1
|
|
|
48
72
|
MODEL_NAME=gpt-4o
|
|
49
73
|
```
|
|
50
74
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
## Folder Structure
|
|
54
|
-
|
|
55
|
-
```txt
|
|
56
|
-
.
|
|
57
|
-
├── src/
|
|
58
|
-
│ ├── ai/ OpenAI client setup, chat completion calls, context trimming, summarization helpers.
|
|
59
|
-
│ ├── cli/ User config storage and validation/doctor checks.
|
|
60
|
-
│ ├── functions/ Tool definitions and local tool execution used by the agent.
|
|
61
|
-
│ ├── prompts/ System and initialization prompts that guide repository review behavior.
|
|
62
|
-
│ ├── ui/ Local HTTP server, project database layer, and browser-agent workflow.
|
|
63
|
-
│ ├── cli.ts CLI entry point that starts the web UI.
|
|
64
|
-
│ └── config.ts Shared runtime configuration defaults and helpers.
|
|
65
|
-
├── ui/
|
|
66
|
-
│ └── app.html Browser UI document, styles, and client-side JavaScript.
|
|
67
|
-
├── package.json Package metadata, scripts, dependencies, and publish file list.
|
|
68
|
-
├── tsconfig.json TypeScript settings for development type checks.
|
|
69
|
-
├── tsconfig.build.json
|
|
70
|
-
│ TypeScript build settings for emitted `dist/` output.
|
|
71
|
-
├── pnpm-lock.yaml Locked dependency graph.
|
|
72
|
-
└── pnpm-workspace.yaml
|
|
73
|
-
pnpm workspace declaration.
|
|
74
|
-
```
|
|
75
|
+
## Local Data and Privacy
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
Gatekeep stores data under your OS config/app-support directory:
|
|
77
78
|
|
|
78
|
-
|
|
79
|
+
- `config.json` for provider/model/base URL/API key
|
|
80
|
+
- `projects.sqlite` for projects, chat history, activity traces, and usage
|
|
79
81
|
|
|
80
|
-
|
|
81
|
-
pnpm run start # Run the TypeScript CLI directly with tsx.
|
|
82
|
-
pnpm run build # Compile TypeScript into dist/.
|
|
83
|
-
pnpm pack # Build and create the installable npm tarball.
|
|
84
|
-
pnpm run typecheck # Type-check without emitting files.
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## Development Notes
|
|
82
|
+
Nothing is uploaded except model API requests sent to your configured provider.
|
|
88
83
|
|
|
89
|
-
|
|
84
|
+
## Common Commands
|
|
90
85
|
|
|
91
|
-
|
|
86
|
+
```sh
|
|
87
|
+
gatekeep --help
|
|
88
|
+
gatekeep start
|
|
89
|
+
gatekeep start --project .
|
|
90
|
+
pnpm run typecheck
|
|
91
|
+
```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { execFileSync
|
|
1
|
+
import { execFileSync } from 'child_process';
|
|
2
2
|
import { createHash } from 'crypto';
|
|
3
3
|
import * as fs from 'fs';
|
|
4
4
|
import * as path from 'path';
|
|
@@ -1016,18 +1016,22 @@ export function executeTool(name, args) {
|
|
|
1016
1016
|
return `Success: Wrote ${content.length} characters to ${filePath}`;
|
|
1017
1017
|
}
|
|
1018
1018
|
if (name === 'get_git_diff') {
|
|
1019
|
-
// Helper: run
|
|
1020
|
-
const tryGit = (
|
|
1019
|
+
// Helper: run git subcommands without shell evaluation and return stdout.
|
|
1020
|
+
const tryGit = (args) => {
|
|
1021
1021
|
try {
|
|
1022
|
-
return
|
|
1022
|
+
return execFileSync('git', args, {
|
|
1023
|
+
cwd: process.cwd(),
|
|
1024
|
+
encoding: 'utf-8',
|
|
1025
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1026
|
+
}).trim();
|
|
1023
1027
|
}
|
|
1024
1028
|
catch {
|
|
1025
1029
|
return '';
|
|
1026
1030
|
}
|
|
1027
1031
|
};
|
|
1028
|
-
const working = tryGit('
|
|
1029
|
-
const staged = tryGit('
|
|
1030
|
-
const log = tryGit('
|
|
1032
|
+
const working = tryGit(['diff']);
|
|
1033
|
+
const staged = tryGit(['diff', '--cached']);
|
|
1034
|
+
const log = tryGit(['log', '--oneline', '--stat', '-10']);
|
|
1031
1035
|
const sections = [
|
|
1032
1036
|
`## Uncommitted changes (working tree)\n${working || 'None.'}`,
|
|
1033
1037
|
`## Staged changes (index)\n${staged || 'None.'}`,
|
package/dist/ui/server.js
CHANGED
|
@@ -112,34 +112,12 @@ function buildConfigFromBody(body) {
|
|
|
112
112
|
function uniqueStrings(values) {
|
|
113
113
|
return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
|
|
114
114
|
}
|
|
115
|
-
function modelListUrl(baseUrl) {
|
|
116
|
-
const normalized = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;
|
|
117
|
-
return new URL('models', normalized).toString();
|
|
118
|
-
}
|
|
119
115
|
async function listModels(config) {
|
|
120
116
|
const fallback = uniqueStrings([config.model, ...CURATED_OPENAI_MODELS]);
|
|
121
117
|
if (!config.apiKey.trim()) {
|
|
122
|
-
return { models: fallback, source: '
|
|
123
|
-
}
|
|
124
|
-
const response = await fetch(modelListUrl(config.baseUrl), {
|
|
125
|
-
headers: {
|
|
126
|
-
authorization: `Bearer ${config.apiKey}`,
|
|
127
|
-
},
|
|
128
|
-
});
|
|
129
|
-
if (!response.ok) {
|
|
130
|
-
return {
|
|
131
|
-
models: fallback,
|
|
132
|
-
source: 'fallback',
|
|
133
|
-
warning: `Could not load models (${response.status}).`,
|
|
134
|
-
};
|
|
118
|
+
return { models: fallback, source: 'static', warning: 'Add an API key to chat with the model you choose.' };
|
|
135
119
|
}
|
|
136
|
-
|
|
137
|
-
const available = new Set((body.data || []).map((model) => typeof model.id === 'string' ? model.id : '').filter(Boolean));
|
|
138
|
-
const models = uniqueStrings([
|
|
139
|
-
config.model,
|
|
140
|
-
...CURATED_OPENAI_MODELS.filter((model) => available.has(model)),
|
|
141
|
-
]);
|
|
142
|
-
return { models: models.length ? models : fallback, source: 'api' };
|
|
120
|
+
return { models: fallback, source: 'static' };
|
|
143
121
|
}
|
|
144
122
|
function pickDirectory() {
|
|
145
123
|
return new Promise((resolve, reject) => {
|