stitchkit 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +373 -4
  3. package/dist/browser/client.d.ts +30 -0
  4. package/dist/browser/client.d.ts.map +1 -0
  5. package/dist/browser/http.d.ts +77 -0
  6. package/dist/browser/http.d.ts.map +1 -0
  7. package/dist/browser/socket-io.d.ts +69 -0
  8. package/dist/browser/socket-io.d.ts.map +1 -0
  9. package/dist/browser/stream.d.ts +2 -0
  10. package/dist/browser/stream.d.ts.map +1 -0
  11. package/dist/contract/define.d.ts +94 -0
  12. package/dist/contract/define.d.ts.map +1 -0
  13. package/dist/contract/errors.d.ts +46 -0
  14. package/dist/contract/errors.d.ts.map +1 -0
  15. package/dist/contract/index.d.ts +4 -0
  16. package/dist/contract/index.d.ts.map +1 -0
  17. package/dist/contract/index.js +26 -0
  18. package/dist/contract/pagination.d.ts +19 -0
  19. package/dist/contract/pagination.d.ts.map +1 -0
  20. package/dist/index-5sxnvwb1.js +368 -0
  21. package/dist/index-7wfkbvss.js +92 -0
  22. package/dist/index-809wc1tt.js +18 -0
  23. package/dist/index-gfzn1n4n.js +29 -0
  24. package/dist/index-ke4mx4ea.js +38 -0
  25. package/dist/index-n7bmdwmz.js +68 -0
  26. package/dist/index.d.ts +7 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +111 -0
  29. package/dist/internal/errors.d.ts +5 -0
  30. package/dist/internal/errors.d.ts.map +1 -0
  31. package/dist/internal/typed.d.ts +9 -0
  32. package/dist/internal/typed.d.ts.map +1 -0
  33. package/dist/observability/audit.d.ts +32 -0
  34. package/dist/observability/audit.d.ts.map +1 -0
  35. package/dist/observability/context.d.ts +60 -0
  36. package/dist/observability/context.d.ts.map +1 -0
  37. package/dist/observability/event.d.ts +49 -0
  38. package/dist/observability/event.d.ts.map +1 -0
  39. package/dist/observability/index.d.ts +14 -0
  40. package/dist/observability/index.d.ts.map +1 -0
  41. package/dist/observability/index.js +266 -0
  42. package/dist/observability/sanitize.d.ts +42 -0
  43. package/dist/observability/sanitize.d.ts.map +1 -0
  44. package/dist/observability/trace.d.ts +42 -0
  45. package/dist/observability/trace.d.ts.map +1 -0
  46. package/dist/react/cache-bridge.d.ts +53 -0
  47. package/dist/react/cache-bridge.d.ts.map +1 -0
  48. package/dist/react/cursor-query.d.ts +37 -0
  49. package/dist/react/cursor-query.d.ts.map +1 -0
  50. package/dist/react.d.ts +3 -0
  51. package/dist/react.d.ts.map +1 -0
  52. package/dist/react.js +52 -0
  53. package/dist/server/cache.d.ts +15 -0
  54. package/dist/server/cache.d.ts.map +1 -0
  55. package/dist/server/context.d.ts +9 -0
  56. package/dist/server/context.d.ts.map +1 -0
  57. package/dist/server/create.d.ts +4 -0
  58. package/dist/server/create.d.ts.map +1 -0
  59. package/dist/server/event-bus.d.ts +24 -0
  60. package/dist/server/event-bus.d.ts.map +1 -0
  61. package/dist/server/implement.d.ts +16 -0
  62. package/dist/server/implement.d.ts.map +1 -0
  63. package/dist/server/index.d.ts +17 -0
  64. package/dist/server/index.d.ts.map +1 -0
  65. package/dist/server/index.js +965 -0
  66. package/dist/server/logger.d.ts +21 -0
  67. package/dist/server/logger.d.ts.map +1 -0
  68. package/dist/server/middleware/auth.d.ts +50 -0
  69. package/dist/server/middleware/auth.d.ts.map +1 -0
  70. package/dist/server/middleware/cookies.d.ts +34 -0
  71. package/dist/server/middleware/cookies.d.ts.map +1 -0
  72. package/dist/server/middleware/cors.d.ts +9 -0
  73. package/dist/server/middleware/cors.d.ts.map +1 -0
  74. package/dist/server/multipart.d.ts +14 -0
  75. package/dist/server/multipart.d.ts.map +1 -0
  76. package/dist/server/rate-limit.d.ts +17 -0
  77. package/dist/server/rate-limit.d.ts.map +1 -0
  78. package/dist/server/request.d.ts +22 -0
  79. package/dist/server/request.d.ts.map +1 -0
  80. package/dist/server/router.d.ts +42 -0
  81. package/dist/server/router.d.ts.map +1 -0
  82. package/dist/server/socket-io.d.ts +42 -0
  83. package/dist/server/socket-io.d.ts.map +1 -0
  84. package/dist/server/stream.d.ts +18 -0
  85. package/dist/server/stream.d.ts.map +1 -0
  86. package/dist/server/swept-map.d.ts +22 -0
  87. package/dist/server/swept-map.d.ts.map +1 -0
  88. package/dist/server/types.d.ts +124 -0
  89. package/dist/server/types.d.ts.map +1 -0
  90. package/dist/tools/agent.d.ts +14 -0
  91. package/dist/tools/agent.d.ts.map +1 -0
  92. package/dist/tools/execute.d.ts +21 -0
  93. package/dist/tools/execute.d.ts.map +1 -0
  94. package/dist/tools/mcp-handler.d.ts +21 -0
  95. package/dist/tools/mcp-handler.d.ts.map +1 -0
  96. package/dist/tools/mcp-stdio.d.ts +25 -0
  97. package/dist/tools/mcp-stdio.d.ts.map +1 -0
  98. package/dist/tools/mcp.d.ts +42 -0
  99. package/dist/tools/mcp.d.ts.map +1 -0
  100. package/dist/tools/mount.d.ts +61 -0
  101. package/dist/tools/mount.d.ts.map +1 -0
  102. package/dist/tools/names.d.ts +2 -0
  103. package/dist/tools/names.d.ts.map +1 -0
  104. package/dist/tools/remote.d.ts +22 -0
  105. package/dist/tools/remote.d.ts.map +1 -0
  106. package/dist/tools/schema.d.ts +4 -0
  107. package/dist/tools/schema.d.ts.map +1 -0
  108. package/dist/tools/view-file.d.ts +57 -0
  109. package/dist/tools/view-file.d.ts.map +1 -0
  110. package/dist/tools.d.ts +8 -0
  111. package/dist/tools.d.ts.map +1 -0
  112. package/dist/tools.js +654 -0
  113. package/package.json +136 -4
