@devaccel-labs/app-comments-toolbar 1.1.0 → 1.3.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 +148 -30
- package/dist/react.js +417 -64
- package/dist/server.js +342 -14
- package/dist/types/capture/api.d.ts +30 -0
- package/dist/types/capture/editor.d.ts +10 -0
- package/dist/types/capture/ignore.d.ts +19 -0
- package/dist/types/capture/index.d.ts +1 -0
- package/dist/types/capture/picker.d.ts +9 -0
- package/dist/types/capture/picture.d.ts +29 -0
- package/dist/types/capture/surface.d.ts +39 -0
- package/dist/types/core/index.d.ts +2 -2
- package/dist/types/core/resolve.d.ts +2 -1
- package/dist/types/core/types.d.ts +11 -0
- package/dist/types/debug-context.d.ts +7 -0
- package/dist/types/dictation.d.ts +9 -0
- package/dist/types/embed/controller.d.ts +61 -0
- package/dist/types/embed/index.d.ts +1 -0
- package/dist/types/embed/options.d.ts +35 -0
- package/dist/types/help/index.d.ts +1 -0
- package/dist/types/help/panel-index.d.ts +1 -0
- package/dist/types/help/panel-styles.d.ts +1 -0
- package/dist/types/help/panel.d.ts +4 -0
- package/dist/types/help/pill-styles.d.ts +11 -0
- package/dist/types/help/pill.d.ts +44 -0
- package/dist/types/help/react.d.ts +12 -0
- package/dist/types/help/requests.d.ts +2 -0
- package/dist/types/help/types.d.ts +119 -0
- package/dist/types/help/wire.d.ts +61 -0
- package/dist/types/native-wire.d.ts +63 -0
- package/dist/types/native.d.ts +43 -0
- package/dist/types/react.d.ts +7 -0
- package/dist/types/replay.d.ts +6 -0
- package/dist/types/runtime/api.d.ts +250 -0
- package/dist/types/runtime/attachment-model.d.ts +16 -0
- package/dist/types/runtime/attachments.d.ts +43 -7
- package/dist/types/runtime/boot.d.ts +39 -0
- package/dist/types/runtime/browser-label.d.ts +5 -0
- package/dist/types/runtime/build-id.d.ts +1 -0
- package/dist/types/runtime/capture-ui.d.ts +45 -21
- package/dist/types/runtime/clarity-model.d.ts +260 -0
- package/dist/types/runtime/clarity-ui.d.ts +62 -0
- package/dist/types/runtime/client.d.ts +6 -197
- package/dist/types/runtime/composer-size.d.ts +30 -0
- package/dist/types/runtime/dashboard.d.ts +17 -2
- package/dist/types/runtime/debug-context-core.d.ts +88 -0
- package/dist/types/runtime/debug-context-host.d.ts +39 -0
- package/dist/types/runtime/debug-context-model.d.ts +352 -0
- package/dist/types/runtime/debug-context-redact.d.ts +48 -0
- package/dist/types/runtime/debug-context.d.ts +36 -0
- package/dist/types/runtime/details-model.d.ts +7 -0
- package/dist/types/runtime/details.d.ts +7 -5
- package/dist/types/runtime/dictation-engine.d.ts +98 -0
- package/dist/types/runtime/dictation-model.d.ts +28 -0
- package/dist/types/runtime/dictation-ui.d.ts +56 -0
- package/dist/types/runtime/dictation.d.ts +66 -0
- package/dist/types/runtime/draft-dock.d.ts +32 -0
- package/dist/types/runtime/draft-model.d.ts +104 -0
- package/dist/types/runtime/draft-store.d.ts +15 -0
- package/dist/types/runtime/edits.d.ts +1 -1
- package/dist/types/runtime/font.d.ts +16 -0
- package/dist/types/runtime/format.d.ts +30 -1
- package/dist/types/runtime/host-watch.d.ts +20 -0
- package/dist/types/runtime/icons.d.ts +16 -2
- package/dist/types/runtime/index.d.ts +2 -0
- package/dist/types/runtime/ink.d.ts +8 -0
- package/dist/types/runtime/kind-model.d.ts +14 -0
- package/dist/types/runtime/live-model.d.ts +25 -0
- package/dist/types/runtime/loader.d.ts +5 -3
- package/dist/types/runtime/markup-editor.d.ts +54 -0
- package/dist/types/runtime/markup-model.d.ts +126 -0
- package/dist/types/runtime/markup.d.ts +69 -0
- package/dist/types/runtime/mention-parse.d.ts +18 -0
- package/dist/types/runtime/mentions.d.ts +4 -4
- package/dist/types/runtime/page-background.d.ts +9 -0
- package/dist/types/runtime/page-image.d.ts +64 -11
- package/dist/types/runtime/placement.d.ts +6 -3
- package/dist/types/runtime/record.d.ts +18 -2
- package/dist/types/runtime/related.d.ts +1 -1
- package/dist/types/runtime/replay-model.d.ts +80 -0
- package/dist/types/runtime/replay.d.ts +5 -38
- package/dist/types/runtime/screen.d.ts +47 -0
- package/dist/types/runtime/screenshot.d.ts +60 -8
- package/dist/types/runtime/session-source.d.ts +45 -0
- package/dist/types/runtime/session.d.ts +20 -18
- package/dist/types/runtime/shield.d.ts +9 -0
- package/dist/types/runtime/shot.d.ts +45 -0
- package/dist/types/runtime/sketch.d.ts +26 -0
- package/dist/types/runtime/styles.d.ts +1 -1
- package/dist/types/runtime/sync.d.ts +1 -0
- package/dist/types/runtime/thread-model.d.ts +18 -0
- package/dist/types/runtime/ticket-form-model.d.ts +57 -0
- package/dist/types/runtime/ticket-form.d.ts +9 -0
- package/dist/types/runtime/toolbar.d.ts +37 -1
- package/dist/types/runtime/ui-scale.d.ts +17 -0
- package/dist/types/runtime/update.d.ts +32 -8
- package/dist/types/runtime/use-debug-context.d.ts +27 -0
- package/dist/types/server/index.d.ts +22 -0
- package/dist/types/server/support.d.ts +20 -0
- package/dist/types/server.d.ts +2 -0
- package/dist/types/vite/plugin.d.ts +15 -0
- package/dist/vite.js +121 -41
- package/package.json +24 -11
- package/src/capture/api.ts +128 -0
- package/src/capture/editor.tsx +178 -0
- package/src/capture/ignore.ts +38 -0
- package/src/capture/index.ts +27 -0
- package/src/capture/picker.tsx +171 -0
- package/src/capture/picture.ts +90 -0
- package/src/capture/surface.tsx +185 -0
- package/src/compiler/annotate.ts +202 -0
- package/src/compiler/babel.d.ts +11 -0
- package/src/compiler/enabled.ts +55 -0
- package/src/compiler/index.ts +2 -0
- package/src/core/index.ts +8 -0
- package/src/core/resolve.ts +307 -0
- package/src/core/types.ts +58 -0
- package/src/debug-context.ts +47 -0
- package/src/dictation.ts +17 -0
- package/src/embed/controller.ts +215 -0
- package/src/embed/index.ts +68 -0
- package/src/embed/options.ts +100 -0
- package/src/help/index.ts +38 -0
- package/src/help/panel-index.ts +17 -0
- package/src/help/panel-styles.ts +123 -0
- package/src/help/panel.ts +840 -0
- package/src/help/pill-styles.ts +75 -0
- package/src/help/pill.ts +338 -0
- package/src/help/react.tsx +143 -0
- package/src/help/requests.ts +111 -0
- package/src/help/types.ts +124 -0
- package/src/help/wire.ts +55 -0
- package/src/native-wire.ts +124 -0
- package/src/native.ts +282 -0
- package/src/react.ts +27 -0
- package/src/replay.ts +13 -0
- package/src/runtime/api.ts +531 -0
- package/src/runtime/attachment-model.ts +42 -0
- package/src/runtime/attachments.tsx +1260 -0
- package/src/runtime/boot.ts +95 -0
- package/src/runtime/browser-label.ts +31 -0
- package/src/runtime/build-id.ts +10 -0
- package/src/runtime/capture-ui.tsx +306 -0
- package/src/runtime/capture.ts +508 -0
- package/src/runtime/clarity-model.ts +634 -0
- package/src/runtime/clarity-ui.tsx +454 -0
- package/src/runtime/client.ts +151 -0
- package/src/runtime/composer-size.tsx +146 -0
- package/src/runtime/dashboard.tsx +1130 -0
- package/src/runtime/debug-context-core.ts +681 -0
- package/src/runtime/debug-context-host.ts +56 -0
- package/src/runtime/debug-context-model.ts +1319 -0
- package/src/runtime/debug-context-redact.ts +259 -0
- package/src/runtime/debug-context.ts +613 -0
- package/src/runtime/details-model.ts +30 -0
- package/src/runtime/details.tsx +395 -0
- package/src/runtime/dictation-engine.ts +616 -0
- package/src/runtime/dictation-model.ts +79 -0
- package/src/runtime/dictation-ui.tsx +363 -0
- package/src/runtime/dictation.ts +271 -0
- package/src/runtime/dock.ts +108 -0
- package/src/runtime/draft-dock.tsx +124 -0
- package/src/runtime/draft-model.ts +251 -0
- package/src/runtime/draft-store.ts +149 -0
- package/src/runtime/edits.tsx +165 -0
- package/src/runtime/font.ts +42 -0
- package/src/runtime/format.ts +129 -0
- package/src/runtime/freshness.ts +23 -0
- package/src/runtime/handoff.ts +76 -0
- package/src/runtime/host-watch.ts +64 -0
- package/src/runtime/icons.tsx +295 -0
- package/src/runtime/idle.ts +20 -0
- package/src/runtime/index.ts +11 -0
- package/src/runtime/ink.ts +6 -0
- package/src/runtime/kind-model.ts +20 -0
- package/src/runtime/live-model.ts +32 -0
- package/src/runtime/loader.tsx +87 -0
- package/src/runtime/markup-editor.tsx +1333 -0
- package/src/runtime/markup-model.ts +485 -0
- package/src/runtime/markup.ts +382 -0
- package/src/runtime/members.ts +58 -0
- package/src/runtime/mention-parse.ts +56 -0
- package/src/runtime/mentions.tsx +205 -0
- package/src/runtime/page-background.ts +51 -0
- package/src/runtime/page-image.ts +1592 -0
- package/src/runtime/placement.ts +336 -0
- package/src/runtime/record.ts +402 -0
- package/src/runtime/redact.ts +30 -0
- package/src/runtime/related.ts +34 -0
- package/src/runtime/render-page.ts +2 -0
- package/src/runtime/replay-model.ts +232 -0
- package/src/runtime/replay.ts +173 -0
- package/src/runtime/runtime-version.ts +7 -0
- package/src/runtime/runtime.tsx +51 -0
- package/src/runtime/screen.ts +182 -0
- package/src/runtime/screenshot.ts +260 -0
- package/src/runtime/session-source.ts +112 -0
- package/src/runtime/session.ts +108 -0
- package/src/runtime/shield.ts +34 -0
- package/src/runtime/shot.tsx +422 -0
- package/src/runtime/sketch.ts +139 -0
- package/src/runtime/styles.ts +1541 -0
- package/src/runtime/sync.ts +300 -0
- package/src/runtime/thread-model.ts +71 -0
- package/src/runtime/ticket-form-model.ts +128 -0
- package/src/runtime/ticket-form.tsx +342 -0
- package/src/runtime/toolbar.tsx +4427 -0
- package/src/runtime/ui-scale.ts +75 -0
- package/src/runtime/update.ts +98 -0
- package/src/runtime/use-debug-context.ts +81 -0
- package/src/server/index.ts +133 -0
- package/src/server/support.ts +499 -0
- package/src/server.ts +4 -0
- package/src/vite/plugin.ts +102 -0
- package/src/vite.ts +1 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What every platform's debug context capture shares, with no DOM and no React Native: errors folded into
|
|
3
|
+
* counts, failed, slow and pending requests, the console's ordinary lines, going offline or to the
|
|
4
|
+
* background, what the host knows, the cache and stores, and turning all of it into the file. The web page
|
|
5
|
+
* (`./debug-context.ts`) and native apps (`@devaccel-labs/app-comments-native`) feed it from their own hooks.
|
|
6
|
+
*
|
|
7
|
+
* The hot path (`requestStarted`, `consoleCall`) does bookkeeping only. Reading a body, reading headers and
|
|
8
|
+
* redacting happen for failed or slow requests, after the app already has its answer.
|
|
9
|
+
*/
|
|
10
|
+
import { type DebugContextFile, type DebugErrorKind, type DebugSignal, type LifecycleEvent, type ResolvedDebugContext } from "./debug-context-model.js";
|
|
11
|
+
import { type RedactionTally } from "./debug-context-redact.js";
|
|
12
|
+
import type { ReplayEvent } from "./replay-model.js";
|
|
13
|
+
export declare const EXCERPT_CHARS = 2048;
|
|
14
|
+
export declare const BODY_CHARS = 16384;
|
|
15
|
+
export declare const GRAPHQL_READ_CHARS = 65536;
|
|
16
|
+
/** Frames from browser extensions and from the toolbar itself. */
|
|
17
|
+
export declare const FOREIGN_FRAME: RegExp;
|
|
18
|
+
/** Response types whose text is worth an excerpt. */
|
|
19
|
+
export declare const TEXTUAL: RegExp;
|
|
20
|
+
export type DebugCaptureStats = {
|
|
21
|
+
calls: number;
|
|
22
|
+
ms: number;
|
|
23
|
+
};
|
|
24
|
+
export declare function errorOf(value: unknown): {
|
|
25
|
+
message: string;
|
|
26
|
+
stack?: string;
|
|
27
|
+
};
|
|
28
|
+
/** A console call's arguments as one line, with the stack of an `Error` among them. */
|
|
29
|
+
export declare function argText(args: readonly unknown[]): {
|
|
30
|
+
message: string;
|
|
31
|
+
stack?: string;
|
|
32
|
+
};
|
|
33
|
+
/** An excerpt with JSON keys that look sensitive masked; other text scrubbed as text. */
|
|
34
|
+
export declare function excerptOf(text: string, max: number, tally: RedactionTally): string;
|
|
35
|
+
export declare function graphqlErrors(text: string, tally: RedactionTally): string[];
|
|
36
|
+
export declare function within<T>(promise: Promise<T> | T, ms: number): Promise<T | undefined>;
|
|
37
|
+
/**
|
|
38
|
+
* Replaces `host[key]` and returns the restore. The restore puts the original back only while ours is still
|
|
39
|
+
* installed, so a patch someone added after ours (Sentry, another tool) is never removed.
|
|
40
|
+
*/
|
|
41
|
+
export declare function patch<T extends object, K extends keyof T>(host: T, key: K, next: T[K]): () => void;
|
|
42
|
+
/** How a platform reads a finished request: headers now, text only when asked (and only once). */
|
|
43
|
+
export type RequestReaders = {
|
|
44
|
+
header: (name: string) => string | null;
|
|
45
|
+
/** The response's text, up to `max` characters. */
|
|
46
|
+
text?: (max: number) => Promise<string | null>;
|
|
47
|
+
/** The request's body as the app passed it. Only a string is ever kept. */
|
|
48
|
+
requestBody?: unknown;
|
|
49
|
+
/** The text could be read for a successful GraphQL request too (a 200 that holds errors). */
|
|
50
|
+
graphqlReadable?: boolean;
|
|
51
|
+
};
|
|
52
|
+
export type DebugCoreEnv = {
|
|
53
|
+
/** The address relative URLs are read against and same-origin URLs are shortened to. */
|
|
54
|
+
pageUrl: () => string | undefined;
|
|
55
|
+
/** Requests that are the toolbar's own (the comment service): never recorded. */
|
|
56
|
+
ignoreUrl?: (url: string) => boolean;
|
|
57
|
+
/** A high-resolution clock for `stats`. Default `Date.now`. */
|
|
58
|
+
clock?: () => number;
|
|
59
|
+
};
|
|
60
|
+
/** What every platform's file says the same way. */
|
|
61
|
+
export type CoreSnapshot = Pick<DebugContextFile, "errors" | "logs" | "network" | "lifecycle" | "steps" | "queries" | "stores" | "realtime" | "identity" | "flags" | "extra" | "build"> & {
|
|
62
|
+
join: Pick<DebugContextFile["join"], "traceId" | "sessionId" | "requestIds">;
|
|
63
|
+
routePattern?: string;
|
|
64
|
+
};
|
|
65
|
+
export declare function createDebugCore(resolved: ResolvedDebugContext, env: DebugCoreEnv): {
|
|
66
|
+
signals: Record<DebugSignal, boolean>;
|
|
67
|
+
options: import("./debug-context-model.js").DebugContextOptions;
|
|
68
|
+
tally: RedactionTally;
|
|
69
|
+
timed: <T>(task: () => T) => T;
|
|
70
|
+
pushError: (kind: DebugErrorKind, level: "error" | "warn", rawMessage: string, stack?: string, source?: string, componentStack?: string[]) => void;
|
|
71
|
+
consoleCall: (level: "error" | "warn" | "log" | "info" | "debug", args: readonly unknown[]) => void;
|
|
72
|
+
requestStarted: (method: string, url: string) => number | null;
|
|
73
|
+
requestFinished: (id: number, status: number, readers: RequestReaders) => void;
|
|
74
|
+
requestAborted: (id: number) => void;
|
|
75
|
+
noteLifecycle: (event: LifecycleEvent) => void;
|
|
76
|
+
reportError: (error: unknown, componentStack?: string | null) => void;
|
|
77
|
+
shared: (reportAt: number, steps: readonly ReplayEvent[] | undefined, fileTally: RedactionTally, toolbarBuild?: string) => Promise<CoreSnapshot>;
|
|
78
|
+
finish: (file: DebugContextFile, fileTally: RedactionTally) => DebugContextFile | null;
|
|
79
|
+
skeletonFile: (reportAt: number, platform: DebugContextFile["platform"]) => DebugContextFile;
|
|
80
|
+
readonly stopped: boolean;
|
|
81
|
+
mark(): void;
|
|
82
|
+
/** The report's moment: the mark, or now. Clears the mark. */
|
|
83
|
+
takeMark(): number;
|
|
84
|
+
clearMark(): void;
|
|
85
|
+
stats: () => DebugCaptureStats;
|
|
86
|
+
stop(): void;
|
|
87
|
+
};
|
|
88
|
+
export type DebugCore = ReturnType<typeof createDebugCore>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a host app calls beside `debugContext`: report an error its error boundary caught, and summarise a
|
|
3
|
+
* TanStack Query cache. Tiny and free of toolbar code, so the npm package and the script tag can both carry it.
|
|
4
|
+
* The toolbar itself is loaded from the service, so the two talk through one window event.
|
|
5
|
+
*/
|
|
6
|
+
import type { QuerySummary } from "./debug-context-model.js";
|
|
7
|
+
export declare const DEBUG_ERROR_EVENT = "comment-tool:error";
|
|
8
|
+
export type DebugErrorDetail = {
|
|
9
|
+
error: unknown;
|
|
10
|
+
componentStack: string | null;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Hands an error an error boundary caught to the toolbar's debug context (the `componentStacks` signal), with
|
|
14
|
+
* React's component stack. Does nothing when the toolbar is not running or the signal is off.
|
|
15
|
+
*
|
|
16
|
+
* <ErrorBoundary onError={(error, info) => reportToolbarError(error, info.componentStack)}>
|
|
17
|
+
*/
|
|
18
|
+
export declare function reportToolbarError(error: unknown, componentStack?: string | null): void;
|
|
19
|
+
/** The part of a TanStack Query `QueryClient` this reads. */
|
|
20
|
+
export type QueryCacheLike = {
|
|
21
|
+
getQueryCache(): {
|
|
22
|
+
getAll(): ReadonlyArray<{
|
|
23
|
+
queryKey: unknown;
|
|
24
|
+
state: {
|
|
25
|
+
status?: string;
|
|
26
|
+
fetchStatus?: string;
|
|
27
|
+
error?: unknown;
|
|
28
|
+
dataUpdatedAt?: number;
|
|
29
|
+
};
|
|
30
|
+
getObserversCount?: () => number;
|
|
31
|
+
}>;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* `debugContext.queries` for a TanStack Query client: each query's key and state, never its data.
|
|
36
|
+
*
|
|
37
|
+
* debugContext={{ signals: { queries: true }, queries: () => queryCacheSummary(queryClient) }}
|
|
38
|
+
*/
|
|
39
|
+
export declare function queryCacheSummary(client: QueryCacheLike, max?: number): QuerySummary[];
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The debug context file (`context-<stamp>.json`): what a ticket carries for whoever fixes the bug, a person or
|
|
3
|
+
* a coding agent. DOM-free, so the web toolbar, native clients, the service's second redaction pass and the
|
|
4
|
+
* console all use the same shape, the same limits and the same brief.
|
|
5
|
+
*
|
|
6
|
+
* Every section is optional: a host turns each signal on or off in code (`DebugContextOptions`), and a reader
|
|
7
|
+
* says "not captured" rather than "nothing happened".
|
|
8
|
+
*/
|
|
9
|
+
import { type JsonBag } from "./debug-context-redact.js";
|
|
10
|
+
export declare const DEBUG_CONTEXT_PREFIX = "context-";
|
|
11
|
+
/** The most a context file may weigh once serialized. Larger files are trimmed (`fitDebugContext`). */
|
|
12
|
+
export declare const DEBUG_CONTEXT_MAX_BYTES: number;
|
|
13
|
+
/** On whenever a host turns debug context on. */
|
|
14
|
+
export declare const DEFAULT_SIGNALS: readonly ["errors", "network", "responseExcerpts", "steps", "environment", "page", "build", "target", "host", "resources", "lifecycle"];
|
|
15
|
+
/** Off unless a host names them. */
|
|
16
|
+
export declare const OPT_IN_SIGNALS: readonly ["staleBuild", "componentStacks", "domExcerpt", "queries", "realtime", "stores", "storeValues", "consoleLog", "performance", "storage", "bodies"];
|
|
17
|
+
export type DebugSignal = (typeof DEFAULT_SIGNALS)[number] | (typeof OPT_IN_SIGNALS)[number];
|
|
18
|
+
export declare const DEBUG_SIGNALS: readonly DebugSignal[];
|
|
19
|
+
/**
|
|
20
|
+
* Who files the report. `reviewer`: people testing the app with the comment toolbar. `support`: the app's own
|
|
21
|
+
* customers through a help form, so failed-response excerpts start off.
|
|
22
|
+
*/
|
|
23
|
+
export type DebugAudience = "reviewer" | "support";
|
|
24
|
+
export type FlagValue = string | number | boolean | null;
|
|
25
|
+
/** The host app's build. `deployed` is the build the server serves now, for spotting a stale tab. */
|
|
26
|
+
export type HostBuild = {
|
|
27
|
+
commit?: string;
|
|
28
|
+
version?: string;
|
|
29
|
+
env?: string;
|
|
30
|
+
builtAt?: string;
|
|
31
|
+
deployed?: string;
|
|
32
|
+
};
|
|
33
|
+
export type RealtimeState = {
|
|
34
|
+
status?: string;
|
|
35
|
+
/** Epoch ms of the last message received. */
|
|
36
|
+
lastMessageAt?: number;
|
|
37
|
+
reconnects?: number;
|
|
38
|
+
lastClose?: {
|
|
39
|
+
code?: number;
|
|
40
|
+
reason?: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
/** What the host knows and the browser does not. Ids, never emails or names of people. */
|
|
44
|
+
export type HostContext = {
|
|
45
|
+
user?: {
|
|
46
|
+
id?: string;
|
|
47
|
+
role?: string;
|
|
48
|
+
plan?: string;
|
|
49
|
+
locale?: string;
|
|
50
|
+
};
|
|
51
|
+
org?: {
|
|
52
|
+
id?: string;
|
|
53
|
+
name?: string;
|
|
54
|
+
};
|
|
55
|
+
flags?: Record<string, FlagValue>;
|
|
56
|
+
build?: HostBuild;
|
|
57
|
+
/** The id the host's backend logs carry for this page or request chain (`traceparent`'s trace id). */
|
|
58
|
+
traceId?: string;
|
|
59
|
+
sessionId?: string;
|
|
60
|
+
/** The router's pattern for the page, e.g. `/projects/:id`. */
|
|
61
|
+
routePattern?: string;
|
|
62
|
+
realtime?: RealtimeState;
|
|
63
|
+
/** A few more facts of the host's own, at most 20. */
|
|
64
|
+
extra?: Record<string, FlagValue>;
|
|
65
|
+
};
|
|
66
|
+
/** One query of a data-fetching cache (TanStack Query, SWR): its state, never its data. */
|
|
67
|
+
export type QuerySummary = {
|
|
68
|
+
key: unknown;
|
|
69
|
+
status?: string;
|
|
70
|
+
fetchStatus?: string;
|
|
71
|
+
error?: unknown;
|
|
72
|
+
/** Epoch ms the data last changed. */
|
|
73
|
+
updatedAt?: number;
|
|
74
|
+
observers?: number;
|
|
75
|
+
};
|
|
76
|
+
/** How a host turns debug context on and what it allows. All of it is code, in the host app. */
|
|
77
|
+
export type DebugContextOptions = {
|
|
78
|
+
/** Default true once an options object is given. */
|
|
79
|
+
enabled?: boolean;
|
|
80
|
+
/** Default `reviewer` in the toolbar. */
|
|
81
|
+
audience?: DebugAudience;
|
|
82
|
+
/** Turns single signals on or off; anything not named keeps its default (`DEFAULT_SIGNALS`). */
|
|
83
|
+
signals?: Partial<Record<DebugSignal, boolean>>;
|
|
84
|
+
/** Static build facts. `getContext().build` wins field by field. */
|
|
85
|
+
build?: HostBuild;
|
|
86
|
+
/** Asked once per report, with a 300 ms limit. */
|
|
87
|
+
getContext?: () => HostContext | Promise<HostContext>;
|
|
88
|
+
/** The last word before the file leaves the browser: change it, or return null to send none. */
|
|
89
|
+
beforeCapture?: (file: DebugContextFile) => DebugContextFile | null;
|
|
90
|
+
/** Told the report's id, so the host can log it beside its own trace. */
|
|
91
|
+
onReport?: (reportId: string) => void;
|
|
92
|
+
/** Read for the `queries` signal. */
|
|
93
|
+
queries?: () => readonly QuerySummary[];
|
|
94
|
+
/** Read for the `stores` signal, by name. */
|
|
95
|
+
stores?: Record<string, () => unknown>;
|
|
96
|
+
/** More response headers that carry request ids. */
|
|
97
|
+
idHeaders?: readonly string[];
|
|
98
|
+
/** Requests whose full bodies are kept (the `bodies` signal): URL prefixes or patterns. */
|
|
99
|
+
bodyUrls?: readonly (string | RegExp)[];
|
|
100
|
+
/** `localStorage`/`sessionStorage` keys whose values are kept (the `storage` signal). Others: names only. */
|
|
101
|
+
storageValueKeys?: readonly string[];
|
|
102
|
+
/** A request slower than this is kept as slow. Default 3000. */
|
|
103
|
+
slowMs?: number;
|
|
104
|
+
};
|
|
105
|
+
/** `true`, `false`, or the options. Off when absent. */
|
|
106
|
+
export type DebugContextConfig = boolean | DebugContextOptions;
|
|
107
|
+
export type ResolvedDebugContext = {
|
|
108
|
+
audience: DebugAudience;
|
|
109
|
+
signals: Record<DebugSignal, boolean>;
|
|
110
|
+
options: DebugContextOptions;
|
|
111
|
+
slowMs: number;
|
|
112
|
+
};
|
|
113
|
+
/** The host's config as one shape, or null when debug context is off. */
|
|
114
|
+
export declare function resolveDebugContext(config: DebugContextConfig | null | undefined, fallbackAudience?: DebugAudience): ResolvedDebugContext | null;
|
|
115
|
+
/**
|
|
116
|
+
* What, of a host's config, decides what is captured: a capture restarts only when this changes. Functions
|
|
117
|
+
* are left out; they are read live (`liveDebugOptions`).
|
|
118
|
+
*/
|
|
119
|
+
export declare function debugContextKey(config: DebugContextConfig | null | undefined): string;
|
|
120
|
+
/**
|
|
121
|
+
* The options as they are now, with every function reading `read()` when it is called: a host that passes a
|
|
122
|
+
* new options object on every render keeps one running capture that still calls its latest functions.
|
|
123
|
+
*/
|
|
124
|
+
export declare function liveDebugOptions(read: () => DebugContextConfig | null | undefined): DebugContextOptions;
|
|
125
|
+
export type DebugErrorKind = "uncaught" | "rejection" | "console" | "boundary" | "resource" | "csp" | "reported";
|
|
126
|
+
export type DebugError = {
|
|
127
|
+
/** Milliseconds before the report (negative). */
|
|
128
|
+
t: number;
|
|
129
|
+
kind: DebugErrorKind;
|
|
130
|
+
level: "error" | "warn";
|
|
131
|
+
message: string;
|
|
132
|
+
stack?: string[];
|
|
133
|
+
/** `file:line:col` where the browser said it happened. */
|
|
134
|
+
source?: string;
|
|
135
|
+
componentStack?: string[];
|
|
136
|
+
count: number;
|
|
137
|
+
};
|
|
138
|
+
export type DebugRequest = {
|
|
139
|
+
t: number;
|
|
140
|
+
method: string;
|
|
141
|
+
url: string;
|
|
142
|
+
/** 0 when there was no answer. */
|
|
143
|
+
status: number;
|
|
144
|
+
ms?: number;
|
|
145
|
+
bytes?: number;
|
|
146
|
+
contentType?: string;
|
|
147
|
+
excerpt?: string;
|
|
148
|
+
graphql?: {
|
|
149
|
+
operation?: string;
|
|
150
|
+
errors: string[];
|
|
151
|
+
};
|
|
152
|
+
ids?: Record<string, string>;
|
|
153
|
+
requestBody?: string;
|
|
154
|
+
responseBody?: string;
|
|
155
|
+
};
|
|
156
|
+
export type DebugStep = {
|
|
157
|
+
t: number;
|
|
158
|
+
type: "navigate";
|
|
159
|
+
path: string;
|
|
160
|
+
} | {
|
|
161
|
+
t: number;
|
|
162
|
+
type: "click";
|
|
163
|
+
label: string;
|
|
164
|
+
} | {
|
|
165
|
+
t: number;
|
|
166
|
+
type: "input";
|
|
167
|
+
label: string;
|
|
168
|
+
redacted: boolean;
|
|
169
|
+
value?: string;
|
|
170
|
+
} | {
|
|
171
|
+
t: number;
|
|
172
|
+
type: "console";
|
|
173
|
+
level: "error" | "warn";
|
|
174
|
+
message: string;
|
|
175
|
+
} | {
|
|
176
|
+
t: number;
|
|
177
|
+
type: "network";
|
|
178
|
+
method: string;
|
|
179
|
+
path: string;
|
|
180
|
+
status: number;
|
|
181
|
+
} | {
|
|
182
|
+
t: number;
|
|
183
|
+
type: "say";
|
|
184
|
+
text: string;
|
|
185
|
+
};
|
|
186
|
+
export type LifecycleEvent = "online" | "offline" | "hidden" | "visible" | "foreground" | "background";
|
|
187
|
+
export type DebugContextFile = {
|
|
188
|
+
v: 1;
|
|
189
|
+
kind: "debug-context";
|
|
190
|
+
capturedAt: string;
|
|
191
|
+
audience: DebugAudience;
|
|
192
|
+
platform: "web" | "ios" | "android";
|
|
193
|
+
page?: {
|
|
194
|
+
url: string;
|
|
195
|
+
route: string;
|
|
196
|
+
routePattern?: string;
|
|
197
|
+
title?: string;
|
|
198
|
+
referrer?: string;
|
|
199
|
+
loadedAgoMs?: number;
|
|
200
|
+
softNavigations?: number;
|
|
201
|
+
visibility?: string;
|
|
202
|
+
};
|
|
203
|
+
build?: {
|
|
204
|
+
host?: HostBuild;
|
|
205
|
+
toolbar?: string;
|
|
206
|
+
staleHost?: boolean;
|
|
207
|
+
};
|
|
208
|
+
client?: {
|
|
209
|
+
browser?: string;
|
|
210
|
+
os?: string;
|
|
211
|
+
device?: string;
|
|
212
|
+
viewport?: [number, number];
|
|
213
|
+
dpr?: number;
|
|
214
|
+
zoom?: number;
|
|
215
|
+
locale?: string;
|
|
216
|
+
timezone?: string;
|
|
217
|
+
colorScheme?: string;
|
|
218
|
+
reducedMotion?: boolean;
|
|
219
|
+
online?: boolean;
|
|
220
|
+
connection?: string;
|
|
221
|
+
touch?: boolean;
|
|
222
|
+
appVersion?: string;
|
|
223
|
+
appBuild?: string;
|
|
224
|
+
appVariant?: string;
|
|
225
|
+
};
|
|
226
|
+
identity?: {
|
|
227
|
+
userId?: string;
|
|
228
|
+
role?: string;
|
|
229
|
+
plan?: string;
|
|
230
|
+
locale?: string;
|
|
231
|
+
orgId?: string;
|
|
232
|
+
orgName?: string;
|
|
233
|
+
};
|
|
234
|
+
flags?: Record<string, FlagValue>;
|
|
235
|
+
extra?: Record<string, FlagValue>;
|
|
236
|
+
target?: {
|
|
237
|
+
component?: string;
|
|
238
|
+
file?: string;
|
|
239
|
+
stack?: string[];
|
|
240
|
+
role?: string;
|
|
241
|
+
name?: string;
|
|
242
|
+
tag?: string;
|
|
243
|
+
html?: string;
|
|
244
|
+
box?: [number, number, number, number];
|
|
245
|
+
styles?: Record<string, string>;
|
|
246
|
+
};
|
|
247
|
+
errors?: DebugError[];
|
|
248
|
+
logs?: {
|
|
249
|
+
t: number;
|
|
250
|
+
level: string;
|
|
251
|
+
message: string;
|
|
252
|
+
}[];
|
|
253
|
+
network?: {
|
|
254
|
+
failed: DebugRequest[];
|
|
255
|
+
slow: DebugRequest[];
|
|
256
|
+
pending: DebugRequest[];
|
|
257
|
+
aborted: number;
|
|
258
|
+
};
|
|
259
|
+
steps?: DebugStep[];
|
|
260
|
+
lifecycle?: {
|
|
261
|
+
t: number;
|
|
262
|
+
event: LifecycleEvent;
|
|
263
|
+
}[];
|
|
264
|
+
performance?: {
|
|
265
|
+
longTasks?: number;
|
|
266
|
+
longestTaskMs?: number;
|
|
267
|
+
inpMs?: number;
|
|
268
|
+
lcpMs?: number;
|
|
269
|
+
cls?: number;
|
|
270
|
+
loadMs?: number;
|
|
271
|
+
heapMb?: number;
|
|
272
|
+
};
|
|
273
|
+
queries?: {
|
|
274
|
+
key: string;
|
|
275
|
+
status?: string;
|
|
276
|
+
fetchStatus?: string;
|
|
277
|
+
error?: string;
|
|
278
|
+
updatedAgoMs?: number;
|
|
279
|
+
observers?: number;
|
|
280
|
+
}[];
|
|
281
|
+
stores?: JsonBag;
|
|
282
|
+
storage?: {
|
|
283
|
+
local?: {
|
|
284
|
+
key: string;
|
|
285
|
+
bytes: number;
|
|
286
|
+
value?: string;
|
|
287
|
+
}[];
|
|
288
|
+
session?: {
|
|
289
|
+
key: string;
|
|
290
|
+
bytes: number;
|
|
291
|
+
value?: string;
|
|
292
|
+
}[];
|
|
293
|
+
cookies?: string[];
|
|
294
|
+
indexedDb?: string[];
|
|
295
|
+
};
|
|
296
|
+
realtime?: {
|
|
297
|
+
status?: string;
|
|
298
|
+
lastMessageAgoMs?: number;
|
|
299
|
+
reconnects?: number;
|
|
300
|
+
lastClose?: {
|
|
301
|
+
code?: number;
|
|
302
|
+
reason?: string;
|
|
303
|
+
};
|
|
304
|
+
};
|
|
305
|
+
join: {
|
|
306
|
+
reportId: string;
|
|
307
|
+
traceId?: string;
|
|
308
|
+
sessionId?: string;
|
|
309
|
+
requestIds?: string[];
|
|
310
|
+
};
|
|
311
|
+
/** Which signals were on, so a reader can tell "off" from "nothing happened". */
|
|
312
|
+
signals: DebugSignal[];
|
|
313
|
+
redaction: {
|
|
314
|
+
rules: 1;
|
|
315
|
+
masked: number;
|
|
316
|
+
dropped: number;
|
|
317
|
+
truncated: boolean;
|
|
318
|
+
};
|
|
319
|
+
};
|
|
320
|
+
export declare function isDebugContextName(name: string): boolean;
|
|
321
|
+
/** `context-<stamp>.json` for a report taken at `at`. */
|
|
322
|
+
export declare function debugContextName(at?: Date): string;
|
|
323
|
+
/** A report id: sortable by time, unguessable, safe in a header or a log line. */
|
|
324
|
+
export declare function newReportId(now?: number): string;
|
|
325
|
+
/**
|
|
326
|
+
* A context file rebuilt from untrusted JSON: only known fields, every string redacted again, every list and
|
|
327
|
+
* string bounded. Null when it is not a context file. Running it on its own output changes nothing but the
|
|
328
|
+
* counts, so the browser, the service and the console can all run it.
|
|
329
|
+
*/
|
|
330
|
+
export declare function sanitizeDebugContext(value: unknown): DebugContextFile | null;
|
|
331
|
+
export declare function debugContextBytes(file: DebugContextFile): number;
|
|
332
|
+
/**
|
|
333
|
+
* The file cut down to `maxBytes`, dropping the least useful parts first: store state, storage, the cache,
|
|
334
|
+
* logs, bodies, then the oldest steps, excerpts and stacks. Marks `redaction.truncated` when anything went.
|
|
335
|
+
*/
|
|
336
|
+
export declare function fitDebugContext(file: DebugContextFile, maxBytes?: number): DebugContextFile;
|
|
337
|
+
export type BriefMeta = {
|
|
338
|
+
title?: string | null;
|
|
339
|
+
body?: string | null;
|
|
340
|
+
author?: string | null;
|
|
341
|
+
kind?: string | null;
|
|
342
|
+
createdAt?: string | null;
|
|
343
|
+
threadUrl?: string | null;
|
|
344
|
+
/** Other files on the thread, by name, so the brief can point at them. */
|
|
345
|
+
files?: readonly string[];
|
|
346
|
+
};
|
|
347
|
+
/**
|
|
348
|
+
* The context as a short markdown brief for a coding agent: what was reported, where to look, what broke
|
|
349
|
+
* (newest first), the steps, the environment, and what else exists. The first three sections are always
|
|
350
|
+
* there, saying so when they are empty. Kept under about 6,000 tokens.
|
|
351
|
+
*/
|
|
352
|
+
export declare function debugContextBrief(file: DebugContextFile, meta?: BriefMeta): string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redaction for the debug context file. DOM-free: the toolbar runs it in the browser before upload, the
|
|
3
|
+
* service runs it again on every stored file, and native clients share it.
|
|
4
|
+
*
|
|
5
|
+
* Over-redact rather than under-redact. Every rule here is applied to text an app wrote (console lines, error
|
|
6
|
+
* messages, response excerpts, store values), so it has to catch secrets and personal data nobody labelled.
|
|
7
|
+
*/
|
|
8
|
+
/** A JSON object whose keys are not known ahead: store state, parsed bodies. Values are redacted before use. */
|
|
9
|
+
export type JsonBag = {
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
};
|
|
12
|
+
/** Counts what was taken out, so a reader knows something is missing instead of assuming it never happened. */
|
|
13
|
+
export type RedactionTally = {
|
|
14
|
+
masked: number;
|
|
15
|
+
dropped: number;
|
|
16
|
+
};
|
|
17
|
+
export declare function newTally(): RedactionTally;
|
|
18
|
+
/**
|
|
19
|
+
* `value` with secrets and personal data replaced, control characters removed and cut at `max`. Placeholders
|
|
20
|
+
* (`[secret]`, `[email]`, …) are stable, so running it twice changes nothing.
|
|
21
|
+
*/
|
|
22
|
+
export declare function scrubText(value: string, max: number, tally?: RedactionTally): string;
|
|
23
|
+
/** Object keys whose values are never kept, at any depth. */
|
|
24
|
+
export declare const SENSITIVE_KEY: RegExp;
|
|
25
|
+
/**
|
|
26
|
+
* A URL with its userinfo removed, secret-looking query values replaced and the rest scrubbed as text. Same-
|
|
27
|
+
* origin URLs keep only path and query. Unparseable input is scrubbed as text.
|
|
28
|
+
*/
|
|
29
|
+
export declare function scrubUrl(value: string, max: number, base?: string, tally?: RedactionTally): string;
|
|
30
|
+
export type ScrubOptions = {
|
|
31
|
+
/** Deepest level kept; anything below becomes "[…]". */
|
|
32
|
+
depth?: number;
|
|
33
|
+
/** Longest string kept. */
|
|
34
|
+
text?: number;
|
|
35
|
+
/** Most entries kept per object or array. */
|
|
36
|
+
entries?: number;
|
|
37
|
+
/** Keep only the shape: types and sizes, no values. */
|
|
38
|
+
shapeOnly?: boolean;
|
|
39
|
+
tally?: RedactionTally;
|
|
40
|
+
};
|
|
41
|
+
/** Any JSON-like value, redacted at every depth: sensitive keys dropped, strings scrubbed, sizes bounded. */
|
|
42
|
+
export declare function scrubValue(value: unknown, options?: ScrubOptions, level?: number): unknown;
|
|
43
|
+
/** Response headers whose values are ids that join a request with backend logs. Values are opaque. */
|
|
44
|
+
export declare const ID_HEADERS: readonly string[];
|
|
45
|
+
/** The id headers to read: the defaults plus a host's own, lowercased, invalid names dropped. */
|
|
46
|
+
export declare function idHeaderNames(extra?: readonly string[]): string[];
|
|
47
|
+
/** An id header's value: opaque, so only control characters and obvious secrets are removed. */
|
|
48
|
+
export declare function scrubId(value: string): string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug context on a web page: the hooks (console, `error`, `unhandledrejection`, fetch, XHR, resources,
|
|
3
|
+
* CSP, online, visibility, performance) that feed the shared core (`./debug-context-core.ts`), and what
|
|
4
|
+
* only a page has: its address, the browser, the element pointed at, storage.
|
|
5
|
+
*
|
|
6
|
+
* Runs only while someone is signed in to the toolbar and the host turned debug context on in code. Nothing
|
|
7
|
+
* leaves the page until a report is posted.
|
|
8
|
+
*/
|
|
9
|
+
import type { Anchor } from "../core/index.js";
|
|
10
|
+
import { type DebugCaptureStats } from "./debug-context-core.js";
|
|
11
|
+
import type { DebugContextFile, ResolvedDebugContext } from "./debug-context-model.js";
|
|
12
|
+
import type { ReplayEvent } from "./replay-model.js";
|
|
13
|
+
export type { DebugCaptureStats } from "./debug-context-core.js";
|
|
14
|
+
export type DebugSnapshotInput = {
|
|
15
|
+
element?: Element | null;
|
|
16
|
+
anchor?: Anchor | null;
|
|
17
|
+
/** The toolbar's step trail (its replay buffer), oldest first. */
|
|
18
|
+
steps?: readonly ReplayEvent[];
|
|
19
|
+
};
|
|
20
|
+
export type DebugCapture = {
|
|
21
|
+
/** The moment the person started the report: the file's clock and the "still pending" list come from it. */
|
|
22
|
+
mark(): void;
|
|
23
|
+
/** The file, redacted and bounded, or null when the host's `beforeCapture` refused it or threw. */
|
|
24
|
+
snapshot(input?: DebugSnapshotInput): Promise<DebugContextFile | null>;
|
|
25
|
+
/** An error the host's error boundary caught (`componentStacks`). */
|
|
26
|
+
reportError(error: unknown, componentStack?: string | null): void;
|
|
27
|
+
/** Time spent in this module's hooks, for measuring the hot path. */
|
|
28
|
+
stats(): DebugCaptureStats;
|
|
29
|
+
stop(): void;
|
|
30
|
+
};
|
|
31
|
+
export type DebugCaptureEnv = {
|
|
32
|
+
/** Requests that are the toolbar's own (the comment service): never recorded. */
|
|
33
|
+
ignoreUrl?: (url: string) => boolean;
|
|
34
|
+
window?: Window & typeof globalThis;
|
|
35
|
+
};
|
|
36
|
+
export declare function startDebugContext(resolved: ResolvedDebugContext, env?: DebugCaptureEnv): DebugCapture;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Role and custom field values on a comment: what is turned on, and what a post sends. DOM-free. */
|
|
2
|
+
import type { Details, Settings } from "./api.js";
|
|
3
|
+
export declare const noDetails: Details;
|
|
4
|
+
export declare function detailsEnabled(settings: Settings | null): boolean;
|
|
5
|
+
export declare function hasFieldValues(details: Details): boolean;
|
|
6
|
+
/** Only sends what is turned on, so a disabled feature never rejects a post. */
|
|
7
|
+
export declare function detailsPayload(settings: Settings | null, details: Details): Partial<Details>;
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { type KeyboardEvent as ReactKeyboardEvent } from "react";
|
|
2
2
|
import type { Details, FieldValue, Settings, Thread } from "./client.js";
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
export declare function hasFieldValues(details: Details): boolean;
|
|
6
|
-
/** Only sends what is turned on, so a disabled feature never rejects a post. */
|
|
7
|
-
export declare function detailsPayload(settings: Settings | null, details: Details): Partial<Details>;
|
|
3
|
+
import { type ReportKind } from "./kind-model.js";
|
|
4
|
+
export { detailsEnabled, detailsPayload, hasFieldValues, noDetails } from "./details-model.js";
|
|
8
5
|
export declare function DetailsInput({ settings, value, onChange, onKeyDown, }: {
|
|
9
6
|
settings: Settings | null;
|
|
10
7
|
value: Details;
|
|
11
8
|
onChange: (next: Details) => void;
|
|
12
9
|
onKeyDown?: (event: ReactKeyboardEvent<HTMLTextAreaElement>) => void;
|
|
13
10
|
}): import("react/jsx-runtime").JSX.Element | null;
|
|
11
|
+
/** A new comment's kind, if the person wants to say; pressing the chosen one again leaves it to the service. */
|
|
12
|
+
export declare function KindInput({ value, onChange, }: {
|
|
13
|
+
value: ReportKind | null;
|
|
14
|
+
onChange: (next: ReportKind | null) => void;
|
|
15
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
14
16
|
export declare function RoleBadge({ role }: {
|
|
15
17
|
role: string | null;
|
|
16
18
|
}): import("react/jsx-runtime").JSX.Element | null;
|