@generative-a11y/devtools 0.1.0 → 0.2.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 +74 -24
- package/dist/index.cjs +89 -4
- package/dist/index.d.cts +41 -7
- package/dist/index.d.ts +41 -7
- package/dist/index.js +88 -3
- package/dist/overlay.cjs +150 -24
- package/dist/overlay.d.cts +6 -6
- package/dist/overlay.d.ts +6 -6
- package/dist/overlay.js +150 -24
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -11,17 +11,17 @@ npm install --save-dev @generative-a11y/devtools
|
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { createStore } from "@generative-a11y/devtools";
|
|
15
|
+
import { adapterInfo } from "@generative-a11y/assistant-ui";
|
|
16
16
|
|
|
17
|
-
const store =
|
|
17
|
+
const store = createStore({ maxEntries: 250 });
|
|
18
18
|
const detach = store.attachRuntime({
|
|
19
19
|
id: "support",
|
|
20
20
|
runtime,
|
|
21
21
|
source: {
|
|
22
|
-
adapter:
|
|
23
|
-
fidelity:
|
|
24
|
-
evidence:
|
|
22
|
+
adapter: adapterInfo.name,
|
|
23
|
+
fidelity: adapterInfo.fidelity,
|
|
24
|
+
evidence: adapterInfo.observedRuntimeMethods,
|
|
25
25
|
},
|
|
26
26
|
});
|
|
27
27
|
const unsubscribe = store.subscribe(renderDiagnostics);
|
|
@@ -39,9 +39,9 @@ store.dispose();
|
|
|
39
39
|
|
|
40
40
|
## Store API
|
|
41
41
|
|
|
42
|
-
- `
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
- `createStore({ maxEntries })` creates an isolated store. `maxEntries` defaults
|
|
43
|
+
to `250`, must be a positive safe integer, and bounds the retained ring
|
|
44
|
+
buffer. `droppedCount` reports records evicted since the last `clear()`.
|
|
45
45
|
- `attachRuntime({ id, runtime })` validates a non-empty ID, subscribes only to
|
|
46
46
|
public diagnostics, captures an initial safe snapshot, and returns an
|
|
47
47
|
idempotent detach function. Attaching the same ID replaces its subscription
|
|
@@ -75,15 +75,20 @@ Pass `source` when attaching a runtime driven by an adapter. This is an
|
|
|
75
75
|
explicit, serializable declaration from the integration, not framework detection
|
|
76
76
|
by devtools. It lets an inspector show the adapter name, documented public
|
|
77
77
|
evidence and declared fidelity without filling gaps in the lifecycle trace.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
78
|
+
Workflow fidelity distinguishes runs, steps, hierarchy, tools, interactions,
|
|
79
|
+
replay, reconnection, and unsupported custom events as exact, partial, or
|
|
80
|
+
unavailable where applicable. The inspector also shows content-free run and step
|
|
81
|
+
parentage, attempt boundaries, active or terminal state, and associated entity
|
|
82
|
+
IDs from the core diagnostic snapshot. `interruption` and `retries` accept
|
|
83
|
+
`exact`, `action-wrapper`, or `unavailable`. `connection` accepts those values
|
|
84
|
+
plus `inferred`, because some integrations can only derive connection state from
|
|
85
|
+
another documented public signal. The store freezes a copy of this metadata and
|
|
86
|
+
includes it in its redacted export. Each captured record references an opaque
|
|
87
|
+
`runtimeSourceId`. Source revisions remain immutable and exportable for as long
|
|
88
|
+
as a retained record references them, even after a runtime detaches or the same
|
|
89
|
+
runtime ID is reattached with different metadata. Unreferenced revisions are
|
|
90
|
+
removed with ring-buffer eviction so repeated attachment cannot create unbounded
|
|
91
|
+
source history.
|
|
87
92
|
|
|
88
93
|
Use an adapter package's exported metadata where it fits the integration. For
|
|
89
94
|
custom adapters, provide only public signals that justify normalized events. Do
|
|
@@ -95,15 +100,30 @@ subscribes to a runtime.
|
|
|
95
100
|
## Browser delivery correlation
|
|
96
101
|
|
|
97
102
|
The store intentionally does not import `@generative-a11y/dom`. Connect the
|
|
98
|
-
|
|
103
|
+
active binding's `onDelivery` callback yourself to capture a content-free
|
|
99
104
|
delivery record alongside runtime decisions:
|
|
100
105
|
|
|
101
106
|
```ts
|
|
102
|
-
|
|
103
|
-
|
|
107
|
+
import { createRuntime } from "@generative-a11y/core";
|
|
108
|
+
import { bindRuntime } from "@generative-a11y/dom";
|
|
109
|
+
import { createStore } from "@generative-a11y/devtools";
|
|
110
|
+
|
|
111
|
+
export const runtime = createRuntime();
|
|
112
|
+
export const store = createStore();
|
|
113
|
+
const detach = store.attachRuntime({ id: "support", runtime });
|
|
114
|
+
const delivery = bindRuntime(runtime, {
|
|
115
|
+
onDelivery(result) {
|
|
104
116
|
store.recordDelivery({ runtimeId: "support", result });
|
|
105
117
|
},
|
|
106
118
|
});
|
|
119
|
+
|
|
120
|
+
// Dispatch your host events through runtime. Keep this binding for the session.
|
|
121
|
+
export function disposeChat() {
|
|
122
|
+
delivery.dispose();
|
|
123
|
+
detach();
|
|
124
|
+
store.dispose();
|
|
125
|
+
runtime.dispose();
|
|
126
|
+
}
|
|
107
127
|
```
|
|
108
128
|
|
|
109
129
|
This exposes the browser-level method and status (`aria-notify`, fallback live
|
|
@@ -128,12 +148,28 @@ focus. The overlay does not trap focus, create a live region, modify host
|
|
|
128
148
|
layout, or install global shortcuts.
|
|
129
149
|
|
|
130
150
|
```ts
|
|
131
|
-
import {
|
|
151
|
+
import { mountOverlay } from "@generative-a11y/devtools/overlay";
|
|
132
152
|
|
|
133
|
-
const overlay =
|
|
134
|
-
overlay.dispose()
|
|
153
|
+
const overlay = mountOverlay({ store });
|
|
154
|
+
// Call overlay.dispose() when removing the workbench.
|
|
135
155
|
```
|
|
136
156
|
|
|
157
|
+
## Attention decisions
|
|
158
|
+
|
|
159
|
+
When core attention control is enabled, runtime snapshots include the observed
|
|
160
|
+
mode, explicit user override, and effective normal/quiet state. The inspector
|
|
161
|
+
shows these values under policy and scheduling. `attention-updated` explains
|
|
162
|
+
control transitions; `attention-quiet` explains discarded routine output without
|
|
163
|
+
an announcement backlog.
|
|
164
|
+
|
|
165
|
+
`DevtoolsRecord.attentionMode` and `attentionOverride` preserve only recognized
|
|
166
|
+
enum values from control events. Invalid mode payloads are omitted. Exports
|
|
167
|
+
contain no DOM targets or reading history; the observation named
|
|
168
|
+
`reading-history` means only the latest registered response is outside the
|
|
169
|
+
intersection while the document is visible and focused. It does not track a
|
|
170
|
+
screen-reader virtual cursor or prove what someone read. Existing trace schema 1
|
|
171
|
+
consumers can ignore the optional fields.
|
|
172
|
+
|
|
137
173
|
## Documentation
|
|
138
174
|
|
|
139
175
|
- [Devtools guide](https://generativea11y.com/docs/devtools)
|
|
@@ -149,3 +185,17 @@ overlay.dispose();
|
|
|
149
185
|
- [`@generative-a11y/core/testing`](https://generativea11y.com/api/core/testing)
|
|
150
186
|
provides deterministic replay and semantic test assertions without another
|
|
151
187
|
package installation.
|
|
188
|
+
|
|
189
|
+
## Localized announcements
|
|
190
|
+
|
|
191
|
+
Runtime snapshots include optional `messages: { catalogId, locale }`. The
|
|
192
|
+
inspector exposes only these fields and `catalog-format-error`; catalog
|
|
193
|
+
messages, formatter arguments/functions and error text are not retained. Use a
|
|
194
|
+
non-sensitive catalog ID.
|
|
195
|
+
|
|
196
|
+
See the
|
|
197
|
+
[localization guide](https://generativea11y.com/docs/localized-announcements).
|
|
198
|
+
|
|
199
|
+
For React, pass the same callback through
|
|
200
|
+
`<A11yProvider delivery={{ onDelivery }}>`. Do not create another announcer
|
|
201
|
+
beside the provider; its existing delivery path supplies the reports.
|
package/dist/index.cjs
CHANGED
|
@@ -20,7 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
23
|
+
createStore: () => createStore
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(index_exports);
|
|
26
26
|
function asRecord(runtimeId, event, captureSequence, runtimeSourceId) {
|
|
@@ -33,7 +33,27 @@ function asRecord(runtimeId, event, captureSequence, runtimeSourceId) {
|
|
|
33
33
|
at: event.at,
|
|
34
34
|
kind: event.kind,
|
|
35
35
|
sourceType: event.event.type,
|
|
36
|
+
...event.event.type === "attention.changed" && [
|
|
37
|
+
"foreground",
|
|
38
|
+
"background",
|
|
39
|
+
"reading-history",
|
|
40
|
+
"away",
|
|
41
|
+
"unknown"
|
|
42
|
+
].includes(event.event.mode) ? { attentionMode: event.event.mode } : {},
|
|
43
|
+
...event.event.type === "attention.override" && ["auto", "normal", "quiet"].includes(event.event.mode) ? { attentionOverride: event.event.mode } : {},
|
|
36
44
|
...event.event.eventId ? { sourceEventId: event.event.eventId } : {},
|
|
45
|
+
..."runId" in event.event && event.event.runId ? { runId: event.event.runId } : {},
|
|
46
|
+
..."runInstanceId" in event.event && event.event.runInstanceId ? { runInstanceId: event.event.runInstanceId } : {},
|
|
47
|
+
..."nextRunInstanceId" in event.event && event.event.nextRunInstanceId ? { nextRunInstanceId: event.event.nextRunInstanceId } : {},
|
|
48
|
+
..."parentRunId" in event.event && event.event.parentRunId ? { parentRunId: event.event.parentRunId } : {},
|
|
49
|
+
..."parentRunInstanceId" in event.event && event.event.parentRunInstanceId ? { parentRunInstanceId: event.event.parentRunInstanceId } : {},
|
|
50
|
+
..."stepId" in event.event && event.event.stepId ? { stepId: event.event.stepId } : {},
|
|
51
|
+
..."stepInstanceId" in event.event && event.event.stepInstanceId ? { stepInstanceId: event.event.stepInstanceId } : {},
|
|
52
|
+
..."nextStepInstanceId" in event.event && event.event.nextStepInstanceId ? { nextStepInstanceId: event.event.nextStepInstanceId } : {},
|
|
53
|
+
..."parentStepId" in event.event && event.event.parentStepId ? { parentStepId: event.event.parentStepId } : {},
|
|
54
|
+
..."parentStepInstanceId" in event.event && event.event.parentStepInstanceId ? { parentStepInstanceId: event.event.parentStepInstanceId } : {},
|
|
55
|
+
..."parentToolId" in event.event && event.event.parentToolId ? { parentToolId: event.event.parentToolId } : {},
|
|
56
|
+
..."parentResponseId" in event.event && event.event.parentResponseId ? { parentResponseId: event.event.parentResponseId } : {},
|
|
37
57
|
..."responseId" in event.event ? { responseId: event.event.responseId } : {},
|
|
38
58
|
..."responseInstanceId" in event.event && event.event.responseInstanceId ? { responseInstanceId: event.event.responseInstanceId } : {},
|
|
39
59
|
..."nextResponseInstanceId" in event.event && event.event.nextResponseInstanceId ? { nextResponseInstanceId: event.event.nextResponseInstanceId } : {},
|
|
@@ -63,6 +83,10 @@ function asRecord(runtimeId, event, captureSequence, runtimeSourceId) {
|
|
|
63
83
|
...event.decision.responseId ? { responseId: event.decision.responseId } : {},
|
|
64
84
|
...event.decision.toolId ? { toolId: event.decision.toolId } : {},
|
|
65
85
|
...event.decision.interactionId ? { interactionId: event.decision.interactionId } : {},
|
|
86
|
+
...event.decision.runId ? { runId: event.decision.runId } : {},
|
|
87
|
+
...event.decision.runInstanceId ? { runInstanceId: event.decision.runInstanceId } : {},
|
|
88
|
+
...event.decision.stepId ? { stepId: event.decision.stepId } : {},
|
|
89
|
+
...event.decision.stepInstanceId ? { stepInstanceId: event.decision.stepInstanceId } : {},
|
|
66
90
|
...event.decision.scheduledAt !== void 0 ? { scheduledAt: event.decision.scheduledAt } : {},
|
|
67
91
|
...event.decision.dueAt !== void 0 ? { dueAt: event.decision.dueAt } : {},
|
|
68
92
|
...event.decision.delayMs !== void 0 ? { delayMs: event.decision.delayMs } : {},
|
|
@@ -86,6 +110,25 @@ function copyRuntimeSource(source) {
|
|
|
86
110
|
throw new TypeError("source fidelity must be an object");
|
|
87
111
|
const lifecycleFidelity = /* @__PURE__ */ new Set(["exact", "action-wrapper", "unavailable"]);
|
|
88
112
|
const connectionFidelity = /* @__PURE__ */ new Set([...lifecycleFidelity, "inferred"]);
|
|
113
|
+
const workflowFidelity = /* @__PURE__ */ new Set(["exact", "partial", "unavailable"]);
|
|
114
|
+
for (const field of [
|
|
115
|
+
"runs",
|
|
116
|
+
"steps",
|
|
117
|
+
"hierarchy",
|
|
118
|
+
"tools",
|
|
119
|
+
"interactions",
|
|
120
|
+
"replay",
|
|
121
|
+
"reconnection"
|
|
122
|
+
]) {
|
|
123
|
+
if (fidelity[field] !== void 0 && !workflowFidelity.has(fidelity[field]))
|
|
124
|
+
throw new TypeError(
|
|
125
|
+
`source ${field} fidelity contains an unsupported value`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
if (fidelity.customEvents !== void 0 && fidelity.customEvents !== "explicit-mapping" && fidelity.customEvents !== "unsupported")
|
|
129
|
+
throw new TypeError(
|
|
130
|
+
"source custom event fidelity contains an unsupported value"
|
|
131
|
+
);
|
|
89
132
|
if (!lifecycleFidelity.has(fidelity.interruption))
|
|
90
133
|
throw new TypeError(
|
|
91
134
|
"source interruption fidelity contains an unsupported value"
|
|
@@ -109,6 +152,14 @@ function copyRuntimeSource(source) {
|
|
|
109
152
|
adapter: source.adapter.trim(),
|
|
110
153
|
evidence: Object.freeze(source.evidence.map((item) => item.trim())),
|
|
111
154
|
fidelity: Object.freeze({
|
|
155
|
+
...fidelity.runs ? { runs: fidelity.runs } : {},
|
|
156
|
+
...fidelity.steps ? { steps: fidelity.steps } : {},
|
|
157
|
+
...fidelity.hierarchy ? { hierarchy: fidelity.hierarchy } : {},
|
|
158
|
+
...fidelity.tools ? { tools: fidelity.tools } : {},
|
|
159
|
+
...fidelity.interactions ? { interactions: fidelity.interactions } : {},
|
|
160
|
+
...fidelity.replay ? { replay: fidelity.replay } : {},
|
|
161
|
+
...fidelity.reconnection ? { reconnection: fidelity.reconnection } : {},
|
|
162
|
+
...fidelity.customEvents ? { customEvents: fidelity.customEvents } : {},
|
|
112
163
|
interruption: fidelity.interruption,
|
|
113
164
|
retries: fidelity.retries,
|
|
114
165
|
connection: fidelity.connection,
|
|
@@ -133,6 +184,10 @@ function asDeliveryRecord(input, captureSequence, runtimeSourceId) {
|
|
|
133
184
|
...result.responseId ? { responseId: result.responseId } : {},
|
|
134
185
|
...result.toolId ? { toolId: result.toolId } : {},
|
|
135
186
|
...result.interactionId ? { interactionId: result.interactionId } : {},
|
|
187
|
+
...result.runId ? { runId: result.runId } : {},
|
|
188
|
+
...result.runInstanceId ? { runInstanceId: result.runInstanceId } : {},
|
|
189
|
+
...result.stepId ? { stepId: result.stepId } : {},
|
|
190
|
+
...result.stepInstanceId ? { stepInstanceId: result.stepInstanceId } : {},
|
|
136
191
|
...result.error?.name ? { errorName: result.error.name } : {}
|
|
137
192
|
});
|
|
138
193
|
}
|
|
@@ -143,8 +198,28 @@ function copyRuntimeSnapshot(source) {
|
|
|
143
198
|
policy: Object.freeze({
|
|
144
199
|
...source.policy,
|
|
145
200
|
text: Object.freeze({ ...source.policy.text }),
|
|
146
|
-
tools: Object.freeze({ ...source.policy.tools })
|
|
201
|
+
tools: Object.freeze({ ...source.policy.tools }),
|
|
202
|
+
workflows: Object.freeze({ ...source.policy.workflows }),
|
|
203
|
+
...source.policy.attention ? {
|
|
204
|
+
attention: Object.freeze({
|
|
205
|
+
...source.policy.attention,
|
|
206
|
+
quietWhen: Object.freeze([...source.policy.attention.quietWhen])
|
|
207
|
+
})
|
|
208
|
+
} : {}
|
|
147
209
|
}),
|
|
210
|
+
...source.messages ? {
|
|
211
|
+
messages: Object.freeze({
|
|
212
|
+
catalogId: source.messages.catalogId,
|
|
213
|
+
locale: source.messages.locale
|
|
214
|
+
})
|
|
215
|
+
} : {},
|
|
216
|
+
...source.attention ? {
|
|
217
|
+
attention: Object.freeze({
|
|
218
|
+
observed: source.attention.observed,
|
|
219
|
+
override: source.attention.override,
|
|
220
|
+
effective: source.attention.effective
|
|
221
|
+
})
|
|
222
|
+
} : {},
|
|
148
223
|
pending: Object.freeze({
|
|
149
224
|
announcements: Object.freeze(
|
|
150
225
|
source.pending.announcements.map((item) => Object.freeze({ ...item }))
|
|
@@ -159,10 +234,20 @@ function copyRuntimeSnapshot(source) {
|
|
|
159
234
|
tools: Object.freeze(
|
|
160
235
|
source.tools.map((item) => Object.freeze({ ...item }))
|
|
161
236
|
),
|
|
237
|
+
...source.runs ? {
|
|
238
|
+
runs: Object.freeze(
|
|
239
|
+
source.runs.map((item) => Object.freeze({ ...item }))
|
|
240
|
+
)
|
|
241
|
+
} : {},
|
|
242
|
+
...source.steps ? {
|
|
243
|
+
steps: Object.freeze(
|
|
244
|
+
source.steps.map((item) => Object.freeze({ ...item }))
|
|
245
|
+
)
|
|
246
|
+
} : {},
|
|
162
247
|
pendingCount: source.pendingCount
|
|
163
248
|
});
|
|
164
249
|
}
|
|
165
|
-
function
|
|
250
|
+
function createStore(options = {}) {
|
|
166
251
|
const maxEntries = options.maxEntries ?? 250;
|
|
167
252
|
if (!Number.isSafeInteger(maxEntries) || maxEntries <= 0)
|
|
168
253
|
throw new RangeError("maxEntries must be a positive safe integer");
|
|
@@ -369,5 +454,5 @@ function createDevtoolsStore(options = {}) {
|
|
|
369
454
|
}
|
|
370
455
|
// Annotate the CommonJS export names for ESM import in node:
|
|
371
456
|
0 && (module.exports = {
|
|
372
|
-
|
|
457
|
+
createStore
|
|
373
458
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Runtime, AdapterFidelity, AttentionMode, AttentionOverride, RuntimeDiagnosticEventV1, RuntimeDiagnosticSnapshotV1 } from '@generative-a11y/core';
|
|
2
2
|
|
|
3
3
|
type DevtoolsRecordKind = RuntimeDiagnosticEventV1["kind"] | "dom-delivery";
|
|
4
4
|
interface DevtoolsRecord {
|
|
5
|
+
readonly attentionMode?: AttentionMode;
|
|
6
|
+
readonly attentionOverride?: AttentionOverride;
|
|
5
7
|
readonly runtimeId: string;
|
|
6
8
|
/** Opaque key for the immutable adapter evidence captured with this record. */
|
|
7
9
|
readonly runtimeSourceId?: string;
|
|
@@ -22,6 +24,30 @@ interface DevtoolsRecord {
|
|
|
22
24
|
readonly toolInstanceId?: string;
|
|
23
25
|
readonly interactionId?: string;
|
|
24
26
|
readonly approvalId?: string;
|
|
27
|
+
/** Stable logical run identity retained as content-free correlation data. */
|
|
28
|
+
readonly runId?: string;
|
|
29
|
+
/** Stable run attempt identity retained as correlation data. */
|
|
30
|
+
readonly runInstanceId?: string;
|
|
31
|
+
/** Replacement run attempt identity on retry evidence. */
|
|
32
|
+
readonly nextRunInstanceId?: string;
|
|
33
|
+
/** Explicit logical parent run identity. */
|
|
34
|
+
readonly parentRunId?: string;
|
|
35
|
+
/** Explicit parent run attempt identity. */
|
|
36
|
+
readonly parentRunInstanceId?: string;
|
|
37
|
+
/** Stable logical step identity retained as content-free correlation data. */
|
|
38
|
+
readonly stepId?: string;
|
|
39
|
+
/** Stable step attempt identity retained as correlation data. */
|
|
40
|
+
readonly stepInstanceId?: string;
|
|
41
|
+
/** Replacement step attempt identity on retry evidence. */
|
|
42
|
+
readonly nextStepInstanceId?: string;
|
|
43
|
+
/** Explicit logical parent step identity. */
|
|
44
|
+
readonly parentStepId?: string;
|
|
45
|
+
/** Explicit parent step attempt identity. */
|
|
46
|
+
readonly parentStepInstanceId?: string;
|
|
47
|
+
/** Explicit tool that delegated to a child run. */
|
|
48
|
+
readonly parentToolId?: string;
|
|
49
|
+
/** Explicit response that owns a child run. */
|
|
50
|
+
readonly parentResponseId?: string;
|
|
25
51
|
readonly progress?: number;
|
|
26
52
|
readonly outcome?: string;
|
|
27
53
|
readonly count?: number;
|
|
@@ -41,7 +67,7 @@ interface DevtoolsRecord {
|
|
|
41
67
|
interface DevtoolsRuntimeSource {
|
|
42
68
|
readonly adapter: string;
|
|
43
69
|
readonly evidence: readonly string[];
|
|
44
|
-
readonly fidelity: Readonly<
|
|
70
|
+
readonly fidelity: Readonly<Pick<AdapterFidelity, "interruption" | "retries" | "connection"> & Partial<Pick<AdapterFidelity, "runs" | "steps" | "hierarchy" | "tools" | "interactions" | "replay" | "reconnection" | "customEvents">> & {
|
|
45
71
|
readonly optionalEvents?: readonly NonNullable<AdapterFidelity["optionalEvents"]>[number][];
|
|
46
72
|
}>;
|
|
47
73
|
}
|
|
@@ -58,6 +84,14 @@ interface DeliveryRecordInput {
|
|
|
58
84
|
readonly responseId?: string;
|
|
59
85
|
readonly toolId?: string;
|
|
60
86
|
readonly interactionId?: string;
|
|
87
|
+
/** Stable logical run identity copied from the delivered intent. */
|
|
88
|
+
readonly runId?: string;
|
|
89
|
+
/** Stable run attempt identity copied from the delivered intent. */
|
|
90
|
+
readonly runInstanceId?: string;
|
|
91
|
+
/** Stable logical step identity copied from the delivered intent. */
|
|
92
|
+
readonly stepId?: string;
|
|
93
|
+
/** Stable step attempt identity copied from the delivered intent. */
|
|
94
|
+
readonly stepInstanceId?: string;
|
|
61
95
|
readonly error?: {
|
|
62
96
|
readonly name: string;
|
|
63
97
|
readonly message?: string;
|
|
@@ -81,15 +115,15 @@ interface DevtoolsTraceExportV1 {
|
|
|
81
115
|
readonly runtimeSnapshots: Readonly<Record<string, RuntimeDiagnosticSnapshotV1>>;
|
|
82
116
|
readonly runtimeSources: Readonly<Record<string, DevtoolsRuntimeSource>>;
|
|
83
117
|
}
|
|
84
|
-
interface
|
|
118
|
+
interface StoreOptions {
|
|
85
119
|
readonly maxEntries?: number;
|
|
86
120
|
}
|
|
87
121
|
interface AttachRuntimeOptions {
|
|
88
122
|
readonly id: string;
|
|
89
|
-
readonly runtime: Pick<
|
|
123
|
+
readonly runtime: Pick<Runtime, "subscribeDiagnosticEvents" | "getDiagnosticSnapshot">;
|
|
90
124
|
readonly source?: DevtoolsRuntimeSource;
|
|
91
125
|
}
|
|
92
|
-
interface
|
|
126
|
+
interface Store {
|
|
93
127
|
attachRuntime(options: AttachRuntimeOptions): () => void;
|
|
94
128
|
getSnapshot(): DevtoolsSnapshot;
|
|
95
129
|
subscribe(listener: () => void): () => void;
|
|
@@ -101,6 +135,6 @@ interface DevtoolsStore {
|
|
|
101
135
|
exportTrace(): DevtoolsTraceExportV1;
|
|
102
136
|
dispose(): void;
|
|
103
137
|
}
|
|
104
|
-
declare function
|
|
138
|
+
declare function createStore(options?: StoreOptions): Store;
|
|
105
139
|
|
|
106
|
-
export { type AttachRuntimeOptions, type DeliveryRecordInput, type DevtoolsRecord, type DevtoolsRecordKind, type DevtoolsRuntimeSource, type DevtoolsSnapshot, type
|
|
140
|
+
export { type AttachRuntimeOptions, type DeliveryRecordInput, type DevtoolsRecord, type DevtoolsRecordKind, type DevtoolsRuntimeSource, type DevtoolsSnapshot, type DevtoolsTraceExportV1, type Store, type StoreOptions, createStore };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Runtime, AdapterFidelity, AttentionMode, AttentionOverride, RuntimeDiagnosticEventV1, RuntimeDiagnosticSnapshotV1 } from '@generative-a11y/core';
|
|
2
2
|
|
|
3
3
|
type DevtoolsRecordKind = RuntimeDiagnosticEventV1["kind"] | "dom-delivery";
|
|
4
4
|
interface DevtoolsRecord {
|
|
5
|
+
readonly attentionMode?: AttentionMode;
|
|
6
|
+
readonly attentionOverride?: AttentionOverride;
|
|
5
7
|
readonly runtimeId: string;
|
|
6
8
|
/** Opaque key for the immutable adapter evidence captured with this record. */
|
|
7
9
|
readonly runtimeSourceId?: string;
|
|
@@ -22,6 +24,30 @@ interface DevtoolsRecord {
|
|
|
22
24
|
readonly toolInstanceId?: string;
|
|
23
25
|
readonly interactionId?: string;
|
|
24
26
|
readonly approvalId?: string;
|
|
27
|
+
/** Stable logical run identity retained as content-free correlation data. */
|
|
28
|
+
readonly runId?: string;
|
|
29
|
+
/** Stable run attempt identity retained as correlation data. */
|
|
30
|
+
readonly runInstanceId?: string;
|
|
31
|
+
/** Replacement run attempt identity on retry evidence. */
|
|
32
|
+
readonly nextRunInstanceId?: string;
|
|
33
|
+
/** Explicit logical parent run identity. */
|
|
34
|
+
readonly parentRunId?: string;
|
|
35
|
+
/** Explicit parent run attempt identity. */
|
|
36
|
+
readonly parentRunInstanceId?: string;
|
|
37
|
+
/** Stable logical step identity retained as content-free correlation data. */
|
|
38
|
+
readonly stepId?: string;
|
|
39
|
+
/** Stable step attempt identity retained as correlation data. */
|
|
40
|
+
readonly stepInstanceId?: string;
|
|
41
|
+
/** Replacement step attempt identity on retry evidence. */
|
|
42
|
+
readonly nextStepInstanceId?: string;
|
|
43
|
+
/** Explicit logical parent step identity. */
|
|
44
|
+
readonly parentStepId?: string;
|
|
45
|
+
/** Explicit parent step attempt identity. */
|
|
46
|
+
readonly parentStepInstanceId?: string;
|
|
47
|
+
/** Explicit tool that delegated to a child run. */
|
|
48
|
+
readonly parentToolId?: string;
|
|
49
|
+
/** Explicit response that owns a child run. */
|
|
50
|
+
readonly parentResponseId?: string;
|
|
25
51
|
readonly progress?: number;
|
|
26
52
|
readonly outcome?: string;
|
|
27
53
|
readonly count?: number;
|
|
@@ -41,7 +67,7 @@ interface DevtoolsRecord {
|
|
|
41
67
|
interface DevtoolsRuntimeSource {
|
|
42
68
|
readonly adapter: string;
|
|
43
69
|
readonly evidence: readonly string[];
|
|
44
|
-
readonly fidelity: Readonly<
|
|
70
|
+
readonly fidelity: Readonly<Pick<AdapterFidelity, "interruption" | "retries" | "connection"> & Partial<Pick<AdapterFidelity, "runs" | "steps" | "hierarchy" | "tools" | "interactions" | "replay" | "reconnection" | "customEvents">> & {
|
|
45
71
|
readonly optionalEvents?: readonly NonNullable<AdapterFidelity["optionalEvents"]>[number][];
|
|
46
72
|
}>;
|
|
47
73
|
}
|
|
@@ -58,6 +84,14 @@ interface DeliveryRecordInput {
|
|
|
58
84
|
readonly responseId?: string;
|
|
59
85
|
readonly toolId?: string;
|
|
60
86
|
readonly interactionId?: string;
|
|
87
|
+
/** Stable logical run identity copied from the delivered intent. */
|
|
88
|
+
readonly runId?: string;
|
|
89
|
+
/** Stable run attempt identity copied from the delivered intent. */
|
|
90
|
+
readonly runInstanceId?: string;
|
|
91
|
+
/** Stable logical step identity copied from the delivered intent. */
|
|
92
|
+
readonly stepId?: string;
|
|
93
|
+
/** Stable step attempt identity copied from the delivered intent. */
|
|
94
|
+
readonly stepInstanceId?: string;
|
|
61
95
|
readonly error?: {
|
|
62
96
|
readonly name: string;
|
|
63
97
|
readonly message?: string;
|
|
@@ -81,15 +115,15 @@ interface DevtoolsTraceExportV1 {
|
|
|
81
115
|
readonly runtimeSnapshots: Readonly<Record<string, RuntimeDiagnosticSnapshotV1>>;
|
|
82
116
|
readonly runtimeSources: Readonly<Record<string, DevtoolsRuntimeSource>>;
|
|
83
117
|
}
|
|
84
|
-
interface
|
|
118
|
+
interface StoreOptions {
|
|
85
119
|
readonly maxEntries?: number;
|
|
86
120
|
}
|
|
87
121
|
interface AttachRuntimeOptions {
|
|
88
122
|
readonly id: string;
|
|
89
|
-
readonly runtime: Pick<
|
|
123
|
+
readonly runtime: Pick<Runtime, "subscribeDiagnosticEvents" | "getDiagnosticSnapshot">;
|
|
90
124
|
readonly source?: DevtoolsRuntimeSource;
|
|
91
125
|
}
|
|
92
|
-
interface
|
|
126
|
+
interface Store {
|
|
93
127
|
attachRuntime(options: AttachRuntimeOptions): () => void;
|
|
94
128
|
getSnapshot(): DevtoolsSnapshot;
|
|
95
129
|
subscribe(listener: () => void): () => void;
|
|
@@ -101,6 +135,6 @@ interface DevtoolsStore {
|
|
|
101
135
|
exportTrace(): DevtoolsTraceExportV1;
|
|
102
136
|
dispose(): void;
|
|
103
137
|
}
|
|
104
|
-
declare function
|
|
138
|
+
declare function createStore(options?: StoreOptions): Store;
|
|
105
139
|
|
|
106
|
-
export { type AttachRuntimeOptions, type DeliveryRecordInput, type DevtoolsRecord, type DevtoolsRecordKind, type DevtoolsRuntimeSource, type DevtoolsSnapshot, type
|
|
140
|
+
export { type AttachRuntimeOptions, type DeliveryRecordInput, type DevtoolsRecord, type DevtoolsRecordKind, type DevtoolsRuntimeSource, type DevtoolsSnapshot, type DevtoolsTraceExportV1, type Store, type StoreOptions, createStore };
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,27 @@ function asRecord(runtimeId, event, captureSequence, runtimeSourceId) {
|
|
|
9
9
|
at: event.at,
|
|
10
10
|
kind: event.kind,
|
|
11
11
|
sourceType: event.event.type,
|
|
12
|
+
...event.event.type === "attention.changed" && [
|
|
13
|
+
"foreground",
|
|
14
|
+
"background",
|
|
15
|
+
"reading-history",
|
|
16
|
+
"away",
|
|
17
|
+
"unknown"
|
|
18
|
+
].includes(event.event.mode) ? { attentionMode: event.event.mode } : {},
|
|
19
|
+
...event.event.type === "attention.override" && ["auto", "normal", "quiet"].includes(event.event.mode) ? { attentionOverride: event.event.mode } : {},
|
|
12
20
|
...event.event.eventId ? { sourceEventId: event.event.eventId } : {},
|
|
21
|
+
..."runId" in event.event && event.event.runId ? { runId: event.event.runId } : {},
|
|
22
|
+
..."runInstanceId" in event.event && event.event.runInstanceId ? { runInstanceId: event.event.runInstanceId } : {},
|
|
23
|
+
..."nextRunInstanceId" in event.event && event.event.nextRunInstanceId ? { nextRunInstanceId: event.event.nextRunInstanceId } : {},
|
|
24
|
+
..."parentRunId" in event.event && event.event.parentRunId ? { parentRunId: event.event.parentRunId } : {},
|
|
25
|
+
..."parentRunInstanceId" in event.event && event.event.parentRunInstanceId ? { parentRunInstanceId: event.event.parentRunInstanceId } : {},
|
|
26
|
+
..."stepId" in event.event && event.event.stepId ? { stepId: event.event.stepId } : {},
|
|
27
|
+
..."stepInstanceId" in event.event && event.event.stepInstanceId ? { stepInstanceId: event.event.stepInstanceId } : {},
|
|
28
|
+
..."nextStepInstanceId" in event.event && event.event.nextStepInstanceId ? { nextStepInstanceId: event.event.nextStepInstanceId } : {},
|
|
29
|
+
..."parentStepId" in event.event && event.event.parentStepId ? { parentStepId: event.event.parentStepId } : {},
|
|
30
|
+
..."parentStepInstanceId" in event.event && event.event.parentStepInstanceId ? { parentStepInstanceId: event.event.parentStepInstanceId } : {},
|
|
31
|
+
..."parentToolId" in event.event && event.event.parentToolId ? { parentToolId: event.event.parentToolId } : {},
|
|
32
|
+
..."parentResponseId" in event.event && event.event.parentResponseId ? { parentResponseId: event.event.parentResponseId } : {},
|
|
13
33
|
..."responseId" in event.event ? { responseId: event.event.responseId } : {},
|
|
14
34
|
..."responseInstanceId" in event.event && event.event.responseInstanceId ? { responseInstanceId: event.event.responseInstanceId } : {},
|
|
15
35
|
..."nextResponseInstanceId" in event.event && event.event.nextResponseInstanceId ? { nextResponseInstanceId: event.event.nextResponseInstanceId } : {},
|
|
@@ -39,6 +59,10 @@ function asRecord(runtimeId, event, captureSequence, runtimeSourceId) {
|
|
|
39
59
|
...event.decision.responseId ? { responseId: event.decision.responseId } : {},
|
|
40
60
|
...event.decision.toolId ? { toolId: event.decision.toolId } : {},
|
|
41
61
|
...event.decision.interactionId ? { interactionId: event.decision.interactionId } : {},
|
|
62
|
+
...event.decision.runId ? { runId: event.decision.runId } : {},
|
|
63
|
+
...event.decision.runInstanceId ? { runInstanceId: event.decision.runInstanceId } : {},
|
|
64
|
+
...event.decision.stepId ? { stepId: event.decision.stepId } : {},
|
|
65
|
+
...event.decision.stepInstanceId ? { stepInstanceId: event.decision.stepInstanceId } : {},
|
|
42
66
|
...event.decision.scheduledAt !== void 0 ? { scheduledAt: event.decision.scheduledAt } : {},
|
|
43
67
|
...event.decision.dueAt !== void 0 ? { dueAt: event.decision.dueAt } : {},
|
|
44
68
|
...event.decision.delayMs !== void 0 ? { delayMs: event.decision.delayMs } : {},
|
|
@@ -62,6 +86,25 @@ function copyRuntimeSource(source) {
|
|
|
62
86
|
throw new TypeError("source fidelity must be an object");
|
|
63
87
|
const lifecycleFidelity = /* @__PURE__ */ new Set(["exact", "action-wrapper", "unavailable"]);
|
|
64
88
|
const connectionFidelity = /* @__PURE__ */ new Set([...lifecycleFidelity, "inferred"]);
|
|
89
|
+
const workflowFidelity = /* @__PURE__ */ new Set(["exact", "partial", "unavailable"]);
|
|
90
|
+
for (const field of [
|
|
91
|
+
"runs",
|
|
92
|
+
"steps",
|
|
93
|
+
"hierarchy",
|
|
94
|
+
"tools",
|
|
95
|
+
"interactions",
|
|
96
|
+
"replay",
|
|
97
|
+
"reconnection"
|
|
98
|
+
]) {
|
|
99
|
+
if (fidelity[field] !== void 0 && !workflowFidelity.has(fidelity[field]))
|
|
100
|
+
throw new TypeError(
|
|
101
|
+
`source ${field} fidelity contains an unsupported value`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
if (fidelity.customEvents !== void 0 && fidelity.customEvents !== "explicit-mapping" && fidelity.customEvents !== "unsupported")
|
|
105
|
+
throw new TypeError(
|
|
106
|
+
"source custom event fidelity contains an unsupported value"
|
|
107
|
+
);
|
|
65
108
|
if (!lifecycleFidelity.has(fidelity.interruption))
|
|
66
109
|
throw new TypeError(
|
|
67
110
|
"source interruption fidelity contains an unsupported value"
|
|
@@ -85,6 +128,14 @@ function copyRuntimeSource(source) {
|
|
|
85
128
|
adapter: source.adapter.trim(),
|
|
86
129
|
evidence: Object.freeze(source.evidence.map((item) => item.trim())),
|
|
87
130
|
fidelity: Object.freeze({
|
|
131
|
+
...fidelity.runs ? { runs: fidelity.runs } : {},
|
|
132
|
+
...fidelity.steps ? { steps: fidelity.steps } : {},
|
|
133
|
+
...fidelity.hierarchy ? { hierarchy: fidelity.hierarchy } : {},
|
|
134
|
+
...fidelity.tools ? { tools: fidelity.tools } : {},
|
|
135
|
+
...fidelity.interactions ? { interactions: fidelity.interactions } : {},
|
|
136
|
+
...fidelity.replay ? { replay: fidelity.replay } : {},
|
|
137
|
+
...fidelity.reconnection ? { reconnection: fidelity.reconnection } : {},
|
|
138
|
+
...fidelity.customEvents ? { customEvents: fidelity.customEvents } : {},
|
|
88
139
|
interruption: fidelity.interruption,
|
|
89
140
|
retries: fidelity.retries,
|
|
90
141
|
connection: fidelity.connection,
|
|
@@ -109,6 +160,10 @@ function asDeliveryRecord(input, captureSequence, runtimeSourceId) {
|
|
|
109
160
|
...result.responseId ? { responseId: result.responseId } : {},
|
|
110
161
|
...result.toolId ? { toolId: result.toolId } : {},
|
|
111
162
|
...result.interactionId ? { interactionId: result.interactionId } : {},
|
|
163
|
+
...result.runId ? { runId: result.runId } : {},
|
|
164
|
+
...result.runInstanceId ? { runInstanceId: result.runInstanceId } : {},
|
|
165
|
+
...result.stepId ? { stepId: result.stepId } : {},
|
|
166
|
+
...result.stepInstanceId ? { stepInstanceId: result.stepInstanceId } : {},
|
|
112
167
|
...result.error?.name ? { errorName: result.error.name } : {}
|
|
113
168
|
});
|
|
114
169
|
}
|
|
@@ -119,8 +174,28 @@ function copyRuntimeSnapshot(source) {
|
|
|
119
174
|
policy: Object.freeze({
|
|
120
175
|
...source.policy,
|
|
121
176
|
text: Object.freeze({ ...source.policy.text }),
|
|
122
|
-
tools: Object.freeze({ ...source.policy.tools })
|
|
177
|
+
tools: Object.freeze({ ...source.policy.tools }),
|
|
178
|
+
workflows: Object.freeze({ ...source.policy.workflows }),
|
|
179
|
+
...source.policy.attention ? {
|
|
180
|
+
attention: Object.freeze({
|
|
181
|
+
...source.policy.attention,
|
|
182
|
+
quietWhen: Object.freeze([...source.policy.attention.quietWhen])
|
|
183
|
+
})
|
|
184
|
+
} : {}
|
|
123
185
|
}),
|
|
186
|
+
...source.messages ? {
|
|
187
|
+
messages: Object.freeze({
|
|
188
|
+
catalogId: source.messages.catalogId,
|
|
189
|
+
locale: source.messages.locale
|
|
190
|
+
})
|
|
191
|
+
} : {},
|
|
192
|
+
...source.attention ? {
|
|
193
|
+
attention: Object.freeze({
|
|
194
|
+
observed: source.attention.observed,
|
|
195
|
+
override: source.attention.override,
|
|
196
|
+
effective: source.attention.effective
|
|
197
|
+
})
|
|
198
|
+
} : {},
|
|
124
199
|
pending: Object.freeze({
|
|
125
200
|
announcements: Object.freeze(
|
|
126
201
|
source.pending.announcements.map((item) => Object.freeze({ ...item }))
|
|
@@ -135,10 +210,20 @@ function copyRuntimeSnapshot(source) {
|
|
|
135
210
|
tools: Object.freeze(
|
|
136
211
|
source.tools.map((item) => Object.freeze({ ...item }))
|
|
137
212
|
),
|
|
213
|
+
...source.runs ? {
|
|
214
|
+
runs: Object.freeze(
|
|
215
|
+
source.runs.map((item) => Object.freeze({ ...item }))
|
|
216
|
+
)
|
|
217
|
+
} : {},
|
|
218
|
+
...source.steps ? {
|
|
219
|
+
steps: Object.freeze(
|
|
220
|
+
source.steps.map((item) => Object.freeze({ ...item }))
|
|
221
|
+
)
|
|
222
|
+
} : {},
|
|
138
223
|
pendingCount: source.pendingCount
|
|
139
224
|
});
|
|
140
225
|
}
|
|
141
|
-
function
|
|
226
|
+
function createStore(options = {}) {
|
|
142
227
|
const maxEntries = options.maxEntries ?? 250;
|
|
143
228
|
if (!Number.isSafeInteger(maxEntries) || maxEntries <= 0)
|
|
144
229
|
throw new RangeError("maxEntries must be a positive safe integer");
|
|
@@ -344,5 +429,5 @@ function createDevtoolsStore(options = {}) {
|
|
|
344
429
|
};
|
|
345
430
|
}
|
|
346
431
|
export {
|
|
347
|
-
|
|
432
|
+
createStore
|
|
348
433
|
};
|
package/dist/overlay.cjs
CHANGED
|
@@ -30,7 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/overlay.ts
|
|
31
31
|
var overlay_exports = {};
|
|
32
32
|
__export(overlay_exports, {
|
|
33
|
-
|
|
33
|
+
mountOverlay: () => mountOverlay
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(overlay_exports);
|
|
36
36
|
var import_react2 = require("react");
|
|
@@ -226,23 +226,65 @@ var key = (record) => String(record.captureSequence);
|
|
|
226
226
|
var time = (value) => value >= 1e10 ? new Date(value).toISOString().slice(11, 23) : `+${(value / 1e3).toFixed(2)}s`;
|
|
227
227
|
var stage = (record) => record.kind === "event-observed" ? "Source evidence" : record.kind === "decision" ? "Runtime decision" : "DOM delivery";
|
|
228
228
|
var title = (record) => record.kind === "event-observed" ? record.sourceType ?? "Observed event" : record.kind === "dom-delivery" ? `${record.deliveryStatus ?? "Delivery"} via ${record.deliveryMethod ?? "browser"}` : record.reason ?? record.disposition ?? "Runtime decision";
|
|
229
|
-
function
|
|
229
|
+
function correlationKeys(record) {
|
|
230
230
|
const prefix = `${record.runtimeId}:`;
|
|
231
|
-
|
|
232
|
-
if (record.
|
|
233
|
-
|
|
234
|
-
if (record.toolId)
|
|
235
|
-
return `${prefix}tool:${record.toolId}:${record.sourceType ?? "unknown"}`;
|
|
231
|
+
const keys = /* @__PURE__ */ new Set();
|
|
232
|
+
if (record.sourceEventId) keys.add(`${prefix}event:${record.sourceEventId}`);
|
|
233
|
+
if (record.responseId) keys.add(`${prefix}response:${record.responseId}`);
|
|
234
|
+
if (record.toolId) keys.add(`${prefix}tool:${record.toolId}`);
|
|
236
235
|
if (record.interactionId)
|
|
237
|
-
|
|
238
|
-
if (record.approvalId)
|
|
236
|
+
keys.add(`${prefix}interaction:${record.interactionId}`);
|
|
237
|
+
if (record.approvalId) keys.add(`${prefix}approval:${record.approvalId}`);
|
|
239
238
|
if (record.announcementId)
|
|
240
|
-
|
|
241
|
-
|
|
239
|
+
keys.add(`${prefix}announcement:${record.announcementId}`);
|
|
240
|
+
if (record.runId)
|
|
241
|
+
keys.add(
|
|
242
|
+
`${prefix}run:${record.runId}:${record.runInstanceId ?? "unidentified"}`
|
|
243
|
+
);
|
|
244
|
+
if (record.runId && record.nextRunInstanceId)
|
|
245
|
+
keys.add(`${prefix}run:${record.runId}:${record.nextRunInstanceId}`);
|
|
246
|
+
if (record.parentRunId)
|
|
247
|
+
keys.add(
|
|
248
|
+
`${prefix}run:${record.parentRunId}:${record.parentRunInstanceId ?? "unidentified"}`
|
|
249
|
+
);
|
|
250
|
+
if (record.stepId)
|
|
251
|
+
keys.add(
|
|
252
|
+
`${prefix}step:${record.runId ?? "unknown"}:${record.runInstanceId ?? "unidentified"}:${record.stepId}:${record.stepInstanceId ?? "unidentified"}`
|
|
253
|
+
);
|
|
254
|
+
if (record.stepId && record.nextStepInstanceId)
|
|
255
|
+
keys.add(
|
|
256
|
+
`${prefix}step:${record.runId ?? "unknown"}:${record.runInstanceId ?? "unidentified"}:${record.stepId}:${record.nextStepInstanceId}`
|
|
257
|
+
);
|
|
258
|
+
if (record.parentStepId)
|
|
259
|
+
keys.add(
|
|
260
|
+
`${prefix}step:${record.runId ?? "unknown"}:${record.runInstanceId ?? "unidentified"}:${record.parentStepId}:${record.parentStepInstanceId ?? "unidentified"}`
|
|
261
|
+
);
|
|
262
|
+
if (record.parentToolId) keys.add(`${prefix}tool:${record.parentToolId}`);
|
|
263
|
+
if (record.parentResponseId)
|
|
264
|
+
keys.add(`${prefix}response:${record.parentResponseId}`);
|
|
265
|
+
if (keys.size === 0) keys.add(`${prefix}record:${record.captureSequence}`);
|
|
266
|
+
return [...keys];
|
|
267
|
+
}
|
|
268
|
+
function relatedRecords(records, selected) {
|
|
269
|
+
const related = /* @__PURE__ */ new Set();
|
|
270
|
+
const keys = new Set(correlationKeys(selected));
|
|
271
|
+
let changed = true;
|
|
272
|
+
while (changed) {
|
|
273
|
+
changed = false;
|
|
274
|
+
for (const record of records) {
|
|
275
|
+
if (related.has(record)) continue;
|
|
276
|
+
const recordKeys = correlationKeys(record);
|
|
277
|
+
if (!recordKeys.some((value) => keys.has(value))) continue;
|
|
278
|
+
related.add(record);
|
|
279
|
+
for (const value of recordKeys) keys.add(value);
|
|
280
|
+
changed = true;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return [...related];
|
|
242
284
|
}
|
|
243
285
|
function explain(record) {
|
|
244
286
|
if (record.kind === "event-observed")
|
|
245
|
-
return "The adapter supplied this normalized public lifecycle signal.";
|
|
287
|
+
return record.sourceType?.startsWith("attention.") ? "The host supplied an attention observation or explicit user override. Browser evidence does not establish what someone is reading." : "The adapter supplied this normalized public lifecycle signal.";
|
|
246
288
|
if (record.kind === "dom-delivery")
|
|
247
289
|
return record.deliveryStatus === "unavailable" ? "The DOM driver was unavailable, so no browser delivery action was observed." : "The DOM driver reported this delivery action.";
|
|
248
290
|
return {
|
|
@@ -250,6 +292,9 @@ function explain(record) {
|
|
|
250
292
|
coalesced: "The runtime merged this work with an existing queued announcement.",
|
|
251
293
|
duplicate: "The runtime suppressed a recently delivered duplicate.",
|
|
252
294
|
"policy-silent": "The active policy intentionally made this event silent.",
|
|
295
|
+
"catalog-format-error": "The host message formatter failed; the runtime used a generic English notice without retaining the error or parameters.",
|
|
296
|
+
"attention-quiet": "Quiet mode discarded routine output without retaining an announcement backlog.",
|
|
297
|
+
"attention-updated": "The runtime updated its attention observation or user override without announcing the control event.",
|
|
253
298
|
"queue-capacity": "The bounded queue rejected or displaced this work.",
|
|
254
299
|
"scope-cancelled": "The lifecycle scope ended before this queued work delivered.",
|
|
255
300
|
"runtime-disposed": "The runtime was disposed and cancelled remaining queued work.",
|
|
@@ -302,6 +347,12 @@ function Detail({
|
|
|
302
347
|
] }) });
|
|
303
348
|
const source = snapshot.runtimeSources[record.runtimeSourceId ?? record.runtimeId];
|
|
304
349
|
const runtime = snapshot.runtimeSnapshots[record.runtimeId];
|
|
350
|
+
const run = record.runInstanceId ? runtime?.runs?.find(
|
|
351
|
+
(item) => item.runId === record.runId && item.instanceId === record.runInstanceId
|
|
352
|
+
) : void 0;
|
|
353
|
+
const step = record.runInstanceId && record.stepInstanceId ? runtime?.steps?.find(
|
|
354
|
+
(item) => item.runId === record.runId && item.stepId === record.stepId && item.runInstanceId === record.runInstanceId && item.instanceId === record.stepInstanceId
|
|
355
|
+
) : void 0;
|
|
305
356
|
const deliveries = related.filter((item) => item.kind === "dom-delivery");
|
|
306
357
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("aside", { className: "ga-trace-detail", "data-testid": "trace-detail", children: [
|
|
307
358
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "ga-detail-intro", children: [
|
|
@@ -314,6 +365,43 @@ function Detail({
|
|
|
314
365
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { children: record.reason?.startsWith("stale") ? "Compare the instance with the current runtime snapshot." : "Inspect related evidence and queue context if this was unexpected." })
|
|
315
366
|
] }),
|
|
316
367
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CausalChain, { records: related }),
|
|
368
|
+
record.runId ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "ga-detail-section", children: [
|
|
369
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h4", { children: "Workflow hierarchy" }),
|
|
370
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("dl", { className: "ga-key-values", children: [
|
|
371
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
372
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Run" }),
|
|
373
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: record.runId })
|
|
374
|
+
] }),
|
|
375
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
376
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Run attempt" }),
|
|
377
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: record.runInstanceId ?? run?.instanceId ?? "Not supplied" })
|
|
378
|
+
] }),
|
|
379
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
380
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Parent run" }),
|
|
381
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: record.parentRunId ?? run?.parentRunId ?? "None" })
|
|
382
|
+
] }),
|
|
383
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
384
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Run state" }),
|
|
385
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: run?.status ?? "Not retained" })
|
|
386
|
+
] }),
|
|
387
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
388
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Step" }),
|
|
389
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: record.stepId ?? "Partial identity" })
|
|
390
|
+
] }),
|
|
391
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
392
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Step attempt" }),
|
|
393
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: record.stepInstanceId ?? step?.instanceId ?? "Not supplied" })
|
|
394
|
+
] }),
|
|
395
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
396
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Parent step" }),
|
|
397
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: record.parentStepId ?? step?.parentStepId ?? "None" })
|
|
398
|
+
] }),
|
|
399
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
400
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Step state" }),
|
|
401
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: step?.status ?? "Not retained" })
|
|
402
|
+
] })
|
|
403
|
+
] })
|
|
404
|
+
] }) : null,
|
|
317
405
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "ga-detail-section", children: [
|
|
318
406
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h4", { children: "Source evidence" }),
|
|
319
407
|
source ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("dl", { className: "ga-key-values", children: [
|
|
@@ -321,6 +409,22 @@ function Detail({
|
|
|
321
409
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Adapter" }),
|
|
322
410
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: source.adapter })
|
|
323
411
|
] }),
|
|
412
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
413
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Runs" }),
|
|
414
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: source.fidelity.runs ?? "Not declared" })
|
|
415
|
+
] }),
|
|
416
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
417
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Steps" }),
|
|
418
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: source.fidelity.steps ?? "Not declared" })
|
|
419
|
+
] }),
|
|
420
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
421
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Hierarchy" }),
|
|
422
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: source.fidelity.hierarchy ?? "Not declared" })
|
|
423
|
+
] }),
|
|
424
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
425
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Replay" }),
|
|
426
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: source.fidelity.replay ?? "Not declared" })
|
|
427
|
+
] }),
|
|
324
428
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
325
429
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Interruption" }),
|
|
326
430
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: source.fidelity.interruption })
|
|
@@ -342,6 +446,30 @@ function Detail({
|
|
|
342
446
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "ga-detail-section", children: [
|
|
343
447
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h4", { children: "Policy and scheduling" }),
|
|
344
448
|
runtime ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("dl", { className: "ga-key-values", children: [
|
|
449
|
+
runtime.messages && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
450
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
451
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Announcement catalog" }),
|
|
452
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: runtime.messages.catalogId })
|
|
453
|
+
] }),
|
|
454
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
455
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Notice language" }),
|
|
456
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: runtime.messages.locale })
|
|
457
|
+
] })
|
|
458
|
+
] }),
|
|
459
|
+
runtime.attention && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
460
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
461
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Effective announcements" }),
|
|
462
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: runtime.attention.effective })
|
|
463
|
+
] }),
|
|
464
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
465
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Observed attention" }),
|
|
466
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: runtime.attention.observed })
|
|
467
|
+
] }),
|
|
468
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
469
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "User override" }),
|
|
470
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { children: runtime.attention.override })
|
|
471
|
+
] })
|
|
472
|
+
] }),
|
|
345
473
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
346
474
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { children: "Queue" }),
|
|
347
475
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("dd", { children: [
|
|
@@ -431,11 +559,7 @@ function List({
|
|
|
431
559
|
}
|
|
432
560
|
);
|
|
433
561
|
}
|
|
434
|
-
function
|
|
435
|
-
store,
|
|
436
|
-
onClose,
|
|
437
|
-
onCopy
|
|
438
|
-
}) {
|
|
562
|
+
function Inspector({ store, onClose, onCopy }) {
|
|
439
563
|
const snapshot = useSnapshot(store);
|
|
440
564
|
const reduceMotion = (0, import_react.useReducedMotion)();
|
|
441
565
|
const [query, setQuery] = React4.useState("");
|
|
@@ -453,13 +577,15 @@ function DevtoolsInspector({
|
|
|
453
577
|
record.responseId,
|
|
454
578
|
record.toolId,
|
|
455
579
|
record.interactionId,
|
|
456
|
-
record.approvalId
|
|
580
|
+
record.approvalId,
|
|
581
|
+
record.runId,
|
|
582
|
+
record.runInstanceId,
|
|
583
|
+
record.stepId,
|
|
584
|
+
record.stepInstanceId
|
|
457
585
|
].filter(Boolean).join(" ").toLowerCase().includes(query.trim().toLowerCase())
|
|
458
586
|
).slice().reverse();
|
|
459
587
|
const selected = visible.find((record) => key(record) === selectedKey) ?? visible[0];
|
|
460
|
-
const related = selected ? snapshot.records
|
|
461
|
-
(record) => correlation(record) === correlation(selected)
|
|
462
|
-
) : [];
|
|
588
|
+
const related = selected ? relatedRecords(snapshot.records, selected) : [];
|
|
463
589
|
React4.useEffect(
|
|
464
590
|
() => () => {
|
|
465
591
|
if (feedbackTimer.current !== void 0)
|
|
@@ -739,7 +865,7 @@ button:focus-visible, input:focus-visible, [role="listbox"]:focus-visible, [role
|
|
|
739
865
|
.ga-workspace-feedback { top: 68px; color: #f7f7f7; background: #111; border-color: #111; border-radius: 3px; box-shadow: none; }
|
|
740
866
|
@media (max-width: 760px) { .ga-bottom-dock { height: min(720px, 80vh); } .ga-inspector-header, .ga-session-toolbar { padding-right: 12px; padding-left: 12px; } .ga-session-toolbar { flex-wrap: wrap; } .ga-inspector-search { width: 100%; } .ga-session-count { margin-left: 0; } .ga-explorer-layout { flex-direction: column; } [data-slot="resizable-handle"] { width: 100%; height: 1px; } .ga-trace-row { grid-template-columns: 70px 1fr; padding: 8px 12px; } .ga-trace-row span, .ga-trace-row code { grid-column: 2; } .ga-trace-detail { padding: 18px 12px; } .ga-key-values { grid-template-columns: 1fr; } .ga-key-values-wide { grid-column: auto; } }
|
|
741
867
|
`;
|
|
742
|
-
function
|
|
868
|
+
function mountOverlay(options) {
|
|
743
869
|
const selectedDocument = options.document ?? (typeof document === "undefined" ? void 0 : document);
|
|
744
870
|
if (!selectedDocument?.body)
|
|
745
871
|
throw new Error("A mountable document is required");
|
|
@@ -794,7 +920,7 @@ function mountDevtoolsOverlay(options) {
|
|
|
794
920
|
return clipboard.writeText(value);
|
|
795
921
|
});
|
|
796
922
|
root.render(
|
|
797
|
-
(0, import_react2.createElement)(
|
|
923
|
+
(0, import_react2.createElement)(Inspector, {
|
|
798
924
|
onClose: close,
|
|
799
925
|
onCopy: copyText,
|
|
800
926
|
store: options.store
|
|
@@ -833,5 +959,5 @@ function mountDevtoolsOverlay(options) {
|
|
|
833
959
|
}
|
|
834
960
|
// Annotate the CommonJS export names for ESM import in node:
|
|
835
961
|
0 && (module.exports = {
|
|
836
|
-
|
|
962
|
+
mountOverlay
|
|
837
963
|
});
|
package/dist/overlay.d.cts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Store } from './index.cjs';
|
|
2
2
|
import '@generative-a11y/core';
|
|
3
3
|
|
|
4
|
-
interface
|
|
5
|
-
readonly store:
|
|
4
|
+
interface OverlayOptions {
|
|
5
|
+
readonly store: Store;
|
|
6
6
|
readonly document?: Document;
|
|
7
7
|
readonly copyText?: (value: string) => void | Promise<void>;
|
|
8
8
|
}
|
|
9
|
-
interface
|
|
9
|
+
interface Overlay {
|
|
10
10
|
readonly host: HTMLElement;
|
|
11
11
|
dispose(): void;
|
|
12
12
|
}
|
|
13
|
-
declare function
|
|
13
|
+
declare function mountOverlay(options: OverlayOptions): Overlay;
|
|
14
14
|
|
|
15
|
-
export { type
|
|
15
|
+
export { type Overlay, type OverlayOptions, mountOverlay };
|
package/dist/overlay.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Store } from './index.js';
|
|
2
2
|
import '@generative-a11y/core';
|
|
3
3
|
|
|
4
|
-
interface
|
|
5
|
-
readonly store:
|
|
4
|
+
interface OverlayOptions {
|
|
5
|
+
readonly store: Store;
|
|
6
6
|
readonly document?: Document;
|
|
7
7
|
readonly copyText?: (value: string) => void | Promise<void>;
|
|
8
8
|
}
|
|
9
|
-
interface
|
|
9
|
+
interface Overlay {
|
|
10
10
|
readonly host: HTMLElement;
|
|
11
11
|
dispose(): void;
|
|
12
12
|
}
|
|
13
|
-
declare function
|
|
13
|
+
declare function mountOverlay(options: OverlayOptions): Overlay;
|
|
14
14
|
|
|
15
|
-
export { type
|
|
15
|
+
export { type Overlay, type OverlayOptions, mountOverlay };
|
package/dist/overlay.js
CHANGED
|
@@ -187,28 +187,70 @@ function ScrollBar({
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
// src/inspector.tsx
|
|
190
|
-
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
190
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
191
191
|
var key = (record) => String(record.captureSequence);
|
|
192
192
|
var time = (value) => value >= 1e10 ? new Date(value).toISOString().slice(11, 23) : `+${(value / 1e3).toFixed(2)}s`;
|
|
193
193
|
var stage = (record) => record.kind === "event-observed" ? "Source evidence" : record.kind === "decision" ? "Runtime decision" : "DOM delivery";
|
|
194
194
|
var title = (record) => record.kind === "event-observed" ? record.sourceType ?? "Observed event" : record.kind === "dom-delivery" ? `${record.deliveryStatus ?? "Delivery"} via ${record.deliveryMethod ?? "browser"}` : record.reason ?? record.disposition ?? "Runtime decision";
|
|
195
|
-
function
|
|
195
|
+
function correlationKeys(record) {
|
|
196
196
|
const prefix = `${record.runtimeId}:`;
|
|
197
|
-
|
|
198
|
-
if (record.
|
|
199
|
-
|
|
200
|
-
if (record.toolId)
|
|
201
|
-
return `${prefix}tool:${record.toolId}:${record.sourceType ?? "unknown"}`;
|
|
197
|
+
const keys = /* @__PURE__ */ new Set();
|
|
198
|
+
if (record.sourceEventId) keys.add(`${prefix}event:${record.sourceEventId}`);
|
|
199
|
+
if (record.responseId) keys.add(`${prefix}response:${record.responseId}`);
|
|
200
|
+
if (record.toolId) keys.add(`${prefix}tool:${record.toolId}`);
|
|
202
201
|
if (record.interactionId)
|
|
203
|
-
|
|
204
|
-
if (record.approvalId)
|
|
202
|
+
keys.add(`${prefix}interaction:${record.interactionId}`);
|
|
203
|
+
if (record.approvalId) keys.add(`${prefix}approval:${record.approvalId}`);
|
|
205
204
|
if (record.announcementId)
|
|
206
|
-
|
|
207
|
-
|
|
205
|
+
keys.add(`${prefix}announcement:${record.announcementId}`);
|
|
206
|
+
if (record.runId)
|
|
207
|
+
keys.add(
|
|
208
|
+
`${prefix}run:${record.runId}:${record.runInstanceId ?? "unidentified"}`
|
|
209
|
+
);
|
|
210
|
+
if (record.runId && record.nextRunInstanceId)
|
|
211
|
+
keys.add(`${prefix}run:${record.runId}:${record.nextRunInstanceId}`);
|
|
212
|
+
if (record.parentRunId)
|
|
213
|
+
keys.add(
|
|
214
|
+
`${prefix}run:${record.parentRunId}:${record.parentRunInstanceId ?? "unidentified"}`
|
|
215
|
+
);
|
|
216
|
+
if (record.stepId)
|
|
217
|
+
keys.add(
|
|
218
|
+
`${prefix}step:${record.runId ?? "unknown"}:${record.runInstanceId ?? "unidentified"}:${record.stepId}:${record.stepInstanceId ?? "unidentified"}`
|
|
219
|
+
);
|
|
220
|
+
if (record.stepId && record.nextStepInstanceId)
|
|
221
|
+
keys.add(
|
|
222
|
+
`${prefix}step:${record.runId ?? "unknown"}:${record.runInstanceId ?? "unidentified"}:${record.stepId}:${record.nextStepInstanceId}`
|
|
223
|
+
);
|
|
224
|
+
if (record.parentStepId)
|
|
225
|
+
keys.add(
|
|
226
|
+
`${prefix}step:${record.runId ?? "unknown"}:${record.runInstanceId ?? "unidentified"}:${record.parentStepId}:${record.parentStepInstanceId ?? "unidentified"}`
|
|
227
|
+
);
|
|
228
|
+
if (record.parentToolId) keys.add(`${prefix}tool:${record.parentToolId}`);
|
|
229
|
+
if (record.parentResponseId)
|
|
230
|
+
keys.add(`${prefix}response:${record.parentResponseId}`);
|
|
231
|
+
if (keys.size === 0) keys.add(`${prefix}record:${record.captureSequence}`);
|
|
232
|
+
return [...keys];
|
|
233
|
+
}
|
|
234
|
+
function relatedRecords(records, selected) {
|
|
235
|
+
const related = /* @__PURE__ */ new Set();
|
|
236
|
+
const keys = new Set(correlationKeys(selected));
|
|
237
|
+
let changed = true;
|
|
238
|
+
while (changed) {
|
|
239
|
+
changed = false;
|
|
240
|
+
for (const record of records) {
|
|
241
|
+
if (related.has(record)) continue;
|
|
242
|
+
const recordKeys = correlationKeys(record);
|
|
243
|
+
if (!recordKeys.some((value) => keys.has(value))) continue;
|
|
244
|
+
related.add(record);
|
|
245
|
+
for (const value of recordKeys) keys.add(value);
|
|
246
|
+
changed = true;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return [...related];
|
|
208
250
|
}
|
|
209
251
|
function explain(record) {
|
|
210
252
|
if (record.kind === "event-observed")
|
|
211
|
-
return "The adapter supplied this normalized public lifecycle signal.";
|
|
253
|
+
return record.sourceType?.startsWith("attention.") ? "The host supplied an attention observation or explicit user override. Browser evidence does not establish what someone is reading." : "The adapter supplied this normalized public lifecycle signal.";
|
|
212
254
|
if (record.kind === "dom-delivery")
|
|
213
255
|
return record.deliveryStatus === "unavailable" ? "The DOM driver was unavailable, so no browser delivery action was observed." : "The DOM driver reported this delivery action.";
|
|
214
256
|
return {
|
|
@@ -216,6 +258,9 @@ function explain(record) {
|
|
|
216
258
|
coalesced: "The runtime merged this work with an existing queued announcement.",
|
|
217
259
|
duplicate: "The runtime suppressed a recently delivered duplicate.",
|
|
218
260
|
"policy-silent": "The active policy intentionally made this event silent.",
|
|
261
|
+
"catalog-format-error": "The host message formatter failed; the runtime used a generic English notice without retaining the error or parameters.",
|
|
262
|
+
"attention-quiet": "Quiet mode discarded routine output without retaining an announcement backlog.",
|
|
263
|
+
"attention-updated": "The runtime updated its attention observation or user override without announcing the control event.",
|
|
219
264
|
"queue-capacity": "The bounded queue rejected or displaced this work.",
|
|
220
265
|
"scope-cancelled": "The lifecycle scope ended before this queued work delivered.",
|
|
221
266
|
"runtime-disposed": "The runtime was disposed and cancelled remaining queued work.",
|
|
@@ -268,6 +313,12 @@ function Detail({
|
|
|
268
313
|
] }) });
|
|
269
314
|
const source = snapshot.runtimeSources[record.runtimeSourceId ?? record.runtimeId];
|
|
270
315
|
const runtime = snapshot.runtimeSnapshots[record.runtimeId];
|
|
316
|
+
const run = record.runInstanceId ? runtime?.runs?.find(
|
|
317
|
+
(item) => item.runId === record.runId && item.instanceId === record.runInstanceId
|
|
318
|
+
) : void 0;
|
|
319
|
+
const step = record.runInstanceId && record.stepInstanceId ? runtime?.steps?.find(
|
|
320
|
+
(item) => item.runId === record.runId && item.stepId === record.stepId && item.runInstanceId === record.runInstanceId && item.instanceId === record.stepInstanceId
|
|
321
|
+
) : void 0;
|
|
271
322
|
const deliveries = related.filter((item) => item.kind === "dom-delivery");
|
|
272
323
|
return /* @__PURE__ */ jsxs2("aside", { className: "ga-trace-detail", "data-testid": "trace-detail", children: [
|
|
273
324
|
/* @__PURE__ */ jsxs2("div", { className: "ga-detail-intro", children: [
|
|
@@ -280,6 +331,43 @@ function Detail({
|
|
|
280
331
|
/* @__PURE__ */ jsx5("p", { children: record.reason?.startsWith("stale") ? "Compare the instance with the current runtime snapshot." : "Inspect related evidence and queue context if this was unexpected." })
|
|
281
332
|
] }),
|
|
282
333
|
/* @__PURE__ */ jsx5(CausalChain, { records: related }),
|
|
334
|
+
record.runId ? /* @__PURE__ */ jsxs2("section", { className: "ga-detail-section", children: [
|
|
335
|
+
/* @__PURE__ */ jsx5("h4", { children: "Workflow hierarchy" }),
|
|
336
|
+
/* @__PURE__ */ jsxs2("dl", { className: "ga-key-values", children: [
|
|
337
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
338
|
+
/* @__PURE__ */ jsx5("dt", { children: "Run" }),
|
|
339
|
+
/* @__PURE__ */ jsx5("dd", { children: record.runId })
|
|
340
|
+
] }),
|
|
341
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
342
|
+
/* @__PURE__ */ jsx5("dt", { children: "Run attempt" }),
|
|
343
|
+
/* @__PURE__ */ jsx5("dd", { children: record.runInstanceId ?? run?.instanceId ?? "Not supplied" })
|
|
344
|
+
] }),
|
|
345
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
346
|
+
/* @__PURE__ */ jsx5("dt", { children: "Parent run" }),
|
|
347
|
+
/* @__PURE__ */ jsx5("dd", { children: record.parentRunId ?? run?.parentRunId ?? "None" })
|
|
348
|
+
] }),
|
|
349
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
350
|
+
/* @__PURE__ */ jsx5("dt", { children: "Run state" }),
|
|
351
|
+
/* @__PURE__ */ jsx5("dd", { children: run?.status ?? "Not retained" })
|
|
352
|
+
] }),
|
|
353
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
354
|
+
/* @__PURE__ */ jsx5("dt", { children: "Step" }),
|
|
355
|
+
/* @__PURE__ */ jsx5("dd", { children: record.stepId ?? "Partial identity" })
|
|
356
|
+
] }),
|
|
357
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
358
|
+
/* @__PURE__ */ jsx5("dt", { children: "Step attempt" }),
|
|
359
|
+
/* @__PURE__ */ jsx5("dd", { children: record.stepInstanceId ?? step?.instanceId ?? "Not supplied" })
|
|
360
|
+
] }),
|
|
361
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
362
|
+
/* @__PURE__ */ jsx5("dt", { children: "Parent step" }),
|
|
363
|
+
/* @__PURE__ */ jsx5("dd", { children: record.parentStepId ?? step?.parentStepId ?? "None" })
|
|
364
|
+
] }),
|
|
365
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
366
|
+
/* @__PURE__ */ jsx5("dt", { children: "Step state" }),
|
|
367
|
+
/* @__PURE__ */ jsx5("dd", { children: step?.status ?? "Not retained" })
|
|
368
|
+
] })
|
|
369
|
+
] })
|
|
370
|
+
] }) : null,
|
|
283
371
|
/* @__PURE__ */ jsxs2("section", { className: "ga-detail-section", children: [
|
|
284
372
|
/* @__PURE__ */ jsx5("h4", { children: "Source evidence" }),
|
|
285
373
|
source ? /* @__PURE__ */ jsxs2("dl", { className: "ga-key-values", children: [
|
|
@@ -287,6 +375,22 @@ function Detail({
|
|
|
287
375
|
/* @__PURE__ */ jsx5("dt", { children: "Adapter" }),
|
|
288
376
|
/* @__PURE__ */ jsx5("dd", { children: source.adapter })
|
|
289
377
|
] }),
|
|
378
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
379
|
+
/* @__PURE__ */ jsx5("dt", { children: "Runs" }),
|
|
380
|
+
/* @__PURE__ */ jsx5("dd", { children: source.fidelity.runs ?? "Not declared" })
|
|
381
|
+
] }),
|
|
382
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
383
|
+
/* @__PURE__ */ jsx5("dt", { children: "Steps" }),
|
|
384
|
+
/* @__PURE__ */ jsx5("dd", { children: source.fidelity.steps ?? "Not declared" })
|
|
385
|
+
] }),
|
|
386
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
387
|
+
/* @__PURE__ */ jsx5("dt", { children: "Hierarchy" }),
|
|
388
|
+
/* @__PURE__ */ jsx5("dd", { children: source.fidelity.hierarchy ?? "Not declared" })
|
|
389
|
+
] }),
|
|
390
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
391
|
+
/* @__PURE__ */ jsx5("dt", { children: "Replay" }),
|
|
392
|
+
/* @__PURE__ */ jsx5("dd", { children: source.fidelity.replay ?? "Not declared" })
|
|
393
|
+
] }),
|
|
290
394
|
/* @__PURE__ */ jsxs2("div", { children: [
|
|
291
395
|
/* @__PURE__ */ jsx5("dt", { children: "Interruption" }),
|
|
292
396
|
/* @__PURE__ */ jsx5("dd", { children: source.fidelity.interruption })
|
|
@@ -308,6 +412,30 @@ function Detail({
|
|
|
308
412
|
/* @__PURE__ */ jsxs2("section", { className: "ga-detail-section", children: [
|
|
309
413
|
/* @__PURE__ */ jsx5("h4", { children: "Policy and scheduling" }),
|
|
310
414
|
runtime ? /* @__PURE__ */ jsxs2("dl", { className: "ga-key-values", children: [
|
|
415
|
+
runtime.messages && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
416
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
417
|
+
/* @__PURE__ */ jsx5("dt", { children: "Announcement catalog" }),
|
|
418
|
+
/* @__PURE__ */ jsx5("dd", { children: runtime.messages.catalogId })
|
|
419
|
+
] }),
|
|
420
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
421
|
+
/* @__PURE__ */ jsx5("dt", { children: "Notice language" }),
|
|
422
|
+
/* @__PURE__ */ jsx5("dd", { children: runtime.messages.locale })
|
|
423
|
+
] })
|
|
424
|
+
] }),
|
|
425
|
+
runtime.attention && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
426
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
427
|
+
/* @__PURE__ */ jsx5("dt", { children: "Effective announcements" }),
|
|
428
|
+
/* @__PURE__ */ jsx5("dd", { children: runtime.attention.effective })
|
|
429
|
+
] }),
|
|
430
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
431
|
+
/* @__PURE__ */ jsx5("dt", { children: "Observed attention" }),
|
|
432
|
+
/* @__PURE__ */ jsx5("dd", { children: runtime.attention.observed })
|
|
433
|
+
] }),
|
|
434
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
435
|
+
/* @__PURE__ */ jsx5("dt", { children: "User override" }),
|
|
436
|
+
/* @__PURE__ */ jsx5("dd", { children: runtime.attention.override })
|
|
437
|
+
] })
|
|
438
|
+
] }),
|
|
311
439
|
/* @__PURE__ */ jsxs2("div", { children: [
|
|
312
440
|
/* @__PURE__ */ jsx5("dt", { children: "Queue" }),
|
|
313
441
|
/* @__PURE__ */ jsxs2("dd", { children: [
|
|
@@ -397,11 +525,7 @@ function List({
|
|
|
397
525
|
}
|
|
398
526
|
);
|
|
399
527
|
}
|
|
400
|
-
function
|
|
401
|
-
store,
|
|
402
|
-
onClose,
|
|
403
|
-
onCopy
|
|
404
|
-
}) {
|
|
528
|
+
function Inspector({ store, onClose, onCopy }) {
|
|
405
529
|
const snapshot = useSnapshot(store);
|
|
406
530
|
const reduceMotion = useReducedMotion();
|
|
407
531
|
const [query, setQuery] = React4.useState("");
|
|
@@ -419,13 +543,15 @@ function DevtoolsInspector({
|
|
|
419
543
|
record.responseId,
|
|
420
544
|
record.toolId,
|
|
421
545
|
record.interactionId,
|
|
422
|
-
record.approvalId
|
|
546
|
+
record.approvalId,
|
|
547
|
+
record.runId,
|
|
548
|
+
record.runInstanceId,
|
|
549
|
+
record.stepId,
|
|
550
|
+
record.stepInstanceId
|
|
423
551
|
].filter(Boolean).join(" ").toLowerCase().includes(query.trim().toLowerCase())
|
|
424
552
|
).slice().reverse();
|
|
425
553
|
const selected = visible.find((record) => key(record) === selectedKey) ?? visible[0];
|
|
426
|
-
const related = selected ? snapshot.records
|
|
427
|
-
(record) => correlation(record) === correlation(selected)
|
|
428
|
-
) : [];
|
|
554
|
+
const related = selected ? relatedRecords(snapshot.records, selected) : [];
|
|
429
555
|
React4.useEffect(
|
|
430
556
|
() => () => {
|
|
431
557
|
if (feedbackTimer.current !== void 0)
|
|
@@ -705,7 +831,7 @@ button:focus-visible, input:focus-visible, [role="listbox"]:focus-visible, [role
|
|
|
705
831
|
.ga-workspace-feedback { top: 68px; color: #f7f7f7; background: #111; border-color: #111; border-radius: 3px; box-shadow: none; }
|
|
706
832
|
@media (max-width: 760px) { .ga-bottom-dock { height: min(720px, 80vh); } .ga-inspector-header, .ga-session-toolbar { padding-right: 12px; padding-left: 12px; } .ga-session-toolbar { flex-wrap: wrap; } .ga-inspector-search { width: 100%; } .ga-session-count { margin-left: 0; } .ga-explorer-layout { flex-direction: column; } [data-slot="resizable-handle"] { width: 100%; height: 1px; } .ga-trace-row { grid-template-columns: 70px 1fr; padding: 8px 12px; } .ga-trace-row span, .ga-trace-row code { grid-column: 2; } .ga-trace-detail { padding: 18px 12px; } .ga-key-values { grid-template-columns: 1fr; } .ga-key-values-wide { grid-column: auto; } }
|
|
707
833
|
`;
|
|
708
|
-
function
|
|
834
|
+
function mountOverlay(options) {
|
|
709
835
|
const selectedDocument = options.document ?? (typeof document === "undefined" ? void 0 : document);
|
|
710
836
|
if (!selectedDocument?.body)
|
|
711
837
|
throw new Error("A mountable document is required");
|
|
@@ -760,7 +886,7 @@ function mountDevtoolsOverlay(options) {
|
|
|
760
886
|
return clipboard.writeText(value);
|
|
761
887
|
});
|
|
762
888
|
root.render(
|
|
763
|
-
createElement(
|
|
889
|
+
createElement(Inspector, {
|
|
764
890
|
onClose: close,
|
|
765
891
|
onCopy: copyText,
|
|
766
892
|
store: options.store
|
|
@@ -798,5 +924,5 @@ function mountDevtoolsOverlay(options) {
|
|
|
798
924
|
};
|
|
799
925
|
}
|
|
800
926
|
export {
|
|
801
|
-
|
|
927
|
+
mountOverlay
|
|
802
928
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@generative-a11y/devtools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Development-only accessibility diagnostics and a redacted trace explorer for screen-reader announcements in AI runtimes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|
|
@@ -56,11 +56,11 @@
|
|
|
56
56
|
"class-variance-authority": "0.7.1",
|
|
57
57
|
"clsx": "2.1.1",
|
|
58
58
|
"lucide-react": "1.31.0",
|
|
59
|
-
"motion": "^
|
|
59
|
+
"motion": "^13.1.1",
|
|
60
60
|
"radix-ui": "1.6.7",
|
|
61
61
|
"react-resizable-panels": "^4.12.3",
|
|
62
62
|
"tailwind-merge": "3.6.0",
|
|
63
|
-
"@generative-a11y/core": "0.
|
|
63
|
+
"@generative-a11y/core": "0.4.0"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
66
|
"react": "^19.0.0",
|