@oddsquad/vite-plugin-lit 0.2.3 → 0.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/CHANGELOG.md +64 -0
- package/LICENSE +28 -0
- package/README.md +153 -0
- package/bin.mjs +154 -0
- package/client.d.ts +61 -0
- package/dist/client/assets/browser-agent-rpc-BXhoSh1z-BvWe4sTJ.js +69 -0
- package/dist/client/assets/browser-agent-rpc-BXhoSh1z-BvWe4sTJ.js.map +1 -0
- package/dist/client/assets/index-CFrVgNfS.js +9740 -0
- package/dist/client/assets/index-CFrVgNfS.js.map +1 -0
- package/{panel → dist/client}/index.html +1 -0
- package/index.d.ts.map +1 -1
- package/index.js +2 -2
- package/index.js.map +1 -1
- package/lib/color-scheme.d.ts.map +1 -1
- package/lib/color-scheme.js +17 -21
- package/lib/color-scheme.js.map +1 -1
- package/lib/devframe/definition.d.ts +45 -0
- package/lib/devframe/definition.d.ts.map +1 -0
- package/lib/devframe/definition.js +547 -0
- package/lib/devframe/definition.js.map +1 -0
- package/lib/devframe/icon.d.ts +8 -0
- package/lib/devframe/icon.d.ts.map +1 -0
- package/lib/devframe/icon.js +21 -0
- package/lib/devframe/icon.js.map +1 -0
- package/lib/devframe/paths.d.ts +12 -0
- package/lib/devframe/paths.d.ts.map +1 -0
- package/lib/devframe/paths.js +38 -0
- package/lib/devframe/paths.js.map +1 -0
- package/lib/devframe/protocol.d.ts +218 -0
- package/lib/devframe/protocol.d.ts.map +1 -0
- package/lib/devframe/protocol.js +76 -0
- package/lib/devframe/protocol.js.map +1 -0
- package/lib/devframe/source.d.ts +49 -0
- package/lib/devframe/source.d.ts.map +1 -0
- package/lib/devframe/source.js +23 -0
- package/lib/devframe/source.js.map +1 -0
- package/lib/devframe/vite.d.ts +116 -0
- package/lib/devframe/vite.d.ts.map +1 -0
- package/lib/devframe/vite.js +291 -0
- package/lib/devframe/vite.js.map +1 -0
- package/lib/http.d.ts +29 -0
- package/lib/http.d.ts.map +1 -0
- package/lib/http.js +35 -0
- package/lib/http.js.map +1 -0
- package/lib/icons.d.ts +2 -0
- package/lib/icons.d.ts.map +1 -1
- package/lib/icons.js +10 -4
- package/lib/icons.js.map +1 -1
- package/lib/plugin.d.ts +15 -4
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +640 -574
- package/lib/plugin.js.map +1 -1
- package/lib/runtime/css.d.ts +2 -2
- package/lib/runtime/css.d.ts.map +1 -1
- package/lib/runtime/css.js +34 -34
- package/lib/runtime/css.js.map +1 -1
- package/lib/runtime/edge-panel.d.ts.map +1 -1
- package/lib/runtime/edge-panel.js +82 -91
- package/lib/runtime/edge-panel.js.map +1 -1
- package/lib/runtime/fonts.d.ts.map +1 -1
- package/lib/runtime/fonts.js +1 -1
- package/lib/runtime/fonts.js.map +1 -1
- package/lib/runtime/indicator.d.ts.map +1 -1
- package/lib/runtime/indicator.js +71 -74
- package/lib/runtime/indicator.js.map +1 -1
- package/lib/runtime/inspector/collect.d.ts.map +1 -1
- package/lib/runtime/inspector/collect.js +83 -90
- package/lib/runtime/inspector/collect.js.map +1 -1
- package/lib/runtime/inspector/highlight.d.ts +16 -0
- package/lib/runtime/inspector/highlight.d.ts.map +1 -0
- package/lib/runtime/inspector/highlight.js +66 -0
- package/lib/runtime/inspector/highlight.js.map +1 -0
- package/lib/runtime/inspector/install.d.ts.map +1 -1
- package/lib/runtime/inspector/install.js +180 -205
- package/lib/runtime/inspector/install.js.map +1 -1
- package/lib/runtime/inspector/serialize.d.ts.map +1 -1
- package/lib/runtime/inspector/serialize.js +86 -107
- package/lib/runtime/inspector/serialize.js.map +1 -1
- package/lib/runtime/intern.d.ts.map +1 -1
- package/lib/runtime/intern.js +31 -29
- package/lib/runtime/intern.js.map +1 -1
- package/lib/runtime/overrides.d.ts.map +1 -1
- package/lib/runtime/overrides.js +14 -13
- package/lib/runtime/overrides.js.map +1 -1
- package/lib/runtime/patch.d.ts +8 -0
- package/lib/runtime/patch.d.ts.map +1 -1
- package/lib/runtime/patch.js +321 -282
- package/lib/runtime/patch.js.map +1 -1
- package/lib/runtime/source-meta.d.ts.map +1 -1
- package/lib/runtime/source-meta.js +1 -1
- package/lib/runtime/source-meta.js.map +1 -1
- package/lib/runtime/source-overlay/editors.d.ts.map +1 -1
- package/lib/runtime/source-overlay/editors.js +27 -27
- package/lib/runtime/source-overlay/editors.js.map +1 -1
- package/lib/runtime/source-overlay/mask-path.d.ts.map +1 -1
- package/lib/runtime/source-overlay/mask-path.js +15 -15
- package/lib/runtime/source-overlay/mask-path.js.map +1 -1
- package/lib/runtime/source-overlay/overlay-element.d.ts.map +1 -1
- package/lib/runtime/source-overlay/overlay-element.js +347 -356
- package/lib/runtime/source-overlay/overlay-element.js.map +1 -1
- package/lib/runtime/source-overlay/source-host.d.ts.map +1 -1
- package/lib/runtime/source-overlay/source-host.js +64 -71
- package/lib/runtime/source-overlay/source-host.js.map +1 -1
- package/lib/runtime/source-overlay/template.d.ts.map +1 -1
- package/lib/runtime/source-overlay/template.js +3 -3
- package/lib/runtime/source-overlay/template.js.map +1 -1
- package/lib/runtime/source-overlay.d.ts.map +1 -1
- package/lib/runtime/source-overlay.js +5 -2
- package/lib/runtime/source-overlay.js.map +1 -1
- package/lib/runtime/timeline/clock.d.ts.map +1 -1
- package/lib/runtime/timeline/clock.js +2 -2
- package/lib/runtime/timeline/clock.js.map +1 -1
- package/lib/runtime/timeline/flash.d.ts +39 -0
- package/lib/runtime/timeline/flash.d.ts.map +1 -0
- package/lib/runtime/timeline/flash.js +169 -0
- package/lib/runtime/timeline/flash.js.map +1 -0
- package/lib/runtime/timeline/identity.d.ts.map +1 -1
- package/lib/runtime/timeline/identity.js +27 -27
- package/lib/runtime/timeline/identity.js.map +1 -1
- package/lib/runtime/timeline/input.d.ts.map +1 -1
- package/lib/runtime/timeline/input.js +54 -67
- package/lib/runtime/timeline/input.js.map +1 -1
- package/lib/runtime/timeline/install.d.ts.map +1 -1
- package/lib/runtime/timeline/install.js +38 -29
- package/lib/runtime/timeline/install.js.map +1 -1
- package/lib/runtime/timeline/lifecycle.d.ts +8 -0
- package/lib/runtime/timeline/lifecycle.d.ts.map +1 -1
- package/lib/runtime/timeline/lifecycle.js +149 -133
- package/lib/runtime/timeline/lifecycle.js.map +1 -1
- package/lib/runtime/timeline/public-api.d.ts.map +1 -1
- package/lib/runtime/timeline/public-api.js +9 -9
- package/lib/runtime/timeline/public-api.js.map +1 -1
- package/lib/runtime/timeline/render.d.ts.map +1 -1
- package/lib/runtime/timeline/render.js +70 -75
- package/lib/runtime/timeline/render.js.map +1 -1
- package/lib/runtime/timeline/transport.d.ts.map +1 -1
- package/lib/runtime/timeline/transport.js +39 -43
- package/lib/runtime/timeline/transport.js.map +1 -1
- package/lib/segmented-tabs.d.ts +3 -1
- package/lib/segmented-tabs.d.ts.map +1 -1
- package/lib/segmented-tabs.js +136 -107
- package/lib/segmented-tabs.js.map +1 -1
- package/lib/snapshot.d.ts +28 -0
- package/lib/snapshot.d.ts.map +1 -0
- package/lib/snapshot.js +57 -0
- package/lib/snapshot.js.map +1 -0
- package/lib/source-meta.d.ts.map +1 -1
- package/lib/source-meta.js +176 -162
- package/lib/source-meta.js.map +1 -1
- package/lib/timeline/derive.d.ts +152 -0
- package/lib/timeline/derive.d.ts.map +1 -0
- package/lib/timeline/derive.js +242 -0
- package/lib/timeline/derive.js.map +1 -0
- package/lib/timeline-plugin.d.ts.map +1 -1
- package/lib/timeline-plugin.js +304 -321
- package/lib/timeline-plugin.js.map +1 -1
- package/lib/tokens.d.ts.map +1 -1
- package/lib/tokens.js +17 -18
- package/lib/tokens.js.map +1 -1
- package/lib/transform.d.ts.map +1 -1
- package/lib/transform.js +62 -57
- package/lib/transform.js.map +1 -1
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +1 -1
- package/lib/types.js.map +1 -1
- package/lib/wrap-table.d.ts.map +1 -1
- package/lib/wrap-table.js +19 -17
- package/lib/wrap-table.js.map +1 -1
- package/package.json +77 -13
- package/types/hmr-incompatibility.d.ts +59 -0
- package/types/hmr-incompatibility.d.ts.map +1 -0
- package/types/hmr-incompatibility.js +30 -0
- package/types/hmr-incompatibility.js.map +1 -0
- package/types/in-page.d.ts +49 -0
- package/types/in-page.d.ts.map +1 -0
- package/types/in-page.js +33 -0
- package/types/in-page.js.map +1 -0
- package/types/inspector.d.ts.map +1 -1
- package/types/inspector.js.map +1 -1
- package/types/snapshot.d.ts +44 -0
- package/types/snapshot.d.ts.map +1 -0
- package/types/snapshot.js +7 -0
- package/types/snapshot.js.map +1 -0
- package/types/timeline.d.ts +11 -0
- package/types/timeline.d.ts.map +1 -1
- package/types/timeline.js.map +1 -1
- package/panel/components-view.d.ts +0 -60
- package/panel/components-view.d.ts.map +0 -1
- package/panel/components-view.js +0 -587
- package/panel/components-view.js.map +0 -1
- package/panel/devtools-settings.d.ts +0 -41
- package/panel/devtools-settings.d.ts.map +0 -1
- package/panel/devtools-settings.js +0 -463
- package/panel/devtools-settings.js.map +0 -1
- package/panel/lit-devtools-panel.d.ts +0 -37
- package/panel/lit-devtools-panel.d.ts.map +0 -1
- package/panel/lit-devtools-panel.js +0 -185
- package/panel/lit-devtools-panel.js.map +0 -1
- package/panel/timeline-event-list.d.ts +0 -43
- package/panel/timeline-event-list.d.ts.map +0 -1
- package/panel/timeline-event-list.js +0 -416
- package/panel/timeline-event-list.js.map +0 -1
- package/panel/timeline-layers.d.ts +0 -25
- package/panel/timeline-layers.d.ts.map +0 -1
- package/panel/timeline-layers.js +0 -96
- package/panel/timeline-layers.js.map +0 -1
- package/panel/timeline-view.d.ts +0 -38
- package/panel/timeline-view.d.ts.map +0 -1
- package/panel/timeline-view.js +0 -234
- package/panel/timeline-view.js.map +0 -1
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* The framework-neutral Lit devframe: RPC functions, shared state, and the
|
|
8
|
+
* timeline stream. Talks to the page runtime only through the injected
|
|
9
|
+
* {@link TimelineSource} port, so it runs unchanged under `createDevServer()`,
|
|
10
|
+
* `createBuild()`, or an MCP server with no Vite in the loop. `vite.ts` wires
|
|
11
|
+
* the real page-runtime bridge and mounts this via `createPluginFromDevframe`.
|
|
12
|
+
*
|
|
13
|
+
* @see plans/devframe-foundation.md
|
|
14
|
+
*/
|
|
15
|
+
import {defineDevframe, defineRpcFunction} from 'devframe';
|
|
16
|
+
import {TIMELINE_LAYERS} from '../../types/timeline.js';
|
|
17
|
+
import {MAX_HMR_INCOMPATIBILITIES} from '../../types/hmr-incompatibility.js';
|
|
18
|
+
import {LIT_LOGO_ICON} from './icon.js';
|
|
19
|
+
import {PANEL_DIST_DIR} from './paths.js';
|
|
20
|
+
import {
|
|
21
|
+
DEFAULT_SESSION_STATE,
|
|
22
|
+
LAYER_FLAGS,
|
|
23
|
+
LIT_DEVFRAME_ID,
|
|
24
|
+
RECENT_EVENTS_BUFFER_SIZE,
|
|
25
|
+
RPC_COMPONENT_DETAILS,
|
|
26
|
+
RPC_GET_META,
|
|
27
|
+
RPC_HMR_INCOMPATIBILITIES,
|
|
28
|
+
RPC_HMR_INCOMPATIBLE,
|
|
29
|
+
RPC_INSPECT,
|
|
30
|
+
RPC_INSPECTOR_MESSAGE,
|
|
31
|
+
RPC_LIST_COMPONENTS,
|
|
32
|
+
RPC_RECENT_EVENTS,
|
|
33
|
+
RPC_SET_RECORDING,
|
|
34
|
+
RPC_EXPORT_SNAPSHOT,
|
|
35
|
+
RPC_OPEN_SOURCE,
|
|
36
|
+
RPC_SET_SETTINGS_OVERRIDE,
|
|
37
|
+
RPC_TOGGLE_LAYER,
|
|
38
|
+
RPC_UPDATE_SUMMARY,
|
|
39
|
+
SESSION_STATE_KEY,
|
|
40
|
+
TIMELINE_STREAM_ID,
|
|
41
|
+
TIMELINE_STREAM_NAME,
|
|
42
|
+
} from './protocol.js';
|
|
43
|
+
import {
|
|
44
|
+
attributeInput,
|
|
45
|
+
rollup,
|
|
46
|
+
toSpans,
|
|
47
|
+
toUpdateCycles,
|
|
48
|
+
} from '../timeline/derive.js';
|
|
49
|
+
import {createNullSource} from './source.js';
|
|
50
|
+
/**
|
|
51
|
+
* Builds the Lit devframe definition. Framework-neutral: everything here
|
|
52
|
+
* runs the same whether the host is Vite (`vite.ts`), a standalone dev
|
|
53
|
+
* server, a static build, or an MCP server.
|
|
54
|
+
*/
|
|
55
|
+
export function createLitDevframe(options) {
|
|
56
|
+
const {source, version, features, replay, sourceRoot} = options;
|
|
57
|
+
return defineDevframe({
|
|
58
|
+
id: LIT_DEVFRAME_ID,
|
|
59
|
+
name: 'Lit',
|
|
60
|
+
description: 'Timeline recorder and component inspector for Lit apps.',
|
|
61
|
+
version,
|
|
62
|
+
packageName: '@oddsquad/vite-plugin-lit',
|
|
63
|
+
homepage: 'https://oddcelot.github.io/vite-plugin-lit/',
|
|
64
|
+
importMetaUrl: import.meta.url,
|
|
65
|
+
icon: LIT_LOGO_ICON,
|
|
66
|
+
dock: {category: 'framework'},
|
|
67
|
+
clientAssets: options.clientAssets ?? PANEL_DIST_DIR,
|
|
68
|
+
// `component-details` takes an id, so `snapshot: true` (which bakes the
|
|
69
|
+
// no-argument call) cannot express it. Bake one record per component the
|
|
70
|
+
// session actually opened -- the only ids that have details to freeze.
|
|
71
|
+
rpc: replay
|
|
72
|
+
? {
|
|
73
|
+
snapshot: [
|
|
74
|
+
{
|
|
75
|
+
method: `${LIT_DEVFRAME_ID}:${RPC_COMPONENT_DETAILS}`,
|
|
76
|
+
inputs: replay.details.map((d) => [{id: d.id}]),
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
}
|
|
80
|
+
: undefined,
|
|
81
|
+
async setup(ctx) {
|
|
82
|
+
const my = ctx.scope(LIT_DEVFRAME_ID);
|
|
83
|
+
// Bind the per-user settings store before any panel can connect.
|
|
84
|
+
// Both sides build it lazily on first access, but only this one backs
|
|
85
|
+
// it with a JSON file -- a client that asks first gets a plain
|
|
86
|
+
// in-memory shared state instead, so the panel's preferences would
|
|
87
|
+
// round-trip happily and then vanish on restart. The panel is the only
|
|
88
|
+
// thing that reads or writes these (see `panel/devtools-settings.ts`);
|
|
89
|
+
// this call exists purely to make them durable.
|
|
90
|
+
await my.settings.global.all();
|
|
91
|
+
const session = await my.rpc.sharedState(SESSION_STATE_KEY, {
|
|
92
|
+
initialValue: replay
|
|
93
|
+
? {
|
|
94
|
+
...DEFAULT_SESSION_STATE,
|
|
95
|
+
// Recorded events carry layer ids; without the custom layers
|
|
96
|
+
// that produced them the frozen panel would show a filter it
|
|
97
|
+
// cannot name.
|
|
98
|
+
customLayers: replay.customLayers,
|
|
99
|
+
}
|
|
100
|
+
: DEFAULT_SESSION_STATE,
|
|
101
|
+
});
|
|
102
|
+
// Latest inspector snapshot, cached so a panel that (re)connects after
|
|
103
|
+
// the runtime already answered can read it without round-tripping to
|
|
104
|
+
// the page again. Pre-filled when replaying: there is no page to ask.
|
|
105
|
+
let cachedRoots = replay ? [...replay.roots] : [];
|
|
106
|
+
const cachedDetails = new Map(replay?.details.map((d) => [d.id, d]));
|
|
107
|
+
// Bounded history for the `recent-events` agent query. A plain array,
|
|
108
|
+
// not devframe's internal per-stream replay buffer, which devframe
|
|
109
|
+
// marks `@internal` (see plans/roadmap/02-agent-timeline-access.md).
|
|
110
|
+
const recentEvents = replay ? [...replay.events] : [];
|
|
111
|
+
// Recent HMR-incompatibility notices, capped the same way
|
|
112
|
+
// `runtime/timeline/transport.ts` caps its pending queue — a long
|
|
113
|
+
// session with many failing edits must not grow this forever.
|
|
114
|
+
const hmrIncompatibilities = replay
|
|
115
|
+
? [...replay.hmrIncompatibilities]
|
|
116
|
+
: [];
|
|
117
|
+
// Terminal echo for an audience that only sees dev-server stdout (an
|
|
118
|
+
// agent, or a CI log) and not the browser console or the panel.
|
|
119
|
+
// Fire-and-log only — the cache above is the read-back store.
|
|
120
|
+
const hmrDiagnostics = ctx.diagnostics.defineDiagnostics({
|
|
121
|
+
docsBase:
|
|
122
|
+
'https://oddcelot.github.io/vite-plugin-lit/reference/limitations/',
|
|
123
|
+
codes: {
|
|
124
|
+
LIT_HMR_ACCESSOR: {
|
|
125
|
+
why: (p) =>
|
|
126
|
+
`<${p.tagName}> can't be hot-patched: standard accessor decorators`,
|
|
127
|
+
docs: 'https://oddcelot.github.io/vite-plugin-lit/reference/limitations/#cannot-be-patched-in-place',
|
|
128
|
+
},
|
|
129
|
+
LIT_HMR_PATCH_FAILED: {
|
|
130
|
+
why: (p) => `<${p.tagName}> can't be hot-patched: ${p.detail}`,
|
|
131
|
+
docs: 'https://oddcelot.github.io/vite-plugin-lit/reference/limitations/#cannot-be-patched-in-place',
|
|
132
|
+
},
|
|
133
|
+
LIT_HMR_ATTRS_CHANGED: {
|
|
134
|
+
why: (p) =>
|
|
135
|
+
`<${p.tagName}> changed observedAttributes; reload recommended`,
|
|
136
|
+
docs: 'https://oddcelot.github.io/vite-plugin-lit/reference/limitations/#cannot-be-patched-in-place',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
ctx.diagnostics.register(hmrDiagnostics);
|
|
141
|
+
// Streaming/source wiring only makes sense for a live session: a
|
|
142
|
+
// static build or MCP run has no page attached (its `source` is a
|
|
143
|
+
// `createNullSource()`), and `ctx.mode` is 'build' there.
|
|
144
|
+
if (ctx.mode === 'dev') {
|
|
145
|
+
const channel = my.rpc.streaming.create(TIMELINE_STREAM_NAME, {
|
|
146
|
+
replayWindow: 512,
|
|
147
|
+
});
|
|
148
|
+
// Started eagerly, not on the first event: `streaming:subscribe` is
|
|
149
|
+
// fire-and-forget on the wire, and a subscribe naming a stream id
|
|
150
|
+
// that does not exist yet is dropped with a DF0030 diagnostic rather
|
|
151
|
+
// than queued. The panel subscribes as soon as it connects, which is
|
|
152
|
+
// normally long before the first event, so the stream has to be
|
|
153
|
+
// there waiting. `??` covers a re-start if the transport aborted it
|
|
154
|
+
// after the last subscriber left.
|
|
155
|
+
channel.start({id: TIMELINE_STREAM_ID});
|
|
156
|
+
const ensureStream = () =>
|
|
157
|
+
channel.get(TIMELINE_STREAM_ID) ??
|
|
158
|
+
channel.start({id: TIMELINE_STREAM_ID});
|
|
159
|
+
source.attach({
|
|
160
|
+
pushEvents(events) {
|
|
161
|
+
if (events.length === 0) return;
|
|
162
|
+
ensureStream().write(events);
|
|
163
|
+
recentEvents.push(...events);
|
|
164
|
+
if (recentEvents.length > RECENT_EVENTS_BUFFER_SIZE) {
|
|
165
|
+
recentEvents.splice(
|
|
166
|
+
0,
|
|
167
|
+
recentEvents.length - RECENT_EVENTS_BUFFER_SIZE
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
addLayer(layer) {
|
|
172
|
+
session.mutate((state) => {
|
|
173
|
+
if (
|
|
174
|
+
!state.customLayers.some((existing) => existing.id === layer.id)
|
|
175
|
+
) {
|
|
176
|
+
state.customLayers.push(layer);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
},
|
|
180
|
+
inspectorMessage(message) {
|
|
181
|
+
if (message.type === 'tree') {
|
|
182
|
+
cachedRoots = message.roots;
|
|
183
|
+
} else if (message.type === 'details') {
|
|
184
|
+
cachedDetails.set(message.details.id, message.details);
|
|
185
|
+
} else if (message.type === 'gone') {
|
|
186
|
+
cachedDetails.delete(message.id);
|
|
187
|
+
}
|
|
188
|
+
void ctx.rpc.broadcast({
|
|
189
|
+
method: `${LIT_DEVFRAME_ID}:${RPC_INSPECTOR_MESSAGE}`,
|
|
190
|
+
args: [message],
|
|
191
|
+
// A page can be open with no panel docked; the runtime keeps
|
|
192
|
+
// answering either way, so a broadcast with no listener is
|
|
193
|
+
// normal rather than a missing-function error.
|
|
194
|
+
optional: true,
|
|
195
|
+
});
|
|
196
|
+
},
|
|
197
|
+
runtimeReady() {
|
|
198
|
+
// A new page means a new timeline clock: the runtime re-zeroes on
|
|
199
|
+
// the rising edge below, so events kept from the previous document
|
|
200
|
+
// would sit in the same buffer on a different time origin and make
|
|
201
|
+
// `recent-events`' `sinceMs` window meaningless. They also describe
|
|
202
|
+
// a page that no longer exists.
|
|
203
|
+
recentEvents.length = 0;
|
|
204
|
+
// Replay current state to a runtime that just booted from its
|
|
205
|
+
// defaults. Unconditional: `setRecording(false)` on a fresh page
|
|
206
|
+
// is a no-op.
|
|
207
|
+
const {layers} = session.value();
|
|
208
|
+
source.setLayers(layers);
|
|
209
|
+
source.setRecording(layers.recordingState);
|
|
210
|
+
},
|
|
211
|
+
hmrIncompatible(event) {
|
|
212
|
+
hmrIncompatibilities.push(event);
|
|
213
|
+
if (hmrIncompatibilities.length > MAX_HMR_INCOMPATIBILITIES) {
|
|
214
|
+
hmrIncompatibilities.splice(
|
|
215
|
+
0,
|
|
216
|
+
hmrIncompatibilities.length - MAX_HMR_INCOMPATIBILITIES
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
void ctx.rpc.broadcast({
|
|
220
|
+
method: `${LIT_DEVFRAME_ID}:${RPC_HMR_INCOMPATIBLE}`,
|
|
221
|
+
args: [event],
|
|
222
|
+
optional: true,
|
|
223
|
+
});
|
|
224
|
+
// Informational terminal echo, never a thrown error.
|
|
225
|
+
if (event.reason.code === 'accessor-decorators') {
|
|
226
|
+
hmrDiagnostics.LIT_HMR_ACCESSOR({tagName: event.tagName});
|
|
227
|
+
} else if (event.reason.code === 'patch-failed') {
|
|
228
|
+
hmrDiagnostics.LIT_HMR_PATCH_FAILED({
|
|
229
|
+
tagName: event.tagName,
|
|
230
|
+
detail: event.reason.detail,
|
|
231
|
+
});
|
|
232
|
+
} else {
|
|
233
|
+
hmrDiagnostics.LIT_HMR_ATTRS_CHANGED({tagName: event.tagName});
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
});
|
|
237
|
+
// Single push point for recording/layer changes: fires for the
|
|
238
|
+
// `set-recording` / `toggle-layer` actions below and for a panel
|
|
239
|
+
// mutating shared state directly through devframe's generic
|
|
240
|
+
// shared-state RPC. Immer only emits when the state reference
|
|
241
|
+
// changes, so a no-op mutate sends nothing.
|
|
242
|
+
//
|
|
243
|
+
// Clearing on the rising edge belongs here rather than in
|
|
244
|
+
// `set-recording` for the same reason: the runtime re-zeroes its
|
|
245
|
+
// timeline clock when recording turns on (`runtime/timeline/clock.ts`),
|
|
246
|
+
// so events kept from the previous recording sit in the buffer on a
|
|
247
|
+
// larger time origin than everything captured after them. A `sinceMs`
|
|
248
|
+
// window reads them as the future, and pairing a start with its end
|
|
249
|
+
// across the seam yields a negative duration. Same rationale as
|
|
250
|
+
// `runtimeReady()` above, one level finer: a new clock, not a new page.
|
|
251
|
+
let wasRecording = session.value().layers.recordingState;
|
|
252
|
+
session.on('updated', (state) => {
|
|
253
|
+
const {recordingState} = state.layers;
|
|
254
|
+
if (recordingState && !wasRecording) {
|
|
255
|
+
recentEvents.length = 0;
|
|
256
|
+
}
|
|
257
|
+
wasRecording = recordingState;
|
|
258
|
+
source.setRecording(recordingState);
|
|
259
|
+
source.setLayers(state.layers);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
my.rpc.register(
|
|
263
|
+
defineRpcFunction({
|
|
264
|
+
name: RPC_GET_META,
|
|
265
|
+
type: 'query',
|
|
266
|
+
jsonSerializable: true,
|
|
267
|
+
snapshot: true,
|
|
268
|
+
agent: {
|
|
269
|
+
description:
|
|
270
|
+
'Get the plugin version, active timeline layers, and resolved feature settings. Call once at the start of a session to learn what timeline layers exist before asking about events.',
|
|
271
|
+
},
|
|
272
|
+
handler: async () => ({
|
|
273
|
+
version,
|
|
274
|
+
// `.value()` returns a deep-readonly snapshot; copy so callers
|
|
275
|
+
// get a plain, mutable `TimelineLayer[]`.
|
|
276
|
+
layers: [...TIMELINE_LAYERS, ...session.value().customLayers],
|
|
277
|
+
features: features ? features() : null,
|
|
278
|
+
stream: {
|
|
279
|
+
channel: `${LIT_DEVFRAME_ID}:${TIMELINE_STREAM_NAME}`,
|
|
280
|
+
id: TIMELINE_STREAM_ID,
|
|
281
|
+
},
|
|
282
|
+
}),
|
|
283
|
+
})
|
|
284
|
+
);
|
|
285
|
+
my.rpc.register(
|
|
286
|
+
defineRpcFunction({
|
|
287
|
+
name: RPC_LIST_COMPONENTS,
|
|
288
|
+
type: 'query',
|
|
289
|
+
jsonSerializable: true,
|
|
290
|
+
// Baked into a static snapshot: takes no required arguments, and
|
|
291
|
+
// by export time its answer is exactly what the session recorded.
|
|
292
|
+
snapshot: true,
|
|
293
|
+
agent: {
|
|
294
|
+
description:
|
|
295
|
+
'List the live Lit component tree of the inspected page. Call this before asking about a specific element to find its id.',
|
|
296
|
+
},
|
|
297
|
+
handler: async () => cachedRoots,
|
|
298
|
+
})
|
|
299
|
+
);
|
|
300
|
+
my.rpc.register(
|
|
301
|
+
defineRpcFunction({
|
|
302
|
+
name: RPC_HMR_INCOMPATIBILITIES,
|
|
303
|
+
type: 'query',
|
|
304
|
+
jsonSerializable: true,
|
|
305
|
+
// Baked into a static snapshot: takes no required arguments, and
|
|
306
|
+
// by export time its answer is exactly what the session recorded.
|
|
307
|
+
snapshot: true,
|
|
308
|
+
agent: {
|
|
309
|
+
description:
|
|
310
|
+
"List recent components the Lit plugin could not hot-patch in place, and why. Call this after an unexplained full-page reload during development, or when a component's state resets unexpectedly on edit.",
|
|
311
|
+
},
|
|
312
|
+
handler: async () => hmrIncompatibilities,
|
|
313
|
+
})
|
|
314
|
+
);
|
|
315
|
+
my.rpc.register(
|
|
316
|
+
defineRpcFunction({
|
|
317
|
+
name: RPC_COMPONENT_DETAILS,
|
|
318
|
+
type: 'query',
|
|
319
|
+
jsonSerializable: true,
|
|
320
|
+
agent: {
|
|
321
|
+
description:
|
|
322
|
+
'Get reactive properties, attributes, and internal state for one component by id. Call list-components first to find the id.',
|
|
323
|
+
},
|
|
324
|
+
handler: async (args) => cachedDetails.get(args.id) ?? null,
|
|
325
|
+
})
|
|
326
|
+
);
|
|
327
|
+
my.rpc.register(
|
|
328
|
+
defineRpcFunction({
|
|
329
|
+
name: RPC_RECENT_EVENTS,
|
|
330
|
+
type: 'query',
|
|
331
|
+
jsonSerializable: true,
|
|
332
|
+
// Baked into a static snapshot: takes no required arguments, and
|
|
333
|
+
// by export time its answer is exactly what the session recorded.
|
|
334
|
+
snapshot: true,
|
|
335
|
+
agent: {
|
|
336
|
+
description:
|
|
337
|
+
'Get recent timeline events (lifecycle, render, mouse, keyboard) to diagnose why a component re-rendered or updated. Call list-components first to find an element’s id, then filter by elementId to see just its events. Check the `recording` field in the response — if false, no events are being captured; ask the developer to enable Recording in the Timeline tab before retrying.',
|
|
338
|
+
},
|
|
339
|
+
// `args` is genuinely absent when an agent calls the tool with no
|
|
340
|
+
// filters — the most common call — so it must default, not just be
|
|
341
|
+
// typed optional.
|
|
342
|
+
handler: async (args = {}) => {
|
|
343
|
+
const recording = session.value().layers.recordingState;
|
|
344
|
+
let filtered = recentEvents;
|
|
345
|
+
if (args.layerId !== undefined) {
|
|
346
|
+
filtered = filtered.filter((e) => e.layerId === args.layerId);
|
|
347
|
+
}
|
|
348
|
+
if (args.elementId !== undefined) {
|
|
349
|
+
filtered = filtered.filter(
|
|
350
|
+
(e) => e.meta?.elementId === args.elementId
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
// Measured against the newest event in the whole buffer, not the
|
|
354
|
+
// newest *matching* one: an element that last rendered 10s ago
|
|
355
|
+
// must come back empty for `sinceMs: 1000`, not report its own
|
|
356
|
+
// stale events as if they were recent.
|
|
357
|
+
if (args.sinceMs !== undefined && recentEvents.length > 0) {
|
|
358
|
+
const newest = recentEvents[recentEvents.length - 1].time;
|
|
359
|
+
const cutoff = newest - args.sinceMs;
|
|
360
|
+
filtered = filtered.filter((e) => e.time >= cutoff);
|
|
361
|
+
}
|
|
362
|
+
const limit = Math.min(args.limit ?? 50, 200);
|
|
363
|
+
const events = filtered.slice(-limit);
|
|
364
|
+
return {
|
|
365
|
+
recording,
|
|
366
|
+
events,
|
|
367
|
+
bufferSize: recentEvents.length,
|
|
368
|
+
truncated: events.length < filtered.length,
|
|
369
|
+
};
|
|
370
|
+
},
|
|
371
|
+
})
|
|
372
|
+
);
|
|
373
|
+
my.rpc.register(
|
|
374
|
+
defineRpcFunction({
|
|
375
|
+
name: RPC_UPDATE_SUMMARY,
|
|
376
|
+
type: 'query',
|
|
377
|
+
jsonSerializable: true,
|
|
378
|
+
// Baked into a static snapshot: takes no required arguments, and by
|
|
379
|
+
// export time its answer is exactly what the session recorded.
|
|
380
|
+
snapshot: true,
|
|
381
|
+
agent: {
|
|
382
|
+
description:
|
|
383
|
+
'Explain component updates: which components re-rendered, how often, how long they took, and which reactive properties changed to cause each update. Prefer this over lit:recent-events for "why did this re-render" and "what is re-rendering too much" — it answers from the same recording without the caller having to pair start/end events itself. Filter to one component with tagName. Check the `recording` field — if false, no events are being captured; call lit:set-recording first.',
|
|
384
|
+
},
|
|
385
|
+
// `args` is genuinely absent when an agent calls the tool with no
|
|
386
|
+
// filters — the most common call — so it must default.
|
|
387
|
+
handler: async (args = {}) => {
|
|
388
|
+
const recording = session.value().layers.recordingState;
|
|
389
|
+
let events = recentEvents;
|
|
390
|
+
// Same window semantics as `recent-events`: measured against the
|
|
391
|
+
// newest event in the whole buffer, not the newest match.
|
|
392
|
+
if (args.sinceMs !== undefined && recentEvents.length > 0) {
|
|
393
|
+
const cutoff =
|
|
394
|
+
recentEvents[recentEvents.length - 1].time - args.sinceMs;
|
|
395
|
+
events = recentEvents.filter((e) => e.time >= cutoff);
|
|
396
|
+
}
|
|
397
|
+
let cycles = attributeInput(
|
|
398
|
+
toUpdateCycles(toSpans(events)),
|
|
399
|
+
events
|
|
400
|
+
);
|
|
401
|
+
if (args.tagName !== undefined) {
|
|
402
|
+
cycles = cycles.filter((c) => c.tagName === args.tagName);
|
|
403
|
+
}
|
|
404
|
+
// Totals cover the whole window; only the per-cycle list is
|
|
405
|
+
// capped, so a limit never silently understates a hot component.
|
|
406
|
+
const components = rollup(cycles);
|
|
407
|
+
const limit = Math.min(args.limit ?? 50, 200);
|
|
408
|
+
const limited = cycles.slice(-limit);
|
|
409
|
+
return {
|
|
410
|
+
recording,
|
|
411
|
+
components,
|
|
412
|
+
cycles: limited,
|
|
413
|
+
bufferSize: recentEvents.length,
|
|
414
|
+
truncated: limited.length < cycles.length,
|
|
415
|
+
};
|
|
416
|
+
},
|
|
417
|
+
})
|
|
418
|
+
);
|
|
419
|
+
my.rpc.register(
|
|
420
|
+
defineRpcFunction({
|
|
421
|
+
name: RPC_INSPECT,
|
|
422
|
+
type: 'action',
|
|
423
|
+
jsonSerializable: true,
|
|
424
|
+
handler: async (command) => {
|
|
425
|
+
// "Pick" starts the overlay's inspect picker, which the host
|
|
426
|
+
// toggles in the page rather than answering from the runtime.
|
|
427
|
+
if (command.type === 'pick') {
|
|
428
|
+
source.toggleOverlay();
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
source.sendInspector(command);
|
|
432
|
+
},
|
|
433
|
+
})
|
|
434
|
+
);
|
|
435
|
+
my.rpc.register(
|
|
436
|
+
defineRpcFunction({
|
|
437
|
+
name: RPC_SET_RECORDING,
|
|
438
|
+
type: 'action',
|
|
439
|
+
jsonSerializable: true,
|
|
440
|
+
// The one agent-exposed mutation. `recent-events` is a dead end
|
|
441
|
+
// when recording is off, so an agent that can read the timeline
|
|
442
|
+
// but never start it just hands the question back to the human.
|
|
443
|
+
// Deliberately still the *only* one: the picker and layer toggles
|
|
444
|
+
// stay panel-only.
|
|
445
|
+
agent: {
|
|
446
|
+
description:
|
|
447
|
+
'Start or stop timeline recording. This is a shared toggle: turning it on also affects the DevTools panel if a developer has it open. Call this if lit:recent-events reports `recording: false`.',
|
|
448
|
+
},
|
|
449
|
+
handler: async (args) => {
|
|
450
|
+
session.mutate((state) => {
|
|
451
|
+
state.layers.recordingState = args.recording;
|
|
452
|
+
});
|
|
453
|
+
},
|
|
454
|
+
})
|
|
455
|
+
);
|
|
456
|
+
my.rpc.register(
|
|
457
|
+
defineRpcFunction({
|
|
458
|
+
name: RPC_TOGGLE_LAYER,
|
|
459
|
+
type: 'action',
|
|
460
|
+
jsonSerializable: true,
|
|
461
|
+
handler: async (args) => {
|
|
462
|
+
const flag = LAYER_FLAGS[args.layerId];
|
|
463
|
+
// Custom layers have no capture flag to toggle — app code owns
|
|
464
|
+
// whether it emits at all.
|
|
465
|
+
if (!flag) return;
|
|
466
|
+
session.mutate((state) => {
|
|
467
|
+
state.layers[flag] = args.enabled;
|
|
468
|
+
});
|
|
469
|
+
},
|
|
470
|
+
})
|
|
471
|
+
);
|
|
472
|
+
my.rpc.register(
|
|
473
|
+
defineRpcFunction({
|
|
474
|
+
name: RPC_SET_SETTINGS_OVERRIDE,
|
|
475
|
+
type: 'action',
|
|
476
|
+
jsonSerializable: true,
|
|
477
|
+
handler: async (override) => {
|
|
478
|
+
source.setSettingsOverride(override);
|
|
479
|
+
},
|
|
480
|
+
})
|
|
481
|
+
);
|
|
482
|
+
my.rpc.register(
|
|
483
|
+
defineRpcFunction({
|
|
484
|
+
name: RPC_OPEN_SOURCE,
|
|
485
|
+
type: 'action',
|
|
486
|
+
jsonSerializable: true,
|
|
487
|
+
// Resolving here rather than in the panel is the whole point of
|
|
488
|
+
// the hop: `file` is relative to the Vite root, while the open
|
|
489
|
+
// service resolves relative paths against the host's
|
|
490
|
+
// `workspaceRoot` -- in a monorepo (or any setup where the served
|
|
491
|
+
// app isn't the workspace) those are different directories, and
|
|
492
|
+
// `launchEditor` silently does nothing for a path that doesn't
|
|
493
|
+
// exist. Not agent-exposed: it spawns a GUI process.
|
|
494
|
+
handler: async (args) => {
|
|
495
|
+
const service = ctx.services.get('@devframes/service-open');
|
|
496
|
+
if (service === undefined) return {opened: false};
|
|
497
|
+
const {isAbsolute, resolve} = await import('node:path');
|
|
498
|
+
const root = sourceRoot?.();
|
|
499
|
+
const path =
|
|
500
|
+
root !== undefined && !isAbsolute(args.file)
|
|
501
|
+
? resolve(root, args.file)
|
|
502
|
+
: args.file;
|
|
503
|
+
await service.openInEditor({path, line: args.line});
|
|
504
|
+
return {opened: true};
|
|
505
|
+
},
|
|
506
|
+
})
|
|
507
|
+
);
|
|
508
|
+
my.rpc.register(
|
|
509
|
+
defineRpcFunction({
|
|
510
|
+
name: RPC_EXPORT_SNAPSHOT,
|
|
511
|
+
type: 'action',
|
|
512
|
+
jsonSerializable: true,
|
|
513
|
+
// Not agent-exposed. It writes a directory to the developer's disk,
|
|
514
|
+
// which is not something a coding agent should be able to do behind
|
|
515
|
+
// their back -- same reasoning as the other mutating actions.
|
|
516
|
+
handler: async (args) => {
|
|
517
|
+
// Imported here, not at module scope: this file has to keep
|
|
518
|
+
// loading in contexts with no filesystem, and the build adapter
|
|
519
|
+
// it pulls in reaches straight for `node:fs`.
|
|
520
|
+
const {buildSnapshot} = await import('../snapshot.js');
|
|
521
|
+
return buildSnapshot(
|
|
522
|
+
{
|
|
523
|
+
capturedAt: new Date().toISOString(),
|
|
524
|
+
version,
|
|
525
|
+
customLayers: [...session.value().customLayers],
|
|
526
|
+
roots: cachedRoots,
|
|
527
|
+
details: [...cachedDetails.values()],
|
|
528
|
+
events: [...recentEvents],
|
|
529
|
+
hmrIncompatibilities: [...hmrIncompatibilities],
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
outDir: args.outDir ?? 'lit-devtools-snapshot',
|
|
533
|
+
features: features ? features() : null,
|
|
534
|
+
clientAssets: options.clientAssets,
|
|
535
|
+
}
|
|
536
|
+
);
|
|
537
|
+
},
|
|
538
|
+
})
|
|
539
|
+
);
|
|
540
|
+
},
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
export default createLitDevframe({
|
|
544
|
+
source: createNullSource(),
|
|
545
|
+
version: '0.0.0',
|
|
546
|
+
});
|
|
547
|
+
//# sourceMappingURL=definition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definition.js","sourceRoot":"","sources":["../../src/lib/devframe/definition.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * The framework-neutral Lit devframe: RPC functions, shared state, and the\n * timeline stream. Talks to the page runtime only through the injected\n * {@link TimelineSource} port, so it runs unchanged under `createDevServer()`,\n * `createBuild()`, or an MCP server with no Vite in the loop. `vite.ts` wires\n * the real page-runtime bridge and mounts this via `createPluginFromDevframe`.\n *\n * @see plans/devframe-foundation.md\n */\n\nimport {defineDevframe, defineRpcFunction} from 'devframe';\n// Type-only: brings in the service's `declare module 'devframe'`\n// augmentation so `ctx.services.get()` types its API. Nothing is\n// imported at runtime, and the service is consumed, never installed\n// here -- a Vite hub already has it (see `panel/open-in-editor.ts`).\nimport type {} from '@devframes/service-open';\nimport type {DevframeDefinition, DevframeNodeContext} from 'devframe';\nimport type {\n InspectorCommand,\n InspectorDetails,\n InspectorTreeNode,\n} from '../../types/inspector.js';\nimport {TIMELINE_LAYERS} from '../../types/timeline.js';\nimport {MAX_HMR_INCOMPATIBILITIES} from '../../types/hmr-incompatibility.js';\nimport type {HmrIncompatibilityEvent} from '../../types/hmr-incompatibility.js';\nimport {LIT_LOGO_ICON} from './icon.js';\nimport {PANEL_DIST_DIR} from './paths.js';\nimport type {\n FeatureSettings,\n SettingsOverride,\n TimelineEvent,\n} from '../../types/timeline.js';\nimport {\n DEFAULT_SESSION_STATE,\n LAYER_FLAGS,\n LIT_DEVFRAME_ID,\n RECENT_EVENTS_BUFFER_SIZE,\n RPC_COMPONENT_DETAILS,\n RPC_GET_META,\n RPC_HMR_INCOMPATIBILITIES,\n RPC_HMR_INCOMPATIBLE,\n RPC_INSPECT,\n RPC_INSPECTOR_MESSAGE,\n RPC_LIST_COMPONENTS,\n RPC_RECENT_EVENTS,\n RPC_SET_RECORDING,\n RPC_EXPORT_SNAPSHOT,\n RPC_OPEN_SOURCE,\n RPC_SET_SETTINGS_OVERRIDE,\n RPC_TOGGLE_LAYER,\n RPC_UPDATE_SUMMARY,\n SESSION_STATE_KEY,\n TIMELINE_STREAM_ID,\n TIMELINE_STREAM_NAME,\n type ComponentDetailsArgs,\n type LitGetMetaResult,\n type RecentEventsArgs,\n type RecentEventsResult,\n type SessionState,\n type ExportSnapshotArgs,\n type ExportSnapshotResult,\n type OpenSourceArgs,\n type OpenSourceResult,\n type SetRecordingArgs,\n type ToggleLayerArgs,\n type UpdateSummaryArgs,\n type UpdateSummaryResult,\n} from './protocol.js';\nimport {\n attributeInput,\n rollup,\n toSpans,\n toUpdateCycles,\n} from '../timeline/derive.js';\nimport {createNullSource, type TimelineSource} from './source.js';\nimport type {SessionSnapshot} from '../../types/snapshot.js';\n\nexport interface CreateLitDevframeOptions {\n /** Page-runtime bridge. Use {@link createNullSource} when no page is attached. */\n source: TimelineSource;\n /** Plugin version, surfaced by `get-meta` and the devframe's own `version`. */\n version: string;\n /** Resolved feature settings, surfaced by `get-meta`. */\n features?: () => FeatureSettings | null;\n /**\n * Directory holding the built panel SPA. Defaults to the package's own\n * `dist/client`; the dev-time panel build points it elsewhere.\n */\n clientAssets?: string;\n /**\n * Absolute directory the injected `ElementSource.file` paths are relative\n * to (the Vite root). Read per call, since a host only knows it once its\n * dev server is up. Without it `open-source` can only open paths that are\n * already absolute.\n */\n sourceRoot?: () => string | undefined;\n /**\n * Boot from a recorded session instead of a live one. Set only by the\n * static-snapshot build (see `lib/snapshot.ts`): the caches below start\n * populated, so the frozen panel has a timeline and a component tree to\n * render with no page and no dev server behind it.\n */\n replay?: SessionSnapshot;\n}\n\n/**\n * Builds the Lit devframe definition. Framework-neutral: everything here\n * runs the same whether the host is Vite (`vite.ts`), a standalone dev\n * server, a static build, or an MCP server.\n */\nexport function createLitDevframe(\n options: CreateLitDevframeOptions\n): DevframeDefinition {\n const {source, version, features, replay, sourceRoot} = options;\n\n return defineDevframe({\n id: LIT_DEVFRAME_ID,\n name: 'Lit',\n description: 'Timeline recorder and component inspector for Lit apps.',\n version,\n packageName: '@oddsquad/vite-plugin-lit',\n homepage: 'https://oddcelot.github.io/vite-plugin-lit/',\n importMetaUrl: import.meta.url,\n icon: LIT_LOGO_ICON,\n dock: {category: 'framework'},\n clientAssets: options.clientAssets ?? PANEL_DIST_DIR,\n\n // `component-details` takes an id, so `snapshot: true` (which bakes the\n // no-argument call) cannot express it. Bake one record per component the\n // session actually opened -- the only ids that have details to freeze.\n rpc: replay\n ? {\n snapshot: [\n {\n method: `${LIT_DEVFRAME_ID}:${RPC_COMPONENT_DETAILS}`,\n inputs: replay.details.map((d) => [{id: d.id}]),\n },\n ],\n }\n : undefined,\n\n async setup(ctx: DevframeNodeContext) {\n const my = ctx.scope(LIT_DEVFRAME_ID);\n\n // Bind the per-user settings store before any panel can connect.\n // Both sides build it lazily on first access, but only this one backs\n // it with a JSON file -- a client that asks first gets a plain\n // in-memory shared state instead, so the panel's preferences would\n // round-trip happily and then vanish on restart. The panel is the only\n // thing that reads or writes these (see `panel/devtools-settings.ts`);\n // this call exists purely to make them durable.\n await my.settings.global.all();\n\n const session = await my.rpc.sharedState<SessionState>(\n SESSION_STATE_KEY,\n {\n initialValue: replay\n ? {\n ...DEFAULT_SESSION_STATE,\n // Recorded events carry layer ids; without the custom layers\n // that produced them the frozen panel would show a filter it\n // cannot name.\n customLayers: replay.customLayers,\n }\n : DEFAULT_SESSION_STATE,\n }\n );\n\n // Latest inspector snapshot, cached so a panel that (re)connects after\n // the runtime already answered can read it without round-tripping to\n // the page again. Pre-filled when replaying: there is no page to ask.\n let cachedRoots: InspectorTreeNode[] = replay ? [...replay.roots] : [];\n const cachedDetails = new Map<number, InspectorDetails>(\n replay?.details.map((d) => [d.id, d])\n );\n\n // Bounded history for the `recent-events` agent query. A plain array,\n // not devframe's internal per-stream replay buffer, which devframe\n // marks `@internal` (see plans/roadmap/02-agent-timeline-access.md).\n const recentEvents: TimelineEvent[] = replay ? [...replay.events] : [];\n\n // Recent HMR-incompatibility notices, capped the same way\n // `runtime/timeline/transport.ts` caps its pending queue — a long\n // session with many failing edits must not grow this forever.\n const hmrIncompatibilities: HmrIncompatibilityEvent[] = replay\n ? [...replay.hmrIncompatibilities]\n : [];\n\n // Terminal echo for an audience that only sees dev-server stdout (an\n // agent, or a CI log) and not the browser console or the panel.\n // Fire-and-log only — the cache above is the read-back store.\n const hmrDiagnostics = ctx.diagnostics.defineDiagnostics({\n docsBase:\n 'https://oddcelot.github.io/vite-plugin-lit/reference/limitations/',\n codes: {\n LIT_HMR_ACCESSOR: {\n why: (p: {tagName: string}) =>\n `<${p.tagName}> can't be hot-patched: standard accessor decorators`,\n docs: 'https://oddcelot.github.io/vite-plugin-lit/reference/limitations/#cannot-be-patched-in-place',\n },\n LIT_HMR_PATCH_FAILED: {\n why: (p: {tagName: string; detail: string}) =>\n `<${p.tagName}> can't be hot-patched: ${p.detail}`,\n docs: 'https://oddcelot.github.io/vite-plugin-lit/reference/limitations/#cannot-be-patched-in-place',\n },\n LIT_HMR_ATTRS_CHANGED: {\n why: (p: {tagName: string}) =>\n `<${p.tagName}> changed observedAttributes; reload recommended`,\n docs: 'https://oddcelot.github.io/vite-plugin-lit/reference/limitations/#cannot-be-patched-in-place',\n },\n },\n });\n ctx.diagnostics.register(hmrDiagnostics);\n\n // Streaming/source wiring only makes sense for a live session: a\n // static build or MCP run has no page attached (its `source` is a\n // `createNullSource()`), and `ctx.mode` is 'build' there.\n if (ctx.mode === 'dev') {\n const channel = my.rpc.streaming.create<TimelineEvent[]>(\n TIMELINE_STREAM_NAME,\n {replayWindow: 512}\n );\n // Started eagerly, not on the first event: `streaming:subscribe` is\n // fire-and-forget on the wire, and a subscribe naming a stream id\n // that does not exist yet is dropped with a DF0030 diagnostic rather\n // than queued. The panel subscribes as soon as it connects, which is\n // normally long before the first event, so the stream has to be\n // there waiting. `??` covers a re-start if the transport aborted it\n // after the last subscriber left.\n channel.start({id: TIMELINE_STREAM_ID});\n const ensureStream = () =>\n channel.get(TIMELINE_STREAM_ID) ??\n channel.start({id: TIMELINE_STREAM_ID});\n\n source.attach({\n pushEvents(events) {\n if (events.length === 0) return;\n ensureStream().write(events);\n recentEvents.push(...events);\n if (recentEvents.length > RECENT_EVENTS_BUFFER_SIZE) {\n recentEvents.splice(\n 0,\n recentEvents.length - RECENT_EVENTS_BUFFER_SIZE\n );\n }\n },\n addLayer(layer) {\n session.mutate((state) => {\n if (\n !state.customLayers.some((existing) => existing.id === layer.id)\n ) {\n state.customLayers.push(layer);\n }\n });\n },\n inspectorMessage(message) {\n if (message.type === 'tree') {\n cachedRoots = message.roots;\n } else if (message.type === 'details') {\n cachedDetails.set(message.details.id, message.details);\n } else if (message.type === 'gone') {\n cachedDetails.delete(message.id);\n }\n void ctx.rpc.broadcast({\n method: `${LIT_DEVFRAME_ID}:${RPC_INSPECTOR_MESSAGE}`,\n args: [message],\n // A page can be open with no panel docked; the runtime keeps\n // answering either way, so a broadcast with no listener is\n // normal rather than a missing-function error.\n optional: true,\n });\n },\n runtimeReady() {\n // A new page means a new timeline clock: the runtime re-zeroes on\n // the rising edge below, so events kept from the previous document\n // would sit in the same buffer on a different time origin and make\n // `recent-events`' `sinceMs` window meaningless. They also describe\n // a page that no longer exists.\n recentEvents.length = 0;\n\n // Replay current state to a runtime that just booted from its\n // defaults. Unconditional: `setRecording(false)` on a fresh page\n // is a no-op.\n const {layers} = session.value();\n source.setLayers(layers);\n source.setRecording(layers.recordingState);\n },\n hmrIncompatible(event) {\n hmrIncompatibilities.push(event);\n if (hmrIncompatibilities.length > MAX_HMR_INCOMPATIBILITIES) {\n hmrIncompatibilities.splice(\n 0,\n hmrIncompatibilities.length - MAX_HMR_INCOMPATIBILITIES\n );\n }\n void ctx.rpc.broadcast({\n method: `${LIT_DEVFRAME_ID}:${RPC_HMR_INCOMPATIBLE}`,\n args: [event],\n optional: true,\n });\n\n // Informational terminal echo, never a thrown error.\n if (event.reason.code === 'accessor-decorators') {\n hmrDiagnostics.LIT_HMR_ACCESSOR({tagName: event.tagName});\n } else if (event.reason.code === 'patch-failed') {\n hmrDiagnostics.LIT_HMR_PATCH_FAILED({\n tagName: event.tagName,\n detail: event.reason.detail,\n });\n } else {\n hmrDiagnostics.LIT_HMR_ATTRS_CHANGED({tagName: event.tagName});\n }\n },\n });\n\n // Single push point for recording/layer changes: fires for the\n // `set-recording` / `toggle-layer` actions below and for a panel\n // mutating shared state directly through devframe's generic\n // shared-state RPC. Immer only emits when the state reference\n // changes, so a no-op mutate sends nothing.\n //\n // Clearing on the rising edge belongs here rather than in\n // `set-recording` for the same reason: the runtime re-zeroes its\n // timeline clock when recording turns on (`runtime/timeline/clock.ts`),\n // so events kept from the previous recording sit in the buffer on a\n // larger time origin than everything captured after them. A `sinceMs`\n // window reads them as the future, and pairing a start with its end\n // across the seam yields a negative duration. Same rationale as\n // `runtimeReady()` above, one level finer: a new clock, not a new page.\n let wasRecording = session.value().layers.recordingState;\n session.on('updated', (state) => {\n const {recordingState} = state.layers;\n if (recordingState && !wasRecording) {\n recentEvents.length = 0;\n }\n wasRecording = recordingState;\n source.setRecording(recordingState);\n source.setLayers(state.layers);\n });\n }\n\n my.rpc.register(\n defineRpcFunction({\n name: RPC_GET_META,\n type: 'query',\n jsonSerializable: true,\n snapshot: true,\n agent: {\n description:\n 'Get the plugin version, active timeline layers, and resolved feature settings. Call once at the start of a session to learn what timeline layers exist before asking about events.',\n },\n handler: async (): Promise<LitGetMetaResult> => ({\n version,\n // `.value()` returns a deep-readonly snapshot; copy so callers\n // get a plain, mutable `TimelineLayer[]`.\n layers: [...TIMELINE_LAYERS, ...session.value().customLayers],\n features: features ? features() : null,\n stream: {\n channel: `${LIT_DEVFRAME_ID}:${TIMELINE_STREAM_NAME}`,\n id: TIMELINE_STREAM_ID,\n },\n }),\n })\n );\n\n my.rpc.register(\n defineRpcFunction({\n name: RPC_LIST_COMPONENTS,\n type: 'query',\n jsonSerializable: true,\n // Baked into a static snapshot: takes no required arguments, and\n // by export time its answer is exactly what the session recorded.\n snapshot: true,\n agent: {\n description:\n 'List the live Lit component tree of the inspected page. Call this before asking about a specific element to find its id.',\n },\n handler: async (): Promise<InspectorTreeNode[]> => cachedRoots,\n })\n );\n\n my.rpc.register(\n defineRpcFunction({\n name: RPC_HMR_INCOMPATIBILITIES,\n type: 'query',\n jsonSerializable: true,\n // Baked into a static snapshot: takes no required arguments, and\n // by export time its answer is exactly what the session recorded.\n snapshot: true,\n agent: {\n description:\n \"List recent components the Lit plugin could not hot-patch in place, and why. Call this after an unexplained full-page reload during development, or when a component's state resets unexpectedly on edit.\",\n },\n handler: async (): Promise<HmrIncompatibilityEvent[]> =>\n hmrIncompatibilities,\n })\n );\n\n my.rpc.register(\n defineRpcFunction({\n name: RPC_COMPONENT_DETAILS,\n type: 'query',\n jsonSerializable: true,\n agent: {\n description:\n 'Get reactive properties, attributes, and internal state for one component by id. Call list-components first to find the id.',\n },\n handler: async (\n args: ComponentDetailsArgs\n ): Promise<InspectorDetails | null> =>\n cachedDetails.get(args.id) ?? null,\n })\n );\n\n my.rpc.register(\n defineRpcFunction({\n name: RPC_RECENT_EVENTS,\n type: 'query',\n jsonSerializable: true,\n // Baked into a static snapshot: takes no required arguments, and\n // by export time its answer is exactly what the session recorded.\n snapshot: true,\n agent: {\n description:\n 'Get recent timeline events (lifecycle, render, mouse, keyboard) to diagnose why a component re-rendered or updated. Call list-components first to find an element’s id, then filter by elementId to see just its events. Check the `recording` field in the response — if false, no events are being captured; ask the developer to enable Recording in the Timeline tab before retrying.',\n },\n // `args` is genuinely absent when an agent calls the tool with no\n // filters — the most common call — so it must default, not just be\n // typed optional.\n handler: async (\n args: RecentEventsArgs = {}\n ): Promise<RecentEventsResult> => {\n const recording = session.value().layers.recordingState;\n let filtered = recentEvents;\n if (args.layerId !== undefined) {\n filtered = filtered.filter((e) => e.layerId === args.layerId);\n }\n if (args.elementId !== undefined) {\n filtered = filtered.filter(\n (e) => e.meta?.elementId === args.elementId\n );\n }\n // Measured against the newest event in the whole buffer, not the\n // newest *matching* one: an element that last rendered 10s ago\n // must come back empty for `sinceMs: 1000`, not report its own\n // stale events as if they were recent.\n if (args.sinceMs !== undefined && recentEvents.length > 0) {\n const newest = recentEvents[recentEvents.length - 1]!.time;\n const cutoff = newest - args.sinceMs;\n filtered = filtered.filter((e) => e.time >= cutoff);\n }\n const limit = Math.min(args.limit ?? 50, 200);\n const events = filtered.slice(-limit);\n return {\n recording,\n events,\n bufferSize: recentEvents.length,\n truncated: events.length < filtered.length,\n };\n },\n })\n );\n\n my.rpc.register(\n defineRpcFunction({\n name: RPC_UPDATE_SUMMARY,\n type: 'query',\n jsonSerializable: true,\n // Baked into a static snapshot: takes no required arguments, and by\n // export time its answer is exactly what the session recorded.\n snapshot: true,\n agent: {\n description:\n 'Explain component updates: which components re-rendered, how often, how long they took, and which reactive properties changed to cause each update. Prefer this over lit:recent-events for \"why did this re-render\" and \"what is re-rendering too much\" — it answers from the same recording without the caller having to pair start/end events itself. Filter to one component with tagName. Check the `recording` field — if false, no events are being captured; call lit:set-recording first.',\n },\n // `args` is genuinely absent when an agent calls the tool with no\n // filters — the most common call — so it must default.\n handler: async (\n args: UpdateSummaryArgs = {}\n ): Promise<UpdateSummaryResult> => {\n const recording = session.value().layers.recordingState;\n let events: readonly TimelineEvent[] = recentEvents;\n // Same window semantics as `recent-events`: measured against the\n // newest event in the whole buffer, not the newest match.\n if (args.sinceMs !== undefined && recentEvents.length > 0) {\n const cutoff =\n recentEvents[recentEvents.length - 1]!.time - args.sinceMs;\n events = recentEvents.filter((e) => e.time >= cutoff);\n }\n let cycles = attributeInput(\n toUpdateCycles(toSpans(events)),\n events\n );\n if (args.tagName !== undefined) {\n cycles = cycles.filter((c) => c.tagName === args.tagName);\n }\n // Totals cover the whole window; only the per-cycle list is\n // capped, so a limit never silently understates a hot component.\n const components = rollup(cycles);\n const limit = Math.min(args.limit ?? 50, 200);\n const limited = cycles.slice(-limit);\n return {\n recording,\n components,\n cycles: limited,\n bufferSize: recentEvents.length,\n truncated: limited.length < cycles.length,\n };\n },\n })\n );\n\n my.rpc.register(\n defineRpcFunction({\n name: RPC_INSPECT,\n type: 'action',\n jsonSerializable: true,\n handler: async (command: InspectorCommand): Promise<void> => {\n // \"Pick\" starts the overlay's inspect picker, which the host\n // toggles in the page rather than answering from the runtime.\n if (command.type === 'pick') {\n source.toggleOverlay();\n return;\n }\n source.sendInspector(command);\n },\n })\n );\n\n my.rpc.register(\n defineRpcFunction({\n name: RPC_SET_RECORDING,\n type: 'action',\n jsonSerializable: true,\n // The one agent-exposed mutation. `recent-events` is a dead end\n // when recording is off, so an agent that can read the timeline\n // but never start it just hands the question back to the human.\n // Deliberately still the *only* one: the picker and layer toggles\n // stay panel-only.\n agent: {\n description:\n 'Start or stop timeline recording. This is a shared toggle: turning it on also affects the DevTools panel if a developer has it open. Call this if lit:recent-events reports `recording: false`.',\n },\n handler: async (args: SetRecordingArgs): Promise<void> => {\n session.mutate((state) => {\n state.layers.recordingState = args.recording;\n });\n },\n })\n );\n\n my.rpc.register(\n defineRpcFunction({\n name: RPC_TOGGLE_LAYER,\n type: 'action',\n jsonSerializable: true,\n handler: async (args: ToggleLayerArgs): Promise<void> => {\n const flag = LAYER_FLAGS[args.layerId];\n // Custom layers have no capture flag to toggle — app code owns\n // whether it emits at all.\n if (!flag) return;\n session.mutate((state) => {\n state.layers[flag] = args.enabled;\n });\n },\n })\n );\n\n my.rpc.register(\n defineRpcFunction({\n name: RPC_SET_SETTINGS_OVERRIDE,\n type: 'action',\n jsonSerializable: true,\n handler: async (override: SettingsOverride): Promise<void> => {\n source.setSettingsOverride(override);\n },\n })\n );\n\n my.rpc.register(\n defineRpcFunction({\n name: RPC_OPEN_SOURCE,\n type: 'action',\n jsonSerializable: true,\n // Resolving here rather than in the panel is the whole point of\n // the hop: `file` is relative to the Vite root, while the open\n // service resolves relative paths against the host's\n // `workspaceRoot` -- in a monorepo (or any setup where the served\n // app isn't the workspace) those are different directories, and\n // `launchEditor` silently does nothing for a path that doesn't\n // exist. Not agent-exposed: it spawns a GUI process.\n handler: async (args: OpenSourceArgs): Promise<OpenSourceResult> => {\n const service = ctx.services.get('@devframes/service-open');\n if (service === undefined) return {opened: false};\n const {isAbsolute, resolve} = await import('node:path');\n const root = sourceRoot?.();\n const path =\n root !== undefined && !isAbsolute(args.file)\n ? resolve(root, args.file)\n : args.file;\n await service.openInEditor({path, line: args.line});\n return {opened: true};\n },\n })\n );\n\n my.rpc.register(\n defineRpcFunction({\n name: RPC_EXPORT_SNAPSHOT,\n type: 'action',\n jsonSerializable: true,\n // Not agent-exposed. It writes a directory to the developer's disk,\n // which is not something a coding agent should be able to do behind\n // their back -- same reasoning as the other mutating actions.\n handler: async (\n args: ExportSnapshotArgs\n ): Promise<ExportSnapshotResult> => {\n // Imported here, not at module scope: this file has to keep\n // loading in contexts with no filesystem, and the build adapter\n // it pulls in reaches straight for `node:fs`.\n const {buildSnapshot} = await import('../snapshot.js');\n return buildSnapshot(\n {\n capturedAt: new Date().toISOString(),\n version,\n customLayers: [...session.value().customLayers],\n roots: cachedRoots,\n details: [...cachedDetails.values()],\n events: [...recentEvents],\n hmrIncompatibilities: [...hmrIncompatibilities],\n },\n {\n outDir: args.outDir ?? 'lit-devtools-snapshot',\n features: features ? features() : null,\n clientAssets: options.clientAssets,\n }\n );\n },\n })\n );\n },\n });\n}\n\nexport default createLitDevframe({\n source: createNullSource(),\n version: '0.0.0',\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../../src/lib/devframe/icon.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgBH,sCAAsC;AACtC,eAAO,MAAM,aAAa,QAEvB,CAAC"}
|