@@ -0,0 +1,18 @@
1
+ // src/internal/typed.ts
2
+ function typedEntries(value) {
3
+ return Object.entries(value);
4
+ }
5
+ function isRecord(value) {
6
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7
+ }
8
+ function mapObject(source, mapper) {
9
+ const result = {};
10
+ for (const [key, value] of typedEntries(source)) {
11
+ const mapped = mapper(key, value);
12
+ if (mapped !== undefined)
13
+ result[key] = mapped;
14
+ }
15
+ return result;
16
+ }
17
+
18
+ export { typedEntries, isRecord, mapObject };
@@ -0,0 +1,29 @@
1
+ import {
2
+ AppError
3
+ } from "./index-7wfkbvss.js";
4
+
5
+ // src/internal/errors.ts
6
+ import { z } from "zod";
7
+ function formatZodError(error) {
8
+ const issues = error.issues.slice(0, 5);
9
+ const lines = issues.map((issue) => {
10
+ const path = issue.path.length > 0 ? issue.path.join(".") : "(root)";
11
+ return `${path}: ${issue.message}`;
12
+ });
13
+ const suffix = error.issues.length > 5 ? `
14
+ ...and ${error.issues.length - 5} more issues` : "";
15
+ return lines.join(`
16
+ `) + suffix;
17
+ }
18
+ function normalizeError(err) {
19
+ if (AppError.is(err))
20
+ return err;
21
+ if (err instanceof z.ZodError) {
22
+ return new AppError("VALIDATION_ERROR", formatZodError(err), 400);
23
+ }
24
+ const msg = err instanceof Error ? err.message : String(err);
25
+ const safeMessage = msg.length > 200 ? `${msg.slice(0, 200)}...` : msg;
26
+ return new AppError("INTERNAL_SERVER_ERROR", safeMessage, 500);
27
+ }
28
+
29
+ export { formatZodError, normalizeError };
@@ -0,0 +1,38 @@
1
+ // src/server/request.ts
2
+ function generateTraceId() {
3
+ return Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
4
+ }
5
+ function resolveTraceId(req) {
6
+ const header = req.headers.get("x-request-id") ?? req.headers.get("x-trace-id");
7
+ const trimmed = header?.trim();
8
+ if (trimmed && trimmed.length <= 128 && /^[\w.-]+$/.test(trimmed)) {
9
+ return trimmed;
10
+ }
11
+ return generateTraceId();
12
+ }
13
+ function extractIp(req) {
14
+ const forwarded = req.headers.get("x-forwarded-for");
15
+ if (forwarded)
16
+ return (forwarded.split(",")[0] ?? "").trim().replace("::ffff:", "");
17
+ const realIp = req.headers.get("x-real-ip");
18
+ if (realIp)
19
+ return realIp.trim().replace("::ffff:", "");
20
+ return "";
21
+ }
22
+ function getClientInfo(req) {
23
+ return {
24
+ ipAddress: extractIp(req) || undefined,
25
+ userAgent: req.headers.get("user-agent") ?? undefined
26
+ };
27
+ }
28
+ function parseQueryParams(url) {
29
+ const query = {};
30
+ for (const key of new Set(url.searchParams.keys())) {
31
+ const values = url.searchParams.getAll(key);
32
+ const [first] = values;
33
+ query[key] = values.length === 1 && first !== undefined ? first : values;
34
+ }
35
+ return query;
36
+ }
37
+
38
+ export { generateTraceId, resolveTraceId, extractIp, getClientInfo, parseQueryParams };
@@ -0,0 +1,68 @@
1
+ // src/server/stream.ts
2
+ function streamSSE(generator) {
3
+ const encoder = new TextEncoder;
4
+ const stream = new ReadableStream({
5
+ async start(controller) {
6
+ try {
7
+ for await (const chunk of generator) {
8
+ const data = JSON.stringify(chunk);
9
+ controller.enqueue(encoder.encode(`data: ${data}
10
+
11
+ `));
12
+ }
13
+ controller.enqueue(encoder.encode(`data: [DONE]
14
+
15
+ `));
16
+ controller.close();
17
+ } catch (err) {
18
+ const msg = err instanceof Error ? err.message : String(err);
19
+ controller.enqueue(encoder.encode(`data: ${JSON.stringify({ error: msg })}
20
+
21
+ `));
22
+ controller.close();
23
+ }
24
+ }
25
+ });
26
+ return new Response(stream, {
27
+ headers: {
28
+ "Content-Type": "text/event-stream",
29
+ "Cache-Control": "no-cache",
30
+ Connection: "keep-alive"
31
+ }
32
+ });
33
+ }
34
+ async function* parseSSE(response, options) {
35
+ const reader = response.body?.getReader();
36
+ if (!reader)
37
+ return;
38
+ const decoder = new TextDecoder;
39
+ let buffer = "";
40
+ try {
41
+ while (true) {
42
+ const { done, value } = await reader.read();
43
+ if (done)
44
+ break;
45
+ buffer += decoder.decode(value, { stream: true });
46
+ const lines = buffer.split(`
47
+ `);
48
+ buffer = lines.pop() ?? "";
49
+ for (const rawLine of lines) {
50
+ const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
51
+ if (!line.startsWith("data: "))
52
+ continue;
53
+ const data = line.slice(6);
54
+ if (data === "[DONE]")
55
+ return;
56
+ try {
57
+ yield JSON.parse(data);
58
+ } catch (err) {
59
+ options?.onParseError?.(data, err instanceof Error ? err : new Error(String(err)));
60
+ }
61
+ }
62
+ }
63
+ } finally {
64
+ reader.releaseLock();
65
+ }
66
+ }
67
+
68
+ export { streamSSE, parseSSE };
@@ -0,0 +1,7 @@
1
+ export { createClient, createClients } from './browser/client';
2
+ export { ApiError, type ApiEvent, type ApiEventListener, createHttpClient, type HeaderProvider, type HttpClient, type HttpClientConfig, type RequestOptions, } from './browser/http';
3
+ export type { SocketEventMap, SocketIOClient, SocketIOClientConfig, } from './browser/socket-io';
4
+ export { createSocketIOClient } from './browser/socket-io';
5
+ export { type ParseSSEOptions, parseSSE } from './browser/stream';
6
+ export * from './contract';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EACL,QAAQ,EACR,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,cAAc,GACpB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,cAAc,EACd,cAAc,EACd,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAClE,cAAc,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,111 @@
1
+ import {
2
+ ApiError,
3
+ createClient,
4
+ createClients,
5
+ createHttpClient
6
+ } from "./index-5sxnvwb1.js";
7
+ import {
8
+ parseSSE
9
+ } from "./index-n7bmdwmz.js";
10
+ import {
11
+ ALL_TRANSPORTS,
12
+ AppError,
13
+ appError,
14
+ badRequest,
15
+ conflict,
16
+ defineContract,
17
+ forbidden,
18
+ notFound,
19
+ paginatedSchema,
20
+ rateLimited,
21
+ unauthorized
22
+ } from "./index-7wfkbvss.js";
23
+ import"./index-809wc1tt.js";
24
+ // src/browser/socket-io.ts
25
+ import { io } from "socket.io-client";
26
+ function createSocketIOClient(config) {
27
+ let socket = null;
28
+ const connectionListeners = new Set;
29
+ const subscriptions = new Set;
30
+ function notifyConnection(connected) {
31
+ for (const listener of connectionListeners)
32
+ listener(connected);
33
+ }
34
+ return {
35
+ get connected() {
36
+ return socket?.connected ?? false;
37
+ },
38
+ connect() {
39
+ if (socket)
40
+ return;
41
+ socket = io(config.url, {
42
+ path: config.path ?? "/socket.io/",
43
+ withCredentials: config.withCredentials ?? true,
44
+ transports: config.transports ?? ["websocket", "polling"],
45
+ autoConnect: false,
46
+ reconnection: true,
47
+ reconnectionAttempts: config.reconnectionAttempts ?? Infinity,
48
+ reconnectionDelay: config.reconnectionDelay ?? 1000,
49
+ reconnectionDelayMax: config.reconnectionDelayMax ?? 5000,
50
+ timeout: config.timeout ?? 20000
51
+ });
52
+ socket.on("connect", () => notifyConnection(true));
53
+ socket.on("disconnect", () => notifyConnection(false));
54
+ for (const attach of subscriptions)
55
+ attach(socket);
56
+ socket.connect();
57
+ },
58
+ disconnect() {
59
+ if (!socket)
60
+ return;
61
+ const wasConnected = socket.connected;
62
+ socket.removeAllListeners();
63
+ socket.disconnect();
64
+ socket = null;
65
+ if (wasConnected)
66
+ notifyConnection(false);
67
+ },
68
+ on(event, handler) {
69
+ const name = event;
70
+ const attach = (s) => {
71
+ s.on(name, handler);
72
+ };
73
+ subscriptions.add(attach);
74
+ if (socket)
75
+ attach(socket);
76
+ return () => {
77
+ subscriptions.delete(attach);
78
+ socket?.off(name, handler);
79
+ };
80
+ },
81
+ emit(event, ...args) {
82
+ if (!socket?.connected)
83
+ return;
84
+ const name = event;
85
+ socket.emit(name, ...args);
86
+ },
87
+ onConnectionChange(listener) {
88
+ connectionListeners.add(listener);
89
+ return () => connectionListeners.delete(listener);
90
+ }
91
+ };
92
+ }
93
+ export {
94
+ unauthorized,
95
+ rateLimited,
96
+ parseSSE,
97
+ paginatedSchema,
98
+ notFound,
99
+ forbidden,
100
+ defineContract,
101
+ createSocketIOClient,
102
+ createHttpClient,
103
+ createClients,
104
+ createClient,
105
+ conflict,
106
+ badRequest,
107
+ appError,
108
+ AppError,
109
+ ApiError,
110
+ ALL_TRANSPORTS
111
+ };
@@ -0,0 +1,5 @@
1
+ import { z } from 'zod';
2
+ import { AppError } from '../contract';
3
+ export declare function formatZodError(error: z.ZodError): string;
4
+ export declare function normalizeError(err: unknown): AppError;
5
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,wBAAgB,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,CASxD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAWrD"}
@@ -0,0 +1,9 @@
1
+ export declare function typedEntries<T extends object>(value: T): Array<{
2
+ [K in keyof T]: [K, T[K]];
3
+ }[keyof T]>;
4
+ /** Narrow an unknown value to a plain object — not `null`, not an array. */
5
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
6
+ export declare function mapObject<TSource extends object, TResult extends {
7
+ [K in keyof TSource]?: unknown;
8
+ }>(source: TSource, mapper: <K extends keyof TSource>(key: K, value: TSource[K]) => TResult[K] | undefined): TResult;
9
+ //# sourceMappingURL=typed.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,32 @@
1
+ import type { ToolCallHooks } from '../tools/execute';
2
+ import type { RequestEvent } from './event';
3
+ import { type SanitizeOptions } from './sanitize';
4
+ /** Config for `createAuditHook`. */
5
+ export interface AuditConfig {
6
+ /**
7
+ * The sink — persists one audit event. It runs fire-and-forget and its own
8
+ * errors are swallowed, so a slow or failing write never blocks or breaks the
9
+ * request it observes. Keep it asynchronous and self-contained.
10
+ */
11
+ write: (event: RequestEvent) => void | Promise<void>;
12
+ /** Keep only events for which this returns `true`. Default: keep every event. */
13
+ filter?: (event: RequestEvent) => boolean;
14
+ /** Payload sanitisation tuning — passed through to `sanitizePayload`. */
15
+ sanitize?: SanitizeOptions;
16
+ }
17
+ /** What `createAuditHook` returns — one wiring point per surface. */
18
+ export interface AuditHook {
19
+ /**
20
+ * Wrap the HTTP fetch handler — audits every request from its final
21
+ * response (success and error alike). Compose it INSIDE `wrapInRequestContext`
22
+ * (it reads that context for trace ids, timing and identity).
23
+ */
24
+ http: <S>(handler: (req: Request, server: S) => Promise<Response>) => (req: Request, server: S) => Promise<Response>;
25
+ /**
26
+ * Tool-call hooks — audits every MCP / agent tool call. Pass as `hooks` to
27
+ * `createMcpHandler`, `createStdioMcpServer` or `mountAgent`.
28
+ */
29
+ toolCall: ToolCallHooks;
30
+ }
31
+ export declare function createAuditHook(config: AuditConfig): AuditHook;
32
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +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;AAElE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAe,KAAK,eAAe,EAAmB,MAAM,YAAY,CAAC;AAGhF,oCAAoC;AACpC,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;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;CAC5B;AAED,qEAAqE;AACrE,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,IAAI,EAAE,CAAC,CAAC,EACN,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,KACpD,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpD;;;OAGG;IACH,QAAQ,EAAE,aAAa,CAAC;CACzB;AAmBD,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CA6F9D"}
@@ -0,0 +1,60 @@
1
+ import type { TransportSource } from '../contract';
2
+ import { type TraceContext } from './trace';
3
+ /** Everything known about the request in flight. */
4
+ export interface RequestContext {
5
+ /** W3C trace ids for this request. */
6
+ trace: TraceContext;
7
+ /** Which surface the request arrived on. */
8
+ source: TransportSource;
9
+ /** HTTP verb. */
10
+ method: string;
11
+ /** Request path. */
12
+ path: string;
13
+ /** Monotonic start, for duration — `process.hrtime.bigint()`. */
14
+ startedAt: bigint;
15
+ /** Client IP, when resolvable. */
16
+ ipAddress?: string;
17
+ /** Client user-agent, when present. */
18
+ userAgent?: string;
19
+ /** Resolved user id — set late, once auth has run. */
20
+ userId?: string;
21
+ /** Error outcome — set late, by the error handler. */
22
+ error?: {
23
+ code?: string;
24
+ message?: string;
25
+ };
26
+ }
27
+ /** Run `fn` with `ctx` as the active request context. */
28
+ export declare function runWithRequestContext<T>(ctx: RequestContext, fn: () => T): T;
29
+ /** The active request context, or `undefined` outside any request. */
30
+ export declare function getRequestContext(): RequestContext | undefined;
31
+ /** The active trace id — the one id to stamp on every log line. */
32
+ export declare function getTraceId(): string | undefined;
33
+ /** The active user id, once auth has resolved it. */
34
+ export declare function getUserId(): string | undefined;
35
+ /**
36
+ * Attach the resolved user to the active context. The ALS record is mutable —
37
+ * the update is visible to everything already holding the context. Call this
38
+ * from the auth hook.
39
+ */
40
+ export declare function setRequestUser(userId: string): void;
41
+ /**
42
+ * Record the error outcome on the active context. Call this from the error
43
+ * handler — the audit hook reads it when the request completes.
44
+ */
45
+ export declare function setRequestError(error: {
46
+ code?: string;
47
+ message?: string;
48
+ }): void;
49
+ /**
50
+ * Wrap a fetch handler so it runs inside a fresh `RequestContext` — trace ids
51
+ * (the inbound `traceparent` continued, or freshly minted), timing and client
52
+ * info.
53
+ *
54
+ * Compose it as the OUTERMOST wrapper of the server's fetch handler. To make
55
+ * the framework router reuse this trace id (so request logs and application
56
+ * logs share one id), pass `traceId: getTraceId` to `createServer` /
57
+ * `createHandler`.
58
+ */
59
+ export declare function wrapInRequestContext<S>(handler: (req: Request, server: S) => Promise<Response>): (req: Request, server: S) => Promise<Response>;
60
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/observability/context.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAEjE,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,KAAK,EAAE,YAAY,CAAC;IACpB,4CAA4C;IAC5C,MAAM,EAAE,eAAe,CAAC;IACxB,iBAAiB;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAID,yDAAyD;AACzD,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE5E;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,SAAS,CAE9D;AAED,mEAAmE;AACnE,wBAAgB,UAAU,IAAI,MAAM,GAAG,SAAS,CAE/C;AAED,qDAAqD;AACrD,wBAAgB,SAAS,IAAI,MAAM,GAAG,SAAS,CAE9C;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGnD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAGhF;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,GACtD,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAYhD"}
@@ -0,0 +1,49 @@
1
+ import type { TransportSource } from '../contract';
2
+ import type { JsonValue } from './sanitize';
3
+ /**
4
+ * A normalised audit event — one shape for a completed call on any surface
5
+ * (an HTTP request, an MCP tool call, an agent tool call). `createAuditHook`
6
+ * produces it and hands it to the project's `write` sink. The project maps it
7
+ * onto its own audit table; stitchkit owns the normalisation.
8
+ */
9
+ export interface RequestEvent {
10
+ /** Surface the call arrived on. */
11
+ source: TransportSource;
12
+ /** HTTP verb, or `TOOL` for a tool call. */
13
+ method: string;
14
+ /** Request path — `/api/...` for HTTP, `/{source}/{tool}` for a tool call. */
15
+ path: string;
16
+ /** Tool name — tool calls only. */
17
+ toolName?: string;
18
+ /** W3C trace id — correlates every span of one logical request. */
19
+ traceId: string;
20
+ /** W3C span id — unique to this call. */
21
+ spanId: string;
22
+ /** Parent span id, when this call is nested under another. */
23
+ parentSpanId?: string;
24
+ /** Whether the call succeeded. */
25
+ ok: boolean;
26
+ /** HTTP status — the real status for HTTP, `200` / `400` for a tool call. */
27
+ statusCode: number;
28
+ /** Wall-clock duration. */
29
+ durationMs: number;
30
+ /** Error code — failures only. */
31
+ errorCode?: string;
32
+ /** Error message — failures only. */
33
+ errorMessage?: string;
34
+ /** Sanitised request payload — the HTTP body or the tool arguments. */
35
+ payload: JsonValue | null;
36
+ /** Item count of the result, when it is a list. */
37
+ resultSize: number | null;
38
+ /** Serialised byte length of the result. */
39
+ responseBytes: number;
40
+ /** Resolved user id, when authenticated. */
41
+ userId?: string;
42
+ /** Client IP. */
43
+ ipAddress?: string;
44
+ /** Client user-agent. */
45
+ userAgent?: string;
46
+ /** When the call started. */
47
+ startedAt: Date;
48
+ }
49
+ //# sourceMappingURL=event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../src/observability/event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,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,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,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,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,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,SAAS,EAAE,IAAI,CAAC;CACjB"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * `stitchkit/observability` — the audit layer one level above the raw hooks.
3
+ *
4
+ * W3C trace context, an `AsyncLocalStorage` request context, payload
5
+ * sanitisation, a normalised `RequestEvent`, and `createAuditHook` to wire it
6
+ * all into one sink. A project's logging becomes a table plus a `write`
7
+ * function — nothing else.
8
+ */
9
+ export { type AuditConfig, type AuditHook, createAuditHook } from './audit';
10
+ export { getRequestContext, getTraceId, getUserId, type RequestContext, runWithRequestContext, setRequestError, setRequestUser, wrapInRequestContext, } from './context';
11
+ export type { RequestEvent } from './event';
12
+ export { type JsonValue, measureSize, redact, type SanitizeOptions, type SizeMeasure, sanitizePayload, truncatePreview, } from './sanitize';
13
+ export { childSpan, createTraceContext, formatTraceparent, parseTraceparent, resolveTraceContext, type TraceContext, } from './trace';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,KAAK,cAAc,EACnB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,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,mBAAmB,EACnB,KAAK,YAAY,GAClB,MAAM,SAAS,CAAC"}