@j0hanz/fetch-url-mcp 1.12.7 → 1.12.8

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 (145) hide show
  1. package/dist/http/auth.d.ts +2 -2
  2. package/dist/http/auth.d.ts.map +1 -1
  3. package/dist/http/auth.js +4 -5
  4. package/dist/http/index.d.ts +6 -0
  5. package/dist/http/index.d.ts.map +1 -0
  6. package/dist/http/index.js +5 -0
  7. package/dist/http/native.d.ts +73 -0
  8. package/dist/http/native.d.ts.map +1 -1
  9. package/dist/http/native.js +554 -10
  10. package/dist/http/rate-limit.d.ts +1 -1
  11. package/dist/http/rate-limit.d.ts.map +1 -1
  12. package/dist/http/rate-limit.js +3 -4
  13. package/dist/index.d.ts +17 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +67 -6
  16. package/dist/lib/config.js +2 -2
  17. package/dist/lib/core.d.ts +56 -4
  18. package/dist/lib/core.d.ts.map +1 -1
  19. package/dist/lib/core.js +155 -4
  20. package/dist/lib/error/classes.d.ts +19 -0
  21. package/dist/lib/error/classes.d.ts.map +1 -0
  22. package/dist/lib/error/classes.js +107 -0
  23. package/dist/lib/error/classify.d.ts +4 -0
  24. package/dist/lib/error/classify.d.ts.map +1 -0
  25. package/dist/lib/error/classify.js +154 -0
  26. package/dist/lib/error/codes.d.ts +23 -0
  27. package/dist/lib/error/codes.d.ts.map +1 -0
  28. package/dist/lib/error/codes.js +22 -0
  29. package/dist/lib/error/index.d.ts +6 -0
  30. package/dist/lib/error/index.d.ts.map +1 -0
  31. package/dist/lib/error/index.js +5 -0
  32. package/dist/lib/{error-messages.d.ts → error/messages.d.ts} +2 -2
  33. package/dist/lib/error/messages.d.ts.map +1 -0
  34. package/dist/lib/{error-messages.js → error/messages.js} +2 -2
  35. package/dist/lib/{tool-errors.d.ts → error/payload.d.ts} +7 -13
  36. package/dist/lib/error/payload.d.ts.map +1 -0
  37. package/dist/lib/error/payload.js +108 -0
  38. package/dist/lib/mcp-interop.d.ts.map +1 -1
  39. package/dist/lib/mcp-interop.js +4 -6
  40. package/dist/lib/net/http.d.ts.map +1 -0
  41. package/dist/lib/{http.js → net/http.js} +4 -7
  42. package/dist/lib/net/index.d.ts +4 -0
  43. package/dist/lib/net/index.d.ts.map +1 -0
  44. package/dist/lib/net/index.js +3 -0
  45. package/dist/lib/{fetch-pipeline.d.ts → net/pipeline.d.ts} +3 -3
  46. package/dist/lib/net/pipeline.d.ts.map +1 -0
  47. package/dist/lib/{fetch-pipeline.js → net/pipeline.js} +3 -5
  48. package/dist/lib/{url.d.ts → net/url.d.ts} +1 -1
  49. package/dist/lib/net/url.d.ts.map +1 -0
  50. package/dist/lib/{url.js → net/url.js} +3 -5
  51. package/dist/lib/utils.d.ts +2 -18
  52. package/dist/lib/utils.d.ts.map +1 -1
  53. package/dist/lib/utils.js +29 -104
  54. package/dist/resources/index.d.ts.map +1 -1
  55. package/dist/resources/index.js +8 -5
  56. package/dist/schemas.d.ts +1 -1
  57. package/dist/server.d.ts.map +1 -1
  58. package/dist/server.js +7 -9
  59. package/dist/tasks/index.d.ts +2 -0
  60. package/dist/tasks/index.d.ts.map +1 -0
  61. package/dist/tasks/index.js +1 -0
  62. package/dist/tasks/manager.d.ts +123 -1
  63. package/dist/tasks/manager.d.ts.map +1 -1
  64. package/dist/tasks/manager.js +745 -10
  65. package/dist/tools/{fetch-url.d.ts → index.d.ts} +4 -5
  66. package/dist/tools/index.d.ts.map +1 -0
  67. package/dist/tools/{fetch-url.js → index.js} +6 -8
  68. package/dist/transform/index.d.ts +279 -0
  69. package/dist/transform/index.d.ts.map +1 -0
  70. package/dist/transform/index.js +5234 -0
  71. package/package.json +2 -2
  72. package/dist/cli.d.ts +0 -19
  73. package/dist/cli.d.ts.map +0 -1
  74. package/dist/cli.js +0 -65
  75. package/dist/http/health.d.ts +0 -8
  76. package/dist/http/health.d.ts.map +0 -1
  77. package/dist/http/health.js +0 -152
  78. package/dist/http/helpers.d.ts +0 -68
  79. package/dist/http/helpers.d.ts.map +0 -1
  80. package/dist/http/helpers.js +0 -402
  81. package/dist/lib/error-codes.d.ts +0 -13
  82. package/dist/lib/error-codes.d.ts.map +0 -1
  83. package/dist/lib/error-codes.js +0 -12
  84. package/dist/lib/error-messages.d.ts.map +0 -1
  85. package/dist/lib/fetch-pipeline.d.ts.map +0 -1
  86. package/dist/lib/http.d.ts.map +0 -1
  87. package/dist/lib/logger-names.d.ts +0 -16
  88. package/dist/lib/logger-names.d.ts.map +0 -1
  89. package/dist/lib/logger-names.js +0 -15
  90. package/dist/lib/session.d.ts +0 -44
  91. package/dist/lib/session.d.ts.map +0 -1
  92. package/dist/lib/session.js +0 -137
  93. package/dist/lib/tool-errors.d.ts.map +0 -1
  94. package/dist/lib/tool-errors.js +0 -253
  95. package/dist/lib/url.d.ts.map +0 -1
  96. package/dist/lib/zod.d.ts +0 -3
  97. package/dist/lib/zod.d.ts.map +0 -1
  98. package/dist/lib/zod.js +0 -27
  99. package/dist/tasks/call-contract.d.ts +0 -25
  100. package/dist/tasks/call-contract.d.ts.map +0 -1
  101. package/dist/tasks/call-contract.js +0 -59
  102. package/dist/tasks/execution.d.ts +0 -16
  103. package/dist/tasks/execution.d.ts.map +0 -1
  104. package/dist/tasks/execution.js +0 -241
  105. package/dist/tasks/handlers.d.ts +0 -11
  106. package/dist/tasks/handlers.d.ts.map +0 -1
  107. package/dist/tasks/handlers.js +0 -157
  108. package/dist/tasks/owner.d.ts +0 -43
  109. package/dist/tasks/owner.d.ts.map +0 -1
  110. package/dist/tasks/owner.js +0 -144
  111. package/dist/tasks/registry.d.ts +0 -20
  112. package/dist/tasks/registry.d.ts.map +0 -1
  113. package/dist/tasks/registry.js +0 -40
  114. package/dist/tasks/waiters.d.ts +0 -27
  115. package/dist/tasks/waiters.d.ts.map +0 -1
  116. package/dist/tasks/waiters.js +0 -114
  117. package/dist/tools/fetch-url.d.ts.map +0 -1
  118. package/dist/transform/dom-prep.d.ts +0 -16
  119. package/dist/transform/dom-prep.d.ts.map +0 -1
  120. package/dist/transform/dom-prep.js +0 -1287
  121. package/dist/transform/html-translators.d.ts +0 -5
  122. package/dist/transform/html-translators.d.ts.map +0 -1
  123. package/dist/transform/html-translators.js +0 -697
  124. package/dist/transform/markdown-cleanup.d.ts +0 -10
  125. package/dist/transform/markdown-cleanup.d.ts.map +0 -1
  126. package/dist/transform/markdown-cleanup.js +0 -542
  127. package/dist/transform/metadata.d.ts +0 -18
  128. package/dist/transform/metadata.d.ts.map +0 -1
  129. package/dist/transform/metadata.js +0 -462
  130. package/dist/transform/next-flight.d.ts +0 -2
  131. package/dist/transform/next-flight.d.ts.map +0 -1
  132. package/dist/transform/next-flight.js +0 -374
  133. package/dist/transform/shared.d.ts +0 -8
  134. package/dist/transform/shared.d.ts.map +0 -1
  135. package/dist/transform/shared.js +0 -137
  136. package/dist/transform/transform.d.ts +0 -38
  137. package/dist/transform/transform.d.ts.map +0 -1
  138. package/dist/transform/transform.js +0 -1042
  139. package/dist/transform/types.d.ts +0 -124
  140. package/dist/transform/types.d.ts.map +0 -1
  141. package/dist/transform/types.js +0 -5
  142. package/dist/transform/worker-pool.d.ts +0 -76
  143. package/dist/transform/worker-pool.d.ts.map +0 -1
  144. package/dist/transform/worker-pool.js +0 -725
  145. /package/dist/lib/{http.d.ts → net/http.d.ts} +0 -0
