@yiaany/ghostapi 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/CHANGELOG.md +29 -0
- package/CONTRIBUTING.md +117 -0
- package/LICENSE +21 -0
- package/README.md +354 -0
- package/SECURITY.md +37 -0
- package/dist/agents/agentPrompt.d.ts +5 -0
- package/dist/agents/agentPrompt.js +30 -0
- package/dist/agents/agentPrompt.js.map +1 -0
- package/dist/ai/aiClient.d.ts +7 -0
- package/dist/ai/aiClient.js +30 -0
- package/dist/ai/aiClient.js.map +1 -0
- package/dist/ai/aiGenerator.d.ts +10 -0
- package/dist/ai/aiGenerator.js +101 -0
- package/dist/ai/aiGenerator.js.map +1 -0
- package/dist/ai/genericInference.d.ts +5 -0
- package/dist/ai/genericInference.js +80 -0
- package/dist/ai/genericInference.js.map +1 -0
- package/dist/ai/index.d.ts +3 -0
- package/dist/ai/index.js +2 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/jsonRepair.d.ts +2 -0
- package/dist/ai/jsonRepair.js +31 -0
- package/dist/ai/jsonRepair.js.map +1 -0
- package/dist/ai/prompts.d.ts +4 -0
- package/dist/ai/prompts.js +81 -0
- package/dist/ai/prompts.js.map +1 -0
- package/dist/behavior/behaviorStore.d.ts +12 -0
- package/dist/behavior/behaviorStore.js +72 -0
- package/dist/behavior/behaviorStore.js.map +1 -0
- package/dist/cache/index.d.ts +9 -0
- package/dist/cache/index.js +34 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cli/errors.d.ts +4 -0
- package/dist/cli/errors.js +9 -0
- package/dist/cli/errors.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +277 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/parser.d.ts +56 -0
- package/dist/cli/parser.js +169 -0
- package/dist/cli/parser.js.map +1 -0
- package/dist/config/localConfig.d.ts +16 -0
- package/dist/config/localConfig.js +58 -0
- package/dist/config/localConfig.js.map +1 -0
- package/dist/config/serverConfig.d.ts +13 -0
- package/dist/config/serverConfig.js +44 -0
- package/dist/config/serverConfig.js.map +1 -0
- package/dist/dashboard/app.js +615 -0
- package/dist/dashboard/dashboard.d.ts +4 -0
- package/dist/dashboard/dashboard.js +20 -0
- package/dist/dashboard/dashboard.js.map +1 -0
- package/dist/dashboard/index.d.ts +1 -0
- package/dist/dashboard/index.html +298 -0
- package/dist/dashboard/index.js +2 -0
- package/dist/dashboard/index.js.map +1 -0
- package/dist/dashboard/styles.css +349 -0
- package/dist/errors/errorEngine.d.ts +3 -0
- package/dist/errors/errorEngine.js +65 -0
- package/dist/errors/errorEngine.js.map +1 -0
- package/dist/errors/index.d.ts +3 -0
- package/dist/errors/index.js +3 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/providerErrors.d.ts +3 -0
- package/dist/errors/providerErrors.js +6 -0
- package/dist/errors/providerErrors.js.map +1 -0
- package/dist/fault/faultLab.d.ts +27 -0
- package/dist/fault/faultLab.js +89 -0
- package/dist/fault/faultLab.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/landing/assets/index-BXR41fAD.css +1 -0
- package/dist/landing/assets/index-D8_ggMRE.js +55 -0
- package/dist/landing/index.html +15 -0
- package/dist/landing/landing.d.ts +3 -0
- package/dist/landing/landing.js +12 -0
- package/dist/landing/landing.js.map +1 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +52 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/providers/discord.d.ts +2 -0
- package/dist/providers/discord.js +11 -0
- package/dist/providers/discord.js.map +1 -0
- package/dist/providers/generic.d.ts +2 -0
- package/dist/providers/generic.js +13 -0
- package/dist/providers/generic.js.map +1 -0
- package/dist/providers/github.d.ts +2 -0
- package/dist/providers/github.js +11 -0
- package/dist/providers/github.js.map +1 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.js +2 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai.d.ts +2 -0
- package/dist/providers/openai.js +15 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/registry.d.ts +12 -0
- package/dist/providers/registry.js +23 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/resend.d.ts +2 -0
- package/dist/providers/resend.js +12 -0
- package/dist/providers/resend.js.map +1 -0
- package/dist/providers/stripe.d.ts +2 -0
- package/dist/providers/stripe.js +15 -0
- package/dist/providers/stripe.js.map +1 -0
- package/dist/providers/twilio.d.ts +2 -0
- package/dist/providers/twilio.js +14 -0
- package/dist/providers/twilio.js.map +1 -0
- package/dist/providers/types.d.ts +13 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/proxy/cacheKey.d.ts +2 -0
- package/dist/proxy/cacheKey.js +37 -0
- package/dist/proxy/cacheKey.js.map +1 -0
- package/dist/proxy/providerDetector.d.ts +11 -0
- package/dist/proxy/providerDetector.js +74 -0
- package/dist/proxy/providerDetector.js.map +1 -0
- package/dist/proxy/proxyHandler.d.ts +3 -0
- package/dist/proxy/proxyHandler.js +114 -0
- package/dist/proxy/proxyHandler.js.map +1 -0
- package/dist/proxy/requestNormalizer.d.ts +11 -0
- package/dist/proxy/requestNormalizer.js +30 -0
- package/dist/proxy/requestNormalizer.js.map +1 -0
- package/dist/report/safetyReport.d.ts +13 -0
- package/dist/report/safetyReport.js +65 -0
- package/dist/report/safetyReport.js.map +1 -0
- package/dist/rules/aiRules.d.ts +7 -0
- package/dist/rules/aiRules.js +31 -0
- package/dist/rules/aiRules.js.map +1 -0
- package/dist/scenarios/scenarioStore.d.ts +37 -0
- package/dist/scenarios/scenarioStore.js +201 -0
- package/dist/scenarios/scenarioStore.js.map +1 -0
- package/dist/security/headerSanitizer.d.ts +3 -0
- package/dist/security/headerSanitizer.js +12 -0
- package/dist/security/headerSanitizer.js.map +1 -0
- package/dist/security/maskSecrets.d.ts +1 -0
- package/dist/security/maskSecrets.js +2 -0
- package/dist/security/maskSecrets.js.map +1 -0
- package/dist/security/secrets.d.ts +4 -0
- package/dist/security/secrets.js +61 -0
- package/dist/security/secrets.js.map +1 -0
- package/dist/server/createServer.d.ts +8 -0
- package/dist/server/createServer.js +42 -0
- package/dist/server/createServer.js.map +1 -0
- package/dist/server/eventsStore.d.ts +17 -0
- package/dist/server/eventsStore.js +31 -0
- package/dist/server/eventsStore.js.map +1 -0
- package/dist/server/routes.d.ts +3 -0
- package/dist/server/routes.js +189 -0
- package/dist/server/routes.js.map +1 -0
- package/dist/server/sse.d.ts +5 -0
- package/dist/server/sse.js +32 -0
- package/dist/server/sse.js.map +1 -0
- package/dist/setup/sdkDetector.d.ts +9 -0
- package/dist/setup/sdkDetector.js +31 -0
- package/dist/setup/sdkDetector.js.map +1 -0
- package/dist/setup/setupGenerator.d.ts +28 -0
- package/dist/setup/setupGenerator.js +146 -0
- package/dist/setup/setupGenerator.js.map +1 -0
- package/dist/state/index.d.ts +1 -0
- package/dist/state/index.js +2 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/stateExtractor.d.ts +3 -0
- package/dist/state/stateExtractor.js +36 -0
- package/dist/state/stateExtractor.js.map +1 -0
- package/dist/state/stateResolver.d.ts +8 -0
- package/dist/state/stateResolver.js +95 -0
- package/dist/state/stateResolver.js.map +1 -0
- package/dist/state/stateStore.d.ts +4 -0
- package/dist/state/stateStore.js +72 -0
- package/dist/state/stateStore.js.map +1 -0
- package/dist/tests/testGenerator.d.ts +6 -0
- package/dist/tests/testGenerator.js +33 -0
- package/dist/tests/testGenerator.js.map +1 -0
- package/dist/utils/json.d.ts +2 -0
- package/dist/utils/json.js +10 -0
- package/dist/utils/json.js.map +1 -0
- package/docs/release-checklist.md +71 -0
- package/examples/agent-instructions/README.md +39 -0
- package/examples/generic-rest/README.md +27 -0
- package/examples/github-fetch/README.md +35 -0
- package/examples/resend-node/README.md +22 -0
- package/examples/stripe-node/README.md +29 -0
- package/examples/twilio-node/README.md +21 -0
- package/package.json +67 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to GhostAPI will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format follows the spirit of [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project uses semantic versioning once public releases begin.
|
|
6
|
+
|
|
7
|
+
## 0.1.0 - 2026-07-14
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Local Express proxy server on `127.0.0.1:8080` by default.
|
|
12
|
+
- CLI commands for `start`, `clear`, `model`, `providers`, `doctor`, and `init`.
|
|
13
|
+
- Native MVP provider adapters for Stripe, Twilio, Resend, GitHub, and Discord.
|
|
14
|
+
- Generic fallback coverage for other REST APIs with lightweight service inference.
|
|
15
|
+
- Request normalization and secret masking for headers, query, and JSON bodies.
|
|
16
|
+
- File-per-entry response cache under `.ghostapi/cache/{provider}/{hash}.json`.
|
|
17
|
+
- Local state store under `.ghostapi/state.json` with save/read/list/delete behavior.
|
|
18
|
+
- Provider-specific validation and error formatting for key MVP flows.
|
|
19
|
+
- LLM-backed JSON mock generation with offline fallback.
|
|
20
|
+
- Realtime dashboard at `/dashboard` with SSE events from `/events`.
|
|
21
|
+
- Persistent telemetry history at `.ghostapi/events.jsonl`.
|
|
22
|
+
- Examples for Stripe, Resend, Twilio, GitHub, generic REST, and AI agent instructions.
|
|
23
|
+
- Open-source project docs, security policy, issue templates, and PR template.
|
|
24
|
+
|
|
25
|
+
### Security
|
|
26
|
+
|
|
27
|
+
- No real external provider API calls by default.
|
|
28
|
+
- Secrets are masked before prompt construction, cache key generation, event logging, and dashboard rendering.
|
|
29
|
+
- `ghostapi doctor` warns about unsafe TLS bypass settings.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Contributing to GhostAPI
|
|
2
|
+
|
|
3
|
+
Thanks for helping improve GhostAPI. This project aims to be small, safe, local-first, and useful for developers and AI coding agents.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
Requirements:
|
|
8
|
+
|
|
9
|
+
- Node.js 20 or newer
|
|
10
|
+
- npm
|
|
11
|
+
|
|
12
|
+
Install dependencies:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Run the local development server:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm run dev
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Open:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
http://localhost:8080/dashboard
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Scripts
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm run typecheck
|
|
34
|
+
npm test
|
|
35
|
+
npm run build
|
|
36
|
+
npm run dev
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Use these before opening a pull request:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm run typecheck
|
|
43
|
+
npm test
|
|
44
|
+
npm run build
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Tests
|
|
48
|
+
|
|
49
|
+
Tests are written with Vitest and must stay local-only. Do not add tests that call real Stripe, Twilio, Resend, GitHub, OpenAI, or any other external API.
|
|
50
|
+
|
|
51
|
+
Current test areas include:
|
|
52
|
+
|
|
53
|
+
- Secret masking
|
|
54
|
+
- Provider detection
|
|
55
|
+
- Cache key stability
|
|
56
|
+
- State save/read/list/delete
|
|
57
|
+
- Provider error formatting
|
|
58
|
+
- Prompt construction and JSON repair
|
|
59
|
+
- Proxy flow integration
|
|
60
|
+
- Dashboard/SSE event formatting
|
|
61
|
+
|
|
62
|
+
Shared fixtures live in `test/fixtures/`.
|
|
63
|
+
|
|
64
|
+
## Coding Style
|
|
65
|
+
|
|
66
|
+
- TypeScript strict mode.
|
|
67
|
+
- ESM modules.
|
|
68
|
+
- Prefer functions and simple objects over classes.
|
|
69
|
+
- Keep modules small and direct.
|
|
70
|
+
- Avoid `any`; use `unknown` and narrow values where possible.
|
|
71
|
+
- Add comments only where behavior is not obvious.
|
|
72
|
+
- Keep user-facing errors actionable.
|
|
73
|
+
- Do not introduce network calls to real provider APIs by default.
|
|
74
|
+
|
|
75
|
+
## Adding A Provider
|
|
76
|
+
|
|
77
|
+
GhostAPI intentionally keeps native adapters limited. For the MVP, native adapters are:
|
|
78
|
+
|
|
79
|
+
- Stripe
|
|
80
|
+
- Twilio
|
|
81
|
+
- Resend
|
|
82
|
+
- GitHub
|
|
83
|
+
- Discord
|
|
84
|
+
- OpenAI
|
|
85
|
+
- Generic fallback
|
|
86
|
+
|
|
87
|
+
Before adding a new native adapter, ask whether generic fallback plus prompt hints is enough. Native adapters should be reserved for providers where contract-specific behavior, validation, or error formatting is clearly worth maintaining.
|
|
88
|
+
|
|
89
|
+
If a native adapter is justified:
|
|
90
|
+
|
|
91
|
+
1. Add the adapter under `src/providers/`.
|
|
92
|
+
2. Register it in `src/providers/registry.ts`.
|
|
93
|
+
3. Add detection rules in `src/proxy/providerDetector.ts`.
|
|
94
|
+
4. Add provider-specific prompt guidance in `src/ai/prompts.ts` only if useful.
|
|
95
|
+
5. Add tests for detection, formatting, validation, and proxy behavior.
|
|
96
|
+
6. Update README provider matrix.
|
|
97
|
+
|
|
98
|
+
## Adding Prompt Hints
|
|
99
|
+
|
|
100
|
+
Most services should use generic fallback. To improve generic behavior:
|
|
101
|
+
|
|
102
|
+
1. Add or refine lightweight inference in `src/ai/genericInference.ts`.
|
|
103
|
+
2. Keep labels best-effort, such as `generic:shopify-like`.
|
|
104
|
+
3. Do not add provider-specific validation or error formats for generic services.
|
|
105
|
+
4. Add tests in `test/genericInference.test.ts`.
|
|
106
|
+
5. Update README coverage if the change affects documented behavior.
|
|
107
|
+
|
|
108
|
+
## Pull Request Checklist
|
|
109
|
+
|
|
110
|
+
- The change is scoped and explained clearly.
|
|
111
|
+
- `npm run typecheck` passes.
|
|
112
|
+
- `npm test` passes.
|
|
113
|
+
- `npm run build` passes.
|
|
114
|
+
- New behavior has tests when practical.
|
|
115
|
+
- No real external API calls were added by default.
|
|
116
|
+
- Secrets are not logged, cached, sent to LLM prompts, or exposed in dashboard payloads.
|
|
117
|
+
- README or examples are updated when user-facing behavior changes.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GhostAPI contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
# GhostAPI
|
|
2
|
+
|
|
3
|
+
**The local internet for AI coding agents.**
|
|
4
|
+
|
|
5
|
+
GhostAPI runs on your machine and simulates third-party APIs like Stripe, Twilio, Resend, GitHub, Discord, OpenAI, and generic REST services. Point your app or coding agent at `localhost`, get realistic provider-shaped responses, inspect everything in a dashboard, replay scenarios, and never hit production by accident.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx ghostapi start --open
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
Your app or agent -> http://127.0.0.1:8080 -> GhostAPI -> local state, cache, scenarios, chaos, dashboard
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Why GhostAPI Exists
|
|
16
|
+
|
|
17
|
+
AI agents are becoming excellent at writing integration code. They also run that code.
|
|
18
|
+
|
|
19
|
+
That is dangerous when the code touches real providers:
|
|
20
|
+
|
|
21
|
+
- Stripe charges can become real money movement.
|
|
22
|
+
- Twilio calls can send real SMS messages.
|
|
23
|
+
- Resend calls can send real email.
|
|
24
|
+
- GitHub calls can mutate real repositories.
|
|
25
|
+
- OpenAI calls can spend real tokens and leak test data.
|
|
26
|
+
- Production API keys can end up in logs, prompts, screenshots, or cache files.
|
|
27
|
+
|
|
28
|
+
GhostAPI gives agents a safe world to develop in: local, observable, stateful, replayable, and controlled by MCP.
|
|
29
|
+
|
|
30
|
+
## What You Get
|
|
31
|
+
|
|
32
|
+
- **Local API proxy** on `127.0.0.1:8080`.
|
|
33
|
+
- **Provider-shaped mocks** for Stripe, Twilio, Resend, GitHub, Discord, OpenAI, and generic REST.
|
|
34
|
+
- **Live dashboard** at `/dashboard` with traffic, request/response inspection, setup generation, scenarios, and Chaos Mode.
|
|
35
|
+
- **MCP server** so Claude CLI, Claude Desktop, Cline, Aider, Codex, OpenCode CLI/Desktop, Gemini CLI, Goose, OpenClaw, Hermes Desktop, and other agents can inspect state and control API behavior.
|
|
36
|
+
- **Scenario presets** for repeatable flows like payment failures and issue creation.
|
|
37
|
+
- **Custom scenarios** saved from traffic or imported as JSON.
|
|
38
|
+
- **Generated tests** from captured request/response events.
|
|
39
|
+
- **Safety reports** that flag live provider hosts and live-looking keys.
|
|
40
|
+
- **Copy-ready agent prompts** for Cursor, Claude, Cline, Aider, Codex, OpenCode, Gemini CLI, Goose, OpenClaw, Hermes, and any MCP client.
|
|
41
|
+
- **Chaos Mode** for realistic `429`, `503`, and latency testing.
|
|
42
|
+
- **Secret masking** before logs, cache, dashboard, events, or prompts.
|
|
43
|
+
- **One-click repo setup** for agent rules and MCP config.
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
Install globally:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm install -g ghostapi
|
|
51
|
+
ghostapi start --open
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Or run without installing:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npx ghostapi start --open
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Open the dashboard manually:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
ghostapi open
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Health check:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
curl http://127.0.0.1:8080/health
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Send a local API request:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
curl -X POST http://127.0.0.1:8080/tasks \
|
|
76
|
+
-H "content-type: application/json" \
|
|
77
|
+
-d '{"title":"Write integration tests","status":"open"}'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Dashboard:
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
http://127.0.0.1:8080/dashboard
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Agent Setup In One Command
|
|
87
|
+
|
|
88
|
+
Generate copy-ready setup for the current repo:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
ghostapi setup
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Write setup files safely without overwriting existing files:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
ghostapi setup --write
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
This detects SDKs in `package.json` and generates:
|
|
101
|
+
|
|
102
|
+
- `.cursorrules`
|
|
103
|
+
- `AGENTS.md`
|
|
104
|
+
- `.cursor/mcp.json`
|
|
105
|
+
- `cline_mcp_settings.json`
|
|
106
|
+
- `claude_desktop_config.json`
|
|
107
|
+
- `.ghostapi/agent-configs/*` snippets for Claude CLI, Claude Desktop, Cline, Aider, Codex, OpenCode CLI, OpenCode Desktop, Gemini CLI, Goose, OpenClaw, Hermes Desktop, and universal MCP clients
|
|
108
|
+
- local env snippets
|
|
109
|
+
- SDK client patches for detected providers
|
|
110
|
+
|
|
111
|
+
The dashboard also includes **Agent Setup**, a copy-first onboarding modal for your agent stack.
|
|
112
|
+
|
|
113
|
+
## MCP Server
|
|
114
|
+
|
|
115
|
+
Start the MCP server:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
ghostapi mcp
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Use this universal stdio MCP block in any client that supports MCP:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"mcpServers": {
|
|
126
|
+
"ghostapi": {
|
|
127
|
+
"command": "ghostapi",
|
|
128
|
+
"args": ["mcp"]
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
GhostAPI generates ready-to-copy snippets for:
|
|
135
|
+
|
|
136
|
+
- Claude CLI
|
|
137
|
+
- Claude Desktop
|
|
138
|
+
- Cline
|
|
139
|
+
- Aider
|
|
140
|
+
- Codex
|
|
141
|
+
- OpenCode CLI
|
|
142
|
+
- OpenCode Desktop
|
|
143
|
+
- Gemini CLI
|
|
144
|
+
- Goose
|
|
145
|
+
- OpenClaw
|
|
146
|
+
- Hermes Desktop
|
|
147
|
+
- any generic stdio MCP client
|
|
148
|
+
|
|
149
|
+
Some clients use different config file locations or command names across versions. GhostAPI writes the canonical server block under `.ghostapi/agent-configs/` so you can paste the same `ghostapi mcp` server into the right place for your client.
|
|
150
|
+
|
|
151
|
+
If you are developing from source, use:
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"mcpServers": {
|
|
156
|
+
"ghostapi": {
|
|
157
|
+
"command": "node",
|
|
158
|
+
"args": ["dist/cli/index.js", "mcp"]
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Available tools:
|
|
165
|
+
|
|
166
|
+
| Tool | Purpose |
|
|
167
|
+
| --- | --- |
|
|
168
|
+
| `inspect_state` | Read local API objects from `.ghostapi/state.json`. |
|
|
169
|
+
| `set_api_behavior` | Force a deterministic response for `method + path`. |
|
|
170
|
+
| `get_traffic_logs` | Read recent local traffic events. |
|
|
171
|
+
| `toggle_chaos_mode` | Enable or disable local failure injection. |
|
|
172
|
+
|
|
173
|
+
This is the core product loop: the agent writes code, GhostAPI simulates the outside world, and MCP lets the agent inspect and control that world.
|
|
174
|
+
|
|
175
|
+
## Scenario Presets
|
|
176
|
+
|
|
177
|
+
GhostAPI ships with replayable API flows:
|
|
178
|
+
|
|
179
|
+
- Stripe customer create
|
|
180
|
+
- Stripe payment intent failure
|
|
181
|
+
- Resend email send
|
|
182
|
+
- GitHub issue create
|
|
183
|
+
|
|
184
|
+
From the dashboard, open **Scenarios** and choose:
|
|
185
|
+
|
|
186
|
+
- **Replay** to apply deterministic behavior overrides.
|
|
187
|
+
- **Export** to copy portable scenario JSON.
|
|
188
|
+
- **Share** to copy a compact `ghostapi://scenario/...` payload.
|
|
189
|
+
|
|
190
|
+
Scenario APIs:
|
|
191
|
+
|
|
192
|
+
```http
|
|
193
|
+
GET /api/scenarios
|
|
194
|
+
POST /api/scenarios
|
|
195
|
+
POST /api/scenarios/save-from-traffic
|
|
196
|
+
POST /api/scenarios/:id/replay
|
|
197
|
+
GET /api/scenarios/:id/export
|
|
198
|
+
POST /api/scenarios/:id/share
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Agent Prompts, Tests, And Safety Reports
|
|
202
|
+
|
|
203
|
+
The dashboard includes copy-first actions for agent workflows:
|
|
204
|
+
|
|
205
|
+
- **Copy Agent Prompt** gives any coding agent a clean GhostAPI operating prompt.
|
|
206
|
+
- **Generate Test** turns a selected traffic event into a Vitest API test.
|
|
207
|
+
- **Safety Report** scans the repo for live provider hosts and live-looking keys.
|
|
208
|
+
- **Save current traffic** turns recent events into a replayable custom scenario.
|
|
209
|
+
|
|
210
|
+
API endpoints:
|
|
211
|
+
|
|
212
|
+
```http
|
|
213
|
+
GET /api/agent-prompt
|
|
214
|
+
GET /api/events/:id/test
|
|
215
|
+
GET /api/safety-report
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
CLI safety report:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
ghostapi report
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Chaos Mode
|
|
225
|
+
|
|
226
|
+
Chaos Mode helps test retry logic and failure handling.
|
|
227
|
+
|
|
228
|
+
When enabled:
|
|
229
|
+
|
|
230
|
+
- 85% of requests pass through normally.
|
|
231
|
+
- 15% get a simulated failure or delay.
|
|
232
|
+
- Failures are provider-shaped `429` or upstream errors like `503`.
|
|
233
|
+
- Latency is randomized between 2 and 5 seconds.
|
|
234
|
+
|
|
235
|
+
Enable it from the dashboard or via MCP.
|
|
236
|
+
|
|
237
|
+
## Provider Support
|
|
238
|
+
|
|
239
|
+
| Provider | Support |
|
|
240
|
+
| --- | --- |
|
|
241
|
+
| Stripe | Detection, validation, provider-shaped responses/errors, stateful objects. |
|
|
242
|
+
| Twilio | Detection, validation, Twilio-shaped errors. |
|
|
243
|
+
| Resend | Detection, validation, email-shaped mocks. |
|
|
244
|
+
| GitHub | Detection and realistic REST-style mocks. |
|
|
245
|
+
| Discord | Detection and local responses. |
|
|
246
|
+
| OpenAI | Detection for chat, responses, embeddings, models, images, audio, files, assistants, threads, vector stores. |
|
|
247
|
+
| Generic REST | Best-effort resource inference for unknown APIs. |
|
|
248
|
+
|
|
249
|
+
## Using SDKs Locally
|
|
250
|
+
|
|
251
|
+
Stripe example:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
import Stripe from "stripe";
|
|
255
|
+
|
|
256
|
+
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY ?? "sk_test_ghostapi", {
|
|
257
|
+
apiBase: process.env.GHOSTAPI_STRIPE_BASE_URL ?? "http://127.0.0.1:8080"
|
|
258
|
+
});
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
OpenAI example:
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
import OpenAI from "openai";
|
|
265
|
+
|
|
266
|
+
export const openai = new OpenAI({
|
|
267
|
+
apiKey: process.env.OPENAI_API_KEY ?? "sk-ghostapi",
|
|
268
|
+
baseURL: process.env.GHOSTAPI_OPENAI_BASE_URL ?? "http://127.0.0.1:8080/v1"
|
|
269
|
+
});
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## CLI
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
ghostapi start [--host 127.0.0.1] [--port 8080] [--model gpt-4o-mini] [--offline] [--https] [--open]
|
|
276
|
+
ghostapi open [--host 127.0.0.1] [--port 8080] [--https]
|
|
277
|
+
ghostapi setup [--write]
|
|
278
|
+
ghostapi report
|
|
279
|
+
ghostapi mcp
|
|
280
|
+
ghostapi doctor [--port 8080]
|
|
281
|
+
ghostapi init
|
|
282
|
+
ghostapi clear cache|state|events|all
|
|
283
|
+
ghostapi model get
|
|
284
|
+
ghostapi model set <model>
|
|
285
|
+
ghostapi providers list
|
|
286
|
+
ghostapi providers inspect <provider>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Local Files
|
|
290
|
+
|
|
291
|
+
GhostAPI writes local development data under `.ghostapi/`:
|
|
292
|
+
|
|
293
|
+
| Path | Purpose |
|
|
294
|
+
| --- | --- |
|
|
295
|
+
| `.ghostapi/config.json` | Project config. |
|
|
296
|
+
| `.ghostapi/state.json` | Local API object state. |
|
|
297
|
+
| `.ghostapi/events.jsonl` | Persisted request events. |
|
|
298
|
+
| `.ghostapi/behaviors.json` | Deterministic behavior overrides from MCP/scenarios. |
|
|
299
|
+
| `.ghostapi/cache/*` | Cached mock responses. |
|
|
300
|
+
|
|
301
|
+
These files are local development artifacts and should not contain production secrets.
|
|
302
|
+
|
|
303
|
+
## Safety Model
|
|
304
|
+
|
|
305
|
+
- No real provider calls by default.
|
|
306
|
+
- Offline fallback works without an LLM key.
|
|
307
|
+
- Secrets are masked from logs, dashboard, cache keys, event history, and AI prompts.
|
|
308
|
+
- Dashboard mutation APIs reject hostile cross-origin requests.
|
|
309
|
+
- Setup writing never overwrites existing files.
|
|
310
|
+
- Chaos Mode is opt-in.
|
|
311
|
+
|
|
312
|
+
## Development
|
|
313
|
+
|
|
314
|
+
Install dependencies:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
npm install
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Run from source:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
npm run dev
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Verify:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
npm run typecheck
|
|
330
|
+
npm test
|
|
331
|
+
npm run build
|
|
332
|
+
npm pack --dry-run
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Current hardening status:
|
|
336
|
+
|
|
337
|
+
- Typecheck passing.
|
|
338
|
+
- Test suite passing: 21 files, 97 tests.
|
|
339
|
+
- Build passing.
|
|
340
|
+
- Package dry-run passing.
|
|
341
|
+
- Real dashboard and HTTP smoke checks passing.
|
|
342
|
+
|
|
343
|
+
## Roadmap
|
|
344
|
+
|
|
345
|
+
- Scenario import and custom scenario builder.
|
|
346
|
+
- Record/replay from real traffic.
|
|
347
|
+
- More provider packs.
|
|
348
|
+
- CI mode for agent-generated integration tests.
|
|
349
|
+
- Shared team workspaces.
|
|
350
|
+
- Hosted docs and landing site.
|
|
351
|
+
|
|
352
|
+
## License
|
|
353
|
+
|
|
354
|
+
MIT. See [LICENSE](./LICENSE).
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
GhostAPI exists to make local integration development safer. Security-sensitive behavior should be treated as core product behavior, not an afterthought.
|
|
4
|
+
|
|
5
|
+
## Supported Versions
|
|
6
|
+
|
|
7
|
+
GhostAPI is pre-1.0. Security fixes target the current `main` branch and the latest published package once releases begin.
|
|
8
|
+
|
|
9
|
+
## Safety Model
|
|
10
|
+
|
|
11
|
+
- GhostAPI does not make real external provider API calls by default.
|
|
12
|
+
- Incoming requests are normalized and sanitized before use in prompts, cache keys, logs, or dashboard events.
|
|
13
|
+
- Secret-looking fields are masked, including `authorization`, `api_key`, `apikey`, `x-api-key`, `access_token`, `refresh_token`, `client_secret`, `password`, `secret`, `token`, and `key`.
|
|
14
|
+
- Known token patterns are masked, including Stripe keys, GitHub tokens, Slack bot tokens, SendGrid keys, and bearer tokens.
|
|
15
|
+
- Local cache entries are stored under `.ghostapi/cache/{provider}/{hash}.json`.
|
|
16
|
+
- Local state is stored under `.ghostapi/state.json`.
|
|
17
|
+
- `ghostapi doctor` warns when `NODE_TLS_REJECT_UNAUTHORIZED=0` is set.
|
|
18
|
+
|
|
19
|
+
## Reporting A Vulnerability
|
|
20
|
+
|
|
21
|
+
Please do not open a public issue for a vulnerability.
|
|
22
|
+
|
|
23
|
+
Until a dedicated security email is published, report privately to the project maintainer or repository owner and include:
|
|
24
|
+
|
|
25
|
+
- A clear description of the issue.
|
|
26
|
+
- Steps to reproduce.
|
|
27
|
+
- Expected impact.
|
|
28
|
+
- Whether secrets, prompts, cache, state, dashboard events, or network behavior are involved.
|
|
29
|
+
- Suggested fix, if you have one.
|
|
30
|
+
|
|
31
|
+
We will acknowledge valid reports as quickly as possible and prioritize fixes that could leak secrets, trigger real external calls unexpectedly, or expose local data.
|
|
32
|
+
|
|
33
|
+
## Out Of Scope
|
|
34
|
+
|
|
35
|
+
- Issues requiring malicious local filesystem access outside GhostAPI's process permissions.
|
|
36
|
+
- Vulnerabilities in unsupported Node.js versions.
|
|
37
|
+
- Reports without reproduction details.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { generateRepoSetup } from "../setup/setupGenerator.js";
|
|
2
|
+
export async function generateAgentPrompt(projectRoot = process.cwd()) {
|
|
3
|
+
const setup = await generateRepoSetup(projectRoot);
|
|
4
|
+
const detected = setup.detected.length > 0 ? setup.detected.join(", ") : "no known SDKs detected";
|
|
5
|
+
return {
|
|
6
|
+
title: "GhostAPI Agent Prompt",
|
|
7
|
+
content: [
|
|
8
|
+
"Use GhostAPI as the local API layer for this repository.",
|
|
9
|
+
"",
|
|
10
|
+
"Rules:",
|
|
11
|
+
"- Do not call production third-party APIs unless the user explicitly asks.",
|
|
12
|
+
"- Route local SDKs and HTTP clients to http://127.0.0.1:8080.",
|
|
13
|
+
"- Use GhostAPI MCP tools when available: inspect_state, set_api_behavior, get_traffic_logs, toggle_chaos_mode.",
|
|
14
|
+
"- Before assuming remote state, inspect GhostAPI state and traffic logs.",
|
|
15
|
+
"- Use scenario replay for payment, email, GitHub, and failure-path tests.",
|
|
16
|
+
"- Use Chaos Mode to verify retry, timeout, and degraded-provider handling.",
|
|
17
|
+
"- Never expose real API keys in logs, screenshots, generated tests, or committed files.",
|
|
18
|
+
"",
|
|
19
|
+
`Detected SDKs: ${detected}.`,
|
|
20
|
+
"",
|
|
21
|
+
"Useful commands:",
|
|
22
|
+
"```bash",
|
|
23
|
+
"ghostapi start --open",
|
|
24
|
+
"ghostapi mcp",
|
|
25
|
+
"ghostapi setup --write",
|
|
26
|
+
"```"
|
|
27
|
+
].join("\n")
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=agentPrompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentPrompt.js","sourceRoot":"","sources":["../../src/agents/agentPrompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAO/D,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE;IACnE,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC;IAClG,OAAO;QACL,KAAK,EAAE,uBAAuB;QAC9B,OAAO,EAAE;YACP,0DAA0D;YAC1D,EAAE;YACF,QAAQ;YACR,4EAA4E;YAC5E,+DAA+D;YAC/D,gHAAgH;YAChH,0EAA0E;YAC1E,2EAA2E;YAC3E,4EAA4E;YAC5E,yFAAyF;YACzF,EAAE;YACF,kBAAkB,QAAQ,GAAG;YAC7B,EAAE;YACF,kBAAkB;YAClB,SAAS;YACT,uBAAuB;YACvB,cAAc;YACd,wBAAwB;YACxB,KAAK;SACN,CAAC,IAAI,CAAC,IAAI,CAAC;KACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export async function askLLM(messages, config) {
|
|
2
|
+
if (!config.apiKey) {
|
|
3
|
+
throw new Error("No LLM API key configured");
|
|
4
|
+
}
|
|
5
|
+
// A basic OpenAI-compatible implementation. Since GPT-4o-mini / GPT-4o are standard defaults,
|
|
6
|
+
// OpenAI chat completions endpoint is assumed for MVP.
|
|
7
|
+
const response = await fetch("https://api.openai.com/v1/chat/completions", {
|
|
8
|
+
method: "POST",
|
|
9
|
+
headers: {
|
|
10
|
+
"Content-Type": "application/json",
|
|
11
|
+
Authorization: `Bearer ${config.apiKey}`
|
|
12
|
+
},
|
|
13
|
+
body: JSON.stringify({
|
|
14
|
+
model: config.model,
|
|
15
|
+
messages,
|
|
16
|
+
temperature: 0.1
|
|
17
|
+
})
|
|
18
|
+
});
|
|
19
|
+
if (!response.ok) {
|
|
20
|
+
const text = await response.text();
|
|
21
|
+
throw new Error(`LLM Error: ${response.status} ${text}`);
|
|
22
|
+
}
|
|
23
|
+
const json = await response.json();
|
|
24
|
+
const content = json.choices?.[0]?.message?.content;
|
|
25
|
+
if (typeof content !== "string" || content.trim() === "") {
|
|
26
|
+
throw new Error("Invalid LLM response shape");
|
|
27
|
+
}
|
|
28
|
+
return content;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=aiClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aiClient.js","sourceRoot":"","sources":["../../src/ai/aiClient.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,QAAqB,EAAE,MAAoB;IACtE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IAED,+FAA+F;IAC/F,uDAAuD;IACvD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,4CAA4C,EAAE;QACzE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE;SACzC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,QAAQ;YACR,WAAW,EAAE,GAAG;SACjB,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,cAAc,QAAQ,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA4B,CAAC;IAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;IACpD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Response } from "express";
|
|
2
|
+
import type { NormalizedRequest } from "../proxy/requestNormalizer.js";
|
|
3
|
+
import type { ServerConfig } from "../config/serverConfig.js";
|
|
4
|
+
import type { ProviderName } from "../providers/types.js";
|
|
5
|
+
export type AiMockResponse = {
|
|
6
|
+
status: number;
|
|
7
|
+
headers: Record<string, string>;
|
|
8
|
+
body: unknown;
|
|
9
|
+
};
|
|
10
|
+
export declare function generateAiMock(request: NormalizedRequest, provider: ProviderName, response: Response, config: ServerConfig): Promise<AiMockResponse | "streamed">;
|