@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.
Files changed (184) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/CONTRIBUTING.md +117 -0
  3. package/LICENSE +21 -0
  4. package/README.md +354 -0
  5. package/SECURITY.md +37 -0
  6. package/dist/agents/agentPrompt.d.ts +5 -0
  7. package/dist/agents/agentPrompt.js +30 -0
  8. package/dist/agents/agentPrompt.js.map +1 -0
  9. package/dist/ai/aiClient.d.ts +7 -0
  10. package/dist/ai/aiClient.js +30 -0
  11. package/dist/ai/aiClient.js.map +1 -0
  12. package/dist/ai/aiGenerator.d.ts +10 -0
  13. package/dist/ai/aiGenerator.js +101 -0
  14. package/dist/ai/aiGenerator.js.map +1 -0
  15. package/dist/ai/genericInference.d.ts +5 -0
  16. package/dist/ai/genericInference.js +80 -0
  17. package/dist/ai/genericInference.js.map +1 -0
  18. package/dist/ai/index.d.ts +3 -0
  19. package/dist/ai/index.js +2 -0
  20. package/dist/ai/index.js.map +1 -0
  21. package/dist/ai/jsonRepair.d.ts +2 -0
  22. package/dist/ai/jsonRepair.js +31 -0
  23. package/dist/ai/jsonRepair.js.map +1 -0
  24. package/dist/ai/prompts.d.ts +4 -0
  25. package/dist/ai/prompts.js +81 -0
  26. package/dist/ai/prompts.js.map +1 -0
  27. package/dist/behavior/behaviorStore.d.ts +12 -0
  28. package/dist/behavior/behaviorStore.js +72 -0
  29. package/dist/behavior/behaviorStore.js.map +1 -0
  30. package/dist/cache/index.d.ts +9 -0
  31. package/dist/cache/index.js +34 -0
  32. package/dist/cache/index.js.map +1 -0
  33. package/dist/cli/errors.d.ts +4 -0
  34. package/dist/cli/errors.js +9 -0
  35. package/dist/cli/errors.js.map +1 -0
  36. package/dist/cli/index.d.ts +2 -0
  37. package/dist/cli/index.js +277 -0
  38. package/dist/cli/index.js.map +1 -0
  39. package/dist/cli/parser.d.ts +56 -0
  40. package/dist/cli/parser.js +169 -0
  41. package/dist/cli/parser.js.map +1 -0
  42. package/dist/config/localConfig.d.ts +16 -0
  43. package/dist/config/localConfig.js +58 -0
  44. package/dist/config/localConfig.js.map +1 -0
  45. package/dist/config/serverConfig.d.ts +13 -0
  46. package/dist/config/serverConfig.js +44 -0
  47. package/dist/config/serverConfig.js.map +1 -0
  48. package/dist/dashboard/app.js +615 -0
  49. package/dist/dashboard/dashboard.d.ts +4 -0
  50. package/dist/dashboard/dashboard.js +20 -0
  51. package/dist/dashboard/dashboard.js.map +1 -0
  52. package/dist/dashboard/index.d.ts +1 -0
  53. package/dist/dashboard/index.html +298 -0
  54. package/dist/dashboard/index.js +2 -0
  55. package/dist/dashboard/index.js.map +1 -0
  56. package/dist/dashboard/styles.css +349 -0
  57. package/dist/errors/errorEngine.d.ts +3 -0
  58. package/dist/errors/errorEngine.js +65 -0
  59. package/dist/errors/errorEngine.js.map +1 -0
  60. package/dist/errors/index.d.ts +3 -0
  61. package/dist/errors/index.js +3 -0
  62. package/dist/errors/index.js.map +1 -0
  63. package/dist/errors/providerErrors.d.ts +3 -0
  64. package/dist/errors/providerErrors.js +6 -0
  65. package/dist/errors/providerErrors.js.map +1 -0
  66. package/dist/fault/faultLab.d.ts +27 -0
  67. package/dist/fault/faultLab.js +89 -0
  68. package/dist/fault/faultLab.js.map +1 -0
  69. package/dist/index.d.ts +2 -0
  70. package/dist/index.js +2 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/landing/assets/index-BXR41fAD.css +1 -0
  73. package/dist/landing/assets/index-D8_ggMRE.js +55 -0
  74. package/dist/landing/index.html +15 -0
  75. package/dist/landing/landing.d.ts +3 -0
  76. package/dist/landing/landing.js +12 -0
  77. package/dist/landing/landing.js.map +1 -0
  78. package/dist/mcp/server.d.ts +1 -0
  79. package/dist/mcp/server.js +52 -0
  80. package/dist/mcp/server.js.map +1 -0
  81. package/dist/providers/discord.d.ts +2 -0
  82. package/dist/providers/discord.js +11 -0
  83. package/dist/providers/discord.js.map +1 -0
  84. package/dist/providers/generic.d.ts +2 -0
  85. package/dist/providers/generic.js +13 -0
  86. package/dist/providers/generic.js.map +1 -0
  87. package/dist/providers/github.d.ts +2 -0
  88. package/dist/providers/github.js +11 -0
  89. package/dist/providers/github.js.map +1 -0
  90. package/dist/providers/index.d.ts +2 -0
  91. package/dist/providers/index.js +2 -0
  92. package/dist/providers/index.js.map +1 -0
  93. package/dist/providers/openai.d.ts +2 -0
  94. package/dist/providers/openai.js +15 -0
  95. package/dist/providers/openai.js.map +1 -0
  96. package/dist/providers/registry.d.ts +12 -0
  97. package/dist/providers/registry.js +23 -0
  98. package/dist/providers/registry.js.map +1 -0
  99. package/dist/providers/resend.d.ts +2 -0
  100. package/dist/providers/resend.js +12 -0
  101. package/dist/providers/resend.js.map +1 -0
  102. package/dist/providers/stripe.d.ts +2 -0
  103. package/dist/providers/stripe.js +15 -0
  104. package/dist/providers/stripe.js.map +1 -0
  105. package/dist/providers/twilio.d.ts +2 -0
  106. package/dist/providers/twilio.js +14 -0
  107. package/dist/providers/twilio.js.map +1 -0
  108. package/dist/providers/types.d.ts +13 -0
  109. package/dist/providers/types.js +2 -0
  110. package/dist/providers/types.js.map +1 -0
  111. package/dist/proxy/cacheKey.d.ts +2 -0
  112. package/dist/proxy/cacheKey.js +37 -0
  113. package/dist/proxy/cacheKey.js.map +1 -0
  114. package/dist/proxy/providerDetector.d.ts +11 -0
  115. package/dist/proxy/providerDetector.js +74 -0
  116. package/dist/proxy/providerDetector.js.map +1 -0
  117. package/dist/proxy/proxyHandler.d.ts +3 -0
  118. package/dist/proxy/proxyHandler.js +114 -0
  119. package/dist/proxy/proxyHandler.js.map +1 -0
  120. package/dist/proxy/requestNormalizer.d.ts +11 -0
  121. package/dist/proxy/requestNormalizer.js +30 -0
  122. package/dist/proxy/requestNormalizer.js.map +1 -0
  123. package/dist/report/safetyReport.d.ts +13 -0
  124. package/dist/report/safetyReport.js +65 -0
  125. package/dist/report/safetyReport.js.map +1 -0
  126. package/dist/rules/aiRules.d.ts +7 -0
  127. package/dist/rules/aiRules.js +31 -0
  128. package/dist/rules/aiRules.js.map +1 -0
  129. package/dist/scenarios/scenarioStore.d.ts +37 -0
  130. package/dist/scenarios/scenarioStore.js +201 -0
  131. package/dist/scenarios/scenarioStore.js.map +1 -0
  132. package/dist/security/headerSanitizer.d.ts +3 -0
  133. package/dist/security/headerSanitizer.js +12 -0
  134. package/dist/security/headerSanitizer.js.map +1 -0
  135. package/dist/security/maskSecrets.d.ts +1 -0
  136. package/dist/security/maskSecrets.js +2 -0
  137. package/dist/security/maskSecrets.js.map +1 -0
  138. package/dist/security/secrets.d.ts +4 -0
  139. package/dist/security/secrets.js +61 -0
  140. package/dist/security/secrets.js.map +1 -0
  141. package/dist/server/createServer.d.ts +8 -0
  142. package/dist/server/createServer.js +42 -0
  143. package/dist/server/createServer.js.map +1 -0
  144. package/dist/server/eventsStore.d.ts +17 -0
  145. package/dist/server/eventsStore.js +31 -0
  146. package/dist/server/eventsStore.js.map +1 -0
  147. package/dist/server/routes.d.ts +3 -0
  148. package/dist/server/routes.js +189 -0
  149. package/dist/server/routes.js.map +1 -0
  150. package/dist/server/sse.d.ts +5 -0
  151. package/dist/server/sse.js +32 -0
  152. package/dist/server/sse.js.map +1 -0
  153. package/dist/setup/sdkDetector.d.ts +9 -0
  154. package/dist/setup/sdkDetector.js +31 -0
  155. package/dist/setup/sdkDetector.js.map +1 -0
  156. package/dist/setup/setupGenerator.d.ts +28 -0
  157. package/dist/setup/setupGenerator.js +146 -0
  158. package/dist/setup/setupGenerator.js.map +1 -0
  159. package/dist/state/index.d.ts +1 -0
  160. package/dist/state/index.js +2 -0
  161. package/dist/state/index.js.map +1 -0
  162. package/dist/state/stateExtractor.d.ts +3 -0
  163. package/dist/state/stateExtractor.js +36 -0
  164. package/dist/state/stateExtractor.js.map +1 -0
  165. package/dist/state/stateResolver.d.ts +8 -0
  166. package/dist/state/stateResolver.js +95 -0
  167. package/dist/state/stateResolver.js.map +1 -0
  168. package/dist/state/stateStore.d.ts +4 -0
  169. package/dist/state/stateStore.js +72 -0
  170. package/dist/state/stateStore.js.map +1 -0
  171. package/dist/tests/testGenerator.d.ts +6 -0
  172. package/dist/tests/testGenerator.js +33 -0
  173. package/dist/tests/testGenerator.js.map +1 -0
  174. package/dist/utils/json.d.ts +2 -0
  175. package/dist/utils/json.js +10 -0
  176. package/dist/utils/json.js.map +1 -0
  177. package/docs/release-checklist.md +71 -0
  178. package/examples/agent-instructions/README.md +39 -0
  179. package/examples/generic-rest/README.md +27 -0
  180. package/examples/github-fetch/README.md +35 -0
  181. package/examples/resend-node/README.md +22 -0
  182. package/examples/stripe-node/README.md +29 -0
  183. package/examples/twilio-node/README.md +21 -0
  184. package/package.json +67 -0
