@rndmjoker/proton-mcp 0.4.4

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 (141) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +405 -0
  3. package/dist/activity.d.ts +49 -0
  4. package/dist/activity.js +72 -0
  5. package/dist/activity.js.map +1 -0
  6. package/dist/bridge/certificate.d.ts +75 -0
  7. package/dist/bridge/certificate.js +176 -0
  8. package/dist/bridge/certificate.js.map +1 -0
  9. package/dist/bridge/connection.d.ts +99 -0
  10. package/dist/bridge/connection.js +244 -0
  11. package/dist/bridge/connection.js.map +1 -0
  12. package/dist/bridge/errors.d.ts +35 -0
  13. package/dist/bridge/errors.js +56 -0
  14. package/dist/bridge/errors.js.map +1 -0
  15. package/dist/config.d.ts +92 -0
  16. package/dist/config.js +142 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/credentials/availability.d.ts +62 -0
  19. package/dist/credentials/availability.js +107 -0
  20. package/dist/credentials/availability.js.map +1 -0
  21. package/dist/credentials/encrypted-file.d.ts +50 -0
  22. package/dist/credentials/encrypted-file.js +156 -0
  23. package/dist/credentials/encrypted-file.js.map +1 -0
  24. package/dist/credentials/keyring.d.ts +48 -0
  25. package/dist/credentials/keyring.js +97 -0
  26. package/dist/credentials/keyring.js.map +1 -0
  27. package/dist/credentials/plain-file.d.ts +24 -0
  28. package/dist/credentials/plain-file.js +78 -0
  29. package/dist/credentials/plain-file.js.map +1 -0
  30. package/dist/credentials/probe-keyring.d.ts +11 -0
  31. package/dist/credentials/probe-keyring.js +57 -0
  32. package/dist/credentials/probe-keyring.js.map +1 -0
  33. package/dist/credentials/session.d.ts +15 -0
  34. package/dist/credentials/session.js +21 -0
  35. package/dist/credentials/session.js.map +1 -0
  36. package/dist/credentials/store.d.ts +80 -0
  37. package/dist/credentials/store.js +94 -0
  38. package/dist/credentials/store.js.map +1 -0
  39. package/dist/in-flight.d.ts +33 -0
  40. package/dist/in-flight.js +78 -0
  41. package/dist/in-flight.js.map +1 -0
  42. package/dist/mail/actions.d.ts +116 -0
  43. package/dist/mail/actions.js +265 -0
  44. package/dist/mail/actions.js.map +1 -0
  45. package/dist/mail/attachments.d.ts +39 -0
  46. package/dist/mail/attachments.js +86 -0
  47. package/dist/mail/attachments.js.map +1 -0
  48. package/dist/mail/compose.d.ts +264 -0
  49. package/dist/mail/compose.js +395 -0
  50. package/dist/mail/compose.js.map +1 -0
  51. package/dist/mail/drafts.d.ts +138 -0
  52. package/dist/mail/drafts.js +449 -0
  53. package/dist/mail/drafts.js.map +1 -0
  54. package/dist/mail/ids.d.ts +78 -0
  55. package/dist/mail/ids.js +135 -0
  56. package/dist/mail/ids.js.map +1 -0
  57. package/dist/mail/labels.d.ts +61 -0
  58. package/dist/mail/labels.js +139 -0
  59. package/dist/mail/labels.js.map +1 -0
  60. package/dist/mail/markup.d.ts +91 -0
  61. package/dist/mail/markup.js +265 -0
  62. package/dist/mail/markup.js.map +1 -0
  63. package/dist/mail/messages.d.ts +147 -0
  64. package/dist/mail/messages.js +219 -0
  65. package/dist/mail/messages.js.map +1 -0
  66. package/dist/mail/quote.d.ts +65 -0
  67. package/dist/mail/quote.js +157 -0
  68. package/dist/mail/quote.js.map +1 -0
  69. package/dist/mail/search.d.ts +66 -0
  70. package/dist/mail/search.js +107 -0
  71. package/dist/mail/search.js.map +1 -0
  72. package/dist/mail/send.d.ts +61 -0
  73. package/dist/mail/send.js +132 -0
  74. package/dist/mail/send.js.map +1 -0
  75. package/dist/mime/parse.d.ts +110 -0
  76. package/dist/mime/parse.js +194 -0
  77. package/dist/mime/parse.js.map +1 -0
  78. package/dist/server.d.ts +13 -0
  79. package/dist/server.js +387 -0
  80. package/dist/server.js.map +1 -0
  81. package/dist/session.d.ts +86 -0
  82. package/dist/session.js +220 -0
  83. package/dist/session.js.map +1 -0
  84. package/dist/settings.d.ts +52 -0
  85. package/dist/settings.js +80 -0
  86. package/dist/settings.js.map +1 -0
  87. package/dist/tools/actions.d.ts +21 -0
  88. package/dist/tools/actions.js +133 -0
  89. package/dist/tools/actions.js.map +1 -0
  90. package/dist/tools/capabilities.d.ts +52 -0
  91. package/dist/tools/capabilities.js +96 -0
  92. package/dist/tools/capabilities.js.map +1 -0
  93. package/dist/tools/confirm.d.ts +84 -0
  94. package/dist/tools/confirm.js +212 -0
  95. package/dist/tools/confirm.js.map +1 -0
  96. package/dist/tools/drafts.d.ts +21 -0
  97. package/dist/tools/drafts.js +199 -0
  98. package/dist/tools/drafts.js.map +1 -0
  99. package/dist/tools/failures.d.ts +46 -0
  100. package/dist/tools/failures.js +157 -0
  101. package/dist/tools/failures.js.map +1 -0
  102. package/dist/tools/format.d.ts +55 -0
  103. package/dist/tools/format.js +220 -0
  104. package/dist/tools/format.js.map +1 -0
  105. package/dist/tools/guidance.d.ts +38 -0
  106. package/dist/tools/guidance.js +226 -0
  107. package/dist/tools/guidance.js.map +1 -0
  108. package/dist/tools/interface.d.ts +28 -0
  109. package/dist/tools/interface.js +63 -0
  110. package/dist/tools/interface.js.map +1 -0
  111. package/dist/tools/labels.d.ts +21 -0
  112. package/dist/tools/labels.js +92 -0
  113. package/dist/tools/labels.js.map +1 -0
  114. package/dist/tools/list-folders.d.ts +14 -0
  115. package/dist/tools/list-folders.js +70 -0
  116. package/dist/tools/list-folders.js.map +1 -0
  117. package/dist/tools/messages.d.ts +9 -0
  118. package/dist/tools/messages.js +221 -0
  119. package/dist/tools/messages.js.map +1 -0
  120. package/dist/tools/send.d.ts +29 -0
  121. package/dist/tools/send.js +236 -0
  122. package/dist/tools/send.js.map +1 -0
  123. package/dist/tools/sign-in-required.d.ts +94 -0
  124. package/dist/tools/sign-in-required.js +168 -0
  125. package/dist/tools/sign-in-required.js.map +1 -0
  126. package/dist/web/layout.d.ts +75 -0
  127. package/dist/web/layout.js +590 -0
  128. package/dist/web/layout.js.map +1 -0
  129. package/dist/web/pages.d.ts +79 -0
  130. package/dist/web/pages.js +284 -0
  131. package/dist/web/pages.js.map +1 -0
  132. package/dist/web/sections.d.ts +105 -0
  133. package/dist/web/sections.js +207 -0
  134. package/dist/web/sections.js.map +1 -0
  135. package/dist/web/security.d.ts +122 -0
  136. package/dist/web/security.js +180 -0
  137. package/dist/web/security.js.map +1 -0
  138. package/dist/web/server.d.ts +153 -0
  139. package/dist/web/server.js +622 -0
  140. package/dist/web/server.js.map +1 -0
  141. package/package.json +70 -0
