@dotsetlabs/tollgate 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 (215) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +885 -0
  3. package/dist/analyzers/filesystem.d.ts +26 -0
  4. package/dist/analyzers/filesystem.d.ts.map +1 -0
  5. package/dist/analyzers/filesystem.js +284 -0
  6. package/dist/analyzers/filesystem.js.map +1 -0
  7. package/dist/analyzers/http.d.ts +90 -0
  8. package/dist/analyzers/http.d.ts.map +1 -0
  9. package/dist/analyzers/http.js +433 -0
  10. package/dist/analyzers/http.js.map +1 -0
  11. package/dist/analyzers/index.d.ts +101 -0
  12. package/dist/analyzers/index.d.ts.map +1 -0
  13. package/dist/analyzers/index.js +342 -0
  14. package/dist/analyzers/index.js.map +1 -0
  15. package/dist/analyzers/loader.d.ts +114 -0
  16. package/dist/analyzers/loader.d.ts.map +1 -0
  17. package/dist/analyzers/loader.js +184 -0
  18. package/dist/analyzers/loader.js.map +1 -0
  19. package/dist/analyzers/prompt-injection.d.ts +95 -0
  20. package/dist/analyzers/prompt-injection.d.ts.map +1 -0
  21. package/dist/analyzers/prompt-injection.js +725 -0
  22. package/dist/analyzers/prompt-injection.js.map +1 -0
  23. package/dist/analyzers/sdk.d.ts +230 -0
  24. package/dist/analyzers/sdk.d.ts.map +1 -0
  25. package/dist/analyzers/sdk.js +283 -0
  26. package/dist/analyzers/sdk.js.map +1 -0
  27. package/dist/analyzers/shell.d.ts +20 -0
  28. package/dist/analyzers/shell.d.ts.map +1 -0
  29. package/dist/analyzers/shell.js +297 -0
  30. package/dist/analyzers/shell.js.map +1 -0
  31. package/dist/analyzers/sql.d.ts +37 -0
  32. package/dist/analyzers/sql.d.ts.map +1 -0
  33. package/dist/analyzers/sql.js +455 -0
  34. package/dist/analyzers/sql.js.map +1 -0
  35. package/dist/analyzers/types.d.ts +117 -0
  36. package/dist/analyzers/types.d.ts.map +1 -0
  37. package/dist/analyzers/types.js +46 -0
  38. package/dist/analyzers/types.js.map +1 -0
  39. package/dist/approval/interactive.d.ts +72 -0
  40. package/dist/approval/interactive.d.ts.map +1 -0
  41. package/dist/approval/interactive.js +550 -0
  42. package/dist/approval/interactive.js.map +1 -0
  43. package/dist/approval/terminal.d.ts +59 -0
  44. package/dist/approval/terminal.d.ts.map +1 -0
  45. package/dist/approval/terminal.js +238 -0
  46. package/dist/approval/terminal.js.map +1 -0
  47. package/dist/approval/types.d.ts +66 -0
  48. package/dist/approval/types.d.ts.map +1 -0
  49. package/dist/approval/types.js +2 -0
  50. package/dist/approval/types.js.map +1 -0
  51. package/dist/audit/exporter.d.ts +138 -0
  52. package/dist/audit/exporter.d.ts.map +1 -0
  53. package/dist/audit/exporter.js +366 -0
  54. package/dist/audit/exporter.js.map +1 -0
  55. package/dist/audit/logger.d.ts +156 -0
  56. package/dist/audit/logger.d.ts.map +1 -0
  57. package/dist/audit/logger.js +406 -0
  58. package/dist/audit/logger.js.map +1 -0
  59. package/dist/audit/redaction.d.ts +110 -0
  60. package/dist/audit/redaction.d.ts.map +1 -0
  61. package/dist/audit/redaction.js +307 -0
  62. package/dist/audit/redaction.js.map +1 -0
  63. package/dist/audit/schema.d.ts +76 -0
  64. package/dist/audit/schema.d.ts.map +1 -0
  65. package/dist/audit/schema.js +122 -0
  66. package/dist/audit/schema.js.map +1 -0
  67. package/dist/cli/commands/doctor.d.ts +34 -0
  68. package/dist/cli/commands/doctor.d.ts.map +1 -0
  69. package/dist/cli/commands/doctor.js +431 -0
  70. package/dist/cli/commands/doctor.js.map +1 -0
  71. package/dist/cli/commands/export.d.ts +18 -0
  72. package/dist/cli/commands/export.d.ts.map +1 -0
  73. package/dist/cli/commands/export.js +63 -0
  74. package/dist/cli/commands/export.js.map +1 -0
  75. package/dist/cli/commands/init.d.ts +12 -0
  76. package/dist/cli/commands/init.d.ts.map +1 -0
  77. package/dist/cli/commands/init.js +102 -0
  78. package/dist/cli/commands/init.js.map +1 -0
  79. package/dist/cli/commands/logs.d.ts +11 -0
  80. package/dist/cli/commands/logs.d.ts.map +1 -0
  81. package/dist/cli/commands/logs.js +60 -0
  82. package/dist/cli/commands/logs.js.map +1 -0
  83. package/dist/cli/commands/scan.d.ts +29 -0
  84. package/dist/cli/commands/scan.d.ts.map +1 -0
  85. package/dist/cli/commands/scan.js +251 -0
  86. package/dist/cli/commands/scan.js.map +1 -0
  87. package/dist/cli/commands/serve.d.ts +26 -0
  88. package/dist/cli/commands/serve.d.ts.map +1 -0
  89. package/dist/cli/commands/serve.js +424 -0
  90. package/dist/cli/commands/serve.js.map +1 -0
  91. package/dist/cli/commands/start.d.ts +20 -0
  92. package/dist/cli/commands/start.d.ts.map +1 -0
  93. package/dist/cli/commands/start.js +82 -0
  94. package/dist/cli/commands/start.js.map +1 -0
  95. package/dist/cli/commands/stats.d.ts +10 -0
  96. package/dist/cli/commands/stats.d.ts.map +1 -0
  97. package/dist/cli/commands/stats.js +42 -0
  98. package/dist/cli/commands/stats.js.map +1 -0
  99. package/dist/cli/commands/templates.d.ts +26 -0
  100. package/dist/cli/commands/templates.d.ts.map +1 -0
  101. package/dist/cli/commands/templates.js +221 -0
  102. package/dist/cli/commands/templates.js.map +1 -0
  103. package/dist/cli/commands/validate.d.ts +12 -0
  104. package/dist/cli/commands/validate.d.ts.map +1 -0
  105. package/dist/cli/commands/validate.js +107 -0
  106. package/dist/cli/commands/validate.js.map +1 -0
  107. package/dist/cli/commands/wrap.d.ts +19 -0
  108. package/dist/cli/commands/wrap.d.ts.map +1 -0
  109. package/dist/cli/commands/wrap.js +59 -0
  110. package/dist/cli/commands/wrap.js.map +1 -0
  111. package/dist/cli/index.d.ts +17 -0
  112. package/dist/cli/index.d.ts.map +1 -0
  113. package/dist/cli/index.js +202 -0
  114. package/dist/cli/index.js.map +1 -0
  115. package/dist/cli/ui.d.ts +139 -0
  116. package/dist/cli/ui.d.ts.map +1 -0
  117. package/dist/cli/ui.js +271 -0
  118. package/dist/cli/ui.js.map +1 -0
  119. package/dist/constants.d.ts +33 -0
  120. package/dist/constants.d.ts.map +1 -0
  121. package/dist/constants.js +54 -0
  122. package/dist/constants.js.map +1 -0
  123. package/dist/errors.d.ts +28 -0
  124. package/dist/errors.d.ts.map +1 -0
  125. package/dist/errors.js +37 -0
  126. package/dist/errors.js.map +1 -0
  127. package/dist/index.d.ts +49 -0
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +82 -0
  130. package/dist/index.js.map +1 -0
  131. package/dist/orchestrator/index.d.ts +11 -0
  132. package/dist/orchestrator/index.d.ts.map +1 -0
  133. package/dist/orchestrator/index.js +10 -0
  134. package/dist/orchestrator/index.js.map +1 -0
  135. package/dist/orchestrator/manager.d.ts +127 -0
  136. package/dist/orchestrator/manager.d.ts.map +1 -0
  137. package/dist/orchestrator/manager.js +498 -0
  138. package/dist/orchestrator/manager.js.map +1 -0
  139. package/dist/orchestrator/types.d.ts +141 -0
  140. package/dist/orchestrator/types.d.ts.map +1 -0
  141. package/dist/orchestrator/types.js +9 -0
  142. package/dist/orchestrator/types.js.map +1 -0
  143. package/dist/policy/engine.d.ts +55 -0
  144. package/dist/policy/engine.d.ts.map +1 -0
  145. package/dist/policy/engine.js +288 -0
  146. package/dist/policy/engine.js.map +1 -0
  147. package/dist/policy/natural-language.d.ts +141 -0
  148. package/dist/policy/natural-language.d.ts.map +1 -0
  149. package/dist/policy/natural-language.js +552 -0
  150. package/dist/policy/natural-language.js.map +1 -0
  151. package/dist/policy/parser.d.ts +141 -0
  152. package/dist/policy/parser.d.ts.map +1 -0
  153. package/dist/policy/parser.js +314 -0
  154. package/dist/policy/parser.js.map +1 -0
  155. package/dist/policy/types.d.ts +428 -0
  156. package/dist/policy/types.d.ts.map +1 -0
  157. package/dist/policy/types.js +32 -0
  158. package/dist/policy/types.js.map +1 -0
  159. package/dist/policy/validator.d.ts +72 -0
  160. package/dist/policy/validator.d.ts.map +1 -0
  161. package/dist/policy/validator.js +453 -0
  162. package/dist/policy/validator.js.map +1 -0
  163. package/dist/proxy/bridge.d.ts +84 -0
  164. package/dist/proxy/bridge.d.ts.map +1 -0
  165. package/dist/proxy/bridge.js +217 -0
  166. package/dist/proxy/bridge.js.map +1 -0
  167. package/dist/proxy/client.d.ts +130 -0
  168. package/dist/proxy/client.d.ts.map +1 -0
  169. package/dist/proxy/client.js +290 -0
  170. package/dist/proxy/client.js.map +1 -0
  171. package/dist/proxy/server.d.ts +111 -0
  172. package/dist/proxy/server.d.ts.map +1 -0
  173. package/dist/proxy/server.js +444 -0
  174. package/dist/proxy/server.js.map +1 -0
  175. package/dist/scanner.d.ts +91 -0
  176. package/dist/scanner.d.ts.map +1 -0
  177. package/dist/scanner.js +373 -0
  178. package/dist/scanner.js.map +1 -0
  179. package/dist/session/index.d.ts +32 -0
  180. package/dist/session/index.d.ts.map +1 -0
  181. package/dist/session/index.js +31 -0
  182. package/dist/session/index.js.map +1 -0
  183. package/dist/session/manager.d.ts +166 -0
  184. package/dist/session/manager.d.ts.map +1 -0
  185. package/dist/session/manager.js +454 -0
  186. package/dist/session/manager.js.map +1 -0
  187. package/dist/session/sqlite-store.d.ts +54 -0
  188. package/dist/session/sqlite-store.d.ts.map +1 -0
  189. package/dist/session/sqlite-store.js +209 -0
  190. package/dist/session/sqlite-store.js.map +1 -0
  191. package/dist/session/types.d.ts +179 -0
  192. package/dist/session/types.d.ts.map +1 -0
  193. package/dist/session/types.js +38 -0
  194. package/dist/session/types.js.map +1 -0
  195. package/dist/templates.d.ts +64 -0
  196. package/dist/templates.d.ts.map +1 -0
  197. package/dist/templates.js +451 -0
  198. package/dist/templates.js.map +1 -0
  199. package/dist/utils/config.d.ts +57 -0
  200. package/dist/utils/config.d.ts.map +1 -0
  201. package/dist/utils/config.js +104 -0
  202. package/dist/utils/config.js.map +1 -0
  203. package/dist/utils/errors.d.ts +18 -0
  204. package/dist/utils/errors.d.ts.map +1 -0
  205. package/dist/utils/errors.js +35 -0
  206. package/dist/utils/errors.js.map +1 -0
  207. package/dist/utils/logger.d.ts +144 -0
  208. package/dist/utils/logger.d.ts.map +1 -0
  209. package/dist/utils/logger.js +300 -0
  210. package/dist/utils/logger.js.map +1 -0
  211. package/dist/wizard.d.ts +68 -0
  212. package/dist/wizard.d.ts.map +1 -0
  213. package/dist/wizard.js +395 -0
  214. package/dist/wizard.js.map +1 -0
  215. package/package.json +99 -0
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Interactive approval handler for Tollgate
3
+ *
4
+ * Serves a web UI for approving tool calls, enabling approval from
5
+ * any browser rather than just the terminal.
6
+ */
7
+ import type { ApprovalHandler, ApprovalRequest, ApprovalResponse } from './types.js';
8
+ /**
9
+ * Interactive approval handler that serves a web UI.
10
+ *
11
+ * When an approval is needed, the handler:
12
+ * 1. Adds the request to a pending queue
13
+ * 2. Notifies connected browsers via Server-Sent Events
14
+ * 3. Waits for a response from the web UI
15
+ * 4. Returns the approval decision
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const handler = new InteractiveApprovalHandler({ port: 9847, timeoutMs: 60000 });
20
+ * await handler.start();
21
+ *
22
+ * // Open http://localhost:9847 to see pending approvals
23
+ * const response = await handler.prompt(request);
24
+ * ```
25
+ */
26
+ export declare class InteractiveApprovalHandler implements ApprovalHandler {
27
+ private server;
28
+ private pendingRequests;
29
+ private sseClients;
30
+ private port;
31
+ private timeoutMs;
32
+ private isStarted;
33
+ constructor(options?: {
34
+ port?: number;
35
+ timeoutMs?: number;
36
+ });
37
+ /**
38
+ * Starts the HTTP server for the web UI.
39
+ */
40
+ start(): Promise<void>;
41
+ prompt(request: ApprovalRequest): Promise<ApprovalResponse>;
42
+ close(): void;
43
+ /**
44
+ * Handles incoming HTTP requests.
45
+ */
46
+ private handleRequest;
47
+ /**
48
+ * Serves the main approval UI.
49
+ */
50
+ private serveUI;
51
+ /**
52
+ * Returns current pending requests as JSON.
53
+ */
54
+ private serveRequests;
55
+ /**
56
+ * Handles Server-Sent Events for real-time updates.
57
+ */
58
+ private handleSSE;
59
+ /**
60
+ * Broadcasts updates to all SSE clients.
61
+ */
62
+ private broadcastUpdate;
63
+ /**
64
+ * Handles approval/denial responses from the UI.
65
+ */
66
+ private handleResponse;
67
+ /**
68
+ * Generates the HTML for the approval UI.
69
+ */
70
+ private generateHTML;
71
+ }
72
+ //# sourceMappingURL=interactive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../src/approval/interactive.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAGjB,MAAM,YAAY,CAAC;AAgBpB;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,0BAA2B,YAAW,eAAe;IAChE,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,eAAe,CAAqC;IAC5D,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;gBAEd,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO;IAK/D;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBtB,MAAM,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA8CjE,KAAK,IAAI,IAAI;IA0Bb;;OAEG;IACH,OAAO,CAAC,aAAa;IA6BrB;;OAEG;IACH,OAAO,CAAC,OAAO;IAKf;;OAEG;IACH,OAAO,CAAC,aAAa;IAkBrB;;OAEG;IACH,OAAO,CAAC,SAAS;IAkBjB;;OAEG;IACH,OAAO,CAAC,eAAe;IAOvB;;OAEG;IACH,OAAO,CAAC,cAAc;IAkEtB;;OAEG;IACH,OAAO,CAAC,YAAY;CA0RrB"}
@@ -0,0 +1,550 @@
1
+ /**
2
+ * Interactive approval handler for Tollgate
3
+ *
4
+ * Serves a web UI for approving tool calls, enabling approval from
5
+ * any browser rather than just the terminal.
6
+ */
7
+ import * as http from 'node:http';
8
+ import { approvalLogger as logger } from '../utils/logger.js';
9
+ import { DEFAULT_APPROVAL_TIMEOUT_MS, DEFAULT_APPROVAL_PORT, MAX_APPROVAL_REQUEST_BODY_BYTES, } from '../constants.js';
10
+ /**
11
+ * Interactive approval handler that serves a web UI.
12
+ *
13
+ * When an approval is needed, the handler:
14
+ * 1. Adds the request to a pending queue
15
+ * 2. Notifies connected browsers via Server-Sent Events
16
+ * 3. Waits for a response from the web UI
17
+ * 4. Returns the approval decision
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const handler = new InteractiveApprovalHandler({ port: 9847, timeoutMs: 60000 });
22
+ * await handler.start();
23
+ *
24
+ * // Open http://localhost:9847 to see pending approvals
25
+ * const response = await handler.prompt(request);
26
+ * ```
27
+ */
28
+ export class InteractiveApprovalHandler {
29
+ server = null;
30
+ pendingRequests = new Map();
31
+ sseClients = new Set();
32
+ port;
33
+ timeoutMs;
34
+ isStarted = false;
35
+ constructor(options = {}) {
36
+ this.port = options.port ?? DEFAULT_APPROVAL_PORT;
37
+ this.timeoutMs = options.timeoutMs ?? DEFAULT_APPROVAL_TIMEOUT_MS;
38
+ }
39
+ /**
40
+ * Starts the HTTP server for the web UI.
41
+ */
42
+ async start() {
43
+ if (this.isStarted)
44
+ return;
45
+ return new Promise((resolve, reject) => {
46
+ this.server = http.createServer((req, res) => this.handleRequest(req, res));
47
+ this.server.on('error', (err) => {
48
+ if (err.code === 'EADDRINUSE') {
49
+ reject(new Error(`Port ${this.port} is already in use. Choose a different port for the approval UI.`));
50
+ }
51
+ else {
52
+ reject(err);
53
+ }
54
+ });
55
+ this.server.listen(this.port, () => {
56
+ this.isStarted = true;
57
+ logger.info('Approval UI available', { url: `http://localhost:${this.port}` });
58
+ resolve();
59
+ });
60
+ });
61
+ }
62
+ async prompt(request) {
63
+ // Auto-start if not started
64
+ if (!this.isStarted) {
65
+ await this.start();
66
+ }
67
+ const startTime = Date.now();
68
+ return new Promise((resolve) => {
69
+ // Set up timeout
70
+ const timeout = setTimeout(() => {
71
+ this.pendingRequests.delete(request.id);
72
+ this.broadcastUpdate();
73
+ logger.warn('Approval request timed out', { requestId: request.id });
74
+ resolve({
75
+ result: 'timeout',
76
+ respondedAt: new Date(),
77
+ durationMs: Date.now() - startTime,
78
+ });
79
+ }, this.timeoutMs);
80
+ // Store pending request
81
+ this.pendingRequests.set(request.id, {
82
+ request,
83
+ resolve: (response) => {
84
+ clearTimeout(timeout);
85
+ this.pendingRequests.delete(request.id);
86
+ this.broadcastUpdate();
87
+ resolve(response);
88
+ },
89
+ startTime,
90
+ timeout,
91
+ });
92
+ // Notify UI of new request
93
+ this.broadcastUpdate();
94
+ // Also log to terminal as a fallback notification
95
+ logger.info('Approval required - open web UI to respond', {
96
+ url: `http://localhost:${this.port}`,
97
+ server: request.context.server,
98
+ tool: request.context.tool,
99
+ });
100
+ });
101
+ }
102
+ close() {
103
+ // Resolve all pending requests as denied
104
+ for (const pending of this.pendingRequests.values()) {
105
+ clearTimeout(pending.timeout);
106
+ pending.resolve({
107
+ result: 'denied',
108
+ respondedAt: new Date(),
109
+ durationMs: Date.now() - pending.startTime,
110
+ });
111
+ }
112
+ this.pendingRequests.clear();
113
+ // Close SSE connections
114
+ for (const client of this.sseClients) {
115
+ client.end();
116
+ }
117
+ this.sseClients.clear();
118
+ // Close server
119
+ if (this.server) {
120
+ this.server.close();
121
+ this.server = null;
122
+ this.isStarted = false;
123
+ }
124
+ }
125
+ /**
126
+ * Handles incoming HTTP requests.
127
+ */
128
+ handleRequest(req, res) {
129
+ const url = new URL(req.url ?? '/', `http://localhost:${this.port}`);
130
+ // Enable CORS for local development
131
+ res.setHeader('Access-Control-Allow-Origin', '*');
132
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
133
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
134
+ if (req.method === 'OPTIONS') {
135
+ res.writeHead(204);
136
+ res.end();
137
+ return;
138
+ }
139
+ // Route requests
140
+ if (url.pathname === '/' && req.method === 'GET') {
141
+ this.serveUI(res);
142
+ }
143
+ else if (url.pathname === '/api/requests' && req.method === 'GET') {
144
+ this.serveRequests(res);
145
+ }
146
+ else if (url.pathname === '/api/events' && req.method === 'GET') {
147
+ this.handleSSE(res);
148
+ }
149
+ else if (url.pathname === '/api/respond' && req.method === 'POST') {
150
+ this.handleResponse(req, res);
151
+ }
152
+ else {
153
+ res.writeHead(404, { 'Content-Type': 'application/json' });
154
+ res.end(JSON.stringify({ error: 'Not found' }));
155
+ }
156
+ }
157
+ /**
158
+ * Serves the main approval UI.
159
+ */
160
+ serveUI(res) {
161
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
162
+ res.end(this.generateHTML());
163
+ }
164
+ /**
165
+ * Returns current pending requests as JSON.
166
+ */
167
+ serveRequests(res) {
168
+ const requests = Array.from(this.pendingRequests.values()).map((p) => ({
169
+ id: p.request.id,
170
+ server: p.request.context.server,
171
+ tool: p.request.context.tool,
172
+ args: p.request.context.args,
173
+ risk: p.request.decision.analysis?.risk ?? 'unknown',
174
+ rule: p.request.decision.matchedRule ?? 'default',
175
+ message: p.request.decision.message,
176
+ timestamp: p.request.timestamp.toISOString(),
177
+ elapsedMs: Date.now() - p.startTime,
178
+ timeoutMs: this.timeoutMs,
179
+ }));
180
+ res.writeHead(200, { 'Content-Type': 'application/json' });
181
+ res.end(JSON.stringify({ requests }));
182
+ }
183
+ /**
184
+ * Handles Server-Sent Events for real-time updates.
185
+ */
186
+ handleSSE(res) {
187
+ res.writeHead(200, {
188
+ 'Content-Type': 'text/event-stream',
189
+ 'Cache-Control': 'no-cache',
190
+ 'Connection': 'keep-alive',
191
+ });
192
+ this.sseClients.add(res);
193
+ // Send initial data
194
+ res.write(`data: ${JSON.stringify({ type: 'connected' })}\n\n`);
195
+ // Handle client disconnect
196
+ res.on('close', () => {
197
+ this.sseClients.delete(res);
198
+ });
199
+ }
200
+ /**
201
+ * Broadcasts updates to all SSE clients.
202
+ */
203
+ broadcastUpdate() {
204
+ const message = `data: ${JSON.stringify({ type: 'update' })}\n\n`;
205
+ for (const client of this.sseClients) {
206
+ client.write(message);
207
+ }
208
+ }
209
+ /**
210
+ * Handles approval/denial responses from the UI.
211
+ */
212
+ handleResponse(req, res) {
213
+ let body = '';
214
+ let bodySize = 0;
215
+ req.on('data', (chunk) => {
216
+ const chunkSize = Buffer.isBuffer(chunk) ? chunk.length : Buffer.byteLength(chunk);
217
+ bodySize += chunkSize;
218
+ // Reject oversized requests to prevent DoS
219
+ if (bodySize > MAX_APPROVAL_REQUEST_BODY_BYTES) {
220
+ res.writeHead(413, { 'Content-Type': 'application/json' });
221
+ res.end(JSON.stringify({ error: 'Request body too large' }));
222
+ req.destroy();
223
+ return;
224
+ }
225
+ body += chunk;
226
+ });
227
+ req.on('end', () => {
228
+ try {
229
+ const data = JSON.parse(body);
230
+ const pending = this.pendingRequests.get(data.requestId);
231
+ if (!pending) {
232
+ res.writeHead(404, { 'Content-Type': 'application/json' });
233
+ res.end(JSON.stringify({ error: 'Request not found or already responded' }));
234
+ return;
235
+ }
236
+ // Build session grant if duration provided
237
+ let sessionGrant;
238
+ if (data.result === 'approved' && data.duration && data.duration !== 'once') {
239
+ sessionGrant = {
240
+ scope: data.scope ?? 'tool',
241
+ duration: data.duration,
242
+ };
243
+ }
244
+ // Resolve the pending request
245
+ pending.resolve({
246
+ result: data.result,
247
+ respondedAt: new Date(),
248
+ durationMs: Date.now() - pending.startTime,
249
+ sessionGrant,
250
+ });
251
+ res.writeHead(200, { 'Content-Type': 'application/json' });
252
+ res.end(JSON.stringify({ success: true }));
253
+ logger.info('Request resolved via web UI', {
254
+ requestId: data.requestId,
255
+ result: data.result,
256
+ });
257
+ }
258
+ catch (_err) {
259
+ res.writeHead(400, { 'Content-Type': 'application/json' });
260
+ res.end(JSON.stringify({ error: 'Invalid request body' }));
261
+ }
262
+ });
263
+ }
264
+ /**
265
+ * Generates the HTML for the approval UI.
266
+ */
267
+ generateHTML() {
268
+ return `<!DOCTYPE html>
269
+ <html lang="en">
270
+ <head>
271
+ <meta charset="UTF-8">
272
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
273
+ <title>Tollgate Approval</title>
274
+ <style>
275
+ * { box-sizing: border-box; margin: 0; padding: 0; }
276
+ body {
277
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
278
+ background: #0f1419;
279
+ color: #e7e9ea;
280
+ min-height: 100vh;
281
+ padding: 2rem;
282
+ }
283
+ .container { max-width: 800px; margin: 0 auto; }
284
+ h1 {
285
+ font-size: 1.5rem;
286
+ margin-bottom: 0.5rem;
287
+ display: flex;
288
+ align-items: center;
289
+ gap: 0.5rem;
290
+ }
291
+ .subtitle { color: #71767b; margin-bottom: 2rem; }
292
+ .badge {
293
+ font-size: 0.75rem;
294
+ padding: 0.25rem 0.5rem;
295
+ border-radius: 9999px;
296
+ background: #22c55e20;
297
+ color: #22c55e;
298
+ }
299
+ .no-requests {
300
+ text-align: center;
301
+ padding: 4rem 2rem;
302
+ background: #16181c;
303
+ border-radius: 1rem;
304
+ border: 1px dashed #2f3336;
305
+ }
306
+ .no-requests h2 { color: #71767b; margin-bottom: 0.5rem; }
307
+ .request-card {
308
+ background: #16181c;
309
+ border: 1px solid #2f3336;
310
+ border-radius: 1rem;
311
+ padding: 1.5rem;
312
+ margin-bottom: 1rem;
313
+ }
314
+ .request-header {
315
+ display: flex;
316
+ justify-content: space-between;
317
+ align-items: flex-start;
318
+ margin-bottom: 1rem;
319
+ }
320
+ .request-title {
321
+ font-size: 1.125rem;
322
+ font-weight: 600;
323
+ }
324
+ .request-meta { font-size: 0.875rem; color: #71767b; }
325
+ .risk-badge {
326
+ font-size: 0.75rem;
327
+ padding: 0.25rem 0.75rem;
328
+ border-radius: 9999px;
329
+ font-weight: 600;
330
+ }
331
+ .risk-safe { background: #22c55e20; color: #22c55e; }
332
+ .risk-read { background: #3b82f620; color: #3b82f6; }
333
+ .risk-write { background: #f59e0b20; color: #f59e0b; }
334
+ .risk-destructive { background: #f97316; color: white; }
335
+ .risk-dangerous { background: #ef4444; color: white; }
336
+ .risk-unknown { background: #71767b20; color: #71767b; }
337
+ .args-section {
338
+ background: #0f1419;
339
+ border-radius: 0.5rem;
340
+ padding: 1rem;
341
+ margin: 1rem 0;
342
+ font-family: 'Monaco', 'Menlo', monospace;
343
+ font-size: 0.8125rem;
344
+ overflow-x: auto;
345
+ white-space: pre-wrap;
346
+ word-break: break-all;
347
+ }
348
+ .message {
349
+ padding: 0.75rem 1rem;
350
+ background: #f59e0b15;
351
+ border-left: 3px solid #f59e0b;
352
+ border-radius: 0 0.5rem 0.5rem 0;
353
+ margin: 1rem 0;
354
+ font-size: 0.875rem;
355
+ }
356
+ .actions {
357
+ display: flex;
358
+ gap: 0.5rem;
359
+ flex-wrap: wrap;
360
+ margin-top: 1rem;
361
+ }
362
+ button {
363
+ padding: 0.625rem 1rem;
364
+ border-radius: 0.5rem;
365
+ font-weight: 600;
366
+ font-size: 0.875rem;
367
+ cursor: pointer;
368
+ border: none;
369
+ transition: all 0.15s;
370
+ }
371
+ button:hover { filter: brightness(1.1); }
372
+ button:disabled { opacity: 0.5; cursor: not-allowed; }
373
+ .btn-approve { background: #22c55e; color: white; }
374
+ .btn-approve-session { background: #3b82f6; color: white; }
375
+ .btn-deny { background: #ef4444; color: white; }
376
+ .timer {
377
+ font-size: 0.75rem;
378
+ color: #71767b;
379
+ margin-top: 0.5rem;
380
+ }
381
+ .timer.urgent { color: #f59e0b; }
382
+ .timer.critical { color: #ef4444; }
383
+ .connected-status {
384
+ position: fixed;
385
+ bottom: 1rem;
386
+ right: 1rem;
387
+ padding: 0.5rem 1rem;
388
+ border-radius: 9999px;
389
+ font-size: 0.75rem;
390
+ background: #16181c;
391
+ border: 1px solid #2f3336;
392
+ }
393
+ .connected-status.online { border-color: #22c55e; color: #22c55e; }
394
+ .connected-status.offline { border-color: #ef4444; color: #ef4444; }
395
+ </style>
396
+ </head>
397
+ <body>
398
+ <div class="container">
399
+ <h1>
400
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
401
+ <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
402
+ </svg>
403
+ Tollgate Approval
404
+ <span class="badge" id="count">0 pending</span>
405
+ </h1>
406
+ <p class="subtitle">Review and approve AI agent actions</p>
407
+
408
+ <div id="requests"></div>
409
+ </div>
410
+
411
+ <div class="connected-status" id="status">Connecting...</div>
412
+
413
+ <script>
414
+ let requests = [];
415
+ let eventSource = null;
416
+
417
+ function formatArgs(args) {
418
+ return JSON.stringify(args, null, 2);
419
+ }
420
+
421
+ function getRiskClass(risk) {
422
+ const classes = {
423
+ safe: 'risk-safe',
424
+ read: 'risk-read',
425
+ write: 'risk-write',
426
+ destructive: 'risk-destructive',
427
+ dangerous: 'risk-dangerous',
428
+ };
429
+ return classes[risk] || 'risk-unknown';
430
+ }
431
+
432
+ function renderRequests() {
433
+ const container = document.getElementById('requests');
434
+ const countEl = document.getElementById('count');
435
+
436
+ countEl.textContent = requests.length + ' pending';
437
+
438
+ if (requests.length === 0) {
439
+ container.innerHTML = \`
440
+ <div class="no-requests">
441
+ <h2>No pending approvals</h2>
442
+ <p>When an AI agent needs approval, it will appear here.</p>
443
+ </div>
444
+ \`;
445
+ return;
446
+ }
447
+
448
+ container.innerHTML = requests.map(req => {
449
+ const remaining = Math.max(0, req.timeoutMs - req.elapsedMs);
450
+ const seconds = Math.ceil(remaining / 1000);
451
+ const timerClass = seconds < 10 ? 'critical' : seconds < 30 ? 'urgent' : '';
452
+
453
+ return \`
454
+ <div class="request-card" data-id="\${req.id}">
455
+ <div class="request-header">
456
+ <div>
457
+ <div class="request-title">\${req.server} → \${req.tool}</div>
458
+ <div class="request-meta">Rule: \${req.rule}</div>
459
+ </div>
460
+ <span class="risk-badge \${getRiskClass(req.risk)}">\${req.risk}</span>
461
+ </div>
462
+
463
+ \${req.message ? \`<div class="message">\${req.message}</div>\` : ''}
464
+
465
+ <div class="args-section">\${formatArgs(req.args)}</div>
466
+
467
+ <div class="actions">
468
+ <button class="btn-deny" onclick="respond('\${req.id}', 'denied')">Deny</button>
469
+ <button class="btn-approve" onclick="respond('\${req.id}', 'approved', null, 'once')">Allow Once</button>
470
+ <button class="btn-approve-session" onclick="respond('\${req.id}', 'approved', 'tool', '5min')">Allow 5 min</button>
471
+ <button class="btn-approve-session" onclick="respond('\${req.id}', 'approved', 'tool', '15min')">Allow 15 min</button>
472
+ <button class="btn-approve-session" onclick="respond('\${req.id}', 'approved', 'tool', 'session')">Allow Session</button>
473
+ </div>
474
+
475
+ <div class="timer \${timerClass}">Auto-deny in \${seconds}s</div>
476
+ </div>
477
+ \`;
478
+ }).join('');
479
+ }
480
+
481
+ async function fetchRequests() {
482
+ try {
483
+ const res = await fetch('/api/requests');
484
+ const data = await res.json();
485
+ requests = data.requests;
486
+ renderRequests();
487
+ } catch (err) {
488
+ console.error('Failed to fetch requests:', err);
489
+ }
490
+ }
491
+
492
+ async function respond(requestId, result, scope, duration) {
493
+ const buttons = document.querySelectorAll(\`[data-id="\${requestId}"] button\`);
494
+ buttons.forEach(btn => btn.disabled = true);
495
+
496
+ try {
497
+ await fetch('/api/respond', {
498
+ method: 'POST',
499
+ headers: { 'Content-Type': 'application/json' },
500
+ body: JSON.stringify({ requestId, result, scope, duration }),
501
+ });
502
+ } catch (err) {
503
+ console.error('Failed to respond:', err);
504
+ buttons.forEach(btn => btn.disabled = false);
505
+ }
506
+ }
507
+
508
+ function connectSSE() {
509
+ const statusEl = document.getElementById('status');
510
+
511
+ eventSource = new EventSource('/api/events');
512
+
513
+ eventSource.onopen = () => {
514
+ statusEl.textContent = 'Connected';
515
+ statusEl.className = 'connected-status online';
516
+ };
517
+
518
+ eventSource.onmessage = (event) => {
519
+ const data = JSON.parse(event.data);
520
+ if (data.type === 'update') {
521
+ fetchRequests();
522
+ }
523
+ };
524
+
525
+ eventSource.onerror = () => {
526
+ statusEl.textContent = 'Disconnected';
527
+ statusEl.className = 'connected-status offline';
528
+ eventSource.close();
529
+ setTimeout(connectSSE, 2000);
530
+ };
531
+ }
532
+
533
+ // Update timers every second
534
+ setInterval(() => {
535
+ requests = requests.map(req => ({
536
+ ...req,
537
+ elapsedMs: req.elapsedMs + 1000,
538
+ }));
539
+ renderRequests();
540
+ }, 1000);
541
+
542
+ // Initial load
543
+ fetchRequests();
544
+ connectSSE();
545
+ </script>
546
+ </body>
547
+ </html>`;
548
+ }
549
+ }
550
+ //# sourceMappingURL=interactive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive.js","sourceRoot":"","sources":["../../src/approval/interactive.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AASlC,OAAO,EAAE,cAAc,IAAI,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,EACrB,+BAA+B,GAChC,MAAM,iBAAiB,CAAC;AASzB;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,0BAA0B;IAC7B,MAAM,GAAuB,IAAI,CAAC;IAClC,eAAe,GAAG,IAAI,GAAG,EAA0B,CAAC;IACpD,UAAU,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC5C,IAAI,CAAS;IACb,SAAS,CAAS;IAClB,SAAS,GAAG,KAAK,CAAC;IAE1B,YAAY,UAAiD,EAAE;QAC7D,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,qBAAqB,CAAC;QAClD,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,2BAA2B,CAAC;IACpE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAE3B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAE5E,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;gBACrD,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAC9B,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,IAAI,kEAAkE,CAAC,CAAC,CAAC;gBACzG,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,GAAG,CAAC,CAAC;gBACd,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE;gBACjC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,GAAG,EAAE,oBAAoB,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC/E,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAwB;QACnC,4BAA4B;QAC5B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,iBAAiB;YACjB,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC9B,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBACxC,IAAI,CAAC,eAAe,EAAE,CAAC;gBACvB,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;gBACrE,OAAO,CAAC;oBACN,MAAM,EAAE,SAAS;oBACjB,WAAW,EAAE,IAAI,IAAI,EAAE;oBACvB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;iBACnC,CAAC,CAAC;YACL,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAEnB,wBAAwB;YACxB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE;gBACnC,OAAO;gBACP,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE;oBACpB,YAAY,CAAC,OAAO,CAAC,CAAC;oBACtB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBACxC,IAAI,CAAC,eAAe,EAAE,CAAC;oBACvB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACpB,CAAC;gBACD,SAAS;gBACT,OAAO;aACR,CAAC,CAAC;YAEH,2BAA2B;YAC3B,IAAI,CAAC,eAAe,EAAE,CAAC;YAEvB,kDAAkD;YAClD,MAAM,CAAC,IAAI,CAAC,4CAA4C,EAAE;gBACxD,GAAG,EAAE,oBAAoB,IAAI,CAAC,IAAI,EAAE;gBACpC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM;gBAC9B,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI;aAC3B,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK;QACH,yCAAyC;QACzC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC;YACpD,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC9B,OAAO,CAAC,OAAO,CAAC;gBACd,MAAM,EAAE,QAAQ;gBAChB,WAAW,EAAE,IAAI,IAAI,EAAE;gBACvB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS;aAC3C,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAE7B,wBAAwB;QACxB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACrC,MAAM,CAAC,GAAG,EAAE,CAAC;QACf,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QAExB,eAAe;QACf,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACpB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,GAAyB,EAAE,GAAwB;QACvE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,oBAAoB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAErE,oCAAoC;QACpC,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;QAClD,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,oBAAoB,CAAC,CAAC;QACpE,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC;QAE9D,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,iBAAiB;QACjB,IAAI,GAAG,CAAC,QAAQ,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YACjD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;aAAM,IAAI,GAAG,CAAC,QAAQ,KAAK,eAAe,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YACpE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,GAAG,CAAC,QAAQ,KAAK,aAAa,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAClE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;aAAM,IAAI,GAAG,CAAC,QAAQ,KAAK,cAAc,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YACpE,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED;;OAEG;IACK,OAAO,CAAC,GAAwB;QACtC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;QACnE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,GAAwB;QAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACrE,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE;YAChB,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM;YAChC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI;YAC5B,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI;YAC5B,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,IAAI,SAAS;YACpD,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,IAAI,SAAS;YACjD,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO;YACnC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE;YAC5C,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,SAAS;YACnC,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC,CAAC;QAEJ,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACK,SAAS,CAAC,GAAwB;QACxC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACjB,cAAc,EAAE,mBAAmB;YACnC,eAAe,EAAE,UAAU;YAC3B,YAAY,EAAE,YAAY;SAC3B,CAAC,CAAC;QAEH,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEzB,oBAAoB;QACpB,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC;QAEhE,2BAA2B;QAC3B,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACnB,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,eAAe;QACrB,MAAM,OAAO,GAAG,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC;QAClE,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACrC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,GAAyB,EAAE,GAAwB;QACxE,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,IAAI,QAAQ,GAAG,CAAC,CAAC;QAEjB,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAsB,EAAE,EAAE;YACxC,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YACnF,QAAQ,IAAI,SAAS,CAAC;YAEtB,2CAA2C;YAC3C,IAAI,QAAQ,GAAG,+BAA+B,EAAE,CAAC;gBAC/C,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAC,CAAC;gBAC7D,GAAG,CAAC,OAAO,EAAE,CAAC;gBACd,OAAO;YACT,CAAC;YAED,IAAI,IAAI,KAAK,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACjB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAK3B,CAAC;gBAEF,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACzD,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;oBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,wCAAwC,EAAE,CAAC,CAAC,CAAC;oBAC7E,OAAO;gBACT,CAAC;gBAED,2CAA2C;gBAC3C,IAAI,YAA0C,CAAC;gBAC/C,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;oBAC5E,YAAY,GAAG;wBACb,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,MAAM;wBAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;qBACxB,CAAC;gBACJ,CAAC;gBAED,8BAA8B;gBAC9B,OAAO,CAAC,OAAO,CAAC;oBACd,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,WAAW,EAAE,IAAI,IAAI,EAAE;oBACvB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS;oBAC1C,YAAY;iBACb,CAAC,CAAC;gBAEH,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;gBAE3C,MAAM,CAAC,IAAI,CAAC,6BAA6B,EAAE;oBACzC,SAAS,EAAE,IAAI,CAAC,SAAS;oBACzB,MAAM,EAAE,IAAI,CAAC,MAAM;iBACpB,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,IAAI,EAAE,CAAC;gBACd,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAuRH,CAAC;IACP,CAAC;CACF"}