@aictrl/hush 0.1.0 → 0.1.6

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.
@@ -0,0 +1,46 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, master ]
6
+ pull_request:
7
+ branches: [ main, master ]
8
+
9
+ jobs:
10
+ test:
11
+ name: Build & Test
12
+ runs-on: ubuntu-latest
13
+
14
+ permissions:
15
+ pull-requests: write
16
+ contents: read
17
+
18
+ strategy:
19
+ matrix:
20
+ node-version: [20.x, 22.x]
21
+
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+
25
+ - name: Use Node.js ${{ matrix.node-version }}
26
+ uses: actions/setup-node@v4
27
+ with:
28
+ node-version: ${{ matrix.node-version }}
29
+ cache: 'npm'
30
+
31
+ - name: Install dependencies
32
+ run: npm ci
33
+
34
+ - name: Build
35
+ run: npm run build
36
+
37
+ - name: Run Tests with Coverage
38
+ run: npm test
39
+
40
+ # Optional: Post coverage report to PR
41
+ - name: Report Coverage
42
+ if: github.event_name == 'pull_request' && matrix.node-version == '22.x'
43
+ uses: davelosert/vitest-coverage-report-action@v2
44
+ with:
45
+ json-summary-path: ./coverage/coverage-summary.json
46
+ json-final-path: ./coverage/coverage-final.json
@@ -0,0 +1,126 @@
1
+ name: E2E - OpenCode + GLM-5 via Hush Gateway
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main, master]
6
+ workflow_dispatch:
7
+ inputs:
8
+ use_real_api:
9
+ description: 'Use real ZhipuAI API key (requires ZHIPUAI_API_KEY secret)'
10
+ type: boolean
11
+ default: false
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ concurrency:
17
+ group: e2e-opencode-${{ github.event.pull_request.number || github.ref }}
18
+ cancel-in-progress: true
19
+
20
+ jobs:
21
+ e2e-gateway-interception:
22
+ name: Gateway PII Interception (Mock Upstream)
23
+ runs-on: ubuntu-latest
24
+
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+
28
+ - name: Use Node.js 22.x
29
+ uses: actions/setup-node@v4
30
+ with:
31
+ node-version: 22.x
32
+ cache: 'npm'
33
+
34
+ - name: Install dependencies
35
+ run: npm ci
36
+
37
+ - name: Run E2E interception test
38
+ run: |
39
+ chmod +x scripts/e2e-opencode.sh
40
+ ./scripts/e2e-opencode.sh
41
+ env:
42
+ CI: true
43
+
44
+ e2e-opencode-live:
45
+ name: OpenCode + GLM-5 Live E2E
46
+ runs-on: ubuntu-latest
47
+ if: >
48
+ github.event_name == 'workflow_dispatch' &&
49
+ github.event.inputs.use_real_api == 'true'
50
+
51
+ steps:
52
+ - uses: actions/checkout@v4
53
+
54
+ - name: Use Node.js 22.x
55
+ uses: actions/setup-node@v4
56
+ with:
57
+ node-version: 22.x
58
+ cache: 'npm'
59
+
60
+ - name: Install dependencies & build
61
+ run: npm ci && npm run build
62
+
63
+ - name: Start Hush Gateway (background)
64
+ run: |
65
+ DEBUG=true node dist/cli.js > /tmp/gateway.log 2>&1 &
66
+ GATEWAY_PID=$!
67
+ echo "GATEWAY_PID=$GATEWAY_PID" >> $GITHUB_ENV
68
+
69
+ # Wait for gateway to be ready
70
+ for i in {1..15}; do
71
+ if curl -sf http://127.0.0.1:4000/health > /dev/null 2>&1; then
72
+ echo "Gateway is ready"
73
+ break
74
+ fi
75
+ echo "Waiting for gateway... ($i/15)"
76
+ sleep 1
77
+ done
78
+
79
+ - name: Check vault is empty before test
80
+ run: |
81
+ HEALTH_BEFORE=$(curl -sf http://127.0.0.1:4000/health)
82
+ echo "Health before: $HEALTH_BEFORE"
83
+ VAULT_BEFORE=$(echo "$HEALTH_BEFORE" | jq -r '.vaultSize // 0')
84
+ echo "Vault size before: $VAULT_BEFORE"
85
+
86
+ - name: Send PII-laden request through gateway to real GLM-5
87
+ env:
88
+ ZHIPU_API_KEY: ${{ secrets.ZHIPUAI_API_KEY }}
89
+ timeout-minutes: 2
90
+ run: |
91
+ # Send a real GLM-5 chat completion through the Hush gateway
92
+ # This proves PII interception works with the actual ZhipuAI API
93
+ HTTP_CODE=$(curl -s -o /tmp/response.json -w "%{http_code}" --max-time 60 \
94
+ -X POST "http://127.0.0.1:4000/api/paas/v4/chat/completions" \
95
+ -H "Content-Type: application/json" \
96
+ -H "Authorization: Bearer $ZHIPU_API_KEY" \
97
+ -d '{
98
+ "model": "glm-5",
99
+ "messages": [{"role": "user", "content": "Please confirm receipt. My email is testuser@example-corp.com and server IP is 10.42.99.7. Credentials: api_key=secret_test_a1b2c3d4e5f6g7h8i9j0"}]
100
+ }') || true
101
+ echo "HTTP Status: $HTTP_CODE"
102
+ echo "Response: $(cat /tmp/response.json | head -c 500)"
103
+ echo ""
104
+ echo "--- Gateway logs ---"
105
+ cat /tmp/gateway.log 2>/dev/null || true
106
+
107
+ - name: Verify PII was intercepted
108
+ run: |
109
+ HEALTH_AFTER=$(curl -sf http://127.0.0.1:4000/health)
110
+ echo "Health after: $HEALTH_AFTER"
111
+ VAULT_AFTER=$(echo "$HEALTH_AFTER" | jq -r '.vaultSize // 0')
112
+ echo "Vault size after: $VAULT_AFTER"
113
+
114
+ if [ "$VAULT_AFTER" -gt 0 ]; then
115
+ echo "SUCCESS: Gateway vault contains $VAULT_AFTER token(s) - PII was intercepted!"
116
+ else
117
+ echo "FAILURE: Gateway vault is empty - PII may not have been intercepted"
118
+ exit 1
119
+ fi
120
+
121
+ - name: Cleanup
122
+ if: always()
123
+ run: |
124
+ if [ -n "$GATEWAY_PID" ]; then
125
+ kill $GATEWAY_PID 2>/dev/null || true
126
+ fi
@@ -0,0 +1,101 @@
1
+ name: OpenCode Review
2
+ on:
3
+ pull_request:
4
+ branches: [main, master]
5
+ workflow_dispatch:
6
+
7
+ concurrency:
8
+ group: opencode-${{ github.event.pull_request.number || github.ref }}
9
+ cancel-in-progress: true
10
+
11
+ jobs:
12
+ opencode:
13
+ name: OpenCode AI Review
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ pull-requests: write
17
+ issues: write
18
+ contents: read
19
+ steps:
20
+ - name: Checkout repository
21
+ uses: actions/checkout@v4
22
+ with:
23
+ fetch-depth: 0
24
+
25
+ - name: Check for Relevant Changes
26
+ id: check_changes
27
+ env:
28
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29
+ run: |
30
+ SHA=${{ github.event.pull_request.head.sha || github.sha }}
31
+ PR_NUMBER=${{ github.event.pull_request.number }}
32
+
33
+ if [ -z "$PR_NUMBER" ]; then
34
+ echo "Not a pull request, proceeding."
35
+ echo "skip=false" >> $GITHUB_OUTPUT
36
+ exit 0
37
+ fi
38
+
39
+ # 1. Check if this SHA was already reviewed
40
+ echo "Checking if SHA $SHA was already reviewed..."
41
+ REVIEW_COMMENTS=$(gh pr view $PR_NUMBER --json comments --jq '.comments[].body' | grep -c "Reviewed SHA:" || true)
42
+ LAST_REVIEW_SHA=$(gh pr view $PR_NUMBER --json comments --jq '.comments[].body' | grep -o "Reviewed SHA: [a-f0-9]\{40\}" | tail -n 1 | cut -d' ' -f3)
43
+
44
+ if [ "$LAST_REVIEW_SHA" == "$SHA" ]; then
45
+ echo "This commit ($SHA) has already been reviewed. Skipping."
46
+ echo "skip=true" >> $GITHUB_OUTPUT
47
+ exit 0
48
+ fi
49
+
50
+ # 2. Skip if 2+ reviews already exist (unless manually triggered)
51
+ IS_MANUAL="${{ github.event_name == 'workflow_dispatch' }}"
52
+ if [ "$REVIEW_COMMENTS" -ge 2 ] && [ "$IS_MANUAL" != "true" ]; then
53
+ echo "PR already has $REVIEW_COMMENTS AI reviews. Skipping (use workflow_dispatch to force)."
54
+ echo "skip=true" >> $GITHUB_OUTPUT
55
+ exit 0
56
+ fi
57
+
58
+ # 3. Check if there are any "actual code" changes
59
+ echo "Checking changed files..."
60
+ # We check src/ and tests/ for relevant logic changes
61
+ CODE_CHANGES=$(git diff --name-only origin/${{ github.event.pull_request.base.ref }}...$SHA | grep -E '\.(ts|js|json|sh|yml|yaml)$' | grep -vE '^docs/|.*\.md$' || true)
62
+
63
+ if [ -z "$CODE_CHANGES" ]; then
64
+ echo "No actual code changes detected. Skipping review."
65
+ echo "skip=true" >> $GITHUB_OUTPUT
66
+ else
67
+ echo "Actual code changes detected:"
68
+ echo "$CODE_CHANGES"
69
+ echo "skip=false" >> $GITHUB_OUTPUT
70
+ fi
71
+
72
+ - name: Setup OpenCode
73
+ if: steps.check_changes.outputs.skip != 'true'
74
+ env:
75
+ ZHIPU_API_KEY: ${{ secrets.ZHIPUAI_API_KEY }}
76
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
77
+ run: |
78
+ # Use GITHUB_TOKEN to avoid rate limits when fetching version info
79
+ curl -fsSL https://opencode.ai/install | bash -s -- --no-modify-path
80
+ echo "$HOME/.opencode/bin" >> $GITHUB_PATH
81
+
82
+ - name: Direct OpenCode Review
83
+ if: steps.check_changes.outputs.skip != 'true'
84
+ env:
85
+ ZHIPU_API_KEY: ${{ secrets.ZHIPUAI_API_KEY }}
86
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
87
+ run: |
88
+ SHA=${{ github.event.pull_request.head.sha || github.sha }}
89
+ echo "Starting review with GLM-5 for SHA $SHA..."
90
+
91
+ $HOME/.opencode/bin/opencode run --model zai-coding-plan/glm-5 "Review the changes in this PR for the Hush Semantic Gateway.
92
+
93
+ Focus areas:
94
+ 1. **Redaction Logic**: Ensure PII patterns are robust and handle edge cases in tool outputs (like JSON or CLI tables).
95
+ 2. **Streaming Integrity**: Check that the SSE/streaming proxy logic doesn't buffer unnecessarily or break the rehydration flow.
96
+ 3. **Security**: Look for potential PII leaks or insecure token handling in the vault.
97
+ 4. **Reliability**: Ensure the proxy handles upstream errors gracefully.
98
+
99
+ Keep the summary concise but technical. Post findings as a markdown comment on the PR.
100
+
101
+ **CRITICAL**: Include the string 'Reviewed SHA: $SHA' at the very end of your comment so I can track which commits have been reviewed."
@@ -0,0 +1,44 @@
1
+ name: Publish to npm
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ contents: read
10
+ id-token: write
11
+
12
+ jobs:
13
+ publish:
14
+ name: Build, Test & Publish
15
+ runs-on: ubuntu-latest
16
+ environment: release
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - uses: actions/setup-node@v4
22
+ with:
23
+ node-version: 24
24
+ cache: 'npm'
25
+
26
+ - name: Install dependencies
27
+ run: npm ci
28
+
29
+ - name: Build
30
+ run: npm run build
31
+
32
+ - name: Run tests
33
+ run: npm test
34
+
35
+ - name: Verify version matches tag
36
+ run: |
37
+ PKG_VERSION="v$(node -p "require('./package.json').version")"
38
+ if [ "$PKG_VERSION" != "${{ github.ref_name }}" ]; then
39
+ echo "::error::Tag ${{ github.ref_name }} does not match package.json version $PKG_VERSION"
40
+ exit 1
41
+ fi
42
+
43
+ - name: Publish to npm
44
+ run: npm publish --provenance --access public
package/CLAUDE.md ADDED
@@ -0,0 +1,6 @@
1
+ # hush 🛡️ Mandates
2
+
3
+ ## Development Workflow
4
+ - **PR-Only Pushes:** All code changes, documentation updates, and asset additions MUST be submitted via a Pull Request. Direct pushes to the `master` branch are strictly prohibited.
5
+ - **Verification:** Every PR must pass all existing tests (`npm test`) and maintain or improve the current test coverage before merging.
6
+ - **Security First:** Never bypass security protocols (like `HUSH_AUTH_TOKEN` or local binding) during development or testing.
@@ -0,0 +1,29 @@
1
+ # Contributing to AICtrl Gateway
2
+
3
+ We're excited that you're interested in contributing to AICtrl Gateway! Here's a quick guide to help you get started.
4
+
5
+ ## How to Contribute
6
+
7
+ 1. **Fork the repository** on GitHub.
8
+ 2. **Clone your fork** locally: `git clone https://github.com/YOUR_USERNAME/gateway.git`
9
+ 3. **Create a new branch** for your feature or bug fix: `git checkout -b my-feature`
10
+ 4. **Make your changes** and ensure tests pass: `npm test`
11
+ 5. **Commit your changes** with a clear message.
12
+ 6. **Push to your branch**: `git push origin my-feature`
13
+ 7. **Open a Pull Request** against the `main` branch.
14
+
15
+ ## Development Setup
16
+
17
+ 1. Install dependencies: `npm install`
18
+ 2. Run tests: `npm test`
19
+ 3. Build the project: `npm run build`
20
+
21
+ ## Code Style
22
+
23
+ Please ensure your code follows the existing style and is well-documented with TSDoc comments.
24
+
25
+ ## Reporting Issues
26
+
27
+ If you find a bug or have a feature request, please [open an issue](https://github.com/aictrl/gateway/issues) on GitHub.
28
+
29
+ Thank you for your help!
package/Dockerfile ADDED
@@ -0,0 +1,25 @@
1
+ # hush 🛡️ - Docker Gateway
2
+ FROM node:18-slim
3
+
4
+ WORKDIR /app
5
+
6
+ # Install dependencies first for layer caching
7
+ COPY package*.json ./
8
+ RUN npm install
9
+
10
+ # Copy source
11
+ COPY . .
12
+
13
+ # Build TypeScript
14
+ RUN npm run build
15
+
16
+ # Default environment
17
+ ENV PORT=4000
18
+ ENV HUSH_HOST=0.0.0.0
19
+ # Note: Bind to 0.0.0.0 inside container so Docker can forward it,
20
+ # but host binding remains safe.
21
+
22
+ EXPOSE 4000
23
+
24
+ # Start the gateway
25
+ CMD ["node", "dist/cli.js"]
package/GEMINI.md ADDED
@@ -0,0 +1,6 @@
1
+ # Mandates
2
+
3
+ All foundational mandates for this project are maintained in [CLAUDE.md](./CLAUDE.md).
4
+
5
+ 1. All code changes MUST be submitted via Pull Request.
6
+ 2. NO direct pushes to `master`.
package/README.md CHANGED
@@ -3,110 +3,125 @@
3
3
  </p>
4
4
 
5
5
  **hush** is a Semantic Security Gateway for AI agents.
6
- It acts as a local proxy between your AI tools (like Claude Code, Cursor, or custom CLI agents) and LLM providers (Anthropic, OpenAI).
6
+ It sits between your AI tools (Claude Code, Codex, OpenCode, Gemini CLI) and LLM providers, ensuring that sensitive data — emails, IP addresses, API keys, credit cards — never leaves your machine.
7
7
 
8
- Hush ensures that sensitive data—like emails, IP addresses, and secrets—never leaves your machine by redacting it from prompts and tool outputs before they hit the cloud.
8
+ ## Quick Start
9
9
 
10
- ## Why Hush?
10
+ ```bash
11
+ npm install -g @aictrl/hush
12
+ hush
13
+ ```
11
14
 
12
- When an AI agent runs a local tool (like `snow` or `ls`), it often returns PII (Personally Identifiable Information) to the terminal. Without Hush, this sensitive data is sent directly to the LLM provider for processing.
15
+ Hush starts on `http://127.0.0.1:4000`. Now point your AI tool at it:
13
16
 
14
- Hush intercepts this traffic, replaces PII with persistent tokens, and stores the original values in a local `TokenVault`.
17
+ ### Claude Code
15
18
 
16
- ## Features
19
+ Add to `~/.claude/settings.json`:
17
20
 
18
- - **Semantic Redaction:** Automatically identifies and masks PII (emails, IPs, secrets, credit cards) using high-entropy random tokens (e.g., `[HUSH_EML_8a2b3c]`).
19
- - **Local Rehydration:** Automatically restores original values in the LLM's response locally. You see the real data; the cloud provider only sees tokens.
20
- - **Live Protection Dashboard:** Run with `--dashboard` to see a real-time TUI showing PII being blocked and intercepted.
21
- - **Zero-Trust Architecture:** Local-only processing. PII never leaves your machine. Bindings default to `127.0.0.1`.
22
- - **Streaming Support:** Robust rehydration for SSE (Server-Sent Events) even when tokens are split across network chunks.
21
+ ```json
22
+ {
23
+ "env": {
24
+ "ANTHROPIC_BASE_URL": "http://127.0.0.1:4000"
25
+ }
26
+ }
27
+ ```
23
28
 
24
- ## Getting Started
29
+ > **Note:** Claude Code subscription (OAuth) tokens are currently blocked by Anthropic for third-party proxies ([anthropics/claude-code#28091](https://github.com/anthropics/claude-code/issues/28091)). If you hit a 401, add `"ANTHROPIC_AUTH_TOKEN": "sk-ant-..."` to the env block above.
25
30
 
26
- ### Installation
31
+ ### Codex (OpenAI)
27
32
 
28
- ```bash
29
- npm install -g @aictrl/hush
33
+ Add to `~/.codex/config.toml` (or `.codex/config.toml` in your project):
34
+
35
+ ```toml
36
+ model_provider = "hush"
37
+
38
+ [model_providers.hush]
39
+ base_url = "http://127.0.0.1:4000/v1"
30
40
  ```
31
41
 
32
- ### Usage
42
+ ### OpenCode (ZhipuAI GLM-5)
33
43
 
34
- 1. **Start the hush Gateway:**
35
- ```bash
36
- hush --dashboard
37
- ```
38
- hush will start listening on `http://127.0.0.1:4000`.
44
+ Create `opencode.json` in your project root:
39
45
 
40
- 2. **Point your AI tool to the Gateway:**
46
+ ```json
47
+ {
48
+ "provider": {
49
+ "zai-coding-plan": {
50
+ "options": {
51
+ "baseURL": "http://127.0.0.1:4000/api/coding/paas/v4"
52
+ }
53
+ }
54
+ }
55
+ }
56
+ ```
41
57
 
42
- For **Claude Code**:
43
- ```bash
44
- export ANTHROPIC_BASE_URL=http://127.0.0.1:4000
45
- claude
46
- ```
58
+ ### Gemini CLI
47
59
 
48
- For **OpenAI-based tools**:
49
- ```bash
50
- export OPENAI_BASE_URL=http://127.0.0.1:4000/v1
51
- ```
60
+ Gemini CLI only supports env vars for endpoint override (no settings file option):
52
61
 
53
- For **Google Gemini**:
54
- ```bash
55
- # For the Google Generative AI SDK
56
- export GOOGLE_GENERATIVE_AI_BASE_URL=http://127.0.0.1:4000
62
+ ```bash
63
+ CODE_ASSIST_ENDPOINT=http://127.0.0.1:4000 gemini
64
+ ```
57
65
 
58
- # For the Gemini CLI
59
- export CODE_ASSIST_ENDPOINT=http://127.0.0.1:4000
60
- ```
66
+ ### Verify it works
61
67
 
62
- ## Configuration
68
+ When your AI tool sends a request containing PII, the hush terminal shows:
63
69
 
64
- | Variable | Description | Default |
65
- |----------|-------------|---------|
66
- | `PORT` | The port the gateway listens on. | `4000` |
67
- | `HUSH_HOST` | The host interface to bind to. | `127.0.0.1` |
68
- | `HUSH_AUTH_TOKEN` | If set, the proxy requires `Authorization: Bearer <token>` | `undefined` |
69
- | `HUSH_DASHBOARD` | Set to `true` to enable the TUI dashboard. | `false` |
70
+ ```
71
+ INFO: Redacted sensitive data from request path="/v1/messages" tokenCount=2 duration=1
72
+ ```
73
+
74
+ Your tool still sees the real data (rehydrated locally). The LLM provider only ever sees tokens like `[USER_EMAIL_f22c5a]`.
70
75
 
71
76
  ## How it Works
72
77
 
73
- 1. **Intercept:** Hush sits locally on your machine as an HTTP proxy.
74
- 2. **Redact:** Before a request is forwarded to Anthropic/OpenAI, Hush scans the message content for sensitive data and swaps it for tokens (e.g., `[USER_EMAIL_1]`).
75
- 3. **Vault:** The original data is saved in a local, in-memory `TokenVault`.
76
- 4. **Forward:** The redacted request is sent to the LLM provider.
77
- 5. **Rehydrate:** When the LLM responds, Hush re-inserts the original values from the vault before showing the response to you.
78
+ 1. **Intercept** Hush sits on your machine between your AI tool and the LLM provider.
79
+ 2. **Redact** Before forwarding, it scans for PII and swaps it for deterministic tokens (`bulat@aictrl.dev` `[USER_EMAIL_f22c5a]`).
80
+ 3. **Vault** Original values are saved in a local, in-memory TokenVault (auto-expires after 1 hour).
81
+ 4. **Forward** The redacted request goes to the provider. They never see your real data.
82
+ 5. **Rehydrate** Responses come back with tokens replaced by originals before reaching your tool.
78
83
 
79
- ## Development
84
+ ## Supported Tools
80
85
 
81
- ### Prerequisites
86
+ | Tool | Config | Route |
87
+ |------|--------|-------|
88
+ | Claude Code | `~/.claude/settings.json` | `/v1/messages` → Anthropic |
89
+ | Codex | `~/.codex/config.toml` | `/v1/chat/completions` → OpenAI |
90
+ | OpenCode | `opencode.json` | `/api/paas/v4/**` → ZhipuAI |
91
+ | Gemini CLI | `CODE_ASSIST_ENDPOINT` env var | `/v1beta/models/**` → Google |
92
+ | Any tool | Point base URL at hush | `/*` catch-all with auto-detect |
82
93
 
83
- - Node.js 18+
84
- - npm
94
+ Hush forwards your existing auth headers transparently — no API keys need to be reconfigured.
85
95
 
86
- ### Setup
96
+ ## Features
87
97
 
88
- ```bash
89
- git clone https://github.com/aictrl-dev/hush.git
90
- cd hush
91
- npm install
92
- ```
98
+ - **Semantic Redaction** — Identifies emails, IPs, secrets, credit cards, phone numbers. Deterministic hash-based tokens (same input → same token).
99
+ - **Local Rehydration** — Restores original values in responses locally. You see real data; the provider sees tokens.
100
+ - **Streaming Support** — SSE-aware rehydration handles tokens split across network chunks.
101
+ - **Live Dashboard** — `hush --dashboard` for a real-time TUI showing PII being blocked.
102
+ - **Zero-Trust** — PII never leaves your machine. Binds to `127.0.0.1` by default.
103
+ - **Universal Proxy** — One instance handles all providers simultaneously. Auto-detects from request path.
93
104
 
94
- ### Testing
105
+ ## Configuration
95
106
 
96
- ```bash
97
- npm test
98
- ```
107
+ | Variable | Description | Default |
108
+ |----------|-------------|---------|
109
+ | `PORT` | Gateway listen port | `4000` |
110
+ | `HUSH_HOST` | Bind address | `127.0.0.1` |
111
+ | `HUSH_AUTH_TOKEN` | Require auth on all requests to the gateway itself | — |
112
+ | `HUSH_DASHBOARD` | Enable TUI dashboard | `false` |
113
+ | `DEBUG` | Show vault size in `/health` | `false` |
99
114
 
100
- ### Building
115
+ ## Development
101
116
 
102
117
  ```bash
103
- npm run build
118
+ git clone https://github.com/aictrl-dev/hush.git
119
+ cd hush && npm install
120
+ npm run dev # dev mode with tsx
121
+ npm test # run tests
122
+ npm run build # production build
104
123
  ```
105
124
 
106
- ## Contributing
107
-
108
- We welcome contributions! Please see our [CONTRIBUTING.md](CONTRIBUTING.md) for details.
109
-
110
125
  ## License
111
126
 
112
- This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
127
+ Apache License 2.0 see [LICENSE](LICENSE).
package/dist/cli.js CHANGED
@@ -3,8 +3,17 @@ import { app } from './index.js';
3
3
  import { createLogger } from './lib/logger.js';
4
4
  const log = createLogger('hush-cli');
5
5
  const PORT = process.env.PORT || 4000;
6
- app.listen(PORT, () => {
6
+ const server = app.listen(PORT, () => {
7
7
  log.info(`Hush Semantic Gateway is listening on http://localhost:${PORT}`);
8
- log.info(`To use with Claude Code: export ANTHROPIC_BASE_URL=http://localhost:${PORT}`);
8
+ log.info(`Routes: /v1/messages Anthropic, /v1/chat/completions OpenAI, /api/paas/v4/** → ZhipuAI, * → Google`);
9
+ });
10
+ server.on('error', (err) => {
11
+ if (err.code === 'EADDRINUSE') {
12
+ log.error(`Port ${PORT} is already in use. Stop the other process or use PORT=<number> hush`);
13
+ }
14
+ else {
15
+ log.error({ err }, 'Failed to start server');
16
+ }
17
+ process.exit(1);
9
18
  });
10
19
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;AACrC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;AAEtC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACpB,GAAG,CAAC,IAAI,CAAC,0DAA0D,IAAI,EAAE,CAAC,CAAC;IAC3E,GAAG,CAAC,IAAI,CAAC,uEAAuE,IAAI,EAAE,CAAC,CAAC;AAC1F,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;AACrC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;AAEtC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACnC,GAAG,CAAC,IAAI,CAAC,0DAA0D,IAAI,EAAE,CAAC,CAAC;IAC3E,GAAG,CAAC,IAAI,CAAC,wGAAwG,CAAC,CAAC;AACrH,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;IAChD,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAC9B,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,sEAAsE,CAAC,CAAC;IAChG,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,wBAAwB,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}