stitchkit 0.45.0 → 0.47.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 +5 -4
- package/dist/browser/cancellation.d.ts +14 -0
- package/dist/browser/cancellation.d.ts.map +1 -0
- package/dist/browser/client-multipart.d.ts +3 -1
- package/dist/browser/client-multipart.d.ts.map +1 -1
- package/dist/browser/client.d.ts +1 -0
- package/dist/browser/client.d.ts.map +1 -1
- package/dist/browser/http.d.ts +1 -0
- package/dist/browser/http.d.ts.map +1 -1
- package/dist/browser/socket-io.d.ts +3 -1
- package/dist/browser/socket-io.d.ts.map +1 -1
- package/dist/cli.js +3 -4
- package/dist/contract/define.d.ts +59 -15
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/contract/errors.d.ts +1 -0
- package/dist/contract/errors.d.ts.map +1 -1
- package/dist/contract/index.d.ts +1 -1
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/contract/index.js +2 -2
- package/dist/{index-w0mec79h.js → index-44xysy8r.js} +697 -301
- package/dist/{index-r6czv7yt.js → index-45dz4m51.js} +50 -3
- package/dist/index-8ekq6res.js +181 -0
- package/dist/{index-yh0p5ddn.js → index-ee621cmy.js} +39 -19
- package/dist/{index-mvjyq9h9.js → index-kp8xamqp.js} +309 -144
- package/dist/{index-36f1xkdb.js → index-nrytvb30.js} +5 -4
- package/dist/{index-6jypn22c.js → index-r1qp4rve.js} +9 -1
- package/dist/{index-s4qsmgwe.js → index-tss6bk5c.js} +4 -1
- package/dist/index-yxpe3phd.js +63 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +315 -134
- package/dist/internal/errors.d.ts.map +1 -1
- package/dist/internal/secure-fetch.d.ts +23 -3
- package/dist/internal/secure-fetch.d.ts.map +1 -1
- package/dist/internal/typed.d.ts +7 -0
- package/dist/internal/typed.d.ts.map +1 -1
- package/dist/internal/within-dir.d.ts +6 -0
- package/dist/internal/within-dir.d.ts.map +1 -1
- package/dist/logger.d.ts +8 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/node.js +3 -4
- package/dist/observability/audit.d.ts +22 -3
- package/dist/observability/audit.d.ts.map +1 -1
- package/dist/observability/event.d.ts +7 -0
- package/dist/observability/event.d.ts.map +1 -1
- package/dist/observability/index.d.ts +1 -1
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +130 -134
- package/dist/observability/sanitize.d.ts +8 -1
- package/dist/observability/sanitize.d.ts.map +1 -1
- package/dist/observability/trace.d.ts +3 -1
- package/dist/observability/trace.d.ts.map +1 -1
- package/dist/react/cache-bridge.d.ts +4 -0
- package/dist/react/cache-bridge.d.ts.map +1 -1
- package/dist/react.js +46 -5
- package/dist/realtime/contract.d.ts +4 -1
- package/dist/realtime/contract.d.ts.map +1 -1
- package/dist/realtime/rejection.d.ts +10 -0
- package/dist/realtime/rejection.d.ts.map +1 -0
- package/dist/realtime/socket.d.ts +14 -1
- package/dist/realtime/socket.d.ts.map +1 -1
- package/dist/server/cache.d.ts +5 -1
- package/dist/server/cache.d.ts.map +1 -1
- package/dist/server/context.d.ts +8 -5
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/error-hook.d.ts +1 -0
- package/dist/server/error-hook.d.ts.map +1 -1
- package/dist/server/file.d.ts +6 -0
- package/dist/server/file.d.ts.map +1 -1
- package/dist/server/implement.d.ts +33 -2
- package/dist/server/implement.d.ts.map +1 -1
- package/dist/server/index.d.ts +5 -6
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +133 -14
- package/dist/server/middleware/auth.d.ts +7 -4
- package/dist/server/middleware/auth.d.ts.map +1 -1
- package/dist/server/middleware/cors.d.ts.map +1 -1
- package/dist/server/multipart.d.ts +13 -18
- package/dist/server/multipart.d.ts.map +1 -1
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/realtime.d.ts +2 -0
- package/dist/server/realtime.d.ts.map +1 -1
- package/dist/server/router.d.ts +0 -8
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/stream.d.ts.map +1 -1
- package/dist/server/types.d.ts +50 -22
- package/dist/server/types.d.ts.map +1 -1
- package/dist/tools/cli-args.d.ts +11 -3
- package/dist/tools/cli-args.d.ts.map +1 -1
- package/dist/tools/cli.d.ts +5 -0
- package/dist/tools/cli.d.ts.map +1 -1
- package/dist/tools/coerce.d.ts.map +1 -1
- package/dist/tools/json-schema.d.ts.map +1 -1
- package/dist/tools/mcp-handler.d.ts +4 -3
- package/dist/tools/mcp-handler.d.ts.map +1 -1
- package/dist/tools/mcp-prepare.d.ts +95 -0
- package/dist/tools/mcp-prepare.d.ts.map +1 -0
- package/dist/tools/mcp-round.d.ts +4 -0
- package/dist/tools/mcp-round.d.ts.map +1 -1
- package/dist/tools/mcp-stdio.d.ts +2 -1
- package/dist/tools/mcp-stdio.d.ts.map +1 -1
- package/dist/tools/mcp.d.ts +2 -78
- package/dist/tools/mcp.d.ts.map +1 -1
- package/dist/tools/mount-download.d.ts +5 -0
- package/dist/tools/mount-download.d.ts.map +1 -1
- package/dist/tools/native-mcp.d.ts +1 -1
- package/dist/tools/native-mcp.d.ts.map +1 -1
- package/dist/tools/oauth-provider.d.ts +20 -1
- package/dist/tools/oauth-provider.d.ts.map +1 -1
- package/dist/tools/tool-logger.d.ts +1 -1
- package/dist/tools/tool-logger.d.ts.map +1 -1
- package/dist/tools/view-file.d.ts +9 -0
- package/dist/tools/view-file.d.ts.map +1 -1
- package/dist/tools.d.ts +2 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +505 -278
- package/llms-full.txt +473 -85
- package/llms.txt +1 -1
- package/package.json +2 -2
- package/dist/index-frfyw9fa.js +0 -33
- package/dist/index-x3fcszf8.js +0 -8
|
@@ -4,9 +4,13 @@ export declare function isPrivateIp(ip: string): boolean;
|
|
|
4
4
|
* Refuse a URL that is not `http(s)`, has no host, or whose host is — or
|
|
5
5
|
* resolves to — a private/internal address. Called on the initial URL and on
|
|
6
6
|
* every redirect hop, so a public host cannot `302` to an internal address or
|
|
7
|
-
* to a `file:` / `gopher:` / `data:` scheme.
|
|
7
|
+
* to a `file:` / `gopher:` / `data:` scheme. The DNS lookup honours `signal`,
|
|
8
|
+
* so a slow resolver cannot outlive the caller's deadline.
|
|
9
|
+
*
|
|
10
|
+
* This is the single host-validation implementation — `fetchGuarded` and
|
|
11
|
+
* `fetchPinnedDocument` both go through `resolvePublicAddress`.
|
|
8
12
|
*/
|
|
9
|
-
export declare function assertPublicUrl(url: URL): Promise<void>;
|
|
13
|
+
export declare function assertPublicUrl(url: URL, signal?: AbortSignal): Promise<void>;
|
|
10
14
|
/**
|
|
11
15
|
* Fetch a URL with the SSRF guard enforced on the initial URL and on every
|
|
12
16
|
* redirect hop — a public host can otherwise `302` to an internal address or a
|
|
@@ -17,7 +21,23 @@ export declare function assertPublicUrl(url: URL): Promise<void>;
|
|
|
17
21
|
* per-hop re-check is the larger and fully-closed hole; a static private DNS
|
|
18
22
|
* record is rejected outright.
|
|
19
23
|
*/
|
|
20
|
-
export
|
|
24
|
+
export interface GuardedFetchOptions {
|
|
25
|
+
/**
|
|
26
|
+
* Deadline for producing the FINAL response headers — DNS, connects and every
|
|
27
|
+
* redirect hop share this single budget, so a redirect chain cannot multiply
|
|
28
|
+
* it. Default 15 seconds.
|
|
29
|
+
*/
|
|
30
|
+
timeoutMs?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Separate deadline for consuming the body once headers have arrived — a slow
|
|
33
|
+
* LARGE download must not be killed by the connection budget, but a drip-feed
|
|
34
|
+
* body must still end. Default 120 seconds.
|
|
35
|
+
*/
|
|
36
|
+
bodyTimeoutMs?: number;
|
|
37
|
+
/** Optional caller cancellation, combined with both deadlines. */
|
|
38
|
+
signal?: AbortSignal;
|
|
39
|
+
}
|
|
40
|
+
export declare function fetchGuarded(start: URL, allowPrivate: boolean, options?: GuardedFetchOptions): Promise<Response>;
|
|
21
41
|
export interface PinnedDocumentFetchOptions {
|
|
22
42
|
maxBytes: number;
|
|
23
43
|
timeoutMs: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secure-fetch.d.ts","sourceRoot":"","sources":["../../src/internal/secure-fetch.ts"],"names":[],"mappings":"AAiEA,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CA8D/C;
|
|
1
|
+
{"version":3,"file":"secure-fetch.d.ts","sourceRoot":"","sources":["../../src/internal/secure-fetch.ts"],"names":[],"mappings":"AAiEA,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CA8D/C;AA4BD;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnF;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,GAAG,EACV,YAAY,EAAE,OAAO,EACrB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,QAAQ,CAAC,CAiDnB;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,6DAA6D;IAC7D,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,GAAG,EAAE,GAAG,CAAC;CACV;AAsCD;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,GAAG,EACV,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,sBAAsB,CAAC,CAkFjC;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoBnF"}
|
package/dist/internal/typed.d.ts
CHANGED
|
@@ -3,6 +3,13 @@ export declare function typedEntries<T extends object>(value: T): Array<{
|
|
|
3
3
|
}[keyof T]>;
|
|
4
4
|
/** Narrow an unknown value to a plain object — not `null`, not an array. */
|
|
5
5
|
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
6
|
+
/** Invoke a runtime-discovered handler after a fail-first function check. */
|
|
7
|
+
export declare function callRuntimeHandler(handler: unknown, context: unknown): unknown;
|
|
8
|
+
/**
|
|
9
|
+
* Isolated loose-to-typed adapter boundary for transports whose decoder is
|
|
10
|
+
* selected at runtime while the contract fixes the generic result type.
|
|
11
|
+
*/
|
|
12
|
+
export declare function transportResult<T>(value: unknown): T;
|
|
6
13
|
export declare function mapObject<TSource extends object, TResult extends {
|
|
7
14
|
[K in keyof TSource]?: unknown;
|
|
8
15
|
}>(source: TSource, mapper: <K extends keyof TSource>(key: K, value: TSource[K]) => TResult[K] | undefined): TResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typed.d.ts","sourceRoot":"","sources":["../../src/internal/typed.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EAC3C,KAAK,EAAE,CAAC,GACP,KAAK,CAAC;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAE/C;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,wBAAgB,SAAS,CACvB,OAAO,SAAS,MAAM,EACtB,OAAO,SAAS;KAAG,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,EAAE,OAAO;CAAE,EAElD,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,CAAC,CAAC,SAAS,MAAM,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,GACrF,OAAO,CAOT;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,SAAS,MAAM,EACtB,OAAO,SAAS;KAAG,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,EAAE,OAAO;CAAE,EAElD,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,OAAO,CAAC,KAAK,OAAO,GACrE,OAAO,CAKT"}
|
|
1
|
+
{"version":3,"file":"typed.d.ts","sourceRoot":"","sources":["../../src/internal/typed.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EAC3C,KAAK,EAAE,CAAC,GACP,KAAK,CAAC;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAE/C;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAK9E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,CAEpD;AAED,wBAAgB,SAAS,CACvB,OAAO,SAAS,MAAM,EACtB,OAAO,SAAS;KAAG,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,EAAE,OAAO;CAAE,EAElD,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,CAAC,CAAC,SAAS,MAAM,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,GACrF,OAAO,CAOT;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,SAAS,MAAM,EACtB,OAAO,SAAS;KAAG,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,EAAE,OAAO;CAAE,EAElD,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,OAAO,CAAC,KAAK,OAAO,GACrE,OAAO,CAKT"}
|
|
@@ -4,4 +4,10 @@
|
|
|
4
4
|
* check behind `staticRoute` and `view_file`'s local-file branch.
|
|
5
5
|
*/
|
|
6
6
|
export declare function isWithinDir(root: string, target: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Resolve both paths through the filesystem and return the real target only
|
|
9
|
+
* when it remains inside the real root. The lexical check must run first at a
|
|
10
|
+
* URL boundary; this second check closes symlink escapes.
|
|
11
|
+
*/
|
|
12
|
+
export declare function realPathWithinDir(root: string, target: string): Promise<string | null>;
|
|
7
13
|
//# sourceMappingURL=within-dir.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"within-dir.d.ts","sourceRoot":"","sources":["../../src/internal/within-dir.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"within-dir.d.ts","sourceRoot":"","sources":["../../src/internal/within-dir.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAQjE;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAO5F"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Minimal structured logger shared by browser-safe and server entrypoints. */
|
|
2
|
+
export interface StitchLogger {
|
|
3
|
+
info(msg: string, data?: Record<string, unknown>): void;
|
|
4
|
+
warn(msg: string, data?: Record<string, unknown>): void;
|
|
5
|
+
error(msg: string, data?: Record<string, unknown>): void;
|
|
6
|
+
debug(msg: string, data?: Record<string, unknown>): void;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC1D"}
|
package/dist/node.js
CHANGED
|
@@ -4,9 +4,8 @@ import {
|
|
|
4
4
|
createImplement,
|
|
5
5
|
createSocketIOServer,
|
|
6
6
|
implement
|
|
7
|
-
} from "./index-
|
|
8
|
-
import"./index-
|
|
9
|
-
import"./index-x3fcszf8.js";
|
|
7
|
+
} from "./index-44xysy8r.js";
|
|
8
|
+
import"./index-r1qp4rve.js";
|
|
10
9
|
import {
|
|
11
10
|
AppError,
|
|
12
11
|
appError,
|
|
@@ -16,7 +15,7 @@ import {
|
|
|
16
15
|
notFound,
|
|
17
16
|
rateLimited,
|
|
18
17
|
unauthorized
|
|
19
|
-
} from "./index-
|
|
18
|
+
} from "./index-ee621cmy.js";
|
|
20
19
|
// src/server/node.ts
|
|
21
20
|
import { serve } from "srvx";
|
|
22
21
|
async function serveNode(config) {
|
|
@@ -5,15 +5,30 @@ import { type SanitizeOptions } from './sanitize';
|
|
|
5
5
|
/** One isolated RequestEvent sink and its sanitisation policy. */
|
|
6
6
|
export interface RequestEventSinkConfig {
|
|
7
7
|
/**
|
|
8
|
-
* The sink — persists one audit event. It runs fire-and-forget
|
|
9
|
-
*
|
|
10
|
-
* request it observes. Keep it asynchronous and self-contained.
|
|
8
|
+
* The sink — persists one audit event. It runs fire-and-forget; failures are
|
|
9
|
+
* reported through `onSinkError` without breaking the observed work.
|
|
11
10
|
*/
|
|
12
11
|
write: (event: RequestEvent) => void | Promise<void>;
|
|
13
12
|
/** Keep only events for which this returns `true`. Default: keep every event. */
|
|
14
13
|
filter?: (event: RequestEvent) => boolean;
|
|
15
14
|
/** Payload sanitisation tuning — passed through to `sanitizePayload`. */
|
|
16
15
|
sanitize?: SanitizeOptions;
|
|
16
|
+
/** Maximum writes concurrently awaiting settlement. Default: 1000. */
|
|
17
|
+
maxPending?: number;
|
|
18
|
+
/** Observe failed filtering, projection or persistence. */
|
|
19
|
+
onSinkError?: (failure: SinkError) => void | Promise<void>;
|
|
20
|
+
/** Observe events rejected by bounded or closed admission. */
|
|
21
|
+
onDrop?: (drop: SinkDrop) => void | Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export type SinkDropReason = 'capacity' | 'closed';
|
|
24
|
+
export interface SinkError {
|
|
25
|
+
error: unknown;
|
|
26
|
+
event?: RequestEvent;
|
|
27
|
+
}
|
|
28
|
+
export interface SinkDrop {
|
|
29
|
+
reason: SinkDropReason;
|
|
30
|
+
event: RequestEvent;
|
|
31
|
+
pending: number;
|
|
17
32
|
}
|
|
18
33
|
export interface RequestObservabilityConfig extends RequestEventSinkConfig {
|
|
19
34
|
/** Clone and record JSON request bodies. Default false. */
|
|
@@ -39,6 +54,10 @@ export interface HttpRequestObserver {
|
|
|
39
54
|
export interface Observability {
|
|
40
55
|
request?: HttpRequestObserver;
|
|
41
56
|
toolCall: ToolCallHooks;
|
|
57
|
+
/** Wait for events admitted before this call. */
|
|
58
|
+
flush(): Promise<void>;
|
|
59
|
+
/** Stop admission and drain every previously accepted event. Idempotent. */
|
|
60
|
+
close(): Promise<void>;
|
|
42
61
|
}
|
|
43
62
|
export declare function createObservability(config: ObservabilityConfig): Observability;
|
|
44
63
|
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/observability/audit.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAe,KAAK,eAAe,EAAmB,MAAM,YAAY,CAAC;AAGhF,kEAAkE;AAClE,MAAM,WAAW,sBAAsB;IACrC
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/observability/audit.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAe,KAAK,eAAe,EAAmB,MAAM,YAAY,CAAC;AAGhF,kEAAkE;AAClE,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,KAAK,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,iFAAiF;IACjF,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC;IAC1C,yEAAyE;IACzE,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,8DAA8D;IAC9D,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,QAAQ,CAAC;AAEnD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,0BAA2B,SAAQ,sBAAsB;IACxE,2DAA2D;IAC3D,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC,KAAK,CAAC,EAAE,sBAAsB,CAAC;CAChC;AAED,gEAAgE;AAChE,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5B;AAED,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACnD;AAED,iFAAiF;AACjF,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,QAAQ,EAAE,aAAa,CAAC;IACxB,iDAAiD;IACjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,4EAA4E;IAC5E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAuKD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa,CAkI9E"}
|
|
@@ -36,6 +36,8 @@ export interface RequestEvent {
|
|
|
36
36
|
dimensions?: Record<string, string>;
|
|
37
37
|
/** Tool name — tool calls only. */
|
|
38
38
|
toolName?: string;
|
|
39
|
+
/** Distinguishes a completed operation from an MRTR input-gating round. */
|
|
40
|
+
toolPhase?: 'operation' | 'input-round';
|
|
39
41
|
/** Validated MCP transport attribution, available only on MCP tool calls. */
|
|
40
42
|
mcp?: {
|
|
41
43
|
era: 'modern' | 'legacy';
|
|
@@ -81,6 +83,11 @@ export interface RequestEvent {
|
|
|
81
83
|
resultSize: number | null;
|
|
82
84
|
/** Serialised byte length of the result. */
|
|
83
85
|
responseBytes: number;
|
|
86
|
+
/**
|
|
87
|
+
* Set when the result could not be serialised at all (bigint, a cycle) —
|
|
88
|
+
* distinguishes `responseBytes: 0` "nothing returned" from "unmeasurable".
|
|
89
|
+
*/
|
|
90
|
+
resultUnserializable?: boolean;
|
|
84
91
|
/** Resolved user id, when authenticated. */
|
|
85
92
|
userId?: string;
|
|
86
93
|
/** How the caller authenticated, when the app records it on the context. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../src/observability/event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,MAAM,EAAE,eAAe,CAAC;IACxB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,GAAG,CAAC,EAAE;QACJ,GAAG,EAAE,QAAQ,GAAG,QAAQ,CAAC;QACzB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,kFAAkF;QAClF,UAAU,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/C,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,4CAA4C;QAC5C,OAAO,CAAC,EAAE,gBAAgB,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;QAC/E,8CAA8C;QAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,uEAAuE;IACvE,OAAO,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1B,mDAAmD;IACnD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,4CAA4C;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,SAAS,EAAE,IAAI,CAAC;CACjB"}
|
|
1
|
+
{"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../src/observability/event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,MAAM,EAAE,eAAe,CAAC;IACxB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,WAAW,GAAG,aAAa,CAAC;IACxC,6EAA6E;IAC7E,GAAG,CAAC,EAAE;QACJ,GAAG,EAAE,QAAQ,GAAG,QAAQ,CAAC;QACzB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,kFAAkF;QAClF,UAAU,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/C,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,4CAA4C;QAC5C,OAAO,CAAC,EAAE,gBAAgB,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;QAC/E,8CAA8C;QAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,uEAAuE;IACvE,OAAO,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1B,mDAAmD;IACnD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,4CAA4C;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,SAAS,EAAE,IAAI,CAAC;CACjB"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* framework-owned HTTP completion plus canonical tool hooks into independent
|
|
7
7
|
* sinks.
|
|
8
8
|
*/
|
|
9
|
-
export { createObservability, type HttpRequestCompletion, type HttpRequestObserver, type Observability, type ObservabilityConfig, type RequestEventSinkConfig, type RequestObservabilityConfig, } from './audit';
|
|
9
|
+
export { createObservability, type HttpRequestCompletion, type HttpRequestObserver, type Observability, type ObservabilityConfig, type RequestEventSinkConfig, type RequestObservabilityConfig, type SinkDrop, type SinkDropReason, type SinkError, } from './audit';
|
|
10
10
|
export { getRequestContext, getTraceId, getUserId, type RequestContext, runWithRequestContext, setRequestDimensions, setRequestEndpoint, setRequestError, setRequestUser, type WrapRequestContextOptions, wrapInRequestContext, } from './context';
|
|
11
11
|
export type { RequestEvent } from './event';
|
|
12
12
|
export { type JsonValue, measureSize, redact, type SanitizeOptions, type SizeMeasure, sanitizePayload, truncatePreview, } from './sanitize';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,mBAAmB,EACnB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,mBAAmB,EACnB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAC/B,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,SAAS,GACf,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,KAAK,cAAc,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,KAAK,yBAAyB,EAC9B,oBAAoB,GACrB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EACL,KAAK,SAAS,EACd,WAAW,EACX,MAAM,EACN,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,yBAAyB,EACzB,mBAAmB,EACnB,KAAK,YAAY,GAClB,MAAM,SAAS,CAAC"}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
measureSize,
|
|
3
|
+
redact,
|
|
4
|
+
sanitizePayload,
|
|
5
|
+
truncatePreview
|
|
6
|
+
} from "../index-8ekq6res.js";
|
|
1
7
|
import {
|
|
2
8
|
childSpan,
|
|
3
9
|
createTraceContext,
|
|
@@ -6,7 +12,6 @@ import {
|
|
|
6
12
|
getTraceId,
|
|
7
13
|
getUserId,
|
|
8
14
|
isRecord,
|
|
9
|
-
isUnsafeKey,
|
|
10
15
|
parseTraceparent,
|
|
11
16
|
recordedErrorMessage,
|
|
12
17
|
resolvePropagationContext,
|
|
@@ -17,88 +22,7 @@ import {
|
|
|
17
22
|
setRequestError,
|
|
18
23
|
setRequestUser,
|
|
19
24
|
wrapInRequestContext
|
|
20
|
-
} from "../index-
|
|
21
|
-
|
|
22
|
-
// src/observability/sanitize.ts
|
|
23
|
-
var DEFAULT_SENSITIVE_KEYS = /(password|passwd|pwd|secret|token|apikey|api[-_ ]?key|auth|authorization|bearer|session|cookie|init[-_ ]?data|credential|private[-_ ]?key)/i;
|
|
24
|
-
var DEFAULT_MAX_BYTES = 16000;
|
|
25
|
-
var DEFAULT_MAX_DEPTH = 20;
|
|
26
|
-
var MASK = "[redacted]";
|
|
27
|
-
function redact(value, options = {}) {
|
|
28
|
-
const sensitive = options.sensitiveKeys ?? DEFAULT_SENSITIVE_KEYS;
|
|
29
|
-
const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
30
|
-
const ancestors = new Set;
|
|
31
|
-
const walk = (input, depth) => {
|
|
32
|
-
if (depth > maxDepth)
|
|
33
|
-
return "[max depth]";
|
|
34
|
-
if (input === null || input === undefined)
|
|
35
|
-
return null;
|
|
36
|
-
if (typeof input === "string" || typeof input === "number" || typeof input === "boolean") {
|
|
37
|
-
return input;
|
|
38
|
-
}
|
|
39
|
-
if (input instanceof Uint8Array || input instanceof ArrayBuffer) {
|
|
40
|
-
return { _type: "binary", size: input.byteLength };
|
|
41
|
-
}
|
|
42
|
-
if (input instanceof Blob) {
|
|
43
|
-
return { _type: "blob", size: input.size, mime: input.type };
|
|
44
|
-
}
|
|
45
|
-
if (typeof FormData !== "undefined" && input instanceof FormData) {
|
|
46
|
-
return { _type: "formdata", keys: [...input.keys()] };
|
|
47
|
-
}
|
|
48
|
-
if (Array.isArray(input)) {
|
|
49
|
-
if (ancestors.has(input))
|
|
50
|
-
return "[circular]";
|
|
51
|
-
ancestors.add(input);
|
|
52
|
-
const result = input.map((item) => walk(item, depth + 1));
|
|
53
|
-
ancestors.delete(input);
|
|
54
|
-
return result;
|
|
55
|
-
}
|
|
56
|
-
if (isRecord(input)) {
|
|
57
|
-
if (ancestors.has(input))
|
|
58
|
-
return "[circular]";
|
|
59
|
-
ancestors.add(input);
|
|
60
|
-
const out = {};
|
|
61
|
-
for (const [key, val] of Object.entries(input)) {
|
|
62
|
-
if (isUnsafeKey(key))
|
|
63
|
-
continue;
|
|
64
|
-
out[key] = sensitive.test(key) ? MASK : walk(val, depth + 1);
|
|
65
|
-
}
|
|
66
|
-
ancestors.delete(input);
|
|
67
|
-
return out;
|
|
68
|
-
}
|
|
69
|
-
return String(input);
|
|
70
|
-
};
|
|
71
|
-
return walk(value, 0);
|
|
72
|
-
}
|
|
73
|
-
function truncatePreview(value, maxBytes = DEFAULT_MAX_BYTES) {
|
|
74
|
-
const json = JSON.stringify(value);
|
|
75
|
-
const bytes = Buffer.byteLength(json, "utf8");
|
|
76
|
-
if (bytes <= maxBytes)
|
|
77
|
-
return value;
|
|
78
|
-
return {
|
|
79
|
-
_truncated: true,
|
|
80
|
-
_originalBytes: bytes,
|
|
81
|
-
preview: `${json.slice(0, maxBytes)}…`
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function sanitizePayload(value, options = {}) {
|
|
85
|
-
if (value === undefined || value === null)
|
|
86
|
-
return null;
|
|
87
|
-
return truncatePreview(redact(value, options), options.maxBytes ?? DEFAULT_MAX_BYTES);
|
|
88
|
-
}
|
|
89
|
-
function measureSize(value) {
|
|
90
|
-
if (value === undefined || value === null) {
|
|
91
|
-
return { resultSize: null, responseBytes: 0 };
|
|
92
|
-
}
|
|
93
|
-
const responseBytes = Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
94
|
-
if (Array.isArray(value)) {
|
|
95
|
-
return { resultSize: value.length, responseBytes };
|
|
96
|
-
}
|
|
97
|
-
if (isRecord(value) && Array.isArray(value.items) && "nextCursor" in value) {
|
|
98
|
-
return { resultSize: value.items.length, responseBytes };
|
|
99
|
-
}
|
|
100
|
-
return { resultSize: null, responseBytes };
|
|
101
|
-
}
|
|
25
|
+
} from "../index-ee621cmy.js";
|
|
102
26
|
|
|
103
27
|
// src/observability/audit.ts
|
|
104
28
|
function toolErrorMessage(result) {
|
|
@@ -139,24 +63,81 @@ function readMcpContext(value) {
|
|
|
139
63
|
...round !== undefined && { round }
|
|
140
64
|
};
|
|
141
65
|
}
|
|
142
|
-
|
|
143
|
-
|
|
66
|
+
var DEFAULT_MAX_PENDING = 1000;
|
|
67
|
+
function invokeIsolated(callback) {
|
|
68
|
+
if (!callback)
|
|
69
|
+
return;
|
|
70
|
+
Promise.resolve().then(callback).catch(() => {});
|
|
71
|
+
}
|
|
72
|
+
function createSinkManager(config) {
|
|
73
|
+
const maxPending = config.maxPending ?? DEFAULT_MAX_PENDING;
|
|
74
|
+
if (!Number.isSafeInteger(maxPending) || maxPending <= 0) {
|
|
75
|
+
throw new TypeError("Observability maxPending must be a positive safe integer");
|
|
76
|
+
}
|
|
77
|
+
let sequence = 0;
|
|
78
|
+
let closed = false;
|
|
79
|
+
let closePromise;
|
|
80
|
+
const preparing = new Map;
|
|
81
|
+
const writes = new Map;
|
|
82
|
+
const reportError = (error, event) => {
|
|
83
|
+
invokeIsolated(config.onSinkError ? () => config.onSinkError?.({ error, ...event !== undefined && { event } }) : undefined);
|
|
84
|
+
};
|
|
85
|
+
const reportDrop = (reason, event) => {
|
|
86
|
+
invokeIsolated(config.onDrop ? () => config.onDrop?.({ reason, event, pending: writes.size }) : undefined);
|
|
87
|
+
};
|
|
88
|
+
const admit = (id, event) => {
|
|
144
89
|
try {
|
|
145
90
|
if (config.filter && !config.filter(event))
|
|
146
91
|
return;
|
|
147
|
-
|
|
148
|
-
|
|
92
|
+
} catch (error) {
|
|
93
|
+
reportError(error, event);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (writes.size >= maxPending) {
|
|
97
|
+
reportDrop("capacity", event);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const write = Promise.resolve().then(() => config.write(event)).catch((error) => reportError(error, event)).finally(() => writes.delete(id));
|
|
101
|
+
writes.set(id, write);
|
|
102
|
+
};
|
|
103
|
+
const awaitGeneration = async (boundary) => {
|
|
104
|
+
const through = (values) => [...values].filter(([id]) => id <= boundary).map(([, value]) => value);
|
|
105
|
+
await Promise.allSettled(through(preparing));
|
|
106
|
+
await Promise.allSettled(through(writes));
|
|
107
|
+
};
|
|
108
|
+
return {
|
|
109
|
+
submit(produce) {
|
|
110
|
+
const id = ++sequence;
|
|
111
|
+
if (closed) {
|
|
112
|
+
Promise.resolve().then(produce).then((event) => reportDrop("closed", event)).catch((error) => reportError(error));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const preparation = Promise.resolve().then(produce).then((event) => admit(id, event)).catch((error) => reportError(error)).finally(() => preparing.delete(id));
|
|
116
|
+
preparing.set(id, preparation);
|
|
117
|
+
},
|
|
118
|
+
flush() {
|
|
119
|
+
return awaitGeneration(sequence);
|
|
120
|
+
},
|
|
121
|
+
close() {
|
|
122
|
+
if (closePromise)
|
|
123
|
+
return closePromise;
|
|
124
|
+
closed = true;
|
|
125
|
+
closePromise = awaitGeneration(sequence);
|
|
126
|
+
return closePromise;
|
|
127
|
+
}
|
|
149
128
|
};
|
|
150
129
|
}
|
|
151
130
|
function createObservability(config) {
|
|
131
|
+
const requestManager = config.request ? createSinkManager(config.request) : undefined;
|
|
132
|
+
const toolManager = config.tools ? createSinkManager(config.tools) : undefined;
|
|
133
|
+
let closePromise;
|
|
152
134
|
const request = config.request ? {
|
|
153
135
|
includePayload: config.request.includePayload ?? false,
|
|
154
136
|
complete: ({ context, statusCode, durationMs, payload }) => {
|
|
155
137
|
const requestConfig = config.request;
|
|
156
138
|
if (!requestConfig)
|
|
157
139
|
return;
|
|
158
|
-
|
|
159
|
-
(async () => {
|
|
140
|
+
requestManager?.submit(async () => {
|
|
160
141
|
let body;
|
|
161
142
|
if (payload) {
|
|
162
143
|
try {
|
|
@@ -165,7 +146,7 @@ function createObservability(config) {
|
|
|
165
146
|
body = undefined;
|
|
166
147
|
}
|
|
167
148
|
}
|
|
168
|
-
|
|
149
|
+
return {
|
|
169
150
|
source: context.source,
|
|
170
151
|
method: context.method,
|
|
171
152
|
path: context.path,
|
|
@@ -194,58 +175,73 @@ function createObservability(config) {
|
|
|
194
175
|
ipAddress: context.ipAddress,
|
|
195
176
|
userAgent: context.userAgent,
|
|
196
177
|
startedAt: new Date(Date.now() - durationMs)
|
|
197
|
-
}
|
|
198
|
-
})
|
|
178
|
+
};
|
|
179
|
+
});
|
|
199
180
|
}
|
|
200
181
|
} : undefined;
|
|
201
182
|
const toolCall = config.tools ? {
|
|
202
183
|
afterToolCall: ({ toolName, args, result, durationMs, context, endpoint, error }) => {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
dimensions
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
184
|
+
try {
|
|
185
|
+
const toolConfig = config.tools;
|
|
186
|
+
if (!toolConfig)
|
|
187
|
+
return;
|
|
188
|
+
const requestCtx = getRequestContext();
|
|
189
|
+
const span = requestCtx ? childSpan(requestCtx.trace) : createTraceContext();
|
|
190
|
+
const measure = result.ok ? measureSize(result.data) : { resultSize: null, responseBytes: 0 };
|
|
191
|
+
const mcp = context.source === "mcp" ? readMcpContext(context.mcp) : undefined;
|
|
192
|
+
const toolPhase = mcp?.outcome === "input_required" ? "input-round" : "operation";
|
|
193
|
+
toolManager?.submit(() => ({
|
|
194
|
+
source: context.source,
|
|
195
|
+
method: "TOOL",
|
|
196
|
+
httpMethod: endpoint.method,
|
|
197
|
+
path: `/${context.source}/${toolName}`,
|
|
198
|
+
serviceName: endpoint.serviceName,
|
|
199
|
+
action: endpoint.key,
|
|
200
|
+
...requestCtx?.dimensions !== undefined && {
|
|
201
|
+
dimensions: requestCtx.dimensions
|
|
202
|
+
},
|
|
203
|
+
toolName,
|
|
204
|
+
toolPhase,
|
|
205
|
+
...mcp !== undefined && { mcp },
|
|
206
|
+
traceId: span.traceId,
|
|
207
|
+
spanId: span.spanId,
|
|
208
|
+
parentSpanId: span.parentSpanId,
|
|
209
|
+
ok: result.ok,
|
|
210
|
+
statusCode: result.ok ? 200 : 400,
|
|
211
|
+
durationMs,
|
|
212
|
+
errorCode: result.ok ? undefined : result.code,
|
|
213
|
+
errorMessage: result.ok ? undefined : auditErrorMessage(result, error),
|
|
214
|
+
...!result.ok && result.details !== undefined && {
|
|
215
|
+
errorDetail: sanitizePayload(result.details, toolConfig.sanitize)
|
|
216
|
+
},
|
|
217
|
+
payload: sanitizePayload(args, toolConfig.sanitize),
|
|
218
|
+
resultSize: measure.resultSize,
|
|
219
|
+
responseBytes: measure.responseBytes,
|
|
220
|
+
..."unserializable" in measure && measure.unserializable && { resultUnserializable: true },
|
|
221
|
+
userId: readString(context.userId),
|
|
222
|
+
authMethod: readString(context.authMethod),
|
|
223
|
+
clientId: readString(context.clientId),
|
|
224
|
+
ipAddress: readString(context.ipAddress),
|
|
225
|
+
userAgent: readString(context.userAgent),
|
|
226
|
+
startedAt: new Date(Date.now() - durationMs)
|
|
227
|
+
}));
|
|
228
|
+
} catch {}
|
|
244
229
|
}
|
|
245
230
|
} : undefined;
|
|
246
231
|
return {
|
|
247
232
|
...request && { request },
|
|
248
|
-
toolCall: toolCall ?? {}
|
|
233
|
+
toolCall: toolCall ?? {},
|
|
234
|
+
async flush() {
|
|
235
|
+
await Promise.all([requestManager?.flush(), toolManager?.flush()]);
|
|
236
|
+
},
|
|
237
|
+
close() {
|
|
238
|
+
if (!closePromise) {
|
|
239
|
+
closePromise = Promise.all([requestManager?.close(), toolManager?.close()]).then(() => {
|
|
240
|
+
return;
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
return closePromise;
|
|
244
|
+
}
|
|
249
245
|
};
|
|
250
246
|
}
|
|
251
247
|
export {
|
|
@@ -4,7 +4,12 @@ export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
|
4
4
|
};
|
|
5
5
|
/** Tuning for `redact` / `sanitizePayload`. */
|
|
6
6
|
export interface SanitizeOptions {
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Keys whose VALUE is masked, tested against the raw key name. When omitted,
|
|
9
|
+
* the default matcher splits the key into words (camelCase, `-`, `_`, spaces)
|
|
10
|
+
* and masks it when a word IS a secret term — so `sessionToken` and
|
|
11
|
+
* `X-Api-Key` are masked while `authorId` and `sessionCount` survive.
|
|
12
|
+
*/
|
|
8
13
|
sensitiveKeys?: RegExp;
|
|
9
14
|
/** Cap on the serialised payload — anything larger collapses to a preview. Default 16 KB. */
|
|
10
15
|
maxBytes?: number;
|
|
@@ -17,6 +22,8 @@ export interface SizeMeasure {
|
|
|
17
22
|
resultSize: number | null;
|
|
18
23
|
/** Serialised byte length. */
|
|
19
24
|
responseBytes: number;
|
|
25
|
+
/** Set when the value cannot be serialised at all (bigint, a cycle). */
|
|
26
|
+
unserializable?: true;
|
|
20
27
|
}
|
|
21
28
|
/**
|
|
22
29
|
* Deep-copy `value` into a JSON-safe shape: secret-named keys masked, binary
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/observability/sanitize.ts"],"names":[],"mappings":"AAOA,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,EAAE,GACX;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEjC,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B
|
|
1
|
+
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/observability/sanitize.ts"],"names":[],"mappings":"AAOA,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,EAAE,GACX;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEjC,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,8BAA8B;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,cAAc,CAAC,EAAE,IAAI,CAAC;CACvB;AAwED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,eAAoB,GAAG,SAAS,CA4F/E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,SAAoB,GAAG,SAAS,CAgBzF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,eAAoB,GAC5B,SAAS,GAAG,IAAI,CAOlB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAqBvD"}
|
|
@@ -20,6 +20,8 @@ export interface TraceContext {
|
|
|
20
20
|
tracestate?: string;
|
|
21
21
|
/** Valid bounded W3C baggage, retained for propagation only. */
|
|
22
22
|
baggage?: string;
|
|
23
|
+
/** W3C trace flags byte, preserved end to end (for example `00` or `01`). */
|
|
24
|
+
traceFlags?: string;
|
|
23
25
|
}
|
|
24
26
|
/** A fresh root trace — a new trace id, a new span id, no parent. */
|
|
25
27
|
export declare function createTraceContext(): TraceContext;
|
|
@@ -30,7 +32,7 @@ export declare function createTraceContext(): TraceContext;
|
|
|
30
32
|
* missing or malformed header.
|
|
31
33
|
*/
|
|
32
34
|
export declare function parseTraceparent(header: string | null | undefined): TraceContext | null;
|
|
33
|
-
/** Render a `TraceContext`
|
|
35
|
+
/** Render a `TraceContext` with its actual W3C trace-flags byte. */
|
|
34
36
|
export declare function formatTraceparent(ctx: TraceContext): string;
|
|
35
37
|
/**
|
|
36
38
|
* The trace for an incoming request — the caller's `traceparent` continued
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/observability/trace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,gFAAgF;AAChF,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/observability/trace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,gFAAgF;AAChF,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAaD,qEAAqE;AACrE,wBAAgB,kBAAkB,IAAI,YAAY,CAEjD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,GAAG,IAAI,CAmBvF;AAED,oEAAoE;AACpE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAE3D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CAE9D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAS5D;AAuBD;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC7C,QAAQ,CAAC,EAAE,YAAY,GACtB,YAAY,CAkBd"}
|
|
@@ -40,6 +40,8 @@ export interface CacheBridgeConfig<TEvents> {
|
|
|
40
40
|
handlers: CacheBridgeHandlers<TEvents>;
|
|
41
41
|
/** Window (ms) after `markFresh()` during which `isFresh()` returns true. Default 500. */
|
|
42
42
|
freshWindow?: number;
|
|
43
|
+
/** Maximum remembered freshness keys. Oldest entries are evicted first. Default 1,000. */
|
|
44
|
+
maxFreshKeys?: number;
|
|
43
45
|
}
|
|
44
46
|
export interface CacheBridge {
|
|
45
47
|
connect(): void;
|
|
@@ -47,6 +49,8 @@ export interface CacheBridge {
|
|
|
47
49
|
/** Mark a query key as just-mutated. Call from a mutation's onSuccess so
|
|
48
50
|
* handlers can skip a stale socket echo via `ctx.isFresh()`. */
|
|
49
51
|
markFresh(key: QueryKey): void;
|
|
52
|
+
/** Forget every freshness marker without changing socket subscriptions. */
|
|
53
|
+
clearFresh(): void;
|
|
50
54
|
}
|
|
51
55
|
export declare function createCacheBridge<TEvents>(config: CacheBridgeConfig<TEvents>): CacheBridge;
|
|
52
56
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache-bridge.d.ts","sourceRoot":"","sources":["../../src/react/cache-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEnE,wEAAwE;AACxE,MAAM,WAAW,iBAAiB,CAAC,OAAO;IACxC,EAAE,CAAC,CAAC,SAAS,MAAM,OAAO,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;CACjF;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,gFAAgF;IAChF,OAAO,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC;CACjC;AAED,oEAAoE;AACpE,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC;AAE3E,MAAM,MAAM,kBAAkB,CAAC,QAAQ,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAE7F,MAAM,MAAM,mBAAmB,CAAC,OAAO,IAAI;KACxC,CAAC,IAAI,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,EAAE,kBAAkB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;CAC7E,CAAC;AAEF,MAAM,WAAW,iBAAiB,CAAC,OAAO;IACxC,MAAM,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACnC;;;;;OAKG;IACH,WAAW,EAAE,WAAW,GAAG,CAAC,MAAM,WAAW,CAAC,CAAC;IAC/C,QAAQ,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACvC,0FAA0F;IAC1F,WAAW,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"cache-bridge.d.ts","sourceRoot":"","sources":["../../src/react/cache-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEnE,wEAAwE;AACxE,MAAM,WAAW,iBAAiB,CAAC,OAAO;IACxC,EAAE,CAAC,CAAC,SAAS,MAAM,OAAO,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;CACjF;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,gFAAgF;IAChF,OAAO,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC;CACjC;AAED,oEAAoE;AACpE,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC;AAE3E,MAAM,MAAM,kBAAkB,CAAC,QAAQ,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAE7F,MAAM,MAAM,mBAAmB,CAAC,OAAO,IAAI;KACxC,CAAC,IAAI,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,EAAE,kBAAkB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;CAC7E,CAAC;AAEF,MAAM,WAAW,iBAAiB,CAAC,OAAO;IACxC,MAAM,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACnC;;;;;OAKG;IACH,WAAW,EAAE,WAAW,GAAG,CAAC,MAAM,WAAW,CAAC,CAAC;IAC/C,QAAQ,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACvC,0FAA0F;IAC1F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0FAA0F;IAC1F,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,IAAI,IAAI,CAAC;IAChB,UAAU,IAAI,IAAI,CAAC;IACnB;qEACiE;IACjE,SAAS,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC/B,2EAA2E;IAC3E,UAAU,IAAI,IAAI,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,iBAAiB,CAAC,OAAO,CAAC,GAAG,WAAW,CAsF1F"}
|