@@ -0,0 +1,31 @@
1
+ import { appendFile, mkdir, rm } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ const EVENTS_FILE_PATH = join(".ghostapi", "events.jsonl");
4
+ const MAX_EVENTS = 200;
5
+ const eventsBuffer = [];
6
+ export async function addEvent(event) {
7
+ eventsBuffer.push(event);
8
+ if (eventsBuffer.length > MAX_EVENTS) {
9
+ eventsBuffer.shift();
10
+ }
11
+ try {
12
+ await mkdir(dirname(EVENTS_FILE_PATH), { recursive: true });
13
+ const serialized = JSON.stringify(event) + "\n";
14
+ await appendFile(EVENTS_FILE_PATH, serialized, "utf8");
15
+ }
16
+ catch {
17
+ // Silently ignore log write failures to strictly preserve proxy operational stability
18
+ }
19
+ }
20
+ export function getEventsHistory() {
21
+ return [...eventsBuffer];
22
+ }
23
+ export function clearEventsHistoryForTests() {
24
+ eventsBuffer.length = 0;
25
+ }
26
+ export async function clearEvents() {
27
+ eventsBuffer.length = 0;
28
+ await mkdir(dirname(EVENTS_FILE_PATH), { recursive: true });
29
+ await rm(EVENTS_FILE_PATH, { force: true });
30
+ }
31
+ //# sourceMappingURL=eventsStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eventsStore.js","sourceRoot":"","sources":["../../src/server/eventsStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAiB1C,MAAM,gBAAgB,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;AAC3D,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB,MAAM,YAAY,GAAiB,EAAE,CAAC;AAEtC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,KAAiB;IAC9C,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEzB,IAAI,YAAY,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;QACrC,YAAY,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;QAChD,MAAM,UAAU,CAAC,gBAAgB,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,sFAAsF;IACxF,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,CAAC,GAAG,YAAY,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,0BAA0B;IACxC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IACxB,MAAM,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,MAAM,EAAE,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Express } from "express";
2
+ import type { ServerConfig } from "../config/serverConfig.js";
3
+ export declare function registerRoutes(app: Express, config: ServerConfig): void;
@@ -0,0 +1,189 @@
1
+ import { proxyHandler } from "../proxy/proxyHandler.js";
2
+ import { addSseClient } from "./sse.js";
3
+ import { clearEvents, getEventsHistory } from "./eventsStore.js";
4
+ import { dashboardHandler, dashboardCssHandler, dashboardJsHandler } from "../dashboard/dashboard.js";
5
+ import { landingAssetsHandler, landingHandler } from "../landing/landing.js";
6
+ import { clearCache } from "../cache/index.js";
7
+ import { clearState } from "../state/stateStore.js";
8
+ import { getFaultLabConfig, updateFaultLabConfig } from "../fault/faultLab.js";
9
+ import { generateAiRules } from "../rules/aiRules.js";
10
+ import { generateRepoSetup } from "../setup/setupGenerator.js";
11
+ import { exportScenario, importScenario, listScenarioPresets, replayScenario, saveEventsAsScenario, shareScenario } from "../scenarios/scenarioStore.js";
12
+ import { generateAgentPrompt } from "../agents/agentPrompt.js";
13
+ import { generateVitestFromEvent } from "../tests/testGenerator.js";
14
+ import { generateSafetyReport } from "../report/safetyReport.js";
15
+ const PROXY_METHODS = ["get", "post", "put", "patch", "delete", "head", "options"];
16
+ const CLEAR_TARGETS = ["cache", "state", "events", "all"];
17
+ export function registerRoutes(app, config) {
18
+ app.get("/", landingHandler);
19
+ app.use("/landing/assets", landingAssetsHandler);
20
+ app.get("/health", (_request, response) => {
21
+ response.status(200).json({ ok: true });
22
+ });
23
+ app.get("/dashboard", dashboardHandler);
24
+ app.get("/dashboard/styles.css", dashboardCssHandler);
25
+ app.get("/dashboard/app.js", dashboardJsHandler);
26
+ app.get("/events", (_request, response) => {
27
+ response.setHeader("Content-Type", "text/event-stream");
28
+ response.setHeader("Cache-Control", "no-cache");
29
+ response.setHeader("Connection", "keep-alive");
30
+ response.flushHeaders();
31
+ addSseClient(response);
32
+ });
33
+ app.get("/api/events", (_request, response) => {
34
+ response.status(200).json(getEventsHistory());
35
+ });
36
+ app.get("/api/fault-lab", (_request, response) => {
37
+ response.status(200).json(getFaultLabConfig());
38
+ });
39
+ app.post("/api/fault-lab", (req, res) => {
40
+ try {
41
+ res.status(200).json(updateFaultLabConfig(req.body));
42
+ }
43
+ catch (error) {
44
+ const message = error instanceof Error ? error.message : "Invalid Fault Lab config.";
45
+ res.status(400).json({ error: { code: "invalid_fault_lab_config", message } });
46
+ }
47
+ });
48
+ app.post("/api/ai-rules", async (_req, res) => {
49
+ try {
50
+ res.status(200).json(await generateAiRules());
51
+ }
52
+ catch (error) {
53
+ const message = error instanceof Error ? error.message : "Unable to generate AI rules.";
54
+ res.status(500).json({ error: { code: "ai_rules_generation_failed", message } });
55
+ }
56
+ });
57
+ app.post("/api/setup", async (_req, res) => {
58
+ try {
59
+ res.status(200).json(await generateRepoSetup());
60
+ }
61
+ catch (error) {
62
+ const message = error instanceof Error ? error.message : "Unable to generate repo setup.";
63
+ res.status(500).json({ error: { code: "setup_generation_failed", message } });
64
+ }
65
+ });
66
+ app.get("/api/scenarios", async (_req, res, next) => {
67
+ try {
68
+ res.status(200).json(await listScenarioPresets());
69
+ }
70
+ catch (error) {
71
+ next(error);
72
+ }
73
+ });
74
+ app.post("/api/scenarios", async (req, res) => {
75
+ try {
76
+ res.status(201).json(await importScenario(req.body));
77
+ }
78
+ catch (error) {
79
+ const message = error instanceof Error ? error.message : "Unable to import scenario.";
80
+ res.status(400).json({ error: { code: "invalid_scenario", message } });
81
+ }
82
+ });
83
+ app.post("/api/scenarios/save-from-traffic", async (req, res) => {
84
+ try {
85
+ res.status(201).json(await saveEventsAsScenario(getEventsHistory(), req.body));
86
+ }
87
+ catch (error) {
88
+ const message = error instanceof Error ? error.message : "Unable to save traffic as scenario.";
89
+ res.status(400).json({ error: { code: "scenario_save_failed", message } });
90
+ }
91
+ });
92
+ app.post("/api/scenarios/:id/replay", async (req, res) => {
93
+ try {
94
+ res.status(200).json(await replayScenario(req.params.id));
95
+ }
96
+ catch (error) {
97
+ const message = error instanceof Error ? error.message : "Unable to replay scenario.";
98
+ res.status(404).json({ error: { code: "scenario_not_found", message } });
99
+ }
100
+ });
101
+ app.get("/api/scenarios/:id/export", async (req, res) => {
102
+ try {
103
+ res.status(200).json(await exportScenario(req.params.id));
104
+ }
105
+ catch (error) {
106
+ const message = error instanceof Error ? error.message : "Unable to export scenario.";
107
+ res.status(404).json({ error: { code: "scenario_not_found", message } });
108
+ }
109
+ });
110
+ app.post("/api/scenarios/:id/share", async (req, res) => {
111
+ try {
112
+ res.status(200).json(await shareScenario(req.params.id));
113
+ }
114
+ catch (error) {
115
+ const message = error instanceof Error ? error.message : "Unable to share scenario.";
116
+ res.status(404).json({ error: { code: "scenario_not_found", message } });
117
+ }
118
+ });
119
+ app.post("/api/clear", async (req, res, next) => {
120
+ try {
121
+ const { target } = req.body;
122
+ if (!isClearTarget(target)) {
123
+ res.status(400).json({ error: { code: "invalid_clear_target", message: "Use target cache, state, events, or all." } });
124
+ return;
125
+ }
126
+ if (target === "cache" || target === "all")
127
+ await clearCache();
128
+ if (target === "state" || target === "all")
129
+ await clearState();
130
+ if (target === "events" || target === "all")
131
+ await clearEvents();
132
+ res.status(200).json({ ok: true, cleared: target });
133
+ }
134
+ catch (e) {
135
+ next(e);
136
+ }
137
+ });
138
+ app.get("/api/agent-prompt", async (_req, res) => {
139
+ try {
140
+ res.status(200).json(await generateAgentPrompt());
141
+ }
142
+ catch (error) {
143
+ const message = error instanceof Error ? error.message : "Unable to generate agent prompt.";
144
+ res.status(500).json({ error: { code: "agent_prompt_failed", message } });
145
+ }
146
+ });
147
+ app.get("/api/events/:id/test", (req, res) => {
148
+ const event = getEventsHistory().find((candidate) => candidate.id === req.params.id);
149
+ if (event === undefined) {
150
+ res.status(404).json({ error: { code: "event_not_found", message: "Event not found." } });
151
+ return;
152
+ }
153
+ res.status(200).json(generateVitestFromEvent(event));
154
+ });
155
+ app.get("/api/safety-report", async (_req, res) => {
156
+ try {
157
+ res.status(200).json(await generateSafetyReport());
158
+ }
159
+ catch (error) {
160
+ const message = error instanceof Error ? error.message : "Unable to generate safety report.";
161
+ res.status(500).json({ error: { code: "safety_report_failed", message } });
162
+ }
163
+ });
164
+ for (const method of PROXY_METHODS) {
165
+ if (method === "options") {
166
+ app.options("*", (_req, res) => { res.sendStatus(204); });
167
+ continue;
168
+ }
169
+ app[method]("*", async (req, res, next) => {
170
+ try {
171
+ await proxyHandler(req, res, config);
172
+ }
173
+ catch (error) {
174
+ next(error);
175
+ }
176
+ });
177
+ }
178
+ // Global Error Handler guaranteeing JSON responses instead of crashing Express
179
+ app.use((err, _req, res, _next) => {
180
+ const message = err instanceof Error ? err.message : "Unknown local proxy error";
181
+ res.status(500).json({
182
+ error: { code: "ghostapi_internal_error", message }
183
+ });
184
+ });
185
+ }
186
+ function isClearTarget(value) {
187
+ return typeof value === "string" && CLEAR_TARGETS.includes(value);
188
+ }
189
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/server/routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Response } from "express";
2
+ import type { ProxyEvent } from "./eventsStore.js";
3
+ export declare function addSseClient(response: Response): void;
4
+ export declare function broadcastEvent(event: ProxyEvent): void;
5
+ export declare function getSseClientCount(): number;
@@ -0,0 +1,32 @@
1
+ const clients = new Set();
2
+ export function addSseClient(response) {
3
+ const client = {
4
+ id: Date.now().toString(36) + Math.random().toString(36).slice(2),
5
+ response
6
+ };
7
+ clients.add(client);
8
+ requestAnimationFrameMock(() => {
9
+ if (!client.response.writableEnded && !client.response.destroyed) {
10
+ client.response.write(`data: ${JSON.stringify({ type: "connected", id: client.id })}\n\n`);
11
+ }
12
+ });
13
+ response.on("close", () => {
14
+ clients.delete(client);
15
+ });
16
+ }
17
+ export function broadcastEvent(event) {
18
+ const payload = `data: ${JSON.stringify({ type: "proxy_event", event })}\n\n`;
19
+ for (const client of clients) {
20
+ if (!client.response.writableEnded && !client.response.destroyed) {
21
+ client.response.write(payload);
22
+ }
23
+ }
24
+ }
25
+ export function getSseClientCount() {
26
+ return clients.size;
27
+ }
28
+ // Ensure non-blocking delayed execution
29
+ function requestAnimationFrameMock(fn) {
30
+ setTimeout(fn, 0);
31
+ }
32
+ //# sourceMappingURL=sse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/server/sse.ts"],"names":[],"mappings":"AAQA,MAAM,OAAO,GAAG,IAAI,GAAG,EAAa,CAAC;AAErC,MAAM,UAAU,YAAY,CAAC,QAAkB;IAC7C,MAAM,MAAM,GAAc;QACxB,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACjE,QAAQ;KACT,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEpB,yBAAyB,CAAC,GAAG,EAAE;QAC7B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;YACjE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACxB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAiB;IAC9C,MAAM,OAAO,GAAG,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC;IAC9E,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;YACjE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,OAAO,CAAC,IAAI,CAAC;AACtB,CAAC;AAED,wCAAwC;AACxC,SAAS,yBAAyB,CAAC,EAAc;IAC/C,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,9 @@
1
+ export type DetectedSdk = "stripe" | "twilio" | "resend" | "openai" | "github" | "discord";
2
+ export type PackageJson = {
3
+ dependencies?: Record<string, string>;
4
+ devDependencies?: Record<string, string>;
5
+ peerDependencies?: Record<string, string>;
6
+ optionalDependencies?: Record<string, string>;
7
+ };
8
+ export declare function readPackageJson(projectRoot?: string): Promise<PackageJson>;
9
+ export declare function detectSdks(packageJson: PackageJson): DetectedSdk[];
@@ -0,0 +1,31 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ const SDK_PACKAGES = {
4
+ stripe: "stripe",
5
+ twilio: "twilio",
6
+ resend: "resend",
7
+ openai: "openai",
8
+ "@octokit/rest": "github",
9
+ "discord.js": "discord"
10
+ };
11
+ export async function readPackageJson(projectRoot = process.cwd()) {
12
+ const raw = await readFile(join(projectRoot, "package.json"), "utf8");
13
+ const parsed = JSON.parse(raw);
14
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
15
+ return {};
16
+ return parsed;
17
+ }
18
+ export function detectSdks(packageJson) {
19
+ const names = new Set();
20
+ for (const group of [packageJson.dependencies, packageJson.devDependencies, packageJson.peerDependencies, packageJson.optionalDependencies]) {
21
+ for (const name of Object.keys(group ?? {}))
22
+ names.add(name);
23
+ }
24
+ const detected = [];
25
+ for (const [packageName, sdk] of Object.entries(SDK_PACKAGES)) {
26
+ if (names.has(packageName))
27
+ detected.push(sdk);
28
+ }
29
+ return detected;
30
+ }
31
+ //# sourceMappingURL=sdkDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdkDetector.js","sourceRoot":"","sources":["../../src/setup/sdkDetector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAWjC,MAAM,YAAY,GAAgC;IAChD,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,eAAe,EAAE,QAAQ;IACzB,YAAY,EAAE,SAAS;CACxB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE;IAC/D,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;IAC1C,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IACtF,OAAO,MAAqB,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,WAAwB;IACjD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,KAAK,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,WAAW,CAAC,eAAe,EAAE,WAAW,CAAC,gBAAgB,EAAE,WAAW,CAAC,oBAAoB,CAAC,EAAE,CAAC;QAC5I,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,KAAK,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9D,IAAI,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { type DetectedSdk } from "./sdkDetector.js";
2
+ export type SetupFile = {
3
+ path: string;
4
+ description: string;
5
+ content: string;
6
+ };
7
+ export type SetupPatch = {
8
+ title: string;
9
+ appliesTo: string;
10
+ content: string;
11
+ };
12
+ export type RepoSetup = {
13
+ projectRoot: string;
14
+ detected: DetectedSdk[];
15
+ commands: string[];
16
+ files: SetupFile[];
17
+ patches: SetupPatch[];
18
+ summary: string;
19
+ };
20
+ export type SetupWriteResult = {
21
+ created: string[];
22
+ skipped: string[];
23
+ };
24
+ export declare function generateRepoSetup(projectRoot?: string): Promise<RepoSetup>;
25
+ export declare function writeRepoSetup(projectRoot?: string): Promise<{
26
+ setup: RepoSetup;
27
+ result: SetupWriteResult;
28
+ }>;
@@ -0,0 +1,146 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { readPackageJson, detectSdks } from "./sdkDetector.js";
4
+ import { generateAiRules } from "../rules/aiRules.js";
5
+ export async function generateRepoSetup(projectRoot = process.cwd()) {
6
+ const packageJson = await readPackageJson(projectRoot);
7
+ const detected = detectSdks(packageJson);
8
+ const rules = await generateAiRules(projectRoot);
9
+ const mcpConfig = buildMcpConfig();
10
+ const mcpServers = { mcpServers: { ghostapi: mcpConfig } };
11
+ const autoApprovedMcpServers = { mcpServers: { ghostapi: { ...mcpConfig, disabled: false, autoApprove: ["inspect_state", "get_traffic_logs"] } } };
12
+ const files = [
13
+ { path: ".cursorrules", description: "Cursor agent rules for GhostAPI-first local API development.", content: rules.content },
14
+ { path: "AGENTS.md", description: "Universal agent instructions for Aider, Codex-style agents, Gemini CLI, OpenCode, Goose, OpenClaw, and Hermes.", content: buildAgentInstructions(detected) },
15
+ { path: ".cursor/mcp.json", description: "Cursor MCP server config.", content: JSON.stringify(mcpServers, null, 2) },
16
+ { path: "cline_mcp_settings.json", description: "Cline MCP server config snippet.", content: JSON.stringify(autoApprovedMcpServers, null, 2) },
17
+ { path: "claude_desktop_config.json", description: "Claude Desktop MCP server config snippet.", content: JSON.stringify(mcpServers, null, 2) },
18
+ { path: ".ghostapi/agent-configs/universal-mcp.json", description: "Universal stdio MCP block for any MCP-compatible client.", content: JSON.stringify(mcpServers, null, 2) },
19
+ { path: ".ghostapi/agent-configs/claude-cli.json", description: "Claude CLI MCP snippet.", content: JSON.stringify(mcpServers, null, 2) },
20
+ { path: ".ghostapi/agent-configs/claude-desktop.json", description: "Claude Desktop MCP snippet.", content: JSON.stringify(mcpServers, null, 2) },
21
+ { path: ".ghostapi/agent-configs/cline.json", description: "Cline MCP snippet.", content: JSON.stringify(autoApprovedMcpServers, null, 2) },
22
+ { path: ".ghostapi/agent-configs/aider.md", description: "Aider instructions and MCP handoff note.", content: buildClientInstructions("Aider", detected) },
23
+ { path: ".ghostapi/agent-configs/codex.json", description: "Codex MCP snippet.", content: JSON.stringify(mcpServers, null, 2) },
24
+ { path: ".ghostapi/agent-configs/opencode-cli.json", description: "OpenCode CLI MCP snippet.", content: JSON.stringify(mcpServers, null, 2) },
25
+ { path: ".ghostapi/agent-configs/opencode-desktop.json", description: "OpenCode Desktop MCP snippet.", content: JSON.stringify(mcpServers, null, 2) },
26
+ { path: ".ghostapi/agent-configs/gemini-cli.json", description: "Gemini CLI MCP snippet.", content: JSON.stringify(mcpServers, null, 2) },
27
+ { path: ".ghostapi/agent-configs/goose.json", description: "Goose MCP snippet.", content: JSON.stringify(mcpServers, null, 2) },
28
+ { path: ".ghostapi/agent-configs/openclaw.json", description: "OpenClaw MCP snippet.", content: JSON.stringify(mcpServers, null, 2) },
29
+ { path: ".ghostapi/agent-configs/hermes-desktop.json", description: "Hermes Desktop MCP snippet.", content: JSON.stringify(mcpServers, null, 2) }
30
+ ];
31
+ return {
32
+ projectRoot,
33
+ detected,
34
+ commands: ["ghostapi init", "ghostapi doctor", "ghostapi start --open", "ghostapi mcp"],
35
+ files,
36
+ patches: buildPatches(detected),
37
+ summary: buildSummary(detected)
38
+ };
39
+ }
40
+ export async function writeRepoSetup(projectRoot = process.cwd()) {
41
+ const setup = await generateRepoSetup(projectRoot);
42
+ const result = { created: [], skipped: [] };
43
+ for (const file of setup.files) {
44
+ const target = join(projectRoot, file.path);
45
+ try {
46
+ await mkdir(dirname(target), { recursive: true });
47
+ await writeFile(target, file.content, { encoding: "utf8", flag: "wx" });
48
+ result.created.push(file.path);
49
+ }
50
+ catch (error) {
51
+ if (error instanceof Error && "code" in error && error.code === "EEXIST") {
52
+ result.skipped.push(file.path);
53
+ continue;
54
+ }
55
+ throw error;
56
+ }
57
+ }
58
+ return { setup, result };
59
+ }
60
+ function buildMcpConfig() {
61
+ return { command: "ghostapi", args: ["mcp"] };
62
+ }
63
+ function buildSummary(detected) {
64
+ const sdkText = detected.length > 0 ? detected.join(", ") : "no known provider SDKs";
65
+ return `Detected ${sdkText}. Copy the generated files into your repo, run ghostapi start --open, and point local SDK clients at http://127.0.0.1:8080.`;
66
+ }
67
+ function buildAgentInstructions(detected) {
68
+ return buildClientInstructions("any coding agent", detected);
69
+ }
70
+ function buildClientInstructions(clientName, detected) {
71
+ const sdkText = detected.length > 0 ? detected.join(", ") : "no known provider SDKs";
72
+ return [
73
+ "# GhostAPI Agent Instructions",
74
+ "",
75
+ `These instructions are for ${clientName} working in this repository.`,
76
+ "",
77
+ "## Local API Runtime",
78
+ "",
79
+ "Use GhostAPI as the local API layer for third-party integrations.",
80
+ "",
81
+ "```bash",
82
+ "ghostapi start --open",
83
+ "ghostapi mcp",
84
+ "```",
85
+ "",
86
+ "Route local SDKs and HTTP clients to `http://127.0.0.1:8080` instead of live providers during development and tests.",
87
+ "",
88
+ "## MCP Server",
89
+ "",
90
+ "If your client supports MCP, add this stdio server:",
91
+ "",
92
+ "```json",
93
+ JSON.stringify({ mcpServers: { ghostapi: buildMcpConfig() } }, null, 2),
94
+ "```",
95
+ "",
96
+ "Use GhostAPI MCP tools to inspect local state, configure deterministic responses, read traffic logs, and toggle Chaos Mode.",
97
+ "",
98
+ "## Detected SDKs",
99
+ "",
100
+ `Detected: ${sdkText}.`,
101
+ "",
102
+ "Never use production API keys or live provider endpoints unless the user explicitly asks."
103
+ ].join("\n");
104
+ }
105
+ function buildPatches(detected) {
106
+ const patches = [
107
+ {
108
+ title: "Local API base URL env",
109
+ appliesTo: ".env.local",
110
+ content: [
111
+ "GHOSTAPI_BASE_URL=http://127.0.0.1:8080",
112
+ "GHOSTAPI_STRIPE_BASE_URL=http://127.0.0.1:8080",
113
+ "GHOSTAPI_OPENAI_BASE_URL=http://127.0.0.1:8080"
114
+ ].join("\n")
115
+ }
116
+ ];
117
+ if (detected.includes("stripe")) {
118
+ patches.push({
119
+ title: "Stripe client patch",
120
+ appliesTo: "Stripe client initialization",
121
+ content: [
122
+ "import Stripe from \"stripe\";",
123
+ "",
124
+ "export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY ?? \"sk_test_ghostapi\", {",
125
+ " apiBase: process.env.GHOSTAPI_STRIPE_BASE_URL ?? \"http://127.0.0.1:8080\"",
126
+ "});"
127
+ ].join("\n")
128
+ });
129
+ }
130
+ if (detected.includes("openai")) {
131
+ patches.push({
132
+ title: "OpenAI client patch",
133
+ appliesTo: "OpenAI client initialization",
134
+ content: [
135
+ "import OpenAI from \"openai\";",
136
+ "",
137
+ "export const openai = new OpenAI({",
138
+ " apiKey: process.env.OPENAI_API_KEY ?? \"sk-ghostapi\",",
139
+ " baseURL: process.env.GHOSTAPI_OPENAI_BASE_URL ?? \"http://127.0.0.1:8080/v1\"",
140
+ "});"
141
+ ].join("\n")
142
+ });
143
+ }
144
+ return patches;
145
+ }
146
+ //# sourceMappingURL=setupGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setupGenerator.js","sourceRoot":"","sources":["../../src/setup/setupGenerator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export type StateRecord = Record<string, unknown>;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import type { NormalizedRequest } from "../proxy/requestNormalizer.js";
2
+ export declare function extractIdFromResponse(responseBody: unknown): string | undefined;
3
+ export declare function extractIdFromPath(request: NormalizedRequest): string | undefined;
@@ -0,0 +1,36 @@
1
+ import { isJsonObject } from "../utils/json.js";
2
+ const ID_FIELDS = ["id", "sid", "uuid", "name", "number"];
3
+ export function extractIdFromResponse(responseBody) {
4
+ if (!isJsonObject(responseBody)) {
5
+ return undefined;
6
+ }
7
+ for (const field of ID_FIELDS) {
8
+ const value = responseBody[field];
9
+ if (typeof value === "string" && value.trim().length > 0) {
10
+ return value;
11
+ }
12
+ if (typeof value === "number") {
13
+ return value.toString();
14
+ }
15
+ }
16
+ return undefined;
17
+ }
18
+ export function extractIdFromPath(request) {
19
+ const { path } = request;
20
+ const segments = path.split("/").filter(Boolean);
21
+ if (segments.length === 0)
22
+ return undefined;
23
+ const lastSegment = segments[segments.length - 1];
24
+ if (lastSegment === undefined)
25
+ return undefined;
26
+ // Test explicitly for ID-like shapes
27
+ if (lastSegment.includes("_") || lastSegment.includes("-") || /\d/.test(lastSegment)) {
28
+ return lastSegment;
29
+ }
30
+ // Pure generic fallback for test mocks like "/v1/customers/1"
31
+ if (segments.length >= 2 && !lastSegment.match(/^[a-z]+s$/i)) {
32
+ return lastSegment;
33
+ }
34
+ return undefined;
35
+ }
36
+ //# sourceMappingURL=stateExtractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateExtractor.js","sourceRoot":"","sources":["../../src/state/stateExtractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AAE1D,MAAM,UAAU,qBAAqB,CAAC,YAAqB;IACzD,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAA0B;IAC1D,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEjD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAE5C,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClD,IAAI,WAAW,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAEhD,qCAAqC;IACrC,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACrF,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,8DAA8D;IAC9D,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7D,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { NormalizedRequest } from "../proxy/requestNormalizer.js";
2
+ type ResolvedState = {
3
+ status: number;
4
+ headers: Record<string, string>;
5
+ body: unknown;
6
+ };
7
+ export declare function resolveState(request: NormalizedRequest, provider: string): Promise<ResolvedState | null>;
8
+ export {};