package/dist/server.js ADDED
@@ -0,0 +1,387 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Entry point of the MCP server.
4
+ *
5
+ * The server speaks over stdio, so the client starts it as a child process.
6
+ * That is not a workaround: the Bridge only listens on 127.0.0.1, so a server
7
+ * running in the cloud could not reach it at all.
8
+ *
9
+ * The local web interface runs for as long as this process does. It is not
10
+ * started on demand: it is where configuration and state live, and it is meant
11
+ * to be opened again and again rather than summoned for one sign-in.
12
+ */
13
+ import { createRequire } from 'node:module';
14
+ import { randomBytes } from 'node:crypto';
15
+ import { McpServer, createRequestStateCodec } from '@modelcontextprotocol/server';
16
+ import { serveStdio } from '@modelcontextprotocol/server/stdio';
17
+ import { loadConfig, credentialsFromEnvironment, portsSetExplicitly, ConfigError, } from './config.js';
18
+ import { Connection } from './bridge/connection.js';
19
+ import { loadPinned, pinPath } from './bridge/certificate.js';
20
+ import { Session } from './session.js';
21
+ import { encryptedFilePath } from './credentials/encrypted-file.js';
22
+ import { loadSettings, saveSettings } from './settings.js';
23
+ import * as activity from './activity.js';
24
+ import { WebInterface } from './web/server.js';
25
+ import { registerListFolders } from './tools/list-folders.js';
26
+ import { registerMessageTools } from './tools/messages.js';
27
+ import { registerInterfaceTool } from './tools/interface.js';
28
+ import { registerLabelTools } from './tools/labels.js';
29
+ import { registerActionTools } from './tools/actions.js';
30
+ import { registerDraftTools } from './tools/drafts.js';
31
+ import { registerSendTools } from './tools/send.js';
32
+ import { setSignInHint, setLockedCheck } from './tools/failures.js';
33
+ import { setHandshakeCapabilities } from './tools/capabilities.js';
34
+ import { registerGuidance, INSTRUCTIONS } from './tools/guidance.js';
35
+ import { waitForIdle } from './in-flight.js';
36
+ // The version number lives in package.json only.
37
+ // Writing it here a second time would mean forgetting it here. From
38
+ // dist/server.js the path points at the package.json of the project root, and
39
+ // in the published package at its own.
40
+ const require = createRequire(import.meta.url);
41
+ const pkg = require('../package.json');
42
+ /**
43
+ * What this server calls itself, which is deliberately not the package name.
44
+ *
45
+ * The package is scoped so that other servers can sit beside it under the same
46
+ * namespace. That scope is an ownership statement for a registry and has no
47
+ * business in a protocol handshake or at the front of every line on stderr,
48
+ * where it would only make both harder to read.
49
+ *
50
+ * Fixed here rather than derived, because deriving it would tie the name a
51
+ * client displays to a decision about where the package is published.
52
+ */
53
+ const NAME = 'proton-mcp';
54
+ const VERSION = pkg.version;
55
+ const notify = (message) => {
56
+ // stderr, never stdout: the protocol runs over stdout.
57
+ process.stderr.write(`${NAME}: ${message}\n`);
58
+ };
59
+ async function main() {
60
+ const startedAt = Date.now();
61
+ let config;
62
+ try {
63
+ config = loadConfig();
64
+ }
65
+ catch (error) {
66
+ if (error instanceof ConfigError) {
67
+ process.stderr.write(`${NAME}: ${error.message}\n`);
68
+ process.exit(1);
69
+ }
70
+ throw error;
71
+ }
72
+ // Stored ports fill in only where the environment said nothing. An explicit
73
+ // BRIDGE_IMAP_PORT has to keep meaning what it says.
74
+ const explicitPorts = portsSetExplicitly();
75
+ // Held rather than read once: every write goes through the whole object, so
76
+ // that saving one setting cannot drop another. saveSettings replaces the file.
77
+ const settings = await loadSettings();
78
+ if (!explicitPorts.imapPort && settings.imapPort !== undefined)
79
+ config.imapPort = settings.imapPort;
80
+ if (!explicitPorts.smtpPort && settings.smtpPort !== undefined)
81
+ config.smtpPort = settings.smtpPort;
82
+ const environmentCredentials = credentialsFromEnvironment();
83
+ const session = new Session({
84
+ ...(environmentCredentials ? { fromEnvironment: environmentCredentials } : {}),
85
+ notify,
86
+ });
87
+ // One connection for the whole process, opened on the first tool call rather
88
+ // than at startup: a client often spawns the server long before the user wants
89
+ // anything, and a locked Bridge should not prevent it from starting.
90
+ const connection = new Connection(config, () => session.credentials(), notify);
91
+ /**
92
+ * Tries credentials against the Bridge before they are trusted.
93
+ *
94
+ * Storing something that does not work would send the user looking in the
95
+ * wrong place, and on the unlock path it is the only way to tell a wrong
96
+ * master password from a Bridge that is simply locked.
97
+ */
98
+ const verify = async (credentials) => {
99
+ const probe = new Connection(config, async () => credentials, notify);
100
+ try {
101
+ await probe.listMailboxes();
102
+ return undefined;
103
+ }
104
+ catch (error) {
105
+ return error.message;
106
+ }
107
+ finally {
108
+ await probe.close();
109
+ }
110
+ };
111
+ const web = new WebInterface({
112
+ port: config.webPort,
113
+ onSignIn: async (credentials, storeKind, masterPassword) => {
114
+ const failure = await verify(credentials);
115
+ if (failure)
116
+ return failure;
117
+ try {
118
+ await session.signIn(credentials, storeKind, masterPassword);
119
+ }
120
+ catch (error) {
121
+ return error.message;
122
+ }
123
+ // Drop the old connection so the next call uses the new credentials.
124
+ await connection.close();
125
+ return undefined;
126
+ },
127
+ onSignOut: async () => {
128
+ await session.signOut();
129
+ await connection.close();
130
+ },
131
+ onUnlock: async (masterPassword) => {
132
+ let credentials;
133
+ try {
134
+ credentials = await session.unlock(masterPassword);
135
+ }
136
+ catch (error) {
137
+ return error.message;
138
+ }
139
+ // The file opened, which only says the master password was right. Whether
140
+ // the Bridge still accepts what was in it is a separate question, and one
141
+ // the user would rather have answered here than at the next tool call.
142
+ const failure = await verify(credentials);
143
+ if (failure) {
144
+ await session.signOut();
145
+ return (`${failure}\n\nThe file was decrypted, so the master password was correct, but the ` +
146
+ 'Bridge password inside it no longer works. Sign in again with a fresh one.');
147
+ }
148
+ await connection.close();
149
+ return undefined;
150
+ },
151
+ onDiscardEncrypted: async () => {
152
+ await session.discardEncrypted();
153
+ notify('the encrypted credentials file was deleted on request');
154
+ },
155
+ getStatus: async () => {
156
+ const pinned = loadPinned(pinPath());
157
+ const base = {
158
+ connected: session.signedIn,
159
+ locked: await session.locked(),
160
+ encryptedPath: encryptedFilePath(),
161
+ bridgeHost: config.host,
162
+ bridgeImapPort: config.imapPort,
163
+ bridgeSmtpPort: config.smtpPort,
164
+ readOnly: config.readOnly,
165
+ uptimeMs: Date.now() - startedAt,
166
+ ...(session.address ? { address: session.address } : {}),
167
+ ...(session.storeKind ? { storeKind: session.storeKind } : {}),
168
+ ...(pinned
169
+ ? {
170
+ certificate: {
171
+ fingerprint: pinned.fingerprint256,
172
+ subject: pinned.subject,
173
+ firstSeen: pinned.firstSeen,
174
+ },
175
+ }
176
+ : {}),
177
+ };
178
+ if (!session.signedIn)
179
+ return base;
180
+ try {
181
+ const mailboxes = await connection.listMailboxes();
182
+ const inbox = await connection.status('INBOX');
183
+ return {
184
+ ...base,
185
+ mailboxCount: mailboxes.filter((box) => box.selectable).length,
186
+ messageCount: inbox.messages,
187
+ unseenCount: inbox.unseen,
188
+ };
189
+ }
190
+ catch {
191
+ // The status page should still render when the Bridge is unreachable.
192
+ return base;
193
+ }
194
+ },
195
+ // Absent when the user set the ports themselves: the form then disappears
196
+ // rather than quietly overriding what they configured.
197
+ ...(explicitPorts.imapPort || explicitPorts.smtpPort
198
+ ? {}
199
+ : {
200
+ onPorts: async (ports) => {
201
+ try {
202
+ await saveSettings({ ...settings, ...ports });
203
+ }
204
+ catch (error) {
205
+ return `The ports could not be saved: ${error.message}`;
206
+ }
207
+ settings.imapPort = ports.imapPort;
208
+ settings.smtpPort = ports.smtpPort;
209
+ // The Connection reads this object on every reconnect, so closing
210
+ // the current one is all that is needed for the change to take.
211
+ config.imapPort = ports.imapPort;
212
+ config.smtpPort = ports.smtpPort;
213
+ await connection.close();
214
+ notify(`ports changed to IMAP ${ports.imapPort}, SMTP ${ports.smtpPort}`);
215
+ return undefined;
216
+ },
217
+ }),
218
+ noticeDismissed: () => settings.noticeDismissed === true,
219
+ onDismissNotice: async () => {
220
+ settings.noticeDismissed = true;
221
+ try {
222
+ await saveSettings(settings);
223
+ }
224
+ catch (error) {
225
+ // Worth a line, not worth failing over: the notice is hidden for this
226
+ // run either way, and the next start simply shows it again.
227
+ notify(`the dismissed notice could not be remembered: ${error.message}`);
228
+ }
229
+ },
230
+ onTest: async () => {
231
+ try {
232
+ const mailboxes = await connection.listMailboxes();
233
+ return {
234
+ ok: true,
235
+ message: `The Bridge answered on ${config.host}:${config.imapPort} and accepted the ` +
236
+ `credentials. ${mailboxes.filter((box) => box.selectable).length} mailboxes are visible.`,
237
+ };
238
+ }
239
+ catch (error) {
240
+ return { ok: false, message: error.message };
241
+ }
242
+ },
243
+ getMailboxes: () => connection.listMailboxes(),
244
+ getActivity: () => {
245
+ const now = Date.now();
246
+ return {
247
+ running: activity.inProgress().map((call) => ({
248
+ tool: call.tool,
249
+ forMs: now - call.startedAt,
250
+ })),
251
+ recent: activity.recent().map((call) => ({
252
+ tool: call.tool,
253
+ at: call.startedAt,
254
+ durationMs: call.durationMs,
255
+ outcome: call.outcome,
256
+ })),
257
+ };
258
+ },
259
+ notify,
260
+ });
261
+ // Every tool answer about a missing sign-in names this address, so the model
262
+ // sends the user there instead of asking for the password in the chat.
263
+ setSignInHint(() => (web.running ? web.url : undefined));
264
+ // So that a tool called while an encrypted file is still closed says what is
265
+ // actually missing: the master password, not the Bridge password.
266
+ setLockedCheck(() => session.locked());
267
+ let webUrl;
268
+ try {
269
+ webUrl = await web.start();
270
+ notify(`web interface at ${webUrl}`);
271
+ if (!session.signedIn && !environmentCredentials) {
272
+ // Asking the session restores from a store, which is what makes this
273
+ // message true. Without it the answer is always "nothing stored": the
274
+ // restore is lazy and has not happened yet at startup, so a perfectly
275
+ // good credentials file was reported as absent every single start.
276
+ const restored = await session.credentials();
277
+ if (restored) {
278
+ notify(`credentials restored from the ${session.storeKind ?? 'store'}, signed in as ${session.address}`);
279
+ }
280
+ else {
281
+ notify((await session.locked())
282
+ ? 'credentials are stored in an encrypted file, open the address above to unlock them'
283
+ : 'no credentials stored yet, open the address above to sign in');
284
+ }
285
+ }
286
+ }
287
+ catch (error) {
288
+ // A web interface that cannot start must not stop the server: with
289
+ // credentials in the environment everything else still works.
290
+ notify(`${error.message} Continuing without it.`);
291
+ }
292
+ /**
293
+ * Seals the confirmation that has to survive a round trip through the client.
294
+ *
295
+ * The key is random and lives only in this process, which is exactly right
296
+ * here: the server speaks over stdio, so the same process serves every round
297
+ * of a flow, and a key that never reaches disk cannot be stolen from it. A
298
+ * restart invalidates any confirmation in flight, which is the safe direction
299
+ * to fail in.
300
+ *
301
+ * Bound to the request method as well, so a sealed state cannot be lifted out
302
+ * of one kind of request and presented in another. Which tool it belongs to is
303
+ * checked separately, in the handler.
304
+ */
305
+ const sendCodec = createRequestStateCodec({
306
+ key: randomBytes(32),
307
+ // Long enough to read a confirmation and think about it, short enough that
308
+ // a yes does not stay usable for the rest of the day.
309
+ ttlSeconds: 300,
310
+ bind: (requestCtx) => String(requestCtx.mcpReq?.method ?? ''),
311
+ });
312
+ const handle = serveStdio(() => {
313
+ const server = new McpServer({ name: NAME, version: VERSION }, {
314
+ // Verifies the seal before a handler ever runs, and hands the decoded
315
+ // payload to it. Without this the state would come back as a raw
316
+ // string the client could have written itself.
317
+ requestState: { verify: sendCodec.verify },
318
+ // Travels with every connection, so it costs context on every session.
319
+ // It names only what a model would otherwise get wrong before it had a
320
+ // reason to look anything up; the detail lives in the resources.
321
+ instructions: INSTRUCTIONS,
322
+ });
323
+ registerGuidance(server);
324
+ registerListFolders(server, connection);
325
+ registerMessageTools(server, connection);
326
+ // Read as a function rather than a value: whether the server may write is a
327
+ // property of the configuration, and the tools should ask at call time.
328
+ registerLabelTools(server, connection, () => config.readOnly);
329
+ registerActionTools(server, connection, () => config.readOnly);
330
+ registerDraftTools(server, connection, () => config.readOnly, () => session.address);
331
+ // What the client declared at handshake time. On this SDK's protocol
332
+ // revision it is the only place the declaration exists, and the confirmation
333
+ // before sending refuses when it cannot see one. Registered here because the
334
+ // instance is built here and does not exist earlier.
335
+ setHandshakeCapabilities(() => server.server?.getClientCapabilities?.());
336
+ registerSendTools(server, {
337
+ config,
338
+ connection,
339
+ getCredentials: () => session.credentials(),
340
+ readOnly: () => config.readOnly,
341
+ from: () => session.address,
342
+ codec: sendCodec,
343
+ });
344
+ registerInterfaceTool(server, {
345
+ url: () => web.url,
346
+ running: () => web.running,
347
+ signedIn: () => session.signedIn,
348
+ address: () => session.address,
349
+ storeKind: () => session.storeKind,
350
+ locked: () => session.locked(),
351
+ });
352
+ return server;
353
+ });
354
+ // Clean shutdown. stdin matters most: when the client dies the stream ends
355
+ // without any signal arriving. Without handling this, the server process
356
+ // would be left orphaned along with its open IMAP connection and its socket.
357
+ let shuttingDown = false;
358
+ const shutdown = async () => {
359
+ if (shuttingDown)
360
+ return;
361
+ shuttingDown = true;
362
+ // Give the event loop one turn first. When the input stream ends there may
363
+ // still be unread messages in the buffer that do not count as in-flight
364
+ // work yet. Without this pause the counter would be zero and the server
365
+ // would exit before the last request even starts.
366
+ await new Promise((next) => setTimeout(next, 50));
367
+ // Let running tool calls finish so their answer still goes out. Bounded,
368
+ // so that a stuck call cannot prevent shutdown.
369
+ const idle = await waitForIdle(5000);
370
+ if (!idle)
371
+ notify('shutdown forced, a call was still running.');
372
+ try {
373
+ await web.stop();
374
+ await connection.close();
375
+ await handle.close();
376
+ }
377
+ finally {
378
+ process.exit(idle ? 0 : 1);
379
+ }
380
+ };
381
+ process.stdin.on('end', () => void shutdown());
382
+ process.stdin.on('close', () => void shutdown());
383
+ process.on('SIGINT', () => void shutdown());
384
+ process.on('SIGTERM', () => void shutdown());
385
+ }
386
+ void main();
387
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAA;AAC/D,OAAO,EACL,UAAU,EACV,0BAA0B,EAC1B,kBAAkB,EAClB,WAAW,GACZ,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC1D,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,YAAY,EAAuB,MAAM,iBAAiB,CAAA;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAEnD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5C,iDAAiD;AACjD,oEAAoE;AACpE,8EAA8E;AAC9E,uCAAuC;AACvC,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAA;AAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAsC,CAAA;AAE3E;;;;;;;;;;GAUG;AACH,MAAM,IAAI,GAAG,YAAY,CAAA;AACzB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAA;AAE3B,MAAM,MAAM,GAAG,CAAC,OAAe,EAAQ,EAAE;IACvC,uDAAuD;IACvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,KAAK,OAAO,IAAI,CAAC,CAAA;AAC/C,CAAC,CAAA;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAE5B,IAAI,MAAM,CAAA;IACV,IAAI,CAAC;QACH,MAAM,GAAG,UAAU,EAAE,CAAA;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;YACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,KAAK,KAAK,CAAC,OAAO,IAAI,CAAC,CAAA;YACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;IAED,4EAA4E;IAC5E,qDAAqD;IACrD,MAAM,aAAa,GAAG,kBAAkB,EAAE,CAAA;IAC1C,4EAA4E;IAC5E,+EAA+E;IAC/E,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAA;IACrC,IAAI,CAAC,aAAa,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS;QAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAA;IACnG,IAAI,CAAC,aAAa,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS;QAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAA;IAEnG,MAAM,sBAAsB,GAAG,0BAA0B,EAAE,CAAA;IAC3D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC;QAC1B,GAAG,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,sBAAsB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9E,MAAM;KACP,CAAC,CAAA;IAEF,6EAA6E;IAC7E,+EAA+E;IAC/E,qEAAqE;IACrE,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,CAAA;IAE9E;;;;;;OAMG;IACH,MAAM,MAAM,GAAG,KAAK,EAAE,WAA2C,EAA+B,EAAE;QAChG,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QACrE,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,aAAa,EAAE,CAAA;YAC3B,OAAO,SAAS,CAAA;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAQ,KAAe,CAAC,OAAO,CAAA;QACjC,CAAC;gBAAS,CAAC;YACT,MAAM,KAAK,CAAC,KAAK,EAAE,CAAA;QACrB,CAAC;IACH,CAAC,CAAA;IAED,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC;QAC3B,IAAI,EAAE,MAAM,CAAC,OAAO;QACpB,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE;YACzD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;YACzC,IAAI,OAAO;gBAAE,OAAO,OAAO,CAAA;YAC3B,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,SAAS,EAAE,cAAc,CAAC,CAAA;YAC9D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAQ,KAAe,CAAC,OAAO,CAAA;YACjC,CAAC;YACD,qEAAqE;YACrE,MAAM,UAAU,CAAC,KAAK,EAAE,CAAA;YACxB,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,OAAO,CAAC,OAAO,EAAE,CAAA;YACvB,MAAM,UAAU,CAAC,KAAK,EAAE,CAAA;QAC1B,CAAC;QACD,QAAQ,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;YACjC,IAAI,WAAW,CAAA;YACf,IAAI,CAAC;gBACH,WAAW,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;YACpD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAQ,KAAe,CAAC,OAAO,CAAA;YACjC,CAAC;YACD,0EAA0E;YAC1E,0EAA0E;YAC1E,uEAAuE;YACvE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;YACzC,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,OAAO,CAAC,OAAO,EAAE,CAAA;gBACvB,OAAO,CACL,GAAG,OAAO,0EAA0E;oBACpF,4EAA4E,CAC7E,CAAA;YACH,CAAC;YACD,MAAM,UAAU,CAAC,KAAK,EAAE,CAAA;YACxB,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,kBAAkB,EAAE,KAAK,IAAI,EAAE;YAC7B,MAAM,OAAO,CAAC,gBAAgB,EAAE,CAAA;YAChC,MAAM,CAAC,uDAAuD,CAAC,CAAA;QACjE,CAAC;QACD,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,CAAA;YACpC,MAAM,IAAI,GAAmB;gBAC3B,SAAS,EAAE,OAAO,CAAC,QAAQ;gBAC3B,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE;gBAC9B,aAAa,EAAE,iBAAiB,EAAE;gBAClC,UAAU,EAAE,MAAM,CAAC,IAAI;gBACvB,cAAc,EAAE,MAAM,CAAC,QAAQ;gBAC/B,cAAc,EAAE,MAAM,CAAC,QAAQ;gBAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;gBAChC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxD,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9D,GAAG,CAAC,MAAM;oBACR,CAAC,CAAC;wBACE,WAAW,EAAE;4BACX,WAAW,EAAE,MAAM,CAAC,cAAc;4BAClC,OAAO,EAAE,MAAM,CAAC,OAAO;4BACvB,SAAS,EAAE,MAAM,CAAC,SAAS;yBAC5B;qBACF;oBACH,CAAC,CAAC,EAAE,CAAC;aACR,CAAA;YACD,IAAI,CAAC,OAAO,CAAC,QAAQ;gBAAE,OAAO,IAAI,CAAA;YAClC,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,aAAa,EAAE,CAAA;gBAClD,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;gBAC9C,OAAO;oBACL,GAAG,IAAI;oBACP,YAAY,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,MAAM;oBAC9D,YAAY,EAAE,KAAK,CAAC,QAAQ;oBAC5B,WAAW,EAAE,KAAK,CAAC,MAAM;iBAC1B,CAAA;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,sEAAsE;gBACtE,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC;QACD,0EAA0E;QAC1E,uDAAuD;QACvD,GAAG,CAAC,aAAa,CAAC,QAAQ,IAAI,aAAa,CAAC,QAAQ;YAClD,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;oBACvB,IAAI,CAAC;wBACH,MAAM,YAAY,CAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,KAAK,EAAE,CAAC,CAAA;oBAC/C,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,OAAO,iCAAkC,KAAe,CAAC,OAAO,EAAE,CAAA;oBACpE,CAAC;oBACD,QAAQ,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAA;oBAClC,QAAQ,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAA;oBAClC,kEAAkE;oBAClE,gEAAgE;oBAChE,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAA;oBAChC,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAA;oBAChC,MAAM,UAAU,CAAC,KAAK,EAAE,CAAA;oBACxB,MAAM,CAAC,yBAAyB,KAAK,CAAC,QAAQ,UAAU,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAA;oBACzE,OAAO,SAAS,CAAA;gBAClB,CAAC;aACF,CAAC;QACN,eAAe,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,eAAe,KAAK,IAAI;QACxD,eAAe,EAAE,KAAK,IAAI,EAAE;YAC1B,QAAQ,CAAC,eAAe,GAAG,IAAI,CAAA;YAC/B,IAAI,CAAC;gBACH,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAA;YAC9B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,sEAAsE;gBACtE,4DAA4D;gBAC5D,MAAM,CAAC,iDAAkD,KAAe,CAAC,OAAO,EAAE,CAAC,CAAA;YACrF,CAAC;QACH,CAAC;QACD,MAAM,EAAE,KAAK,IAAI,EAAE;YACjB,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,aAAa,EAAE,CAAA;gBAClD,OAAO;oBACL,EAAE,EAAE,IAAI;oBACR,OAAO,EACL,0BAA0B,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,oBAAoB;wBAC5E,gBAAgB,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,MAAM,yBAAyB;iBAC5F,CAAA;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAG,KAAe,CAAC,OAAO,EAAE,CAAA;YACzD,CAAC;QACH,CAAC;QACD,YAAY,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,aAAa,EAAE;QAC9C,WAAW,EAAE,GAAG,EAAE;YAChB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YACtB,OAAO;gBACL,OAAO,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBAC5C,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,KAAK,EAAE,GAAG,GAAG,IAAI,CAAC,SAAS;iBAC5B,CAAC,CAAC;gBACH,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBACvC,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,EAAE,EAAE,IAAI,CAAC,SAAS;oBAClB,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;iBACtB,CAAC,CAAC;aACJ,CAAA;QACH,CAAC;QACD,MAAM;KACP,CAAC,CAAA;IAEF,6EAA6E;IAC7E,uEAAuE;IACvE,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAA;IACxD,6EAA6E;IAC7E,kEAAkE;IAClE,cAAc,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAEtC,IAAI,MAA0B,CAAA;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,CAAA;QAC1B,MAAM,CAAC,oBAAoB,MAAM,EAAE,CAAC,CAAA;QACpC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,sBAAsB,EAAE,CAAC;YACjD,qEAAqE;YACrE,sEAAsE;YACtE,sEAAsE;YACtE,mEAAmE;YACnE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAA;YAC5C,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,CAAC,iCAAiC,OAAO,CAAC,SAAS,IAAI,OAAO,kBAAkB,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;YAC1G,CAAC;iBAAM,CAAC;gBACN,MAAM,CACJ,CAAC,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;oBACtB,CAAC,CAAC,oFAAoF;oBACtF,CAAC,CAAC,8DAA8D,CACnE,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,mEAAmE;QACnE,8DAA8D;QAC9D,MAAM,CAAC,GAAI,KAAe,CAAC,OAAO,yBAAyB,CAAC,CAAA;IAC9D,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,MAAM,SAAS,GAAG,uBAAuB,CAAc;QACrD,GAAG,EAAE,WAAW,CAAC,EAAE,CAAC;QACpB,2EAA2E;QAC3E,sDAAsD;QACtD,UAAU,EAAE,GAAG;QACf,IAAI,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE,CAAC;KAC9D,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE;QAC7B,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAChC;YACE,sEAAsE;YACtE,iEAAiE;YACjE,+CAA+C;YAC/C,YAAY,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE;YAC1C,uEAAuE;YACvE,uEAAuE;YACvE,iEAAiE;YACjE,YAAY,EAAE,YAAY;SAC3B,CACF,CAAA;QACD,gBAAgB,CAAC,MAAM,CAAC,CAAA;QACxB,mBAAmB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;QACvC,oBAAoB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;QACxC,4EAA4E;QAC5E,wEAAwE;QACxE,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAC7D,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAC9D,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QACpF,qEAAqE;QACrE,6EAA6E;QAC7E,6EAA6E;QAC7E,qDAAqD;QACrD,wBAAwB,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,qBAAqB,EAAE,EAAE,CAAC,CAAA;QAExE,iBAAiB,CAAC,MAAM,EAAE;YACxB,MAAM;YACN,UAAU;YACV,cAAc,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE;YAC3C,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ;YAC/B,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO;YAC3B,KAAK,EAAE,SAAS;SACjB,CAAC,CAAA;QACF,qBAAqB,CAAC,MAAM,EAAE;YAC5B,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG;YAClB,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO;YAC1B,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ;YAChC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO;YAC9B,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS;YAClC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE;SAC/B,CAAC,CAAA;QACF,OAAO,MAAM,CAAA;IACf,CAAC,CAAC,CAAA;IAEF,2EAA2E;IAC3E,yEAAyE;IACzE,6EAA6E;IAC7E,IAAI,YAAY,GAAG,KAAK,CAAA;IACxB,MAAM,QAAQ,GAAG,KAAK,IAAmB,EAAE;QACzC,IAAI,YAAY;YAAE,OAAM;QACxB,YAAY,GAAG,IAAI,CAAA;QAEnB,2EAA2E;QAC3E,wEAAwE;QACxE,wEAAwE;QACxE,kDAAkD;QAClD,MAAM,IAAI,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAA;QAEjD,yEAAyE;QACzE,gDAAgD;QAChD,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAA;QACpC,IAAI,CAAC,IAAI;YAAE,MAAM,CAAC,4CAA4C,CAAC,CAAA;QAE/D,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;YAChB,MAAM,UAAU,CAAC,KAAK,EAAE,CAAA;YACxB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;QACtB,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC5B,CAAC;IACH,CAAC,CAAA;IAED,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAA;IAC9C,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAA;IAChD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAA;IAC3C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAA;AAC9C,CAAC;AAED,KAAK,IAAI,EAAE,CAAA"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * The signed-in state of the server.
3
+ *
4
+ * Credentials used to be part of the configuration, read once at startup. That
5
+ * no longer works: with the web interface they can arrive at any time, and they
6
+ * can be revoked while the server keeps running. This is the one place that
7
+ * knows whether we are signed in.
8
+ *
9
+ * It also decides where credentials come from on startup, in this order:
10
+ *
11
+ * 1. Environment variables, when set. An explicit setting is never overruled.
12
+ * 2. The plain file, which is the interim path and the one existing setups use.
13
+ * 3. The system keyring, if something was stored there.
14
+ *
15
+ * The encrypted file is deliberately not in that list, because it cannot be:
16
+ * decrypting it needs a master password, and there is nowhere to ask for one
17
+ * while a stdio server starts up. It is instead reported as **locked**, which
18
+ * the web interface turns into a page asking for that one password. This is
19
+ * the whole reason `locked()` and `unlock()` exist rather than a fourth entry
20
+ * in the loop above.
21
+ */
22
+ import type { Credentials, CredentialStore, StoreKind } from './credentials/store.js';
23
+ export interface SessionOptions {
24
+ /** Credentials from the environment, when they were set. */
25
+ fromEnvironment?: Credentials;
26
+ /** Where notices go. stderr, never stdout, which carries the protocol. */
27
+ notify?: (message: string) => void;
28
+ /** Replaces the stores. Used by tests. */
29
+ stores?: Partial<Record<StoreKind, CredentialStore>>;
30
+ }
31
+ export declare class Session {
32
+ #private;
33
+ constructor(options?: SessionOptions);
34
+ get storeKind(): StoreKind | undefined;
35
+ get signedIn(): boolean;
36
+ /** The address we are signed in as, for display. Never the password. */
37
+ get address(): string | undefined;
38
+ /**
39
+ * Returns the credentials, restoring them from a store on first use.
40
+ *
41
+ * Restoring happens here rather than at startup so that a locked keyring
42
+ * cannot block the server from starting. It costs one attempt on the first
43
+ * tool call instead.
44
+ */
45
+ credentials(): Promise<Credentials | undefined>;
46
+ /**
47
+ * Whether credentials are stored that only a master password can open.
48
+ *
49
+ * Distinct from "not signed in": the user does not need to fetch their Bridge
50
+ * password from the Bridge again, they need to type one thing. A page that
51
+ * asked for everything would make the encrypted option feel broken.
52
+ */
53
+ locked(): Promise<boolean>;
54
+ /**
55
+ * Opens the encrypted file with the given master password.
56
+ *
57
+ * Returns the credentials so the caller can verify them against the Bridge.
58
+ * On failure the password is dropped again: keeping a wrong one would make
59
+ * every later attempt fail with a message about the file instead of about
60
+ * the password.
61
+ */
62
+ unlock(masterPassword: string): Promise<Credentials>;
63
+ /**
64
+ * Throws away the encrypted file without opening it.
65
+ *
66
+ * The way out for someone who forgot their master password. Without it they
67
+ * would be stuck on the unlock page for good, because nothing anywhere can
68
+ * decrypt that file. What is destroyed is a Bridge password that can be
69
+ * looked up in the Bridge again, so this is recoverable in the only sense
70
+ * that matters.
71
+ */
72
+ discardEncrypted(): Promise<void>;
73
+ /**
74
+ * Stores credentials and marks the session as signed in.
75
+ *
76
+ * The caller has already verified them against the Bridge: storing something
77
+ * that does not work would be worse than not storing it.
78
+ */
79
+ signIn(credentials: Credentials, storeKind: StoreKind,
80
+ /** Required for the encrypted file, meaningless for every other store. */
81
+ masterPassword?: string): Promise<void>;
82
+ /** Forgets the credentials everywhere they might be. */
83
+ signOut(): Promise<void>;
84
+ /** Replaces a store. Used by tests and by the startup wiring. */
85
+ setStore(kind: StoreKind, store: CredentialStore): void;
86
+ }