@inso_web/els-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +482 -0
- package/dist/audit/prisma.d.ts +67 -0
- package/dist/audit/prisma.d.ts.map +1 -0
- package/dist/audit/prisma.js +65 -0
- package/dist/audit/prisma.js.map +1 -0
- package/dist/audit/service.d.ts +72 -0
- package/dist/audit/service.d.ts.map +1 -0
- package/dist/audit/service.js +137 -0
- package/dist/audit/service.js.map +1 -0
- package/dist/billing/limits.d.ts +34 -0
- package/dist/billing/limits.d.ts.map +1 -0
- package/dist/billing/limits.js +51 -0
- package/dist/billing/limits.js.map +1 -0
- package/dist/billing/tracker.d.ts +39 -0
- package/dist/billing/tracker.d.ts.map +1 -0
- package/dist/billing/tracker.js +92 -0
- package/dist/billing/tracker.js.map +1 -0
- package/dist/cache/cachedElsClient.d.ts +71 -0
- package/dist/cache/cachedElsClient.d.ts.map +1 -0
- package/dist/cache/cachedElsClient.js +167 -0
- package/dist/cache/cachedElsClient.js.map +1 -0
- package/dist/cache/index.d.ts +10 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +6 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/policies.d.ts +60 -0
- package/dist/cache/policies.d.ts.map +1 -0
- package/dist/cache/policies.js +90 -0
- package/dist/cache/policies.js.map +1 -0
- package/dist/cache/redis.d.ts +52 -0
- package/dist/cache/redis.d.ts.map +1 -0
- package/dist/cache/redis.js +134 -0
- package/dist/cache/redis.js.map +1 -0
- package/dist/cache/types.d.ts +32 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cache/types.js +32 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/cache/wrapper.d.ts +38 -0
- package/dist/cache/wrapper.d.ts.map +1 -0
- package/dist/cache/wrapper.js +109 -0
- package/dist/cache/wrapper.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +86 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +105 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +211 -0
- package/dist/config.js.map +1 -0
- package/dist/elsClient.d.ts +137 -0
- package/dist/elsClient.d.ts.map +1 -0
- package/dist/elsClient.js +285 -0
- package/dist/elsClient.js.map +1 -0
- package/dist/http/app.d.ts +40 -0
- package/dist/http/app.d.ts.map +1 -0
- package/dist/http/app.js +135 -0
- package/dist/http/app.js.map +1 -0
- package/dist/http/jwks.d.ts +8 -0
- package/dist/http/jwks.d.ts.map +1 -0
- package/dist/http/jwks.js +34 -0
- package/dist/http/jwks.js.map +1 -0
- package/dist/http/middleware/auth.d.ts +11 -0
- package/dist/http/middleware/auth.d.ts.map +1 -0
- package/dist/http/middleware/auth.js +225 -0
- package/dist/http/middleware/auth.js.map +1 -0
- package/dist/http/middleware/dcrRateLimit.d.ts +29 -0
- package/dist/http/middleware/dcrRateLimit.d.ts.map +1 -0
- package/dist/http/middleware/dcrRateLimit.js +59 -0
- package/dist/http/middleware/dcrRateLimit.js.map +1 -0
- package/dist/http/middleware/errorHandler.d.ts +12 -0
- package/dist/http/middleware/errorHandler.d.ts.map +1 -0
- package/dist/http/middleware/errorHandler.js +26 -0
- package/dist/http/middleware/errorHandler.js.map +1 -0
- package/dist/http/middleware/originGuard.d.ts +28 -0
- package/dist/http/middleware/originGuard.d.ts.map +1 -0
- package/dist/http/middleware/originGuard.js +55 -0
- package/dist/http/middleware/originGuard.js.map +1 -0
- package/dist/http/middleware/requestId.d.ts +19 -0
- package/dist/http/middleware/requestId.d.ts.map +1 -0
- package/dist/http/middleware/requestId.js +23 -0
- package/dist/http/middleware/requestId.js.map +1 -0
- package/dist/http/routes/health.d.ts +24 -0
- package/dist/http/routes/health.d.ts.map +1 -0
- package/dist/http/routes/health.js +73 -0
- package/dist/http/routes/health.js.map +1 -0
- package/dist/http/routes/metrics.d.ts +18 -0
- package/dist/http/routes/metrics.d.ts.map +1 -0
- package/dist/http/routes/metrics.js +42 -0
- package/dist/http/routes/metrics.js.map +1 -0
- package/dist/http/routes/wellKnown.d.ts +15 -0
- package/dist/http/routes/wellKnown.d.ts.map +1 -0
- package/dist/http/routes/wellKnown.js +43 -0
- package/dist/http/routes/wellKnown.js.map +1 -0
- package/dist/http/types.d.ts +40 -0
- package/dist/http/types.d.ts.map +1 -0
- package/dist/http/types.js +9 -0
- package/dist/http/types.js.map +1 -0
- package/dist/instrumentation.d.ts +22 -0
- package/dist/instrumentation.d.ts.map +1 -0
- package/dist/instrumentation.js +38 -0
- package/dist/instrumentation.js.map +1 -0
- package/dist/lib/cursor.d.ts +22 -0
- package/dist/lib/cursor.d.ts.map +1 -0
- package/dist/lib/cursor.js +95 -0
- package/dist/lib/cursor.js.map +1 -0
- package/dist/lib/errors.d.ts +49 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +83 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/responseFormat.d.ts +14 -0
- package/dist/lib/responseFormat.d.ts.map +1 -0
- package/dist/lib/responseFormat.js +74 -0
- package/dist/lib/responseFormat.js.map +1 -0
- package/dist/middleware/withMiddleware.d.ts +53 -0
- package/dist/middleware/withMiddleware.d.ts.map +1 -0
- package/dist/middleware/withMiddleware.js +190 -0
- package/dist/middleware/withMiddleware.js.map +1 -0
- package/dist/observability/health.d.ts +51 -0
- package/dist/observability/health.d.ts.map +1 -0
- package/dist/observability/health.js +77 -0
- package/dist/observability/health.js.map +1 -0
- package/dist/observability/index.d.ts +8 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +5 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/logger.d.ts +45 -0
- package/dist/observability/logger.d.ts.map +1 -0
- package/dist/observability/logger.js +75 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/metrics.d.ts +49 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +184 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/observability/tracing.d.ts +28 -0
- package/dist/observability/tracing.d.ts.map +1 -0
- package/dist/observability/tracing.js +56 -0
- package/dist/observability/tracing.js.map +1 -0
- package/dist/prompts/index.d.ts +20 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +202 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/redaction/argsRedactor.d.ts +22 -0
- package/dist/redaction/argsRedactor.d.ts.map +1 -0
- package/dist/redaction/argsRedactor.js +97 -0
- package/dist/redaction/argsRedactor.js.map +1 -0
- package/dist/redaction/fields.d.ts +64 -0
- package/dist/redaction/fields.d.ts.map +1 -0
- package/dist/redaction/fields.js +155 -0
- package/dist/redaction/fields.js.map +1 -0
- package/dist/redaction/index.d.ts +52 -0
- package/dist/redaction/index.d.ts.map +1 -0
- package/dist/redaction/index.js +160 -0
- package/dist/redaction/index.js.map +1 -0
- package/dist/redaction/promptInjection.d.ts +32 -0
- package/dist/redaction/promptInjection.d.ts.map +1 -0
- package/dist/redaction/promptInjection.js +68 -0
- package/dist/redaction/promptInjection.js.map +1 -0
- package/dist/redaction/url.d.ts +8 -0
- package/dist/redaction/url.d.ts.map +1 -0
- package/dist/redaction/url.js +26 -0
- package/dist/redaction/url.js.map +1 -0
- package/dist/redaction/userAgent.d.ts +9 -0
- package/dist/redaction/userAgent.d.ts.map +1 -0
- package/dist/redaction/userAgent.js +39 -0
- package/dist/redaction/userAgent.js.map +1 -0
- package/dist/resources/index.d.ts +24 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +150 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/server.d.ts +37 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +35 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/baselineCompare.d.ts +36 -0
- package/dist/tools/baselineCompare.d.ts.map +1 -0
- package/dist/tools/baselineCompare.js +69 -0
- package/dist/tools/baselineCompare.js.map +1 -0
- package/dist/tools/errorHeatmap.d.ts +40 -0
- package/dist/tools/errorHeatmap.d.ts.map +1 -0
- package/dist/tools/errorHeatmap.js +69 -0
- package/dist/tools/errorHeatmap.js.map +1 -0
- package/dist/tools/errorHistogram.d.ts +39 -0
- package/dist/tools/errorHistogram.d.ts.map +1 -0
- package/dist/tools/errorHistogram.js +61 -0
- package/dist/tools/errorHistogram.js.map +1 -0
- package/dist/tools/errorStatsBreakdown.d.ts +43 -0
- package/dist/tools/errorStatsBreakdown.d.ts.map +1 -0
- package/dist/tools/errorStatsBreakdown.js +77 -0
- package/dist/tools/errorStatsBreakdown.js.map +1 -0
- package/dist/tools/errorsInSession.d.ts +44 -0
- package/dist/tools/errorsInSession.d.ts.map +1 -0
- package/dist/tools/errorsInSession.js +91 -0
- package/dist/tools/errorsInSession.js.map +1 -0
- package/dist/tools/explainError.d.ts +35 -0
- package/dist/tools/explainError.d.ts.map +1 -0
- package/dist/tools/explainError.js +98 -0
- package/dist/tools/explainError.js.map +1 -0
- package/dist/tools/findCorrelatedErrors.d.ts +43 -0
- package/dist/tools/findCorrelatedErrors.d.ts.map +1 -0
- package/dist/tools/findCorrelatedErrors.js +59 -0
- package/dist/tools/findCorrelatedErrors.js.map +1 -0
- package/dist/tools/findSimilarErrors.d.ts +44 -0
- package/dist/tools/findSimilarErrors.d.ts.map +1 -0
- package/dist/tools/findSimilarErrors.js +59 -0
- package/dist/tools/findSimilarErrors.js.map +1 -0
- package/dist/tools/getLogDetails.d.ts +30 -0
- package/dist/tools/getLogDetails.d.ts.map +1 -0
- package/dist/tools/getLogDetails.js +49 -0
- package/dist/tools/getLogDetails.js.map +1 -0
- package/dist/tools/groupedErrors.d.ts +46 -0
- package/dist/tools/groupedErrors.d.ts.map +1 -0
- package/dist/tools/groupedErrors.js +71 -0
- package/dist/tools/groupedErrors.js.map +1 -0
- package/dist/tools/impactAnalysis.d.ts +42 -0
- package/dist/tools/impactAnalysis.d.ts.map +1 -0
- package/dist/tools/impactAnalysis.js +61 -0
- package/dist/tools/impactAnalysis.js.map +1 -0
- package/dist/tools/index.d.ts +41 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +83 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/listApps.d.ts +27 -0
- package/dist/tools/listApps.d.ts.map +1 -0
- package/dist/tools/listApps.js +78 -0
- package/dist/tools/listApps.js.map +1 -0
- package/dist/tools/queryLogsJql.d.ts +44 -0
- package/dist/tools/queryLogsJql.d.ts.map +1 -0
- package/dist/tools/queryLogsJql.js +107 -0
- package/dist/tools/queryLogsJql.js.map +1 -0
- package/dist/tools/searchLogs.d.ts +60 -0
- package/dist/tools/searchLogs.d.ts.map +1 -0
- package/dist/tools/searchLogs.js +127 -0
- package/dist/tools/searchLogs.js.map +1 -0
- package/dist/tools/topErrorMessages.d.ts +42 -0
- package/dist/tools/topErrorMessages.d.ts.map +1 -0
- package/dist/tools/topErrorMessages.js +63 -0
- package/dist/tools/topErrorMessages.js.map +1 -0
- package/dist/tools/trafficStats.d.ts +39 -0
- package/dist/tools/trafficStats.d.ts.map +1 -0
- package/dist/tools/trafficStats.js +57 -0
- package/dist/tools/trafficStats.js.map +1 -0
- package/dist/tools/triageRecentCritical.d.ts +26 -0
- package/dist/tools/triageRecentCritical.d.ts.map +1 -0
- package/dist/tools/triageRecentCritical.js +81 -0
- package/dist/tools/triageRecentCritical.js.map +1 -0
- package/dist/tools/versionRegression.d.ts +29 -0
- package/dist/tools/versionRegression.d.ts.map +1 -0
- package/dist/tools/versionRegression.js +80 -0
- package/dist/tools/versionRegression.js.map +1 -0
- package/dist/transports/http-server.d.ts +25 -0
- package/dist/transports/http-server.d.ts.map +1 -0
- package/dist/transports/http-server.js +84 -0
- package/dist/transports/http-server.js.map +1 -0
- package/dist/transports/http.d.ts +71 -0
- package/dist/transports/http.d.ts.map +1 -0
- package/dist/transports/http.js +315 -0
- package/dist/transports/http.js.map +1 -0
- package/dist/transports/stdio.d.ts +13 -0
- package/dist/transports/stdio.d.ts.map +1 -0
- package/dist/transports/stdio.js +16 -0
- package/dist/transports/stdio.js.map +1 -0
- package/dist/types.d.ts +150 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ErrorLog, ErrorLogCompact, ErrorLogSummary, ResponseFormat } from '../types.js';
|
|
2
|
+
export interface ApplyResponseFormatResult<T> {
|
|
3
|
+
items: T[];
|
|
4
|
+
truncated: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function applyResponseFormat(items: ErrorLog[], format: ResponseFormat): ApplyResponseFormatResult<ErrorLog | ErrorLogCompact | ErrorLogSummary>;
|
|
7
|
+
/**
|
|
8
|
+
* Сокращает поля одного ErrorLog (для get_log_details при compact-format).
|
|
9
|
+
*/
|
|
10
|
+
export declare function applyResponseFormatSingle(row: ErrorLog, format: 'compact' | 'full'): {
|
|
11
|
+
log: ErrorLog | ErrorLogCompact;
|
|
12
|
+
truncated: boolean;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=responseFormat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responseFormat.d.ts","sourceRoot":"","sources":["../../src/lib/responseFormat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,eAAe,EACf,eAAe,EACf,cAAc,EACf,MAAM,aAAa,CAAC;AAiBrB,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAC1C,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,QAAQ,EAAE,EACjB,MAAM,EAAE,cAAc,GACrB,yBAAyB,CAAC,QAAQ,GAAG,eAAe,GAAG,eAAe,CAAC,CAsCzE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,QAAQ,EACb,MAAM,EAAE,SAAS,GAAG,MAAM,GACzB;IAAE,GAAG,EAAE,QAAQ,GAAG,eAAe,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAgBzD"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Применяет `response_format` к массиву ErrorLog items.
|
|
3
|
+
*
|
|
4
|
+
* - `compact` (default): убирает `stack`, `componentStack`, `userAgent`,
|
|
5
|
+
* обрезает `message` до 200 символов. Подходит для LLM-context-safe browse.
|
|
6
|
+
* - `full`: возвращает items как есть.
|
|
7
|
+
* - `summary`: только traceId/message/level/lastSeen/count.
|
|
8
|
+
*
|
|
9
|
+
* Также возвращает флаг `truncated` — true, если хотя бы один message был обрезан
|
|
10
|
+
* (используется в `_meta.truncated`).
|
|
11
|
+
*/
|
|
12
|
+
const MESSAGE_MAX_COMPACT = 200;
|
|
13
|
+
const MESSAGE_MAX_SUMMARY = 200;
|
|
14
|
+
export function applyResponseFormat(items, format) {
|
|
15
|
+
if (format === 'full') {
|
|
16
|
+
return { items, truncated: false };
|
|
17
|
+
}
|
|
18
|
+
if (format === 'summary') {
|
|
19
|
+
let truncated = false;
|
|
20
|
+
const result = items.map((row) => {
|
|
21
|
+
const msg = row.message ?? '';
|
|
22
|
+
const sliced = msg.length > MESSAGE_MAX_SUMMARY ? msg.slice(0, MESSAGE_MAX_SUMMARY) : msg;
|
|
23
|
+
if (sliced.length < msg.length)
|
|
24
|
+
truncated = true;
|
|
25
|
+
return {
|
|
26
|
+
traceId: row.traceId,
|
|
27
|
+
message: sliced,
|
|
28
|
+
level: row.level,
|
|
29
|
+
lastSeen: row.receivedAt,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
return { items: result, truncated };
|
|
33
|
+
}
|
|
34
|
+
// compact (default)
|
|
35
|
+
let truncated = false;
|
|
36
|
+
const result = items.map((row) => {
|
|
37
|
+
const msg = row.message ?? '';
|
|
38
|
+
const sliced = msg.length > MESSAGE_MAX_COMPACT ? msg.slice(0, MESSAGE_MAX_COMPACT) : msg;
|
|
39
|
+
if (sliced.length < msg.length)
|
|
40
|
+
truncated = true;
|
|
41
|
+
return {
|
|
42
|
+
traceId: row.traceId,
|
|
43
|
+
level: row.level,
|
|
44
|
+
message: sliced,
|
|
45
|
+
serviceName: row.serviceName || null,
|
|
46
|
+
url: row.url ?? null,
|
|
47
|
+
fingerprint: row.fingerprint ?? null,
|
|
48
|
+
receivedAt: row.receivedAt,
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
return { items: result, truncated };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Сокращает поля одного ErrorLog (для get_log_details при compact-format).
|
|
55
|
+
*/
|
|
56
|
+
export function applyResponseFormatSingle(row, format) {
|
|
57
|
+
if (format === 'full')
|
|
58
|
+
return { log: row, truncated: false };
|
|
59
|
+
const msg = row.message ?? '';
|
|
60
|
+
const sliced = msg.length > MESSAGE_MAX_COMPACT ? msg.slice(0, MESSAGE_MAX_COMPACT) : msg;
|
|
61
|
+
return {
|
|
62
|
+
log: {
|
|
63
|
+
traceId: row.traceId,
|
|
64
|
+
level: row.level,
|
|
65
|
+
message: sliced,
|
|
66
|
+
serviceName: row.serviceName || null,
|
|
67
|
+
url: row.url ?? null,
|
|
68
|
+
fingerprint: row.fingerprint ?? null,
|
|
69
|
+
receivedAt: row.receivedAt,
|
|
70
|
+
},
|
|
71
|
+
truncated: sliced.length < msg.length,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=responseFormat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responseFormat.js","sourceRoot":"","sources":["../../src/lib/responseFormat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 5 tool-handler middleware:
|
|
3
|
+
* 1. Quota check (`checkQuota`) перед основным запросом.
|
|
4
|
+
* 2. Audit log + usage tracker (fire-and-forget) после.
|
|
5
|
+
* 3. Redaction items в response (если ENV redactionEnabled = true).
|
|
6
|
+
*
|
|
7
|
+
* Не вносит изменений в существующие tool handlers — оборачивает их в
|
|
8
|
+
* registry. Это позволяет Phase 2 параллельно дописывать новые tools, не
|
|
9
|
+
* боясь merge conflicts.
|
|
10
|
+
*
|
|
11
|
+
* См. todo/error-logs-service/mcp/06-security.md §2.4, §3, 08-billing-integration.md §2.
|
|
12
|
+
*/
|
|
13
|
+
import type { Logger } from 'pino';
|
|
14
|
+
import type { ToolResult } from '../types.js';
|
|
15
|
+
import { type RedactionConfig } from '../redaction/index.js';
|
|
16
|
+
import { type AuditService } from '../audit/service.js';
|
|
17
|
+
import { type UsageTracker } from '../billing/tracker.js';
|
|
18
|
+
import type { Tier, QuotaDecision } from '../billing/limits.js';
|
|
19
|
+
export interface ToolContext {
|
|
20
|
+
/** Текущий app (из API-key / OAuth claim / config.defaultAppId). */
|
|
21
|
+
appId: string;
|
|
22
|
+
/** Prefix API-key (8 chars). */
|
|
23
|
+
keyId: string;
|
|
24
|
+
/** Tier для quota-check. */
|
|
25
|
+
tier: Tier;
|
|
26
|
+
/** Optional logger. */
|
|
27
|
+
log?: Logger;
|
|
28
|
+
/** Optional request meta для audit (ip/userAgent/sessionId). */
|
|
29
|
+
ip?: string | null;
|
|
30
|
+
userAgent?: string | null;
|
|
31
|
+
sessionId?: string | null;
|
|
32
|
+
}
|
|
33
|
+
export interface MiddlewareDeps {
|
|
34
|
+
audit?: AuditService;
|
|
35
|
+
usage?: UsageTracker;
|
|
36
|
+
redactionConfig?: RedactionConfig;
|
|
37
|
+
/** В Phase 5 опциональный — quota берётся из usage tracker. */
|
|
38
|
+
quotaCheck?: (ctx: ToolContext) => Promise<QuotaDecision>;
|
|
39
|
+
}
|
|
40
|
+
type AnyArgs = Record<string, unknown>;
|
|
41
|
+
type Handler<TArgs extends AnyArgs, TClient> = (args: TArgs, client: TClient) => Promise<ToolResult>;
|
|
42
|
+
/**
|
|
43
|
+
* Оборачивает существующий tool handler.
|
|
44
|
+
*
|
|
45
|
+
* Семантика:
|
|
46
|
+
* - Если `quotaCheck`-result `allowed=false` → возвращаем ToolError('TIER_QUOTA_EXCEEDED').
|
|
47
|
+
* - При `overage=true` (grace) добавляем `_meta.overage=true` к ответу.
|
|
48
|
+
* - После handler-вызова прогоняем items / log через redaction.
|
|
49
|
+
* - Audit + usage пишутся fire-and-forget (void).
|
|
50
|
+
*/
|
|
51
|
+
export declare function withMiddleware<TArgs extends AnyArgs, TClient>(toolName: string, handler: Handler<TArgs, TClient>, getContext: (args: TArgs, client: TClient) => ToolContext, deps?: MiddlewareDeps): Handler<TArgs, TClient>;
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=withMiddleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withMiddleware.d.ts","sourceRoot":"","sources":["../../src/middleware/withMiddleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAgC,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,IAAI,EAAE,IAAI,CAAC;IACX,uBAAuB;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,+DAA+D;IAC/D,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;CAC3D;AAED,KAAK,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACvC,KAAK,OAAO,CAAC,KAAK,SAAS,OAAO,EAAE,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;AAErG;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,SAAS,OAAO,EAAE,OAAO,EAC3D,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,EAChC,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,KAAK,WAAW,EACzD,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAqHzB"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 5 tool-handler middleware:
|
|
3
|
+
* 1. Quota check (`checkQuota`) перед основным запросом.
|
|
4
|
+
* 2. Audit log + usage tracker (fire-and-forget) после.
|
|
5
|
+
* 3. Redaction items в response (если ENV redactionEnabled = true).
|
|
6
|
+
*
|
|
7
|
+
* Не вносит изменений в существующие tool handlers — оборачивает их в
|
|
8
|
+
* registry. Это позволяет Phase 2 параллельно дописывать новые tools, не
|
|
9
|
+
* боясь merge conflicts.
|
|
10
|
+
*
|
|
11
|
+
* См. todo/error-logs-service/mcp/06-security.md §2.4, §3, 08-billing-integration.md §2.
|
|
12
|
+
*/
|
|
13
|
+
import { ToolError } from '../lib/errors.js';
|
|
14
|
+
import { redactErrorLogs, redactValue } from '../redaction/index.js';
|
|
15
|
+
import { getAuditService } from '../audit/service.js';
|
|
16
|
+
import { getUsageTracker } from '../billing/tracker.js';
|
|
17
|
+
/**
|
|
18
|
+
* Оборачивает существующий tool handler.
|
|
19
|
+
*
|
|
20
|
+
* Семантика:
|
|
21
|
+
* - Если `quotaCheck`-result `allowed=false` → возвращаем ToolError('TIER_QUOTA_EXCEEDED').
|
|
22
|
+
* - При `overage=true` (grace) добавляем `_meta.overage=true` к ответу.
|
|
23
|
+
* - После handler-вызова прогоняем items / log через redaction.
|
|
24
|
+
* - Audit + usage пишутся fire-and-forget (void).
|
|
25
|
+
*/
|
|
26
|
+
export function withMiddleware(toolName, handler, getContext, deps = {}) {
|
|
27
|
+
return async (args, client) => {
|
|
28
|
+
const ctx = getContext(args, client);
|
|
29
|
+
const log = ctx.log;
|
|
30
|
+
const start = Date.now();
|
|
31
|
+
const audit = deps.audit ?? getAuditService();
|
|
32
|
+
const usage = deps.usage ?? getUsageTracker();
|
|
33
|
+
// 1. Quota
|
|
34
|
+
let quota = null;
|
|
35
|
+
try {
|
|
36
|
+
quota = deps.quotaCheck
|
|
37
|
+
? await deps.quotaCheck(ctx)
|
|
38
|
+
: await usage.checkQuota(ctx.appId, ctx.tier);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
log?.warn?.({ err }, 'Quota check failed; allowing request');
|
|
42
|
+
}
|
|
43
|
+
if (quota && !quota.allowed) {
|
|
44
|
+
const latencyMs = Date.now() - start;
|
|
45
|
+
void audit.recordToolCall({
|
|
46
|
+
appId: ctx.appId,
|
|
47
|
+
keyId: ctx.keyId,
|
|
48
|
+
tool: toolName,
|
|
49
|
+
args: redactValue(args).value,
|
|
50
|
+
resultBytes: 0,
|
|
51
|
+
latencyMs,
|
|
52
|
+
cacheHit: false,
|
|
53
|
+
...(ctx.ip !== undefined ? { ip: ctx.ip } : {}),
|
|
54
|
+
...(ctx.userAgent !== undefined ? { userAgent: ctx.userAgent } : {}),
|
|
55
|
+
...(ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : {}),
|
|
56
|
+
statusCode: 429,
|
|
57
|
+
error: 'TIER_QUOTA_EXCEEDED',
|
|
58
|
+
});
|
|
59
|
+
const err = new ToolError('TIER_QUOTA_EXCEEDED', `Daily request quota exceeded for ${ctx.tier} tier. Try again after ${quota.retryAfter ?? 0}s.`, {
|
|
60
|
+
...(quota.retryAfter !== undefined ? { retryAfter: quota.retryAfter } : {}),
|
|
61
|
+
suggestedAction: 'Wait for the daily reset or upgrade your tier.',
|
|
62
|
+
meta: { tier: ctx.tier, remaining: 0 },
|
|
63
|
+
});
|
|
64
|
+
return err.toToolResult();
|
|
65
|
+
}
|
|
66
|
+
// 2. Run handler
|
|
67
|
+
let result;
|
|
68
|
+
let statusCode = 200;
|
|
69
|
+
let errorMessage = null;
|
|
70
|
+
try {
|
|
71
|
+
result = await handler(args, client);
|
|
72
|
+
if (result.isError) {
|
|
73
|
+
statusCode = 500;
|
|
74
|
+
const meta = (result._meta ?? {});
|
|
75
|
+
const code = typeof meta.code === 'string' ? meta.code : 'INTERNAL';
|
|
76
|
+
errorMessage = code;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
statusCode = 500;
|
|
81
|
+
errorMessage = err instanceof Error ? err.message : String(err);
|
|
82
|
+
const latencyMs = Date.now() - start;
|
|
83
|
+
void audit.recordToolCall({
|
|
84
|
+
appId: ctx.appId,
|
|
85
|
+
keyId: ctx.keyId,
|
|
86
|
+
tool: toolName,
|
|
87
|
+
args: redactValue(args).value,
|
|
88
|
+
resultBytes: 0,
|
|
89
|
+
latencyMs,
|
|
90
|
+
cacheHit: false,
|
|
91
|
+
...(ctx.ip !== undefined ? { ip: ctx.ip } : {}),
|
|
92
|
+
...(ctx.userAgent !== undefined ? { userAgent: ctx.userAgent } : {}),
|
|
93
|
+
...(ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : {}),
|
|
94
|
+
statusCode,
|
|
95
|
+
error: errorMessage,
|
|
96
|
+
});
|
|
97
|
+
throw err;
|
|
98
|
+
}
|
|
99
|
+
// 3. Redaction
|
|
100
|
+
const redacted = applyRedactionToResult(result, deps.redactionConfig);
|
|
101
|
+
// Add quota meta if grace zone
|
|
102
|
+
if (quota?.overage) {
|
|
103
|
+
const meta = (redacted._meta ?? {});
|
|
104
|
+
redacted._meta = { ...meta, overage: true, tier: ctx.tier };
|
|
105
|
+
}
|
|
106
|
+
// 4. Audit + usage (fire-and-forget)
|
|
107
|
+
const latencyMs = Date.now() - start;
|
|
108
|
+
const resultBytes = estimateBytes(redacted);
|
|
109
|
+
void audit.recordToolCall({
|
|
110
|
+
appId: ctx.appId,
|
|
111
|
+
keyId: ctx.keyId,
|
|
112
|
+
tool: toolName,
|
|
113
|
+
args: redactValue(args).value,
|
|
114
|
+
resultBytes,
|
|
115
|
+
latencyMs,
|
|
116
|
+
cacheHit: !!(redacted.structuredContent?._meta && redacted.structuredContent._meta.cached === true),
|
|
117
|
+
...(ctx.ip !== undefined ? { ip: ctx.ip } : {}),
|
|
118
|
+
...(ctx.userAgent !== undefined ? { userAgent: ctx.userAgent } : {}),
|
|
119
|
+
...(ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : {}),
|
|
120
|
+
statusCode,
|
|
121
|
+
error: errorMessage,
|
|
122
|
+
});
|
|
123
|
+
void usage.trackUsage({
|
|
124
|
+
appId: ctx.appId,
|
|
125
|
+
tool: toolName,
|
|
126
|
+
bytesOut: resultBytes,
|
|
127
|
+
});
|
|
128
|
+
return redacted;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Применяет redaction к items / log внутри ToolResult.structuredContent.
|
|
133
|
+
*
|
|
134
|
+
* Эвристика:
|
|
135
|
+
* - Если есть `items: array` — прогоняем через `redactErrorLogs`.
|
|
136
|
+
* - Если есть `log: object` — прогоняем `redactErrorLog`-аналог.
|
|
137
|
+
* - Помечаем `_meta.redactionApplied = true` если что-то отредактировано.
|
|
138
|
+
*/
|
|
139
|
+
function applyRedactionToResult(result, cfg) {
|
|
140
|
+
const sc = result.structuredContent;
|
|
141
|
+
if (!sc)
|
|
142
|
+
return result;
|
|
143
|
+
const newSc = { ...sc };
|
|
144
|
+
let redactionAppliedAny = false;
|
|
145
|
+
if (Array.isArray(newSc.items)) {
|
|
146
|
+
const items = newSc.items;
|
|
147
|
+
const { items: redactedItems, stats } = redactErrorLogs(items, cfg ? { config: cfg } : {});
|
|
148
|
+
newSc.items = redactedItems;
|
|
149
|
+
if (stats.fieldsHit.length > 0 || stats.suspiciousContentBlocked) {
|
|
150
|
+
redactionAppliedAny = true;
|
|
151
|
+
}
|
|
152
|
+
if (stats.suspiciousContentBlocked) {
|
|
153
|
+
const meta = (newSc._meta ?? {});
|
|
154
|
+
newSc._meta = {
|
|
155
|
+
...meta,
|
|
156
|
+
suspiciousContentBlocked: true,
|
|
157
|
+
suspiciousRule: stats.suspiciousRule,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (newSc.log && typeof newSc.log === 'object' && !Array.isArray(newSc.log)) {
|
|
162
|
+
const { items: redactedItems, stats } = redactErrorLogs([newSc.log], cfg ? { config: cfg } : {});
|
|
163
|
+
newSc.log = redactedItems[0];
|
|
164
|
+
if (stats.fieldsHit.length > 0 || stats.suspiciousContentBlocked) {
|
|
165
|
+
redactionAppliedAny = true;
|
|
166
|
+
}
|
|
167
|
+
if (stats.suspiciousContentBlocked) {
|
|
168
|
+
const meta = (newSc._meta ?? {});
|
|
169
|
+
newSc._meta = {
|
|
170
|
+
...meta,
|
|
171
|
+
suspiciousContentBlocked: true,
|
|
172
|
+
suspiciousRule: stats.suspiciousRule,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (redactionAppliedAny) {
|
|
177
|
+
const meta = (newSc._meta ?? {});
|
|
178
|
+
newSc._meta = { ...meta, redactionApplied: true };
|
|
179
|
+
}
|
|
180
|
+
return { ...result, structuredContent: newSc };
|
|
181
|
+
}
|
|
182
|
+
function estimateBytes(result) {
|
|
183
|
+
try {
|
|
184
|
+
return Buffer.byteLength(JSON.stringify(result), 'utf8');
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return 0;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=withMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withMiddleware.js","sourceRoot":"","sources":["../../src/middleware/withMiddleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAE,eAAe,EAAE,WAAW,EAAwB,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,eAAe,EAAqB,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAqB,MAAM,uBAAuB,CAAC;AA6B3E;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,QAAgB,EAChB,OAAgC,EAChC,UAAyD,EACzD,OAAuB,EAAE;IAEzB,OAAO,KAAK,EAAE,IAAW,EAAE,MAAe,EAAuB,EAAE;QACjE,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACrC,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC;QAE9C,WAAW;QACX,IAAI,KAAK,GAAyB,IAAI,CAAC;QACvC,IAAI,CAAC;YACH,KAAK,GAAG,IAAI,CAAC,UAAU;gBACrB,CAAC,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAC5B,CAAC,CAAC,MAAM,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,sCAAsC,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YACrC,KAAK,KAAK,CAAC,cAAc,CAAC;gBACxB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,KAAgC;gBACxD,WAAW,EAAE,CAAC;gBACd,SAAS;gBACT,QAAQ,EAAE,KAAK;gBACf,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/C,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpE,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpE,UAAU,EAAE,GAAG;gBACf,KAAK,EAAE,qBAAqB;aAC7B,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,SAAS,CACvB,qBAAqB,EACrB,oCAAoC,GAAG,CAAC,IAAI,0BAA0B,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,EAC/F;gBACE,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3E,eAAe,EAAE,gDAAgD;gBACjE,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE;aACvC,CACF,CAAC;YACF,OAAO,GAAG,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;QAED,iBAAiB;QACjB,IAAI,MAAkB,CAAC;QACvB,IAAI,UAAU,GAAG,GAAG,CAAC;QACrB,IAAI,YAAY,GAAkB,IAAI,CAAC;QAEvC,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACrC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,UAAU,GAAG,GAAG,CAAC;gBACjB,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAA4B,CAAC;gBAC7D,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC;gBACpE,YAAY,GAAG,IAAI,CAAC;YACtB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,UAAU,GAAG,GAAG,CAAC;YACjB,YAAY,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAChE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YACrC,KAAK,KAAK,CAAC,cAAc,CAAC;gBACxB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,KAAgC;gBACxD,WAAW,EAAE,CAAC;gBACd,SAAS;gBACT,QAAQ,EAAE,KAAK;gBACf,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/C,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpE,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpE,UAAU;gBACV,KAAK,EAAE,YAAY;aACpB,CAAC,CAAC;YACH,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,eAAe;QACf,MAAM,QAAQ,GAAG,sBAAsB,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAEtE,+BAA+B;QAC/B,IAAI,KAAK,EAAE,OAAO,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAA4B,CAAC;YAC/D,QAAQ,CAAC,KAAK,GAAG,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9D,CAAC;QAED,qCAAqC;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QACrC,MAAM,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QAE5C,KAAK,KAAK,CAAC,cAAc,CAAC;YACxB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,KAAgC;YACxD,WAAW;YACX,SAAS;YACT,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,iBAAiB,EAAE,KAAK,IAAK,QAAQ,CAAC,iBAAiB,CAAC,KAAiC,CAAC,MAAM,KAAK,IAAI,CAAC;YAChI,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/C,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,UAAU;YACV,KAAK,EAAE,YAAY;SACpB,CAAC,CAAC;QAEH,KAAK,KAAK,CAAC,UAAU,CAAC;YACpB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,WAAW;SACtB,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,sBAAsB,CAAC,MAAkB,EAAE,GAAqB;IACvE,MAAM,EAAE,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACpC,IAAI,CAAC,EAAE;QAAE,OAAO,MAAM,CAAC;IAEvB,MAAM,KAAK,GAA4B,EAAE,GAAG,EAAE,EAAE,CAAC;IACjD,IAAI,mBAAmB,GAAG,KAAK,CAAC;IAEhC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAuC,CAAC;QAC5D,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3F,KAAK,CAAC,KAAK,GAAG,aAAa,CAAC;QAC5B,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,wBAAwB,EAAE,CAAC;YACjE,mBAAmB,GAAG,IAAI,CAAC;QAC7B,CAAC;QACD,IAAI,KAAK,CAAC,wBAAwB,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAA4B,CAAC;YAC5D,KAAK,CAAC,KAAK,GAAG;gBACZ,GAAG,IAAI;gBACP,wBAAwB,EAAE,IAAI;gBAC9B,cAAc,EAAE,KAAK,CAAC,cAAc;aACrC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,GAAG,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5E,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,eAAe,CACrD,CAAC,KAAK,CAAC,GAA8B,CAAC,EACtC,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAC3B,CAAC;QACF,KAAK,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QAC7B,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,wBAAwB,EAAE,CAAC;YACjE,mBAAmB,GAAG,IAAI,CAAC;QAC7B,CAAC;QACD,IAAI,KAAK,CAAC,wBAAwB,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAA4B,CAAC;YAC5D,KAAK,CAAC,KAAK,GAAG;gBACZ,GAAG,IAAI;gBACP,wBAAwB,EAAE,IAAI;gBAC9B,cAAc,EAAE,KAAK,CAAC,cAAc;aACrC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,mBAAmB,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAA4B,CAAC;QAC5D,KAAK,CAAC,KAAK,GAAG,EAAE,GAAG,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC;IACpD,CAAC;IAED,OAAO,EAAE,GAAG,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC;AACjD,CAAC;AAED,SAAS,aAAa,CAAC,MAAkB;IACvC,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Logger } from 'pino';
|
|
2
|
+
import type { RedisService } from '../cache/redis.js';
|
|
3
|
+
import type { ElsClient } from '../elsClient.js';
|
|
4
|
+
/**
|
|
5
|
+
* Health checks для k8s liveness/readiness probes.
|
|
6
|
+
*
|
|
7
|
+
* - `liveness` — всегда 200 OK, если процесс жив (EventLoop не deadlock'нут).
|
|
8
|
+
* Используется k8s `livenessProbe` для рестарта pod'а.
|
|
9
|
+
*
|
|
10
|
+
* - `readiness` — 200 если ВСЕ зависимости healthy:
|
|
11
|
+
* * Redis: `PING` → `PONG`
|
|
12
|
+
* * ELS upstream: HEAD/GET `/health` (или просто `/`)
|
|
13
|
+
* 503 если хотя бы одна failed. Используется k8s `readinessProbe`
|
|
14
|
+
* (исключение pod'а из service endpoints).
|
|
15
|
+
*
|
|
16
|
+
* Phase 3 (HTTP transport) подцепит эти функции в Express routes
|
|
17
|
+
* `/els/healthz` и `/els/readyz` через DI.
|
|
18
|
+
*/
|
|
19
|
+
export interface LivenessResult {
|
|
20
|
+
status: 'ok';
|
|
21
|
+
uptimeSec: number;
|
|
22
|
+
version: string;
|
|
23
|
+
}
|
|
24
|
+
export interface ReadinessResult {
|
|
25
|
+
status: 'ready' | 'not_ready';
|
|
26
|
+
checks: {
|
|
27
|
+
redis: {
|
|
28
|
+
ok: boolean;
|
|
29
|
+
latencyMs?: number;
|
|
30
|
+
error?: string;
|
|
31
|
+
};
|
|
32
|
+
upstream: {
|
|
33
|
+
ok: boolean;
|
|
34
|
+
latencyMs?: number;
|
|
35
|
+
error?: string;
|
|
36
|
+
status?: number;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export declare function checkLiveness(): LivenessResult;
|
|
41
|
+
export interface ReadinessDeps {
|
|
42
|
+
redis?: RedisService | null;
|
|
43
|
+
elsClient?: ElsClient | null;
|
|
44
|
+
/** Override endpoint для probe; иначе используется heuristic /health. */
|
|
45
|
+
elsHealthPath?: string;
|
|
46
|
+
log?: Logger;
|
|
47
|
+
/** Timeout per check, ms. */
|
|
48
|
+
timeoutMs?: number;
|
|
49
|
+
}
|
|
50
|
+
export declare function checkReadiness(deps?: ReadinessDeps): Promise<ReadinessResult>;
|
|
51
|
+
//# sourceMappingURL=health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/observability/health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,IAAI,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,GAAG,WAAW,CAAC;IAC9B,MAAM,EAAE;QACN,KAAK,EAAE;YAAE,EAAE,EAAE,OAAO,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC3D,QAAQ,EAAE;YAAE,EAAE,EAAE,OAAO,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAChF,CAAC;CACH;AAID,wBAAgB,aAAa,IAAI,cAAc,CAM9C;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,yEAAyE;IACzE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,cAAc,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,eAAe,CAAC,CAiBvF"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const SERVICE_VERSION = process.env.GIT_SHA ?? process.env.npm_package_version ?? '0.1.0-alpha.0';
|
|
2
|
+
export function checkLiveness() {
|
|
3
|
+
return {
|
|
4
|
+
status: 'ok',
|
|
5
|
+
uptimeSec: Math.round(process.uptime()),
|
|
6
|
+
version: SERVICE_VERSION,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export async function checkReadiness(deps = {}) {
|
|
10
|
+
const timeoutMs = deps.timeoutMs ?? 3000;
|
|
11
|
+
const [redisCheck, upstreamCheck] = await Promise.all([
|
|
12
|
+
deps.redis ? withTimeout(checkRedis(deps.redis), timeoutMs) : Promise.resolve({ ok: true }),
|
|
13
|
+
deps.elsClient
|
|
14
|
+
? withTimeout(checkUpstream(deps.elsClient, deps.elsHealthPath), timeoutMs)
|
|
15
|
+
: Promise.resolve({ ok: true }),
|
|
16
|
+
]);
|
|
17
|
+
const ready = redisCheck.ok && upstreamCheck.ok;
|
|
18
|
+
return {
|
|
19
|
+
status: ready ? 'ready' : 'not_ready',
|
|
20
|
+
checks: {
|
|
21
|
+
redis: redisCheck,
|
|
22
|
+
upstream: upstreamCheck,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async function checkRedis(redis) {
|
|
27
|
+
// Redis "недоступен" — это допустимое degraded состояние: cache miss всегда.
|
|
28
|
+
// Поэтому для readyz считаем "ok" если либо Redis pingается, либо disabled.
|
|
29
|
+
// Если был сконфигурирован, но не отвечает → not ready (force k8s degrade).
|
|
30
|
+
const start = Date.now();
|
|
31
|
+
try {
|
|
32
|
+
const ok = await redis.ping();
|
|
33
|
+
const latencyMs = Date.now() - start;
|
|
34
|
+
if (!ok) {
|
|
35
|
+
return { ok: false, latencyMs, error: 'ping failed' };
|
|
36
|
+
}
|
|
37
|
+
return { ok: true, latencyMs };
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
return { ok: false, error: err.message };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function checkUpstream(client, pathHint) {
|
|
44
|
+
// ELS известен через client'а. Не у всех методов есть health-check;
|
|
45
|
+
// делаем "lightweight probe" — пробуем listApps() с очень коротким timeout.
|
|
46
|
+
// Если 401/403 — endpoint reachable, но key недостаточно для list_apps; всё равно ok.
|
|
47
|
+
// Если 5xx или connection refused — not ready.
|
|
48
|
+
void pathHint;
|
|
49
|
+
const start = Date.now();
|
|
50
|
+
try {
|
|
51
|
+
await client.listApps();
|
|
52
|
+
return { ok: true, latencyMs: Date.now() - start };
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
const e = err;
|
|
56
|
+
const status = e?.meta?.status;
|
|
57
|
+
// INSUFFICIENT_SCOPE (403) / NOT_FOUND (404) — ELS reachable, это ok.
|
|
58
|
+
if (e?.code === 'INSUFFICIENT_SCOPE' ||
|
|
59
|
+
e?.code === 'NOT_FOUND' ||
|
|
60
|
+
e?.code === 'INVALID_ARGS') {
|
|
61
|
+
return { ok: true, latencyMs: Date.now() - start, ...(status !== undefined ? { status } : {}) };
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
ok: false,
|
|
65
|
+
latencyMs: Date.now() - start,
|
|
66
|
+
error: e?.message ?? 'unknown',
|
|
67
|
+
...(status !== undefined ? { status } : {}),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function withTimeout(p, ms) {
|
|
72
|
+
return Promise.race([
|
|
73
|
+
p,
|
|
74
|
+
new Promise((resolve) => setTimeout(() => resolve({ ok: false, error: 'timeout' }), ms)),
|
|
75
|
+
]);
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/observability/health.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { registry, mcpRequestsTotal, mcpRequestDuration, mcpErrorsTotal, mcpCacheHitsTotal, mcpCacheMissesTotal, mcpCacheHitRatio, mcpElsUpstreamErrorsTotal, mcpSseConnectionsActive, mcpRedactionAppliedTotal, mcpBillingEventsTotal, recordCacheHit, recordCacheMiss, recordToolRequest, recordToolError, recordUpstreamError, recordRedaction, recordBillingEvent, resetMetricsForTests, getMetricsText, getMetricsContentType, } from './metrics.js';
|
|
2
|
+
export { createLogger, getLogger, setLogger, withRequestContext } from './logger.js';
|
|
3
|
+
export type { LoggerConfig, RequestLogFields } from './logger.js';
|
|
4
|
+
export { setupTracing } from './tracing.js';
|
|
5
|
+
export type { TracingHandle } from './tracing.js';
|
|
6
|
+
export { checkLiveness, checkReadiness } from './health.js';
|
|
7
|
+
export type { LivenessResult, ReadinessResult, ReadinessDeps } from './health.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,yBAAyB,EACzB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,qBAAqB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACrF,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC5D,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { registry, mcpRequestsTotal, mcpRequestDuration, mcpErrorsTotal, mcpCacheHitsTotal, mcpCacheMissesTotal, mcpCacheHitRatio, mcpElsUpstreamErrorsTotal, mcpSseConnectionsActive, mcpRedactionAppliedTotal, mcpBillingEventsTotal, recordCacheHit, recordCacheMiss, recordToolRequest, recordToolError, recordUpstreamError, recordRedaction, recordBillingEvent, resetMetricsForTests, getMetricsText, getMetricsContentType, } from './metrics.js';
|
|
2
|
+
export { createLogger, getLogger, setLogger, withRequestContext } from './logger.js';
|
|
3
|
+
export { setupTracing } from './tracing.js';
|
|
4
|
+
export { checkLiveness, checkReadiness } from './health.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,yBAAyB,EACzB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,qBAAqB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAErF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type Logger } from 'pino';
|
|
2
|
+
/**
|
|
3
|
+
* Structured logger (pino, JSON output).
|
|
4
|
+
*
|
|
5
|
+
* Принципы:
|
|
6
|
+
* - stdout зарезервирован под JSON-RPC (stdio transport) → все pino-логи
|
|
7
|
+
* идут в stderr.
|
|
8
|
+
* - Format: JSON по умолчанию. Pretty-print в dev (`NODE_ENV=development`,
|
|
9
|
+
* если установлен pino-pretty).
|
|
10
|
+
* - Redaction: secrets автоматически замещаются на `<REDACTED>` (см. § 2.4
|
|
11
|
+
* спеки `07-observability.md`).
|
|
12
|
+
* - Base fields: service, version, pod (HOSTNAME).
|
|
13
|
+
*
|
|
14
|
+
* Per-request child logger создаётся в HTTP middleware (Phase 3) через
|
|
15
|
+
* `logger.child({ requestId, sessionId, appSlug, tool })`.
|
|
16
|
+
*/
|
|
17
|
+
export interface LoggerConfig {
|
|
18
|
+
level?: string;
|
|
19
|
+
service?: string;
|
|
20
|
+
/** Используется в `base.version`. */
|
|
21
|
+
version?: string;
|
|
22
|
+
/** Используется в `base.pod` (для k8s identification). */
|
|
23
|
+
pod?: string;
|
|
24
|
+
/** Pretty-print для dev. */
|
|
25
|
+
pretty?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare function createLogger(cfg?: LoggerConfig): Logger;
|
|
28
|
+
/** Singleton accessor. */
|
|
29
|
+
export declare function getLogger(): Logger;
|
|
30
|
+
export declare function setLogger(logger: Logger): void;
|
|
31
|
+
/**
|
|
32
|
+
* Per-request child logger. Поля:
|
|
33
|
+
* - requestId, sessionId, appSlug, keyPrefix, tool — для корреляции.
|
|
34
|
+
*/
|
|
35
|
+
export interface RequestLogFields {
|
|
36
|
+
requestId?: string;
|
|
37
|
+
sessionId?: string;
|
|
38
|
+
appSlug?: string | null;
|
|
39
|
+
keyPrefix?: string;
|
|
40
|
+
tool?: string;
|
|
41
|
+
cached?: boolean;
|
|
42
|
+
latencyMs?: number;
|
|
43
|
+
}
|
|
44
|
+
export declare function withRequestContext(logger: Logger, fields: RequestLogFields): Logger;
|
|
45
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/observability/logger.ts"],"names":[],"mappings":"AAAA,OAAa,EAAE,KAAK,MAAM,EAA8C,MAAM,MAAM,CAAC;AAErF;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAiBD,wBAAgB,YAAY,CAAC,GAAG,GAAE,YAAiB,GAAG,MAAM,CAkD3D;AAED,0BAA0B;AAC1B,wBAAgB,SAAS,IAAI,MAAM,CAKlC;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAE9C;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAEnF"}
|