foldkit 0.77.0 → 0.78.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.
@@ -1 +1 @@
1
- {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/devTools/overlay.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,MAAM,EAGN,OAAO,EAGP,MAAM,EASP,MAAM,QAAQ,CAAA;AAEf,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAU9C,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAQ3E,OAAO,EACL,KAAK,aAAa,EAInB,MAAM,YAAY,CAAA;AAuOnB,eAAO,MAAM,MAAM;;EAA0C,CAAA;AAC7D,eAAO,MAAM,YAAY;;;;;;EAGxB,CAAA;AACD,eAAO,MAAM,aAAa;;;;;;EAGzB,CAAA;AACD,eAAO,MAAM,MAAM;;EAA4C,CAAA;AAC/D,eAAO,MAAM,KAAK;;EAA0C,CAAA;AAC5D,eAAO,MAAM,UAAU;;EAA6C,CAAA;AACpE,eAAO,MAAM,YAAY;;EAAiD,CAAA;AAC1E,eAAO,MAAM,WAAW;;EAA+C,CAAA;AAkzCvE,eAAO,MAAM,aAAa,GACxB,OAAO,aAAa,EACpB,UAAU,gBAAgB,EAC1B,MAAM,YAAY,EAClB,aAAa,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,sCAkDhC,CAAA"}
1
+ {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/devTools/overlay.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,MAAM,EAGN,OAAO,EAGP,MAAM,EASP,MAAM,QAAQ,CAAA;AAEf,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAU9C,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAQ3E,OAAO,EAAE,KAAK,aAAa,EAA+B,MAAM,YAAY,CAAA;AA4M5E,eAAO,MAAM,MAAM;;EAA0C,CAAA;AAC7D,eAAO,MAAM,YAAY;;;;;;EAGxB,CAAA;AACD,eAAO,MAAM,aAAa;;;;;;EAGzB,CAAA;AACD,eAAO,MAAM,MAAM;;EAA4C,CAAA;AAC/D,eAAO,MAAM,KAAK;;EAA0C,CAAA;AAC5D,eAAO,MAAM,UAAU;;EAA6C,CAAA;AACpE,eAAO,MAAM,YAAY;;EAAiD,CAAA;AAC1E,eAAO,MAAM,WAAW;;EAA+C,CAAA;AAkzCvE,eAAO,MAAM,aAAa,GACxB,OAAO,aAAa,EACpB,UAAU,gBAAgB,EAC1B,MAAM,YAAY,EAClB,aAAa,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,sCAkDhC,CAAA"}
@@ -12,7 +12,8 @@ import * as Listbox from '../ui/listbox/public.js';
12
12
  import * as Tabs from '../ui/tabs/public.js';
13
13
  import { overlayStyles } from './overlay-styles.js';
14
14
  import { toInspectableValue } from './serialize.js';
15
- import { INIT_INDEX, } from './store.js';
15
+ import { INIT_INDEX } from './store.js';
16
+ import { GOT_MESSAGE_PATTERN, extractSubmodelInfo, isTagged, } from './submodelPath.js';
16
17
  // MODEL
17
18
  const DisplayEntry = S.Struct({
18
19
  tag: S.String,
@@ -107,26 +108,8 @@ const ALL_MESSAGES_VALUE = '';
107
108
  const formatTimeDelta = (deltaMs) => M.value(deltaMs).pipe(M.when(0, () => '0ms'), M.when(Number_.lessThan(MILLIS_PER_SECOND), ms => `+${Math.round(ms)}ms`), M.orElse(ms => `+${(ms / MILLIS_PER_SECOND).toFixed(1)}s`));
108
109
  const MESSAGE_LIST_SELECTOR = '.message-list';
109
110
  const computeSubmodelTags = (entries) => pipe(entries, Array_.flatMap(({ submodelPath }) => submodelPath), Array_.dedupe, Array_.sort(Order.string));
110
- const GOT_MESSAGE_PATTERN = /^Got.+Message$/;
111
- const extractSubmodelInfo = (entry) => {
112
- if (!GOT_MESSAGE_PATTERN.test(entry.tag)) {
113
- return { submodelPath: [], maybeLeafTag: Option.none() };
114
- }
115
- const path = [entry.tag];
116
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
117
- let current = entry.message?.['message'];
118
- while (isTagged(current) && GOT_MESSAGE_PATTERN.test(current._tag)) {
119
- path.push(current._tag);
120
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
121
- current = current?.['message'];
122
- }
123
- return {
124
- submodelPath: path,
125
- maybeLeafTag: pipe(current, Option.liftPredicate(isTagged), Option.map(({ _tag }) => _tag)),
126
- };
127
- };
128
111
  const toDisplayEntries = ({ entries }) => Array_.map(entries, entry => {
129
- const { submodelPath, maybeLeafTag } = extractSubmodelInfo(entry);
112
+ const { submodelPath, maybeLeafTag } = extractSubmodelInfo(entry.tag, entry.message);
130
113
  return {
131
114
  tag: entry.tag,
132
115
  submodelPath,
@@ -144,8 +127,6 @@ const toDisplayState = (state) => ({
144
127
  pausedAtIndex: state.pausedAtIndex,
145
128
  });
146
129
  const isExpandable = (value) => Predicate.isObject(value);
147
- const Tagged = S.Struct({ _tag: S.String });
148
- const isTagged = S.is(Tagged);
149
130
  const objectPreview = (value) => pipe(value, Record.keys, Array_.filter(key => key !== '_tag'), Array_.match({
150
131
  onEmpty: () => '{}',
151
132
  onNonEmpty: keys => {
@@ -1,5 +1,5 @@
1
1
  import { Schema as S } from 'effect';
2
- /** A serialized history entry as it appears on the wire. */
2
+ /** A serialized history entry as it appears on the wire. `submodelPath` lists `Got<Child>Message` wrapper tags from outer to inner when the entry came up through a Submodel chain; `maybeLeafTag` is `Some` with the innermost child Message tag when one exists. */
3
3
  export declare const SerializedEntry: S.Struct<{
4
4
  index: typeof S.Number;
5
5
  tag: typeof S.String;
@@ -9,6 +9,8 @@ export declare const SerializedEntry: S.Struct<{
9
9
  isModelChanged: typeof S.Boolean;
10
10
  changedPaths: S.Array$<typeof S.String>;
11
11
  affectedPaths: S.Array$<typeof S.String>;
12
+ submodelPath: S.Array$<typeof S.String>;
13
+ maybeLeafTag: S.Option<typeof S.String>;
12
14
  }>;
13
15
  /** A serialized history entry suitable for transmission over the WS protocol. */
14
16
  export type SerializedEntry = typeof SerializedEntry.Type;
@@ -26,14 +28,23 @@ export declare const RuntimeInfo: S.Struct<{
26
28
  }>;
27
29
  /** Metadata about a connected browser runtime. */
28
30
  export type RuntimeInfo = typeof RuntimeInfo.Type;
29
- /** Request the current Model snapshot. */
30
- export declare const RequestGetModel: import("../schema/index.js").CallableTaggedStruct<"RequestGetModel", {}>;
31
+ /** Request the current Model snapshot, optionally narrowed to a path and/or expanded. */
32
+ export declare const RequestGetModel: import("../schema/index.js").CallableTaggedStruct<"RequestGetModel", {
33
+ maybePath: S.Option<typeof S.String>;
34
+ expand: typeof S.Boolean;
35
+ }>;
36
+ /** Request a historical Model snapshot at an absolute history index, optionally narrowed to a path and/or expanded. Use `index: -1` for the initial Model. */
37
+ export declare const RequestGetModelAt: import("../schema/index.js").CallableTaggedStruct<"RequestGetModelAt", {
38
+ index: typeof S.Number;
39
+ maybePath: S.Option<typeof S.String>;
40
+ expand: typeof S.Boolean;
41
+ }>;
31
42
  /** Request recent history entries, optionally starting from a given index. */
32
43
  export declare const RequestListMessages: import("../schema/index.js").CallableTaggedStruct<"RequestListMessages", {
33
44
  limit: typeof S.Number;
34
45
  maybeSinceIndex: S.Option<typeof S.Number>;
35
46
  }>;
36
- /** Request a single history entry by index, including before/after Model snapshots. */
47
+ /** Request a single history entry by index. To inspect the Model around the entry, call `RequestGetModelAt` with `index - 1` (before) and `index` (after). */
37
48
  export declare const RequestGetMessage: import("../schema/index.js").CallableTaggedStruct<"RequestGetMessage", {
38
49
  index: typeof S.Number;
39
50
  }>;
@@ -45,6 +56,10 @@ export declare const RequestReplayToKeyframe: import("../schema/index.js").Calla
45
56
  }>;
46
57
  /** Request the runtime resume normal execution from a paused state. */
47
58
  export declare const RequestResume: import("../schema/index.js").CallableTaggedStruct<"RequestResume", {}>;
59
+ /** Request the recorded init data: the initial Model and the names of Commands returned from `init`. */
60
+ export declare const RequestGetInit: import("../schema/index.js").CallableTaggedStruct<"RequestGetInit", {}>;
61
+ /** Request a snapshot of the runtime's DevTools state: history bounds, current paused/live status, and whether init is recorded. */
62
+ export declare const RequestGetRuntimeState: import("../schema/index.js").CallableTaggedStruct<"RequestGetRuntimeState", {}>;
48
63
  /** Request the runtime dispatch a Message at the current state. The payload is opaque to the protocol; the runtime validates against the app's Message Schema. */
49
64
  export declare const RequestDispatchMessage: import("../schema/index.js").CallableTaggedStruct<"RequestDispatchMessage", {
50
65
  message: typeof S.Unknown;
@@ -52,7 +67,14 @@ export declare const RequestDispatchMessage: import("../schema/index.js").Callab
52
67
  /** Request the list of currently connected browser runtimes. Handled by the Vite plugin, not forwarded to a runtime. */
53
68
  export declare const RequestListRuntimes: import("../schema/index.js").CallableTaggedStruct<"RequestListRuntimes", {}>;
54
69
  /** A request from the MCP server. RequestListRuntimes is handled at the Vite plugin layer; all other requests are routed to a browser runtime. */
55
- export declare const Request: S.Union<[import("../schema/index.js").CallableTaggedStruct<"RequestGetModel", {}>, import("../schema/index.js").CallableTaggedStruct<"RequestListMessages", {
70
+ export declare const Request: S.Union<[import("../schema/index.js").CallableTaggedStruct<"RequestGetModel", {
71
+ maybePath: S.Option<typeof S.String>;
72
+ expand: typeof S.Boolean;
73
+ }>, import("../schema/index.js").CallableTaggedStruct<"RequestGetModelAt", {
74
+ index: typeof S.Number;
75
+ maybePath: S.Option<typeof S.String>;
76
+ expand: typeof S.Boolean;
77
+ }>, import("../schema/index.js").CallableTaggedStruct<"RequestListMessages", {
56
78
  limit: typeof S.Number;
57
79
  maybeSinceIndex: S.Option<typeof S.Number>;
58
80
  }>, import("../schema/index.js").CallableTaggedStruct<"RequestGetMessage", {
@@ -61,12 +83,14 @@ export declare const Request: S.Union<[import("../schema/index.js").CallableTagg
61
83
  keyframeIndex: typeof S.Number;
62
84
  }>, import("../schema/index.js").CallableTaggedStruct<"RequestResume", {}>, import("../schema/index.js").CallableTaggedStruct<"RequestDispatchMessage", {
63
85
  message: typeof S.Unknown;
64
- }>, import("../schema/index.js").CallableTaggedStruct<"RequestListRuntimes", {}>]>;
86
+ }>, import("../schema/index.js").CallableTaggedStruct<"RequestListRuntimes", {}>, import("../schema/index.js").CallableTaggedStruct<"RequestGetInit", {}>, import("../schema/index.js").CallableTaggedStruct<"RequestGetRuntimeState", {}>]>;
65
87
  /** A request from the MCP server. */
66
88
  export type Request = typeof Request.Type;
67
- /** Response carrying the current Model snapshot. */
89
+ /** Response carrying a Model snapshot. The `value` is the resolved subtree at `atPath` (or the whole Model when no path was supplied). When `summarized` is true, large arrays/records/strings have been collapsed to `_summary` placeholders to keep payloads small for AI agents; pass `expand: true` on the Request to receive the literal value. */
68
90
  export declare const ResponseModel: import("../schema/index.js").CallableTaggedStruct<"ResponseModel", {
69
- model: typeof S.Unknown;
91
+ value: typeof S.Unknown;
92
+ atPath: typeof S.String;
93
+ summarized: typeof S.Boolean;
70
94
  }>;
71
95
  /** Response carrying a page of history entries. `maybeNextIndex` is `Some` when more entries are available beyond this page (pass it as `RequestListMessages.maybeSinceIndex` to fetch the next page) and `None` when this page reaches the current end of history. */
72
96
  export declare const ResponseMessages: import("../schema/index.js").CallableTaggedStruct<"ResponseMessages", {
@@ -79,10 +103,12 @@ export declare const ResponseMessages: import("../schema/index.js").CallableTagg
79
103
  isModelChanged: typeof S.Boolean;
80
104
  changedPaths: S.Array$<typeof S.String>;
81
105
  affectedPaths: S.Array$<typeof S.String>;
106
+ submodelPath: S.Array$<typeof S.String>;
107
+ maybeLeafTag: S.Option<typeof S.String>;
82
108
  }>>;
83
109
  maybeNextIndex: S.Option<typeof S.Number>;
84
110
  }>;
85
- /** Response carrying a single history entry with surrounding Model snapshots. */
111
+ /** Response carrying a single history entry. Model snapshots are not included; use `RequestGetModelAt` with `index - 1` and `index` to inspect Model state around the entry. */
86
112
  export declare const ResponseMessage: import("../schema/index.js").CallableTaggedStruct<"ResponseMessage", {
87
113
  entry: S.Struct<{
88
114
  index: typeof S.Number;
@@ -93,9 +119,9 @@ export declare const ResponseMessage: import("../schema/index.js").CallableTagge
93
119
  isModelChanged: typeof S.Boolean;
94
120
  changedPaths: S.Array$<typeof S.String>;
95
121
  affectedPaths: S.Array$<typeof S.String>;
122
+ submodelPath: S.Array$<typeof S.String>;
123
+ maybeLeafTag: S.Option<typeof S.String>;
96
124
  }>;
97
- modelBefore: typeof S.Unknown;
98
- modelAfter: typeof S.Unknown;
99
125
  }>;
100
126
  /** Response carrying the list of available keyframes. */
101
127
  export declare const ResponseKeyframes: import("../schema/index.js").CallableTaggedStruct<"ResponseKeyframes", {
@@ -121,13 +147,29 @@ export declare const ResponseRuntimes: import("../schema/index.js").CallableTagg
121
147
  title: typeof S.String;
122
148
  }>>;
123
149
  }>;
150
+ /** Response carrying the recorded init data. `maybeModel` is `None` until the runtime has finished its first render and recorded init; once set it stays set for the rest of the runtime's life. `commandNames` lists the Commands returned from the application's `init` function in the order they were produced. */
151
+ export declare const ResponseInit: import("../schema/index.js").CallableTaggedStruct<"ResponseInit", {
152
+ maybeModel: S.Option<typeof S.Unknown>;
153
+ commandNames: S.Array$<typeof S.String>;
154
+ }>;
155
+ /** Response carrying a snapshot of the runtime's DevTools state. `currentIndex` is the absolute index of the most recently recorded Message, or -1 when no Messages have been recorded yet. `startIndex` is the earliest absolute index still retained in the rolling buffer (older entries are evicted past `maxEntries`). `totalEntries` is the number of retained entries. `isPaused` is true while the runtime is paused at a replayed snapshot; `maybePausedAtIndex` is `Some(index)` then and `None` otherwise. `hasInitModel` is true once the runtime has finished initialising. */
156
+ export declare const ResponseRuntimeState: import("../schema/index.js").CallableTaggedStruct<"ResponseRuntimeState", {
157
+ currentIndex: typeof S.Number;
158
+ startIndex: typeof S.Number;
159
+ totalEntries: typeof S.Number;
160
+ isPaused: typeof S.Boolean;
161
+ maybePausedAtIndex: S.Option<typeof S.Number>;
162
+ hasInitModel: typeof S.Boolean;
163
+ }>;
124
164
  /** Response carrying an error reason for a failed Request. */
125
165
  export declare const ResponseError: import("../schema/index.js").CallableTaggedStruct<"ResponseError", {
126
166
  reason: typeof S.String;
127
167
  }>;
128
168
  /** A response replying to a Request. */
129
169
  export declare const Response: S.Union<[import("../schema/index.js").CallableTaggedStruct<"ResponseModel", {
130
- model: typeof S.Unknown;
170
+ value: typeof S.Unknown;
171
+ atPath: typeof S.String;
172
+ summarized: typeof S.Boolean;
131
173
  }>, import("../schema/index.js").CallableTaggedStruct<"ResponseMessages", {
132
174
  entries: S.Array$<S.Struct<{
133
175
  index: typeof S.Number;
@@ -138,6 +180,8 @@ export declare const Response: S.Union<[import("../schema/index.js").CallableTag
138
180
  isModelChanged: typeof S.Boolean;
139
181
  changedPaths: S.Array$<typeof S.String>;
140
182
  affectedPaths: S.Array$<typeof S.String>;
183
+ submodelPath: S.Array$<typeof S.String>;
184
+ maybeLeafTag: S.Option<typeof S.String>;
141
185
  }>>;
142
186
  maybeNextIndex: S.Option<typeof S.Number>;
143
187
  }>, import("../schema/index.js").CallableTaggedStruct<"ResponseMessage", {
@@ -150,9 +194,9 @@ export declare const Response: S.Union<[import("../schema/index.js").CallableTag
150
194
  isModelChanged: typeof S.Boolean;
151
195
  changedPaths: S.Array$<typeof S.String>;
152
196
  affectedPaths: S.Array$<typeof S.String>;
197
+ submodelPath: S.Array$<typeof S.String>;
198
+ maybeLeafTag: S.Option<typeof S.String>;
153
199
  }>;
154
- modelBefore: typeof S.Unknown;
155
- modelAfter: typeof S.Unknown;
156
200
  }>, import("../schema/index.js").CallableTaggedStruct<"ResponseKeyframes", {
157
201
  keyframes: S.Array$<S.Struct<{
158
202
  index: typeof S.Number;
@@ -167,6 +211,16 @@ export declare const Response: S.Union<[import("../schema/index.js").CallableTag
167
211
  url: typeof S.String;
168
212
  title: typeof S.String;
169
213
  }>>;
214
+ }>, import("../schema/index.js").CallableTaggedStruct<"ResponseInit", {
215
+ maybeModel: S.Option<typeof S.Unknown>;
216
+ commandNames: S.Array$<typeof S.String>;
217
+ }>, import("../schema/index.js").CallableTaggedStruct<"ResponseRuntimeState", {
218
+ currentIndex: typeof S.Number;
219
+ startIndex: typeof S.Number;
220
+ totalEntries: typeof S.Number;
221
+ isPaused: typeof S.Boolean;
222
+ maybePausedAtIndex: S.Option<typeof S.Number>;
223
+ hasInitModel: typeof S.Boolean;
170
224
  }>, import("../schema/index.js").CallableTaggedStruct<"ResponseError", {
171
225
  reason: typeof S.String;
172
226
  }>]>;
@@ -200,7 +254,14 @@ export type Event = typeof Event.Type;
200
254
  export declare const RequestFrame: S.Struct<{
201
255
  id: typeof S.String;
202
256
  maybeConnectionId: S.Option<typeof S.String>;
203
- request: S.Union<[import("../schema/index.js").CallableTaggedStruct<"RequestGetModel", {}>, import("../schema/index.js").CallableTaggedStruct<"RequestListMessages", {
257
+ request: S.Union<[import("../schema/index.js").CallableTaggedStruct<"RequestGetModel", {
258
+ maybePath: S.Option<typeof S.String>;
259
+ expand: typeof S.Boolean;
260
+ }>, import("../schema/index.js").CallableTaggedStruct<"RequestGetModelAt", {
261
+ index: typeof S.Number;
262
+ maybePath: S.Option<typeof S.String>;
263
+ expand: typeof S.Boolean;
264
+ }>, import("../schema/index.js").CallableTaggedStruct<"RequestListMessages", {
204
265
  limit: typeof S.Number;
205
266
  maybeSinceIndex: S.Option<typeof S.Number>;
206
267
  }>, import("../schema/index.js").CallableTaggedStruct<"RequestGetMessage", {
@@ -209,7 +270,7 @@ export declare const RequestFrame: S.Struct<{
209
270
  keyframeIndex: typeof S.Number;
210
271
  }>, import("../schema/index.js").CallableTaggedStruct<"RequestResume", {}>, import("../schema/index.js").CallableTaggedStruct<"RequestDispatchMessage", {
211
272
  message: typeof S.Unknown;
212
- }>, import("../schema/index.js").CallableTaggedStruct<"RequestListRuntimes", {}>]>;
273
+ }>, import("../schema/index.js").CallableTaggedStruct<"RequestListRuntimes", {}>, import("../schema/index.js").CallableTaggedStruct<"RequestGetInit", {}>, import("../schema/index.js").CallableTaggedStruct<"RequestGetRuntimeState", {}>]>;
213
274
  }>;
214
275
  /** A wire frame carrying a Request from the MCP server. */
215
276
  export type RequestFrame = typeof RequestFrame.Type;
@@ -217,7 +278,9 @@ export type RequestFrame = typeof RequestFrame.Type;
217
278
  export declare const ResponseFrame: S.Struct<{
218
279
  id: typeof S.String;
219
280
  response: S.Union<[import("../schema/index.js").CallableTaggedStruct<"ResponseModel", {
220
- model: typeof S.Unknown;
281
+ value: typeof S.Unknown;
282
+ atPath: typeof S.String;
283
+ summarized: typeof S.Boolean;
221
284
  }>, import("../schema/index.js").CallableTaggedStruct<"ResponseMessages", {
222
285
  entries: S.Array$<S.Struct<{
223
286
  index: typeof S.Number;
@@ -228,6 +291,8 @@ export declare const ResponseFrame: S.Struct<{
228
291
  isModelChanged: typeof S.Boolean;
229
292
  changedPaths: S.Array$<typeof S.String>;
230
293
  affectedPaths: S.Array$<typeof S.String>;
294
+ submodelPath: S.Array$<typeof S.String>;
295
+ maybeLeafTag: S.Option<typeof S.String>;
231
296
  }>>;
232
297
  maybeNextIndex: S.Option<typeof S.Number>;
233
298
  }>, import("../schema/index.js").CallableTaggedStruct<"ResponseMessage", {
@@ -240,9 +305,9 @@ export declare const ResponseFrame: S.Struct<{
240
305
  isModelChanged: typeof S.Boolean;
241
306
  changedPaths: S.Array$<typeof S.String>;
242
307
  affectedPaths: S.Array$<typeof S.String>;
308
+ submodelPath: S.Array$<typeof S.String>;
309
+ maybeLeafTag: S.Option<typeof S.String>;
243
310
  }>;
244
- modelBefore: typeof S.Unknown;
245
- modelAfter: typeof S.Unknown;
246
311
  }>, import("../schema/index.js").CallableTaggedStruct<"ResponseKeyframes", {
247
312
  keyframes: S.Array$<S.Struct<{
248
313
  index: typeof S.Number;
@@ -257,6 +322,16 @@ export declare const ResponseFrame: S.Struct<{
257
322
  url: typeof S.String;
258
323
  title: typeof S.String;
259
324
  }>>;
325
+ }>, import("../schema/index.js").CallableTaggedStruct<"ResponseInit", {
326
+ maybeModel: S.Option<typeof S.Unknown>;
327
+ commandNames: S.Array$<typeof S.String>;
328
+ }>, import("../schema/index.js").CallableTaggedStruct<"ResponseRuntimeState", {
329
+ currentIndex: typeof S.Number;
330
+ startIndex: typeof S.Number;
331
+ totalEntries: typeof S.Number;
332
+ isPaused: typeof S.Boolean;
333
+ maybePausedAtIndex: S.Option<typeof S.Number>;
334
+ hasInitModel: typeof S.Boolean;
260
335
  }>, import("../schema/index.js").CallableTaggedStruct<"ResponseError", {
261
336
  reason: typeof S.String;
262
337
  }>]>;
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/devTools/protocol.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/devTools/protocol.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { Schema as S } from 'effect';
2
2
  import { ts } from '../schema/index.js';
3
3
  // SHARED
4
- /** A serialized history entry as it appears on the wire. */
4
+ /** A serialized history entry as it appears on the wire. `submodelPath` lists `Got<Child>Message` wrapper tags from outer to inner when the entry came up through a Submodel chain; `maybeLeafTag` is `Some` with the innermost child Message tag when one exists. */
5
5
  export const SerializedEntry = S.Struct({
6
6
  index: S.Number,
7
7
  tag: S.String,
@@ -11,6 +11,8 @@ export const SerializedEntry = S.Struct({
11
11
  isModelChanged: S.Boolean,
12
12
  changedPaths: S.Array(S.String),
13
13
  affectedPaths: S.Array(S.String),
14
+ submodelPath: S.Array(S.String),
15
+ maybeLeafTag: S.Option(S.String),
14
16
  });
15
17
  /** Metadata about a single keyframe. The index identifies the point in history where the runtime can replay back to. */
16
18
  export const KeyframeInfo = S.Struct({
@@ -23,14 +25,23 @@ export const RuntimeInfo = S.Struct({
23
25
  title: S.String,
24
26
  });
25
27
  // REQUEST
26
- /** Request the current Model snapshot. */
27
- export const RequestGetModel = ts('RequestGetModel');
28
+ /** Request the current Model snapshot, optionally narrowed to a path and/or expanded. */
29
+ export const RequestGetModel = ts('RequestGetModel', {
30
+ maybePath: S.Option(S.String),
31
+ expand: S.Boolean,
32
+ });
33
+ /** Request a historical Model snapshot at an absolute history index, optionally narrowed to a path and/or expanded. Use `index: -1` for the initial Model. */
34
+ export const RequestGetModelAt = ts('RequestGetModelAt', {
35
+ index: S.Number,
36
+ maybePath: S.Option(S.String),
37
+ expand: S.Boolean,
38
+ });
28
39
  /** Request recent history entries, optionally starting from a given index. */
29
40
  export const RequestListMessages = ts('RequestListMessages', {
30
41
  limit: S.Number,
31
42
  maybeSinceIndex: S.Option(S.Number),
32
43
  });
33
- /** Request a single history entry by index, including before/after Model snapshots. */
44
+ /** Request a single history entry by index. To inspect the Model around the entry, call `RequestGetModelAt` with `index - 1` (before) and `index` (after). */
34
45
  export const RequestGetMessage = ts('RequestGetMessage', {
35
46
  index: S.Number,
36
47
  });
@@ -42,6 +53,10 @@ export const RequestReplayToKeyframe = ts('RequestReplayToKeyframe', {
42
53
  });
43
54
  /** Request the runtime resume normal execution from a paused state. */
44
55
  export const RequestResume = ts('RequestResume');
56
+ /** Request the recorded init data: the initial Model and the names of Commands returned from `init`. */
57
+ export const RequestGetInit = ts('RequestGetInit');
58
+ /** Request a snapshot of the runtime's DevTools state: history bounds, current paused/live status, and whether init is recorded. */
59
+ export const RequestGetRuntimeState = ts('RequestGetRuntimeState');
45
60
  /** Request the runtime dispatch a Message at the current state. The payload is opaque to the protocol; the runtime validates against the app's Message Schema. */
46
61
  export const RequestDispatchMessage = ts('RequestDispatchMessage', {
47
62
  message: S.Unknown,
@@ -49,22 +64,22 @@ export const RequestDispatchMessage = ts('RequestDispatchMessage', {
49
64
  /** Request the list of currently connected browser runtimes. Handled by the Vite plugin, not forwarded to a runtime. */
50
65
  export const RequestListRuntimes = ts('RequestListRuntimes');
51
66
  /** A request from the MCP server. RequestListRuntimes is handled at the Vite plugin layer; all other requests are routed to a browser runtime. */
52
- export const Request = S.Union(RequestGetModel, RequestListMessages, RequestGetMessage, RequestListKeyframes, RequestReplayToKeyframe, RequestResume, RequestDispatchMessage, RequestListRuntimes);
67
+ export const Request = S.Union(RequestGetModel, RequestGetModelAt, RequestListMessages, RequestGetMessage, RequestListKeyframes, RequestReplayToKeyframe, RequestResume, RequestDispatchMessage, RequestListRuntimes, RequestGetInit, RequestGetRuntimeState);
53
68
  // RESPONSE
54
- /** Response carrying the current Model snapshot. */
69
+ /** Response carrying a Model snapshot. The `value` is the resolved subtree at `atPath` (or the whole Model when no path was supplied). When `summarized` is true, large arrays/records/strings have been collapsed to `_summary` placeholders to keep payloads small for AI agents; pass `expand: true` on the Request to receive the literal value. */
55
70
  export const ResponseModel = ts('ResponseModel', {
56
- model: S.Unknown,
71
+ value: S.Unknown,
72
+ atPath: S.String,
73
+ summarized: S.Boolean,
57
74
  });
58
75
  /** Response carrying a page of history entries. `maybeNextIndex` is `Some` when more entries are available beyond this page (pass it as `RequestListMessages.maybeSinceIndex` to fetch the next page) and `None` when this page reaches the current end of history. */
59
76
  export const ResponseMessages = ts('ResponseMessages', {
60
77
  entries: S.Array(SerializedEntry),
61
78
  maybeNextIndex: S.Option(S.Number),
62
79
  });
63
- /** Response carrying a single history entry with surrounding Model snapshots. */
80
+ /** Response carrying a single history entry. Model snapshots are not included; use `RequestGetModelAt` with `index - 1` and `index` to inspect Model state around the entry. */
64
81
  export const ResponseMessage = ts('ResponseMessage', {
65
82
  entry: SerializedEntry,
66
- modelBefore: S.Unknown,
67
- modelAfter: S.Unknown,
68
83
  });
69
84
  /** Response carrying the list of available keyframes. */
70
85
  export const ResponseKeyframes = ts('ResponseKeyframes', {
@@ -84,12 +99,26 @@ export const ResponseDispatched = ts('ResponseDispatched', {
84
99
  export const ResponseRuntimes = ts('ResponseRuntimes', {
85
100
  runtimes: S.Array(RuntimeInfo),
86
101
  });
102
+ /** Response carrying the recorded init data. `maybeModel` is `None` until the runtime has finished its first render and recorded init; once set it stays set for the rest of the runtime's life. `commandNames` lists the Commands returned from the application's `init` function in the order they were produced. */
103
+ export const ResponseInit = ts('ResponseInit', {
104
+ maybeModel: S.Option(S.Unknown),
105
+ commandNames: S.Array(S.String),
106
+ });
107
+ /** Response carrying a snapshot of the runtime's DevTools state. `currentIndex` is the absolute index of the most recently recorded Message, or -1 when no Messages have been recorded yet. `startIndex` is the earliest absolute index still retained in the rolling buffer (older entries are evicted past `maxEntries`). `totalEntries` is the number of retained entries. `isPaused` is true while the runtime is paused at a replayed snapshot; `maybePausedAtIndex` is `Some(index)` then and `None` otherwise. `hasInitModel` is true once the runtime has finished initialising. */
108
+ export const ResponseRuntimeState = ts('ResponseRuntimeState', {
109
+ currentIndex: S.Number,
110
+ startIndex: S.Number,
111
+ totalEntries: S.Number,
112
+ isPaused: S.Boolean,
113
+ maybePausedAtIndex: S.Option(S.Number),
114
+ hasInitModel: S.Boolean,
115
+ });
87
116
  /** Response carrying an error reason for a failed Request. */
88
117
  export const ResponseError = ts('ResponseError', {
89
118
  reason: S.String,
90
119
  });
91
120
  /** A response replying to a Request. */
92
- export const Response = S.Union(ResponseModel, ResponseMessages, ResponseMessage, ResponseKeyframes, ResponseReplayed, ResponseResumed, ResponseDispatched, ResponseRuntimes, ResponseError);
121
+ export const Response = S.Union(ResponseModel, ResponseMessages, ResponseMessage, ResponseKeyframes, ResponseReplayed, ResponseResumed, ResponseDispatched, ResponseRuntimes, ResponseInit, ResponseRuntimeState, ResponseError);
93
122
  // EVENT
94
123
  /** A new browser runtime connected. */
95
124
  export const EventConnected = ts('EventConnected', {
@@ -1,2 +1,2 @@
1
- export { EventConnected, EventDisconnected, EventFrame, Event, KeyframeInfo, RequestDispatchMessage, RequestFrame, RequestGetMessage, RequestGetModel, RequestListKeyframes, RequestListMessages, RequestListRuntimes, RequestReplayToKeyframe, RequestResume, Request, ResponseDispatched, ResponseError, ResponseFrame, ResponseKeyframes, ResponseMessage, ResponseMessages, ResponseModel, ResponseReplayed, ResponseResumed, ResponseRuntimes, Response, RuntimeInfo, SerializedEntry, } from './protocol.js';
1
+ export { EventConnected, EventDisconnected, EventFrame, Event, KeyframeInfo, RequestDispatchMessage, RequestFrame, RequestGetInit, RequestGetMessage, RequestGetModel, RequestGetModelAt, RequestGetRuntimeState, RequestListKeyframes, RequestListMessages, RequestListRuntimes, RequestReplayToKeyframe, RequestResume, Request, ResponseDispatched, ResponseError, ResponseFrame, ResponseInit, ResponseKeyframes, ResponseMessage, ResponseMessages, ResponseModel, ResponseReplayed, ResponseResumed, ResponseRuntimes, ResponseRuntimeState, Response, RuntimeInfo, SerializedEntry, } from './protocol.js';
2
2
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/devTools/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,KAAK,EACL,YAAY,EACZ,sBAAsB,EACtB,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACvB,aAAa,EACb,OAAO,EACP,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACR,WAAW,EACX,eAAe,GAChB,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/devTools/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,KAAK,EACL,YAAY,EACZ,sBAAsB,EACtB,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACvB,aAAa,EACb,OAAO,EACP,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,QAAQ,EACR,WAAW,EACX,eAAe,GAChB,MAAM,eAAe,CAAA"}
@@ -1 +1 @@
1
- export { EventConnected, EventDisconnected, EventFrame, Event, KeyframeInfo, RequestDispatchMessage, RequestFrame, RequestGetMessage, RequestGetModel, RequestListKeyframes, RequestListMessages, RequestListRuntimes, RequestReplayToKeyframe, RequestResume, Request, ResponseDispatched, ResponseError, ResponseFrame, ResponseKeyframes, ResponseMessage, ResponseMessages, ResponseModel, ResponseReplayed, ResponseResumed, ResponseRuntimes, Response, RuntimeInfo, SerializedEntry, } from './protocol.js';
1
+ export { EventConnected, EventDisconnected, EventFrame, Event, KeyframeInfo, RequestDispatchMessage, RequestFrame, RequestGetInit, RequestGetMessage, RequestGetModel, RequestGetModelAt, RequestGetRuntimeState, RequestListKeyframes, RequestListMessages, RequestListRuntimes, RequestReplayToKeyframe, RequestResume, Request, ResponseDispatched, ResponseError, ResponseFrame, ResponseInit, ResponseKeyframes, ResponseMessage, ResponseMessages, ResponseModel, ResponseReplayed, ResponseResumed, ResponseRuntimes, ResponseRuntimeState, Response, RuntimeInfo, SerializedEntry, } from './protocol.js';
@@ -1 +1 @@
1
- {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/devTools/serialize.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,KAAG,OAiBjD,CAAA;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAC5B,OAAO,YAAY,EACnB,OAAO,MAAM,KACZ,eASD,CAAA"}
1
+ {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/devTools/serialize.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAG9C;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,KAAG,OAiBjD,CAAA;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAC5B,OAAO,YAAY,EACnB,OAAO,MAAM,KACZ,eAkBF,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import { Array as Array_, Function, HashSet, Match as M, Predicate, Record, } from 'effect';
2
+ import { extractSubmodelInfo } from './submodelPath.js';
2
3
  /**
3
4
  * Convert DOM-class instances (File, Blob, Date, URL) to plain-object
4
5
  * representations so the tree renderer's key-enumeration walk can see their
@@ -22,13 +23,18 @@ export const toInspectableValue = (value) => M.value(value).pipe(M.when(M.instan
22
23
  * plain string arrays for JSON transmission and runs the message body through
23
24
  * `toInspectableValue` so DOM-class instances become inspectable objects.
24
25
  */
25
- export const toSerializedEntry = (entry, index) => ({
26
- index,
27
- tag: entry.tag,
28
- message: toInspectableValue(entry.message),
29
- commandNames: entry.commandNames,
30
- timestamp: entry.timestamp,
31
- isModelChanged: entry.isModelChanged,
32
- changedPaths: HashSet.toValues(entry.diff.changedPaths),
33
- affectedPaths: HashSet.toValues(entry.diff.affectedPaths),
34
- });
26
+ export const toSerializedEntry = (entry, index) => {
27
+ const { submodelPath, maybeLeafTag } = extractSubmodelInfo(entry.tag, entry.message);
28
+ return {
29
+ index,
30
+ tag: entry.tag,
31
+ message: toInspectableValue(entry.message),
32
+ commandNames: entry.commandNames,
33
+ timestamp: entry.timestamp,
34
+ isModelChanged: entry.isModelChanged,
35
+ changedPaths: HashSet.toValues(entry.diff.changedPaths),
36
+ affectedPaths: HashSet.toValues(entry.diff.affectedPaths),
37
+ submodelPath,
38
+ maybeLeafTag,
39
+ };
40
+ };
@@ -0,0 +1,27 @@
1
+ import { Option } from 'effect';
2
+ export declare const GOT_MESSAGE_PATTERN: RegExp;
3
+ export declare const isTagged: (u: unknown, overrideOptions?: import("effect/SchemaAST").ParseOptions | number) => u is {
4
+ readonly _tag: string;
5
+ };
6
+ /** Submodel chain information extracted from a recorded Message. */
7
+ export type SubmodelInfo = Readonly<{
8
+ submodelPath: ReadonlyArray<string>;
9
+ maybeLeafTag: Option.Option<string>;
10
+ }>;
11
+ /**
12
+ * Walk a chain of `Got<Submodel>Message` wrappers in a recorded Message and
13
+ * return the wrapper tags plus the innermost leaf tag.
14
+ *
15
+ * The Submodel pattern propagates child Messages up to a parent by wrapping
16
+ * them in `GotChildMessage({ message: childMessage })`. Nested submodels stack
17
+ * those wrappers. Walking the chain reveals the parent → child → grandchild
18
+ * dispatch path that produced the entry.
19
+ *
20
+ * Returns an empty path and `Option.none` for top-level Messages whose tag
21
+ * doesn't match the `Got*Message` pattern. Otherwise the path lists wrapper
22
+ * tags from outer to inner, and `maybeLeafTag` is `Some` when the innermost
23
+ * wrapped value is itself a tagged Message (the underlying child Message that
24
+ * originated the chain).
25
+ */
26
+ export declare const extractSubmodelInfo: (tag: string, message: unknown) => SubmodelInfo;
27
+ //# sourceMappingURL=submodelPath.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"submodelPath.d.ts","sourceRoot":"","sources":["../../src/devTools/submodelPath.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,QAAQ,CAAA;AAElD,eAAO,MAAM,mBAAmB,QAAmB,CAAA;AAGnD,eAAO,MAAM,QAAQ;;CAAe,CAAA;AAEpC,oEAAoE;AACpE,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC;IAClC,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACnC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;CACpC,CAAC,CAAA;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,GAC9B,KAAK,MAAM,EACX,SAAS,OAAO,KACf,YAuBF,CAAA"}
@@ -0,0 +1,36 @@
1
+ import { Option, Schema as S, pipe } from 'effect';
2
+ export const GOT_MESSAGE_PATTERN = /^Got.+Message$/;
3
+ const Tagged = S.Struct({ _tag: S.String });
4
+ export const isTagged = S.is(Tagged);
5
+ /**
6
+ * Walk a chain of `Got<Submodel>Message` wrappers in a recorded Message and
7
+ * return the wrapper tags plus the innermost leaf tag.
8
+ *
9
+ * The Submodel pattern propagates child Messages up to a parent by wrapping
10
+ * them in `GotChildMessage({ message: childMessage })`. Nested submodels stack
11
+ * those wrappers. Walking the chain reveals the parent → child → grandchild
12
+ * dispatch path that produced the entry.
13
+ *
14
+ * Returns an empty path and `Option.none` for top-level Messages whose tag
15
+ * doesn't match the `Got*Message` pattern. Otherwise the path lists wrapper
16
+ * tags from outer to inner, and `maybeLeafTag` is `Some` when the innermost
17
+ * wrapped value is itself a tagged Message (the underlying child Message that
18
+ * originated the chain).
19
+ */
20
+ export const extractSubmodelInfo = (tag, message) => {
21
+ if (!GOT_MESSAGE_PATTERN.test(tag)) {
22
+ return { submodelPath: [], maybeLeafTag: Option.none() };
23
+ }
24
+ const path = [tag];
25
+ /* eslint-disable @typescript-eslint/consistent-type-assertions */
26
+ let current = message?.['message'];
27
+ while (isTagged(current) && GOT_MESSAGE_PATTERN.test(current._tag)) {
28
+ path.push(current._tag);
29
+ current = current?.['message'];
30
+ }
31
+ /* eslint-enable @typescript-eslint/consistent-type-assertions */
32
+ return {
33
+ submodelPath: path,
34
+ maybeLeafTag: pipe(current, Option.liftPredicate(isTagged), Option.map(({ _tag }) => _tag)),
35
+ };
36
+ };
@@ -0,0 +1,46 @@
1
+ import { Schema as S } from 'effect';
2
+ declare const PathResolution: S.Union<[import("../schema/index.js").CallableTaggedStruct<"Found", {
3
+ value: typeof S.Unknown;
4
+ atPath: typeof S.String;
5
+ }>, import("../schema/index.js").CallableTaggedStruct<"NotFound", {
6
+ failedAt: typeof S.String;
7
+ reason: typeof S.String;
8
+ availableKeys: S.Array$<typeof S.String>;
9
+ }>]>;
10
+ /**
11
+ * Result of resolving a dot-string path against a Model snapshot.
12
+ *
13
+ * The path representation matches `SerializedEntry.changedPaths` exactly:
14
+ * dot-separated, anchored at the literal segment `root`. `Found.atPath`
15
+ * echoes the canonicalized path; `NotFound.availableKeys` lists the keys
16
+ * present at the deepest segment that resolved, so an agent can recover with
17
+ * one follow-up call.
18
+ */
19
+ export type PathResolution = typeof PathResolution.Type;
20
+ /**
21
+ * Walk a dot-string path against a Model snapshot. Returns the resolved value
22
+ * on success, or a structured `NotFound` describing the deepest segment that
23
+ * resolved plus its available keys so an agent can refine.
24
+ */
25
+ export declare const resolvePath: (root: unknown, path: string) => PathResolution;
26
+ /**
27
+ * Apply structural summarization rules to a value:
28
+ * - Arrays collapse to `{ _summary, length, sample: [head, last] }` at every depth.
29
+ * - Records walk to a depth of 3, then collapse to `{ _summary, keys }`.
30
+ * - Long strings collapse to `{ _summary, length, head }`.
31
+ * - Tagged values (`{ _tag, ... }`) keep their `_tag` since it's a record key.
32
+ *
33
+ * The result is JSON-serializable and intended for transmission to MCP clients
34
+ * with `expand: false`. Use raw values directly when `expand: true`.
35
+ */
36
+ export declare const summarizeValue: (value: unknown) => unknown;
37
+ /**
38
+ * Format a `NotFound` resolution as a single human-readable line for the
39
+ * `ResponseError.reason` channel. Includes the available keys at the failure
40
+ * point so an agent can refine the path on the next call.
41
+ */
42
+ export declare const formatPathNotFound: (notFound: Extract<PathResolution, {
43
+ _tag: "NotFound";
44
+ }>) => string;
45
+ export {};
46
+ //# sourceMappingURL=summarize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarize.d.ts","sourceRoot":"","sources":["../../src/devTools/summarize.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,MAAM,IAAI,CAAC,EACZ,MAAM,QAAQ,CAAA;AAwBf,QAAA,MAAM,cAAc;;;;;;;IAA2B,CAAA;AAE/C;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAA;AAiCvD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,OAAO,EAAE,MAAM,MAAM,KAAG,cAmCzD,CAAA;AA2DD;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,OAAgC,CAAA;AAYhF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAC7B,UAAU,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,KACtD,MAIC,CAAA"}
@@ -0,0 +1,111 @@
1
+ import { Array as Array_, Function, Match as M, Option, Predicate, Record, Schema as S, } from 'effect';
2
+ import { OptionExt } from '../effectExtensions/index.js';
3
+ import { ts } from '../schema/index.js';
4
+ const ROOT = 'root';
5
+ const PATH_SEPARATOR = '.';
6
+ const MAX_DEPTH = 3;
7
+ const STRING_TRUNCATE = 200;
8
+ const ARRAY_SAMPLE = 2;
9
+ // PATH
10
+ const Found = ts('Found', {
11
+ value: S.Unknown,
12
+ atPath: S.String,
13
+ });
14
+ const NotFound = ts('NotFound', {
15
+ failedAt: S.String,
16
+ reason: S.String,
17
+ availableKeys: S.Array(S.String),
18
+ });
19
+ const PathResolution = S.Union(Found, NotFound);
20
+ const isExpandable = (value) => Predicate.isReadonlyRecord(value) || Array.isArray(value);
21
+ const keysOf = (value) => M.value(value).pipe(M.when(Array.isArray, items => Array_.makeBy(items.length, index => index.toString())), M.when(Predicate.isReadonlyRecord, Record.keys), M.orElse(() => []));
22
+ const segmentsOf = (path) => path === ROOT ? [] : path.split(PATH_SEPARATOR).slice(1);
23
+ const isRootAnchored = (path) => path === ROOT || path.startsWith(`${ROOT}${PATH_SEPARATOR}`);
24
+ const descend = (parent, segment) => M.value(parent).pipe(M.when(Array.isArray, array => Option.liftPredicate(Number(segment), Number.isInteger).pipe(Option.flatMap(index => Array_.get(array, index)))), M.when(Predicate.isReadonlyRecord, record => Record.get(record, segment)), M.orElse(() => Option.none()));
25
+ /**
26
+ * Walk a dot-string path against a Model snapshot. Returns the resolved value
27
+ * on success, or a structured `NotFound` describing the deepest segment that
28
+ * resolved plus its available keys so an agent can refine.
29
+ */
30
+ export const resolvePath = (root, path) => {
31
+ if (!isRootAnchored(path)) {
32
+ return NotFound({
33
+ failedAt: '',
34
+ reason: `Path must start with '${ROOT}'. Received: '${path}'.`,
35
+ availableKeys: [],
36
+ });
37
+ }
38
+ const initial = Found({ value: root, atPath: ROOT });
39
+ return Array_.reduce(segmentsOf(path), initial, (resolution, segment) => {
40
+ if (resolution._tag === 'NotFound') {
41
+ return resolution;
42
+ }
43
+ return Option.match(descend(resolution.value, segment), {
44
+ onNone: () => NotFound({
45
+ failedAt: resolution.atPath,
46
+ reason: isExpandable(resolution.value)
47
+ ? `No '${segment}' at '${resolution.atPath}'.`
48
+ : `Cannot descend into a primitive at '${resolution.atPath}' (looking for '${segment}').`,
49
+ availableKeys: keysOf(resolution.value),
50
+ }),
51
+ onSome: descended => Found({
52
+ value: descended,
53
+ atPath: `${resolution.atPath}${PATH_SEPARATOR}${segment}`,
54
+ }),
55
+ });
56
+ });
57
+ };
58
+ // SUMMARIZE
59
+ const truncateString = (value) => value.length <= STRING_TRUNCATE
60
+ ? value
61
+ : {
62
+ _summary: 'string',
63
+ length: value.length,
64
+ head: value.slice(0, STRING_TRUNCATE),
65
+ };
66
+ const sampleArray = (items, depth) => {
67
+ const sample = items.length <= ARRAY_SAMPLE
68
+ ? items
69
+ : [
70
+ ...Array_.take(items, ARRAY_SAMPLE - 1),
71
+ ...Option.toArray(Array_.last(items)),
72
+ ];
73
+ return Array_.map(sample, item => summarizeAt(item, depth + 1));
74
+ };
75
+ const summarizeArray = (items, depth) => ({
76
+ _summary: 'array',
77
+ length: items.length,
78
+ sample: sampleArray(items, depth),
79
+ });
80
+ const summarizeRecord = (value, depth) => {
81
+ if (depth >= MAX_DEPTH) {
82
+ return {
83
+ _summary: 'record',
84
+ keys: Record.keys(value),
85
+ };
86
+ }
87
+ return Record.map(value, child => summarizeAt(child, depth + 1));
88
+ };
89
+ const summarizeAt = (value, depth) => M.value(value).pipe(M.when(Predicate.isString, truncateString), M.when(Array.isArray, items => summarizeArray(items, depth)), M.when(Predicate.isReadonlyRecord, record => summarizeRecord(record, depth)), M.orElse(Function.identity));
90
+ /**
91
+ * Apply structural summarization rules to a value:
92
+ * - Arrays collapse to `{ _summary, length, sample: [head, last] }` at every depth.
93
+ * - Records walk to a depth of 3, then collapse to `{ _summary, keys }`.
94
+ * - Long strings collapse to `{ _summary, length, head }`.
95
+ * - Tagged values (`{ _tag, ... }`) keep their `_tag` since it's a record key.
96
+ *
97
+ * The result is JSON-serializable and intended for transmission to MCP clients
98
+ * with `expand: false`. Use raw values directly when `expand: true`.
99
+ */
100
+ export const summarizeValue = (value) => summarizeAt(value, 0);
101
+ // FORMAT
102
+ const formatAvailableKeys = (keys) => OptionExt.when(Array_.isNonEmptyReadonlyArray(keys), `Available keys: ${keys.join(', ')}.`);
103
+ /**
104
+ * Format a `NotFound` resolution as a single human-readable line for the
105
+ * `ResponseError.reason` channel. Includes the available keys at the failure
106
+ * point so an agent can refine the path on the next call.
107
+ */
108
+ export const formatPathNotFound = (notFound) => Option.match(formatAvailableKeys(notFound.availableKeys), {
109
+ onNone: () => notFound.reason,
110
+ onSome: hint => `${notFound.reason} ${hint}`,
111
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"webSocketBridge.d.ts","sourceRoot":"","sources":["../../src/devTools/webSocketBridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,MAAM,EAIN,MAAM,EAGN,MAAM,IAAI,CAAC,EAGZ,MAAM,QAAQ,CAAA;AAuBf,OAAO,EAAE,KAAK,aAAa,EAAc,MAAM,YAAY,CAAA;AAE3D,KAAK,GAAG,GAAG,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAA;AAczC;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,oBAAoB,GAC/B,OAAO,aAAa,EACpB,KAAK,GAAG,EACR,UAAU,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EACnD,oBAAoB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,KAC3D,MAAM,CAAC,MAAM,CAAC,IAAI,CA0EjB,CAAA"}
1
+ {"version":3,"file":"webSocketBridge.d.ts","sourceRoot":"","sources":["../../src/devTools/webSocketBridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,MAAM,EAIN,MAAM,EAGN,MAAM,IAAI,CAAC,EAGZ,MAAM,QAAQ,CAAA;AAyBf,OAAO,EAAE,KAAK,aAAa,EAAc,MAAM,YAAY,CAAA;AAQ3D,KAAK,GAAG,GAAG,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAA;AAczC;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,oBAAoB,GAC/B,OAAO,aAAa,EACpB,KAAK,GAAG,EACR,UAAU,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EACnD,oBAAoB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,KAC3D,MAAM,CAAC,MAAM,CAAC,IAAI,CA0EjB,CAAA"}
@@ -1,8 +1,9 @@
1
1
  import { Array, Cause, Effect, Either, HashMap, Match, Option, Order, Runtime, Schema as S, SubscriptionRef, pipe, } from 'effect';
2
2
  import { OptionExt } from '../effectExtensions/index.js';
3
- import { EventConnected, EventDisconnected, KeyframeInfo, RequestFrame, ResponseDispatched, ResponseError, ResponseKeyframes, ResponseMessage, ResponseMessages, ResponseModel, ResponseReplayed, ResponseResumed, RuntimeInfo, } from './protocol.js';
3
+ import { EventConnected, EventDisconnected, KeyframeInfo, RequestFrame, ResponseDispatched, ResponseError, ResponseInit, ResponseKeyframes, ResponseMessage, ResponseMessages, ResponseModel, ResponseReplayed, ResponseResumed, ResponseRuntimeState, RuntimeInfo, } from './protocol.js';
4
4
  import { toInspectableValue, toSerializedEntry } from './serialize.js';
5
5
  import { INIT_INDEX } from './store.js';
6
+ import { formatPathNotFound, resolvePath, summarizeValue, } from './summarize.js';
6
7
  const REQUEST_CHANNEL = 'foldkit:devTools:request';
7
8
  const RESPONSE_CHANNEL = 'foldkit:devTools:response';
8
9
  const EVENT_CHANNEL = 'foldkit:devTools:event';
@@ -80,14 +81,25 @@ export const startWebSocketBridge = (store, hot, dispatch, maybeMessageSchema) =
80
81
  });
81
82
  window.addEventListener('beforeunload', emitDisconnect, { once: true });
82
83
  });
84
+ const presentResolution = (resolution, expand) => Match.value(resolution).pipe(Match.tag('Found', ({ value, atPath }) => ResponseModel({
85
+ value: expand ? value : summarizeValue(value),
86
+ atPath,
87
+ summarized: !expand,
88
+ })), Match.orElse(notFound => ResponseError({ reason: formatPathNotFound(notFound) })));
89
+ const readModelResponse = (store, index, maybePath, expand) => Effect.gen(function* () {
90
+ const model = yield* store.getModelAtIndex(index);
91
+ const path = Option.getOrElse(maybePath, () => 'root');
92
+ return presentResolution(resolvePath(toInspectableValue(model), path), expand);
93
+ }).pipe(Effect.catchAllCause(cause => Effect.succeed(ResponseError({
94
+ reason: `Failed to read Model at index ${index}: ${Cause.pretty(cause)}`,
95
+ }))));
83
96
  const dispatchRequest = (store, dispatch, maybeMessageSchema, request) => Match.value(request).pipe(Match.tagsExhaustive({
84
- RequestGetModel: () => Effect.gen(function* () {
97
+ RequestGetModel: ({ maybePath, expand }) => Effect.gen(function* () {
85
98
  const state = yield* SubscriptionRef.get(store.stateRef);
86
99
  const index = currentAbsoluteIndex(state.entries.length, state.startIndex);
87
- return yield* pipe(index, store.getModelAtIndex, Effect.map(model => ResponseModel({ model: toInspectableValue(model) })), Effect.catchAllCause(cause => Effect.succeed(ResponseError({
88
- reason: `Failed to read current Model: ${Cause.pretty(cause)}`,
89
- }))));
100
+ return yield* readModelResponse(store, index, maybePath, expand);
90
101
  }),
102
+ RequestGetModelAt: ({ index, maybePath, expand }) => readModelResponse(store, index, maybePath, expand),
91
103
  RequestListMessages: ({ limit, maybeSinceIndex }) => Effect.gen(function* () {
92
104
  const state = yield* SubscriptionRef.get(store.stateRef);
93
105
  const startAbsolute = Option.getOrElse(maybeSinceIndex, () => state.startIndex);
@@ -106,16 +118,9 @@ const dispatchRequest = (store, dispatch, maybeMessageSchema, request) => Match.
106
118
  onNone: () => Effect.succeed(ResponseError({
107
119
  reason: `No entry at index ${index} (have ${state.startIndex} to ${state.startIndex + state.entries.length - 1})`,
108
120
  })),
109
- onSome: entry => pipe({
110
- modelBefore: store.getModelAtIndex(index - 1),
111
- modelAfter: store.getModelAtIndex(index),
112
- }, Effect.all, Effect.map(({ modelBefore, modelAfter }) => ResponseMessage({
121
+ onSome: entry => Effect.succeed(ResponseMessage({
113
122
  entry: toSerializedEntry(entry, index),
114
- modelBefore: toInspectableValue(modelBefore),
115
- modelAfter: toInspectableValue(modelAfter),
116
- })), Effect.catchAllCause(cause => Effect.succeed(ResponseError({
117
- reason: `Failed to read Models around index ${index}: ${Cause.pretty(cause)}`,
118
- })))),
123
+ })),
119
124
  });
120
125
  }),
121
126
  RequestListKeyframes: () => Effect.gen(function* () {
@@ -158,4 +163,23 @@ const dispatchRequest = (store, dispatch, maybeMessageSchema, request) => Match.
158
163
  RequestListRuntimes: () => Effect.succeed(ResponseError({
159
164
  reason: 'RequestListRuntimes is plugin-handled and should not reach the runtime bridge',
160
165
  })),
166
+ RequestGetInit: () => Effect.gen(function* () {
167
+ const state = yield* SubscriptionRef.get(store.stateRef);
168
+ return ResponseInit({
169
+ maybeModel: Option.map(state.maybeInitModel, toInspectableValue),
170
+ commandNames: state.initCommandNames,
171
+ });
172
+ }),
173
+ RequestGetRuntimeState: () => Effect.gen(function* () {
174
+ const state = yield* SubscriptionRef.get(store.stateRef);
175
+ const currentIndex = currentAbsoluteIndex(state.entries.length, state.startIndex);
176
+ return ResponseRuntimeState({
177
+ currentIndex,
178
+ startIndex: state.startIndex,
179
+ totalEntries: state.entries.length,
180
+ isPaused: state.isPaused,
181
+ maybePausedAtIndex: OptionExt.when(state.isPaused, state.pausedAtIndex),
182
+ hasInitModel: Option.isSome(state.maybeInitModel),
183
+ });
184
+ }),
161
185
  }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foldkit",
3
- "version": "0.77.0",
3
+ "version": "0.78.0",
4
4
  "description": "A frontend framework for TypeScript, built on Effect, using The Elm Architecture",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",