@@ -1,253 +0,0 @@
1
- import { ErrorCode, McpError, } from '@modelcontextprotocol/sdk/types.js';
2
- import { z } from 'zod';
3
- import { logError, logWarn } from './core.js';
4
- import { SystemErrors } from './error-codes.js';
5
- import { FetchError, isAbortError, isObject, isSystemError } from './utils.js';
6
- const toolErrorPayloadSchema = z.strictObject({
7
- error: z.string(),
8
- url: z.string(),
9
- category: z.string().optional(),
10
- code: z.union([z.string(), z.number()]).optional(),
11
- statusCode: z.number().int().optional(),
12
- upstreamMessage: z.string().optional(),
13
- details: z.record(z.string(), z.unknown()).optional(),
14
- data: z.unknown().optional(),
15
- });
16
- const PUBLIC_ERROR_REASONS = new Set([
17
- 'aborted',
18
- SystemErrors.QUEUE_FULL,
19
- 'timeout',
20
- ]);
21
- function sanitizeToolErrorDetails(details) {
22
- const sanitized = {};
23
- const { retryAfter, timeout, reason } = details;
24
- if (typeof retryAfter === 'number' ||
25
- typeof retryAfter === 'string' ||
26
- retryAfter === null) {
27
- sanitized['retryAfter'] = retryAfter;
28
- }
29
- if (typeof timeout === 'number' && Number.isFinite(timeout) && timeout >= 0) {
30
- sanitized['timeout'] = timeout;
31
- }
32
- if (typeof reason === 'string' && PUBLIC_ERROR_REASONS.has(reason)) {
33
- sanitized['reason'] = reason;
34
- }
35
- return Object.keys(sanitized).length > 0 ? sanitized : undefined;
36
- }
37
- export function createToolErrorResponse(message, url, extra) {
38
- const errorContent = createToolErrorPayload(message, url, extra);
39
- return {
40
- content: [{ type: 'text', text: JSON.stringify(errorContent) }],
41
- isError: true,
42
- };
43
- }
44
- export function createToolErrorPayload(message, url, extra) {
45
- const payload = {
46
- error: message,
47
- url,
48
- };
49
- if (extra?.category !== undefined)
50
- payload.category = extra.category;
51
- if (extra?.code !== undefined)
52
- payload.code = extra.code;
53
- if (extra?.statusCode !== undefined)
54
- payload.statusCode = extra.statusCode;
55
- if (extra?.upstreamMessage !== undefined) {
56
- payload.upstreamMessage = extra.upstreamMessage;
57
- }
58
- if (extra?.details)
59
- payload.details = extra.details;
60
- if (extra?.data !== undefined)
61
- payload.data = extra.data;
62
- return payload;
63
- }
64
- function normalizeToolErrorPayload(value) {
65
- return createToolErrorPayload(value.error, value.url, {
66
- ...(value.category !== undefined ? { category: value.category } : {}),
67
- ...(value.code !== undefined ? { code: value.code } : {}),
68
- ...(value.statusCode !== undefined ? { statusCode: value.statusCode } : {}),
69
- ...(value.upstreamMessage !== undefined
70
- ? { upstreamMessage: value.upstreamMessage }
71
- : {}),
72
- ...(value.details ? { details: value.details } : {}),
73
- ...(value.data !== undefined ? { data: value.data } : {}),
74
- });
75
- }
76
- export function tryReadToolErrorPayload(value) {
77
- if (!isObject(value))
78
- return undefined;
79
- const structuredContent = toolErrorPayloadSchema.safeParse(value['structuredContent']);
80
- if (structuredContent.success) {
81
- return normalizeToolErrorPayload(structuredContent.data);
82
- }
83
- const { content } = value;
84
- if (!Array.isArray(content) || content.length === 0)
85
- return undefined;
86
- const firstBlock = content[0];
87
- if (!isObject(firstBlock))
88
- return undefined;
89
- if (firstBlock['type'] !== 'text')
90
- return undefined;
91
- if (typeof firstBlock['text'] !== 'string')
92
- return undefined;
93
- try {
94
- const payload = toolErrorPayloadSchema.safeParse(JSON.parse(firstBlock['text']));
95
- return payload.success
96
- ? normalizeToolErrorPayload(payload.data)
97
- : undefined;
98
- }
99
- catch {
100
- return undefined;
101
- }
102
- }
103
- export function tryReadToolErrorMessage(value) {
104
- return tryReadToolErrorPayload(value)?.error;
105
- }
106
- function renderToolErrorResponse(presentation) {
107
- return createToolErrorResponse(presentation.message, presentation.url, {
108
- ...(presentation.category !== undefined
109
- ? { category: presentation.category }
110
- : {}),
111
- ...(presentation.code !== undefined ? { code: presentation.code } : {}),
112
- ...(presentation.statusCode !== undefined
113
- ? { statusCode: presentation.statusCode }
114
- : {}),
115
- ...(presentation.upstreamMessage !== undefined
116
- ? { upstreamMessage: presentation.upstreamMessage }
117
- : {}),
118
- ...(presentation.details ? { details: presentation.details } : {}),
119
- ...(presentation.data !== undefined ? { data: presentation.data } : {}),
120
- });
121
- }
122
- function isValidationError(error) {
123
- return (error instanceof Error &&
124
- isSystemError(error) &&
125
- error.code === SystemErrors.VALIDATION_ERROR);
126
- }
127
- function buildUpstreamHttpMessage(error) {
128
- const { statusCode } = error;
129
- if (statusCode === 404) {
130
- return `We couldn't find the resource at the target URL.`;
131
- }
132
- return `An error occurred when communicating with the target URL.`;
133
- }
134
- function mapFetchToolError(error, fallbackUrl) {
135
- const { code: detailsCode, reason } = error.details;
136
- let { code } = error;
137
- if (typeof detailsCode === 'string') {
138
- code = detailsCode;
139
- }
140
- else if (reason === SystemErrors.QUEUE_FULL) {
141
- code = SystemErrors.QUEUE_FULL;
142
- }
143
- const url = error.url || fallbackUrl;
144
- const details = sanitizeToolErrorDetails(error.details);
145
- if (reason === 'timeout') {
146
- return {
147
- message: 'The request to the target timed out.',
148
- url,
149
- category: 'upstream_timeout',
150
- code,
151
- statusCode: error.statusCode,
152
- upstreamMessage: error.message,
153
- ...(details ? { details } : {}),
154
- };
155
- }
156
- if (reason === 'aborted') {
157
- return {
158
- message: 'The request to the target was cancelled.',
159
- url,
160
- category: 'upstream_aborted',
161
- code,
162
- statusCode: error.statusCode,
163
- upstreamMessage: error.message,
164
- ...(details ? { details } : {}),
165
- };
166
- }
167
- if (reason === SystemErrors.QUEUE_FULL) {
168
- return {
169
- message: error.message,
170
- url,
171
- category: 'queue_full',
172
- code,
173
- statusCode: error.statusCode,
174
- ...(details ? { details } : {}),
175
- };
176
- }
177
- const isRealHttpError = typeof error.details['httpStatus'] === 'number';
178
- if (isRealHttpError && error.statusCode >= 400) {
179
- return {
180
- message: buildUpstreamHttpMessage(error),
181
- url,
182
- category: error.statusCode === 429
183
- ? 'upstream_rate_limited'
184
- : 'upstream_http_error',
185
- code,
186
- statusCode: error.statusCode,
187
- upstreamMessage: error.message,
188
- ...(details ? { details } : {}),
189
- };
190
- }
191
- return {
192
- message: error.message,
193
- url,
194
- category: 'fetch_error',
195
- code,
196
- statusCode: error.statusCode,
197
- ...(details ? { details } : {}),
198
- };
199
- }
200
- function mapGenericToolError(error, url, fallbackMessage) {
201
- if (isValidationError(error)) {
202
- return {
203
- message: error.message,
204
- url,
205
- category: 'validation_error',
206
- code: SystemErrors.VALIDATION_ERROR,
207
- };
208
- }
209
- const isAborted = isAbortError(error);
210
- return {
211
- message: error instanceof Error
212
- ? error.message
213
- : `${fallbackMessage}: unknown error`,
214
- url,
215
- category: isAborted ? 'upstream_aborted' : 'fetch_error',
216
- code: isAborted ? SystemErrors.ABORTED : SystemErrors.FETCH_ERROR,
217
- };
218
- }
219
- function resolveToolErrorPresentation(error, url, fallbackMessage) {
220
- if (error instanceof FetchError) {
221
- return mapFetchToolError(error, url);
222
- }
223
- return mapGenericToolError(error, url, fallbackMessage);
224
- }
225
- export function handleToolError(error, url, fallbackMessage = 'Operation failed') {
226
- return renderToolErrorResponse(resolveToolErrorPresentation(error, url, fallbackMessage));
227
- }
228
- export function classifyAndLogToolError(error, meta, loggerName, toolName, fallbackMessage) {
229
- if (error instanceof McpError) {
230
- if (error.code === ErrorCode.InvalidParams ||
231
- error.code === ErrorCode.MethodNotFound) {
232
- logError(`${toolName} tool protocol error`, { url: meta.url, durationMs: meta.durationMs, error }, loggerName);
233
- throw error;
234
- }
235
- logWarn(`${toolName} tool domain error`, { url: meta.url, durationMs: meta.durationMs, error }, loggerName);
236
- return handleToolError(error, meta.url, fallbackMessage);
237
- }
238
- if (error instanceof FetchError || isAbortError(error)) {
239
- logWarn(`${toolName} request failed`, {
240
- url: meta.url,
241
- error: error instanceof Error ? error.message : String(error),
242
- durationMs: meta.durationMs,
243
- }, loggerName);
244
- }
245
- else {
246
- logError(`${toolName} request failed unexpectedly`, {
247
- url: meta.url,
248
- error: error instanceof Error ? error.message : String(error),
249
- durationMs: meta.durationMs,
250
- }, loggerName);
251
- }
252
- return handleToolError(error, meta.url, fallbackMessage);
253
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/lib/url.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAiB,MAAM,UAAU,CAAC;AAG1D,OAAO,EAAE,MAAM,EAAY,MAAM,WAAW,CAAC;AA0D7C,qBAAa,eAAe;IAOxB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IARtC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAG3B;gBAGgB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,cAAc,EACxB,mBAAmB,EAAE,SAAS,MAAM,EAAE;IAGzD,OAAO,CAAC,eAAe;IAWjB,kBAAkB,CACtB,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC;IAmDlB,OAAO,CAAC,iBAAiB;YAIX,oBAAoB;YAwBpB,YAAY;CAqC3B;AACD,KAAK,iBAAiB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAMhF,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,eAAe,GAC3B,iBAAiB,CAKnB;AACD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc1D;AAWD,KAAK,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAyChC,wBAAgB,sBAAsB,IAAI,SAAS,CAMlD;AASD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,GACZ;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,GAAG,IAAI,CAiBzC;AACD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAuDD,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAE3C,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IAkB/C,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAW/C,OAAO,CAAC,mBAAmB;IAgB3B,OAAO,CAAC,QAAQ;IAUhB,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,mBAAmB;IAmB3B,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,mBAAmB;IAkB3B,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,qBAAqB;IAwB7B,OAAO,CAAC,eAAe;IAuBvB,OAAO,CAAC,kBAAkB;CAkB3B;AACD,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC9D;AACD,eAAO,MAAM,qBAAqB,oBAAgC,CAAC;AAKnE,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAA4B,CAAC;AAIhF,KAAK,cAAc,GAAG,OAAO,MAAM,CAAC,QAAQ,CAAC;AAC7C,KAAK,WAAW,GACZ,gBAAgB,GAChB,cAAc,GACd,YAAY,GACZ,gBAAgB,CAAC;AACrB,KAAK,gBAAgB,GAAG,QAAQ,CAAC;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC,CAAC;AAC1D,qBAAa,SAAS;IAUR,OAAO,CAAC,QAAQ,CAAC,QAAQ;IATrC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAKzC;IAEH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4B;gBAEzB,QAAQ,EAAE,cAAc;IAErD,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IASjD,WAAW,CACT,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,gBAAgB,GAAG,IAAI;IAuB1B,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIvC,aAAa,CACX,QAAQ,EAAE,MAAM,EAChB,mBAAmB,EAAE,SAAS,MAAM,EAAE,GACrC,OAAO;CAMX;AACD,KAAK,eAAe,GAAG,OAAO,MAAM,CAAC,SAAS,CAAC;AAC/C,qBAAa,aAAa;IAEtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,mBAAmB;gBAHnB,SAAS,EAAE,eAAe,EAC1B,QAAQ,EAAE,cAAc,EACxB,SAAS,EAAE,SAAS,EACpB,mBAAmB,EAAE,SAAS,MAAM,EAAE;IAGzD,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAgCzE,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI/C,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,qBAAqB;CAgB9B;AACD,OAAO,EAAE,IAAI,EAAE,CAAC;AAEhB,wBAAgB,SAAS,CACvB,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAC/C,MAAM,CAER;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIvD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS9D"}
package/dist/lib/zod.d.ts DELETED
@@ -1,3 +0,0 @@
1
- import { z } from 'zod';
2
- export declare function formatZodError(error: z.ZodError): string;
3
- //# sourceMappingURL=zod.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"zod.d.ts","sourceRoot":"","sources":["../../src/lib/zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgBxB,wBAAgB,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,CAYxD"}
package/dist/lib/zod.js DELETED
@@ -1,27 +0,0 @@
1
- import { z } from 'zod';
2
- function formatPathSegment(segment) {
3
- if (typeof segment === 'number')
4
- return `[${segment}]`;
5
- if (typeof segment === 'string')
6
- return segment;
7
- return segment.description ?? '<symbol>';
8
- }
9
- function formatIssuePath(path) {
10
- return path.reduce((acc, segment) => {
11
- const isNum = typeof segment === 'number';
12
- const formatted = formatPathSegment(segment);
13
- return acc ? `${acc}${isNum ? '' : '.'}${formatted}` : formatted;
14
- }, '');
15
- }
16
- export function formatZodError(error) {
17
- const parts = error.issues.map((issue) => {
18
- const path = formatIssuePath(issue.path);
19
- return path ? `${path}: ${issue.message}` : issue.message;
20
- });
21
- const uniqueParts = [
22
- ...new Set(parts.filter((val) => val.trim().length > 0)),
23
- ];
24
- if (uniqueParts.length > 0)
25
- return uniqueParts.join('; ');
26
- return z.prettifyError(error).replace(/\s+/g, ' ').trim() || 'Invalid input';
27
- }
@@ -1,25 +0,0 @@
1
- import type { ServerResult } from '@modelcontextprotocol/sdk/types.js';
2
- import { z } from 'zod';
3
- export declare const extendedCallToolRequestSchema: z.ZodObject<{
4
- method: z.ZodLiteral<"tools/call">;
5
- params: z.ZodObject<{
6
- name: z.ZodString;
7
- arguments: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
8
- task: z.ZodOptional<z.ZodObject<{
9
- ttl: z.ZodOptional<z.ZodNumber>;
10
- }, z.core.$strict>>;
11
- _meta: z.ZodOptional<z.ZodObject<{
12
- progressToken: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
13
- 'io.modelcontextprotocol/related-task': z.ZodOptional<z.ZodObject<{
14
- taskId: z.ZodString;
15
- }, z.core.$strict>>;
16
- }, z.core.$loose>>;
17
- }, z.core.$strict>;
18
- }, z.core.$loose>;
19
- export type ExtendedCallToolRequest = z.infer<typeof extendedCallToolRequestSchema>;
20
- export type ToolCallRequestMeta = ExtendedCallToolRequest['params']['_meta'];
21
- export declare function parseExtendedCallToolRequest(request: unknown): ExtendedCallToolRequest;
22
- export declare function sanitizeToolCallMeta(meta?: ToolCallRequestMeta): ToolCallRequestMeta | undefined;
23
- export declare function buildRelatedTaskMeta(taskId: string, meta?: ToolCallRequestMeta): Record<string, unknown>;
24
- export declare function withRelatedTaskMeta(result: ServerResult, taskId: string): ServerResult;
25
- //# sourceMappingURL=call-contract.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"call-contract.d.ts","sourceRoot":"","sources":["../../src/tasks/call-contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAEvE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiBxB,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;iBAiBxC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AACF,MAAM,MAAM,mBAAmB,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC;AAE7E,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,OAAO,GACf,uBAAuB,CAKzB;AAED,wBAAgB,oBAAoB,CAClC,IAAI,CAAC,EAAE,mBAAmB,GACzB,mBAAmB,GAAG,SAAS,CAMjC;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,mBAAmB,GACzB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKzB;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,GACb,YAAY,CAQd"}
@@ -1,59 +0,0 @@
1
- import { ErrorCode } from '@modelcontextprotocol/sdk/types.js';
2
- import { z } from 'zod';
3
- import { createMcpError } from '../lib/mcp-interop.js';
4
- import { formatZodError } from '../lib/zod.js';
5
- const MIN_TASK_TTL_MS = 1_000;
6
- const MAX_TASK_TTL_MS = 86_400_000;
7
- const relatedTaskMetaSchema = z.strictObject({
8
- taskId: z.string(),
9
- });
10
- const toolCallMetaSchema = z.looseObject({
11
- progressToken: z.union([z.string(), z.number()]).optional(),
12
- 'io.modelcontextprotocol/related-task': relatedTaskMetaSchema.optional(),
13
- });
14
- export const extendedCallToolRequestSchema = z.looseObject({
15
- method: z.literal('tools/call'),
16
- params: z.strictObject({
17
- name: z.string().min(1, 'Tool name required'),
18
- arguments: z.record(z.string(), z.unknown()).optional(),
19
- task: z
20
- .strictObject({
21
- ttl: z
22
- .number()
23
- .int()
24
- .min(MIN_TASK_TTL_MS, `Minimum ${MIN_TASK_TTL_MS}ms`)
25
- .max(MAX_TASK_TTL_MS, `Maximum ${MAX_TASK_TTL_MS}ms`)
26
- .optional(),
27
- })
28
- .optional(),
29
- _meta: toolCallMetaSchema.optional(),
30
- }),
31
- });
32
- export function parseExtendedCallToolRequest(request) {
33
- const parsed = extendedCallToolRequestSchema.safeParse(request);
34
- if (parsed.success)
35
- return parsed.data;
36
- throw createMcpError(ErrorCode.InvalidParams, formatZodError(parsed.error));
37
- }
38
- export function sanitizeToolCallMeta(meta) {
39
- if (!meta)
40
- return undefined;
41
- const sanitized = { ...meta };
42
- delete sanitized['io.modelcontextprotocol/related-task'];
43
- return Object.keys(sanitized).length > 0 ? sanitized : undefined;
44
- }
45
- export function buildRelatedTaskMeta(taskId, meta) {
46
- return {
47
- ...(sanitizeToolCallMeta(meta) ?? {}),
48
- 'io.modelcontextprotocol/related-task': { taskId },
49
- };
50
- }
51
- export function withRelatedTaskMeta(result, taskId) {
52
- return {
53
- ...result,
54
- _meta: {
55
- ...result._meta,
56
- 'io.modelcontextprotocol/related-task': { taskId },
57
- },
58
- };
59
- }
@@ -1,16 +0,0 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { type ServerResult } from '@modelcontextprotocol/sdk/types.js';
3
- import { type ExtendedCallToolRequest } from './call-contract.js';
4
- import { type CreateTaskResult, type TaskState } from './manager.js';
5
- import { type ToolCallContext } from './owner.js';
6
- export declare function abortTaskExecution(taskId: string): void;
7
- export declare function cancelTasksForOwner(ownerKey: string, statusMessage?: string): number;
8
- export declare function abortAllTaskExecutions(): void;
9
- type TaskSummary = CreateTaskResult['task'];
10
- type TaskLifecycleProjection = Pick<TaskState, 'taskId' | 'status' | 'statusMessage' | 'progress' | 'total' | 'createdAt' | 'lastUpdatedAt' | 'ttl' | 'pollInterval'>;
11
- export declare function toTaskSummary(task: TaskLifecycleProjection): TaskSummary;
12
- export declare function emitTaskStatusNotification(server: McpServer, task: TaskState): void;
13
- export declare function throwTaskNotFound(): never;
14
- export declare function handleToolCallRequest(server: McpServer, request: ExtendedCallToolRequest, context: ToolCallContext): Promise<ServerResult>;
15
- export {};
16
- //# sourceMappingURL=execution.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../../src/tasks/execution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,oCAAoC,CAAC;AAiB5C,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AAkCpB,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGvD;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,aAAa,SAA4D,GACxE,MAAM,CAOR;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAMD,KAAK,WAAW,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAC5C,KAAK,uBAAuB,GAAG,IAAI,CACjC,SAAS,EACP,QAAQ,GACR,QAAQ,GACR,eAAe,GACf,UAAU,GACV,OAAO,GACP,WAAW,GACX,eAAe,GACf,KAAK,GACL,cAAc,CACjB,CAAC;AAEF,wBAAgB,aAAa,CAAC,IAAI,EAAE,uBAAuB,GAAG,WAAW,CAYxE;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,SAAS,GACd,IAAI,CAmBN;AAED,wBAAgB,iBAAiB,IAAI,KAAK,CAEzC;AAgKD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,uBAAuB,EAChC,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,YAAY,CAAC,CAwFvB"}
@@ -1,241 +0,0 @@
1
- import { ErrorCode, McpError, } from '@modelcontextprotocol/sdk/types.js';
2
- import { config } from '../lib/core.js';
3
- import { logDebug, logError, logInfo, logWarn, runWithRequestContext, } from '../lib/core.js';
4
- import { Loggers } from '../lib/logger-names.js';
5
- import { createMcpError } from '../lib/mcp-interop.js';
6
- import {} from '../lib/mcp-interop.js';
7
- import { tryReadToolErrorMessage } from '../lib/tool-errors.js';
8
- import { getErrorMessage } from '../lib/utils.js';
9
- import { isObject } from '../lib/utils.js';
10
- import { buildRelatedTaskMeta, } from './call-contract.js';
11
- import { taskManager, } from './manager.js';
12
- import { buildToolHandlerExtra, compact, } from './owner.js';
13
- import { getTaskCapableTool, getTaskCapableToolSupport, } from './registry.js';
14
- /* -------------------------------------------------------------------------------------------------
15
- * Abort-controller management for in-flight task executions
16
- * ------------------------------------------------------------------------------------------------- */
17
- // Intentionally process-global (not session-scoped): abortAllTaskExecutions() is called
18
- // during SIGTERM/SIGINT shutdown to cancel every in-flight task across all sessions.
19
- const taskAbortControllers = new Map();
20
- function attachAbortController(taskId) {
21
- taskAbortControllers.get(taskId)?.abort();
22
- if (taskAbortControllers.size >= config.tasks.maxTotal) {
23
- logWarn('Abort controller map reached task capacity — possible leak', {
24
- size: taskAbortControllers.size,
25
- maxTotal: config.tasks.maxTotal,
26
- }, Loggers.LOG_TASKS);
27
- }
28
- const controller = new AbortController();
29
- taskAbortControllers.set(taskId, controller);
30
- return controller;
31
- }
32
- export function abortTaskExecution(taskId) {
33
- taskAbortControllers.get(taskId)?.abort();
34
- taskAbortControllers.delete(taskId);
35
- }
36
- export function cancelTasksForOwner(ownerKey, statusMessage = 'The task was cancelled because its owner session ended.') {
37
- if (!ownerKey)
38
- return 0;
39
- const cancelled = taskManager.cancelTasksByOwner(ownerKey, statusMessage);
40
- for (const task of cancelled) {
41
- abortTaskExecution(task.taskId);
42
- }
43
- return cancelled.length;
44
- }
45
- export function abortAllTaskExecutions() {
46
- for (const taskId of taskAbortControllers.keys())
47
- abortTaskExecution(taskId);
48
- }
49
- export function toTaskSummary(task) {
50
- return {
51
- taskId: task.taskId,
52
- status: task.status,
53
- ...(task.statusMessage ? { statusMessage: task.statusMessage } : {}),
54
- ...(task.progress !== undefined ? { progress: task.progress } : {}),
55
- ...(task.total !== undefined ? { total: task.total } : {}),
56
- createdAt: task.createdAt,
57
- lastUpdatedAt: task.lastUpdatedAt,
58
- ttl: task.ttl,
59
- pollInterval: task.pollInterval,
60
- };
61
- }
62
- export function emitTaskStatusNotification(server, task) {
63
- if (!config.tasks.emitStatusNotifications || !server.isConnected())
64
- return;
65
- void server.server
66
- .notification({
67
- method: 'notifications/tasks/status',
68
- params: { ...toTaskSummary(task) },
69
- })
70
- .catch((error) => {
71
- logError('Failed to send task status notification', {
72
- taskId: task.taskId,
73
- status: task.status,
74
- error: getErrorMessage(error),
75
- }, Loggers.LOG_TASKS);
76
- });
77
- }
78
- export function throwTaskNotFound() {
79
- throw createMcpError(ErrorCode.InvalidParams, 'Task not found');
80
- }
81
- /* -------------------------------------------------------------------------------------------------
82
- * Execution pipeline
83
- * ------------------------------------------------------------------------------------------------- */
84
- function updateTaskAndEmitStatus(server, taskId, update) {
85
- taskManager.updateTask(taskId, update);
86
- const task = taskManager.getTask(taskId);
87
- if (task)
88
- emitTaskStatusNotification(server, task);
89
- }
90
- function buildTaskFailureState(error) {
91
- const mcpErrorMessage = error instanceof McpError
92
- ? (/^(?:MCP )?[Ee]rror -?\d+:\s*(.*)$/s.exec(error.message)?.[1] ??
93
- error.message)
94
- : undefined;
95
- const statusMessage = mcpErrorMessage ?? getErrorMessage(error);
96
- if (error instanceof McpError) {
97
- return {
98
- status: 'failed',
99
- statusMessage,
100
- error: {
101
- code: error.code,
102
- ...(error.data !== undefined ? { data: error.data } : {}),
103
- message: statusMessage,
104
- },
105
- };
106
- }
107
- return {
108
- status: 'failed',
109
- statusMessage,
110
- error: {
111
- code: ErrorCode.InternalError,
112
- message: statusMessage,
113
- },
114
- };
115
- }
116
- function buildTaskCompletionUpdate(result, tool) {
117
- const isError = isObject(result) && 'isError' in result && result.isError === true;
118
- return {
119
- status: isError ? 'failed' : 'completed',
120
- statusMessage: isError
121
- ? (tryReadToolErrorMessage(result) ?? 'Execution failed')
122
- : (tool.getCompletionStatusMessage?.(result) ??
123
- 'Task completed successfully.'),
124
- result,
125
- };
126
- }
127
- async function runTaskToolExecution(params) {
128
- const { server, taskId, args, tool, meta, sessionId, sendNotification } = params;
129
- return runWithRequestContext({
130
- requestId: taskId,
131
- operationId: taskId,
132
- ...(sessionId ? { sessionId } : {}),
133
- }, async () => {
134
- const controller = attachAbortController(taskId);
135
- const progressState = { closed: false };
136
- try {
137
- logInfo('Task execution started', { taskId, tool: tool.name }, Loggers.LOG_TASKS);
138
- const relatedMeta = buildRelatedTaskMeta(taskId, meta);
139
- const result = await tool.execute(args, {
140
- signal: controller.signal,
141
- requestId: taskId,
142
- _meta: relatedMeta,
143
- progressState,
144
- canReportProgress: () => taskManager.getTask(taskId)?.status === 'working',
145
- ...compact({ sendNotification }),
146
- onProgress: (progress, message, total) => {
147
- const current = taskManager.getTask(taskId);
148
- if (current?.status === 'working' &&
149
- (current.statusMessage !== message ||
150
- current.progress !== progress ||
151
- (total !== undefined && current.total !== total))) {
152
- updateTaskAndEmitStatus(server, taskId, {
153
- statusMessage: message,
154
- progress,
155
- ...(total !== undefined ? { total } : {}),
156
- });
157
- }
158
- },
159
- });
160
- const completionUpdate = buildTaskCompletionUpdate(result, tool);
161
- updateTaskAndEmitStatus(server, taskId, completionUpdate);
162
- if (completionUpdate.status === 'completed') {
163
- logInfo('Task execution completed', { taskId, tool: tool.name }, Loggers.LOG_TASKS);
164
- }
165
- else {
166
- logWarn('Task execution completed with tool error result', { taskId, tool: tool.name }, Loggers.LOG_TASKS);
167
- }
168
- }
169
- catch (error) {
170
- logError('Task execution failed', {
171
- taskId,
172
- tool: tool.name,
173
- error: getErrorMessage(error),
174
- }, Loggers.LOG_TASKS);
175
- updateTaskAndEmitStatus(server, taskId, buildTaskFailureState(error));
176
- }
177
- finally {
178
- progressState.closed = true;
179
- taskAbortControllers.delete(taskId);
180
- }
181
- });
182
- }
183
- export async function handleToolCallRequest(server, request, context) {
184
- const { params } = request;
185
- // Validate the tool name first so an unknown tool always produces MethodNotFound
186
- const tool = getTaskCapableTool(server, params.name);
187
- if (!tool) {
188
- throw createMcpError(ErrorCode.MethodNotFound, `Unknown tool: ${params.name}`);
189
- }
190
- if (params.task) {
191
- if (getTaskCapableToolSupport(server, params.name) === 'forbidden') {
192
- throw createMcpError(ErrorCode.MethodNotFound, `Task mode is not supported for tool: ${params.name}`);
193
- }
194
- const args = tool.parseArguments(params.arguments);
195
- const task = taskManager.createTask(params.task.ttl !== undefined ? { ttl: params.task.ttl } : undefined, 'Task started', context.ownerKey);
196
- logInfo('Task execution queued', {
197
- taskId: task.taskId,
198
- tool: params.name,
199
- ...(params.task.ttl !== undefined ? { ttl: params.task.ttl } : {}),
200
- }, Loggers.LOG_TASKS);
201
- void runTaskToolExecution({
202
- server,
203
- taskId: task.taskId,
204
- args,
205
- tool,
206
- ...compact({
207
- meta: params._meta,
208
- sessionId: context.sessionId,
209
- sendNotification: context.sendNotification,
210
- }),
211
- });
212
- return {
213
- task: toTaskSummary(task),
214
- ...(tool.immediateResponse
215
- ? {
216
- _meta: {
217
- 'io.modelcontextprotocol/model-immediate-response': tool.immediateResponse,
218
- },
219
- }
220
- : {}),
221
- };
222
- }
223
- if (getTaskCapableToolSupport(server, params.name) === 'required') {
224
- throw createMcpError(ErrorCode.MethodNotFound, `Task mode is required for tool: ${params.name}`);
225
- }
226
- const args = tool.parseArguments(params.arguments);
227
- const progressState = { closed: false };
228
- logDebug('Executing task-capable tool inline', {
229
- tool: params.name,
230
- hasProgressToken: params._meta?.progressToken !== undefined,
231
- }, Loggers.LOG_TASKS);
232
- try {
233
- return await tool.execute(args, {
234
- ...buildToolHandlerExtra(context, params._meta),
235
- progressState,
236
- });
237
- }
238
- finally {
239
- progressState.closed = true;
240
- }
241
- }
@@ -1,11 +0,0 @@
1
- import { type McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export { cancelTasksForOwner, abortAllTaskExecutions } from './execution.js';
3
- interface TaskHandlerRegistrationOptions {
4
- requireInterception?: boolean;
5
- }
6
- interface TaskHandlerRegistrationResult {
7
- interceptedToolsCall: boolean;
8
- taskCapableToolsRegistered: boolean;
9
- }
10
- export declare function registerTaskHandlers(server: McpServer, options?: TaskHandlerRegistrationOptions): TaskHandlerRegistrationResult;
11
- //# sourceMappingURL=handlers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/tasks/handlers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAmCzE,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AA4D7E,UAAU,8BAA8B;IACtC,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,UAAU,6BAA6B;IACrC,oBAAoB,EAAE,OAAO,CAAC;IAC9B,0BAA0B,EAAE,OAAO,CAAC;CACrC;AAkBD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,EACjB,OAAO,CAAC,EAAE,8BAA8B,GACvC,6BAA6B,CAoK/B"}