libretto 0.6.10 → 0.6.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +4 -0
  2. package/README.template.md +4 -0
  3. package/dist/cli/cli.js +4 -3
  4. package/dist/cli/commands/ai.js +3 -2
  5. package/dist/cli/commands/browser.js +17 -17
  6. package/dist/cli/commands/execution.js +254 -234
  7. package/dist/cli/commands/experiments.js +100 -0
  8. package/dist/cli/commands/setup.js +20 -34
  9. package/dist/cli/commands/shared.js +10 -0
  10. package/dist/cli/commands/snapshot.js +81 -9
  11. package/dist/cli/commands/status.js +5 -4
  12. package/dist/cli/core/ai-model.js +6 -3
  13. package/dist/cli/core/browser.js +300 -121
  14. package/dist/cli/core/config.js +4 -2
  15. package/dist/cli/core/context.js +4 -0
  16. package/dist/cli/core/daemon/config.js +0 -6
  17. package/dist/cli/core/daemon/daemon.js +535 -89
  18. package/dist/cli/core/daemon/ipc.js +170 -129
  19. package/dist/cli/core/daemon/snapshot.js +72 -6
  20. package/dist/cli/core/experiments.js +66 -0
  21. package/dist/cli/core/session.js +5 -4
  22. package/dist/cli/core/skill-version.js +2 -1
  23. package/dist/cli/core/snapshot-analyzer.js +4 -3
  24. package/dist/cli/core/workflow-runner/runner.js +147 -0
  25. package/dist/cli/core/workflow-runtime.js +60 -0
  26. package/dist/cli/router.js +4 -1
  27. package/dist/shared/debug/pause-handler.d.ts +9 -0
  28. package/dist/shared/debug/pause-handler.js +15 -0
  29. package/dist/shared/debug/pause.d.ts +1 -2
  30. package/dist/shared/debug/pause.js +13 -36
  31. package/dist/shared/ipc/child-process-transport.d.ts +7 -0
  32. package/dist/shared/ipc/child-process-transport.js +60 -0
  33. package/dist/shared/ipc/child-process-transport.spec.d.ts +2 -0
  34. package/dist/shared/ipc/child-process-transport.spec.js +68 -0
  35. package/dist/shared/ipc/ipc.d.ts +46 -0
  36. package/dist/shared/ipc/ipc.js +165 -0
  37. package/dist/shared/ipc/ipc.spec.d.ts +2 -0
  38. package/dist/shared/ipc/ipc.spec.js +114 -0
  39. package/dist/shared/ipc/socket-transport.d.ts +9 -0
  40. package/dist/shared/ipc/socket-transport.js +143 -0
  41. package/dist/shared/ipc/socket-transport.spec.d.ts +2 -0
  42. package/dist/shared/ipc/socket-transport.spec.js +117 -0
  43. package/dist/shared/package-manager.d.ts +7 -0
  44. package/dist/shared/package-manager.js +60 -0
  45. package/dist/shared/paths/paths.d.ts +1 -8
  46. package/dist/shared/paths/paths.js +1 -49
  47. package/dist/shared/snapshot/capture-snapshot.d.ts +9 -0
  48. package/dist/shared/snapshot/capture-snapshot.js +463 -0
  49. package/dist/shared/snapshot/diff-snapshots.d.ts +72 -0
  50. package/dist/shared/snapshot/diff-snapshots.js +358 -0
  51. package/dist/shared/snapshot/render-snapshot.d.ts +39 -0
  52. package/dist/shared/snapshot/render-snapshot.js +651 -0
  53. package/dist/shared/snapshot/snapshot.spec.d.ts +2 -0
  54. package/dist/shared/snapshot/snapshot.spec.js +333 -0
  55. package/dist/shared/snapshot/types.d.ts +40 -0
  56. package/dist/shared/snapshot/types.js +0 -0
  57. package/dist/shared/snapshot/wait-for-page-stable.d.ts +17 -0
  58. package/dist/shared/snapshot/wait-for-page-stable.js +281 -0
  59. package/dist/shared/state/session-state.d.ts +1 -0
  60. package/dist/shared/state/session-state.js +1 -0
  61. package/docs/experiments.md +67 -0
  62. package/package.json +4 -2
  63. package/skills/libretto/SKILL.md +3 -1
  64. package/skills/libretto-readonly/SKILL.md +1 -1
  65. package/src/cli/AGENTS.md +7 -0
  66. package/src/cli/cli.ts +4 -3
  67. package/src/cli/commands/ai.ts +3 -2
  68. package/src/cli/commands/browser.ts +13 -11
  69. package/src/cli/commands/execution.ts +303 -271
  70. package/src/cli/commands/experiments.ts +120 -0
  71. package/src/cli/commands/setup.ts +18 -36
  72. package/src/cli/commands/shared.ts +20 -0
  73. package/src/cli/commands/snapshot.ts +99 -11
  74. package/src/cli/commands/status.ts +5 -4
  75. package/src/cli/core/ai-model.ts +6 -3
  76. package/src/cli/core/browser.ts +369 -147
  77. package/src/cli/core/config.ts +3 -1
  78. package/src/cli/core/context.ts +4 -0
  79. package/src/cli/core/daemon/config.ts +35 -19
  80. package/src/cli/core/daemon/daemon.ts +686 -106
  81. package/src/cli/core/daemon/ipc.ts +330 -214
  82. package/src/cli/core/daemon/snapshot.ts +106 -8
  83. package/src/cli/core/experiments.ts +85 -0
  84. package/src/cli/core/session.ts +5 -4
  85. package/src/cli/core/skill-version.ts +2 -1
  86. package/src/cli/core/snapshot-analyzer.ts +4 -3
  87. package/src/cli/core/workflow-runner/runner.ts +237 -0
  88. package/src/cli/core/workflow-runtime.ts +85 -0
  89. package/src/cli/router.ts +4 -1
  90. package/src/shared/debug/pause-handler.ts +20 -0
  91. package/src/shared/debug/pause.ts +14 -48
  92. package/src/shared/ipc/AGENTS.md +24 -0
  93. package/src/shared/ipc/child-process-transport.spec.ts +86 -0
  94. package/src/shared/ipc/child-process-transport.ts +96 -0
  95. package/src/shared/ipc/ipc.spec.ts +161 -0
  96. package/src/shared/ipc/ipc.ts +288 -0
  97. package/src/shared/ipc/socket-transport.spec.ts +141 -0
  98. package/src/shared/ipc/socket-transport.ts +189 -0
  99. package/src/shared/package-manager.ts +76 -0
  100. package/src/shared/paths/paths.ts +0 -72
  101. package/src/shared/snapshot/capture-snapshot.ts +615 -0
  102. package/src/shared/snapshot/diff-snapshots.ts +579 -0
  103. package/src/shared/snapshot/render-snapshot.ts +962 -0
  104. package/src/shared/snapshot/snapshot.spec.ts +388 -0
  105. package/src/shared/snapshot/types.ts +43 -0
  106. package/src/shared/snapshot/wait-for-page-stable.ts +425 -0
  107. package/src/shared/state/session-state.ts +1 -0
  108. package/dist/cli/core/daemon/index.js +0 -16
  109. package/dist/cli/core/daemon/spawn.js +0 -90
  110. package/dist/cli/core/pause-signals.js +0 -29
  111. package/dist/cli/workers/run-integration-runtime.js +0 -235
  112. package/dist/cli/workers/run-integration-worker-protocol.js +0 -17
  113. package/dist/cli/workers/run-integration-worker.js +0 -64
  114. package/src/cli/core/daemon/index.ts +0 -24
  115. package/src/cli/core/daemon/spawn.ts +0 -171
  116. package/src/cli/core/pause-signals.ts +0 -35
  117. package/src/cli/workers/run-integration-runtime.ts +0 -326
  118. package/src/cli/workers/run-integration-worker-protocol.ts +0 -19
  119. package/src/cli/workers/run-integration-worker.ts +0 -72
@@ -0,0 +1,358 @@
1
+ import {
2
+ renderChildrenTruncationNotice,
3
+ renderFrame,
4
+ renderNode,
5
+ renderSnapshotFrames
6
+ } from "./render-snapshot.js";
7
+ const MAX_DIFF_CHILDREN_PER_PARENT = 4;
8
+ const MAX_LABEL_CHARS = 140;
9
+ const LOW_SIGNAL_DIFF_ATTRS = /* @__PURE__ */ new Set(["ref"]);
10
+ function diffSnapshots(before, after) {
11
+ const beforeFrames = renderSnapshotFrames(before);
12
+ const afterFrames = renderSnapshotFrames(after);
13
+ const pageChanged = before.title !== after.title || before.url !== after.url;
14
+ const frames = diffFrames(beforeFrames, afterFrames);
15
+ return {
16
+ before,
17
+ after,
18
+ pageChanged,
19
+ frames,
20
+ changed: pageChanged || frames.length > 0
21
+ };
22
+ }
23
+ function renderSnapshotDiff(diff) {
24
+ if (!diff.changed) return "";
25
+ if (diff.pageChanged && diff.frames.length === 0) {
26
+ return [
27
+ renderPageOpen(diff.before, "- ", true),
28
+ renderPageOpen(diff.after, "+ ", true)
29
+ ].join("\n");
30
+ }
31
+ const lines = [renderPageOpen(diff.after, "")];
32
+ for (const frameDiff of diff.frames) renderFrameDiff(frameDiff, 1, lines);
33
+ lines.push("</page>");
34
+ return lines.join("\n");
35
+ }
36
+ function renderPageOpen(snapshot, prefix, selfClosing = false) {
37
+ return `${prefix}${formatTag(
38
+ "page",
39
+ [
40
+ ["title", firstNonEmpty(snapshot.title, snapshot.url) ?? ""],
41
+ ["url", snapshot.url]
42
+ ],
43
+ !selfClosing
44
+ )}`;
45
+ }
46
+ function renderFrameLine(frame, depth, prefix, selfClosing) {
47
+ const attrs = [
48
+ ["index", String(frame.index)],
49
+ ["url", normalizeText(frame.url, MAX_LABEL_CHARS)]
50
+ ];
51
+ if (frame.name)
52
+ attrs.push(["name", normalizeText(frame.name, MAX_LABEL_CHARS)]);
53
+ if (frame.parentId) attrs.push(["parent", frame.parentId]);
54
+ if (frame.status === "unavailable") {
55
+ attrs.push(["error", normalizeText(frame.error, 180)]);
56
+ }
57
+ return `${prefix}${indent(depth)}${formatTag("frame", attrs, !selfClosing)}`;
58
+ }
59
+ function renderTextNode(node, depth, prefix) {
60
+ return `${prefix}${indent(depth)}${escapeText(node.text)}`;
61
+ }
62
+ function indent(depth) {
63
+ return " ".repeat(depth);
64
+ }
65
+ function formatTag(tagName, attributes, hasChildren) {
66
+ const attrs = attributes.filter(([, value]) => value !== "").map(([name, value]) => ` ${name}="${escapeAttribute(value)}"`).join("");
67
+ return hasChildren ? `<${tagName}${attrs}>` : `<${tagName}${attrs} />`;
68
+ }
69
+ function diffFrames(beforeFrames, afterFrames) {
70
+ const diffs = [];
71
+ const maxLength = Math.max(beforeFrames.length, afterFrames.length);
72
+ for (let index = 0; index < maxLength; index += 1) {
73
+ const before = beforeFrames[index];
74
+ const after = afterFrames[index];
75
+ if (before && !after) {
76
+ diffs.push({ type: "removed", frame: before });
77
+ } else if (!before && after) {
78
+ diffs.push({ type: "added", frame: after });
79
+ } else if (before && after) {
80
+ const diff = diffFrame(before, after);
81
+ if (diff) diffs.push(diff);
82
+ }
83
+ }
84
+ return diffs;
85
+ }
86
+ function diffFrame(before, after) {
87
+ if (before.status !== after.status)
88
+ return { type: "modified", before, after };
89
+ if (before.status === "unavailable" || after.status === "unavailable") {
90
+ return comparableFrame(before) === comparableFrame(after) ? null : { type: "modified", before, after };
91
+ }
92
+ const children = diffChildren(before.roots, after.roots);
93
+ const frameChanged = comparableFrame(before) !== comparableFrame(after);
94
+ if (!frameChanged && children.length === 0) return null;
95
+ if (frameChanged && children.length === 0)
96
+ return { type: "modified", before, after };
97
+ return { type: "context", frame: after, children };
98
+ }
99
+ function diffChildren(beforeChildren, afterChildren) {
100
+ const diffs = [];
101
+ const usedBefore = /* @__PURE__ */ new Set();
102
+ for (let afterIndex = 0; afterIndex < afterChildren.length; afterIndex += 1) {
103
+ const after = afterChildren[afterIndex];
104
+ const beforeIndex = findMatchingBeforeChild(
105
+ after,
106
+ afterIndex,
107
+ beforeChildren,
108
+ usedBefore
109
+ );
110
+ if (beforeIndex === -1) {
111
+ diffs.push(addedChild(after));
112
+ continue;
113
+ }
114
+ usedBefore.add(beforeIndex);
115
+ const childDiff = diffChild(beforeChildren[beforeIndex], after);
116
+ if (childDiff) diffs.push(childDiff);
117
+ }
118
+ for (let beforeIndex = 0; beforeIndex < beforeChildren.length; beforeIndex += 1) {
119
+ if (!usedBefore.has(beforeIndex))
120
+ diffs.push(removedChild(beforeChildren[beforeIndex]));
121
+ }
122
+ return diffs;
123
+ }
124
+ function diffChild(before, after) {
125
+ if (before.kind === "text" || after.kind === "text") {
126
+ if (before.kind === "text" && after.kind === "text") {
127
+ return before.text === after.text ? null : { kind: "text", type: "modified", before, after };
128
+ }
129
+ return after.kind === "text" ? addedChild(after) : removedChild(before);
130
+ }
131
+ const children = diffChildren(before.children, after.children);
132
+ const selfChanged = comparableNode(before) !== comparableNode(after);
133
+ const directTextChanged = children.some((child) => child.kind === "text");
134
+ if (!selfChanged && children.length === 0) return null;
135
+ if (selfChanged || sameRef(before, after) && directTextChanged) {
136
+ return { kind: "node", type: "modified", before, after, children };
137
+ }
138
+ return { kind: "node", type: "context", node: after, children };
139
+ }
140
+ function findMatchingBeforeChild(after, afterIndex, beforeChildren, usedBefore) {
141
+ const beforeAtSameIndex = beforeChildren[afterIndex];
142
+ if (beforeAtSameIndex && !usedBefore.has(afterIndex) && arePositionallySimilarChildren(beforeAtSameIndex, after)) {
143
+ return afterIndex;
144
+ }
145
+ if (after.kind === "node") {
146
+ const byKey = beforeChildren.findIndex(
147
+ (before, index) => !usedBefore.has(index) && before.kind === "node" && before.key === after.key
148
+ );
149
+ if (byKey !== -1) return byKey;
150
+ const afterFingerprint = childFingerprint(after);
151
+ const byFingerprint = beforeChildren.findIndex(
152
+ (before, index) => !usedBefore.has(index) && before.kind === "node" && childFingerprint(before) === afterFingerprint
153
+ );
154
+ if (byFingerprint !== -1) return byFingerprint;
155
+ }
156
+ return -1;
157
+ }
158
+ function addedChild(child) {
159
+ return child.kind === "text" ? { kind: "text", type: "added", node: child } : { kind: "node", type: "added", node: child };
160
+ }
161
+ function removedChild(child) {
162
+ return child.kind === "text" ? { kind: "text", type: "removed", node: child } : { kind: "node", type: "removed", node: child };
163
+ }
164
+ function arePositionallySimilarChildren(before, after) {
165
+ if (before.kind !== after.kind) return false;
166
+ if (before.kind === "text" && after.kind === "text") return true;
167
+ if (before.kind === "node" && after.kind === "node") {
168
+ return before.key === after.key || before.role === after.role;
169
+ }
170
+ return false;
171
+ }
172
+ function renderFrameDiff(diff, depth, lines) {
173
+ if (diff.type === "added") {
174
+ renderFrame(diff.frame, depth, lines, "+ ");
175
+ } else if (diff.type === "removed") {
176
+ renderFrame(diff.frame, depth, lines, "- ");
177
+ } else if (diff.type === "modified") {
178
+ renderFrame(diff.before, depth, lines, "- ");
179
+ renderFrame(diff.after, depth, lines, "+ ");
180
+ } else if (diff.frame.status === "ok") {
181
+ lines.push(renderFrameLine(diff.frame, depth, "", false));
182
+ if (diff.frame.roots.length > diff.children.length && diff.children.length > 0) {
183
+ lines.push(`${indent(depth + 1)}...`);
184
+ }
185
+ renderChildDiffs(diff.children, depth + 1, lines);
186
+ lines.push(`${indent(depth)}</frame>`);
187
+ }
188
+ }
189
+ function renderChildDiffs(diffs, depth, lines) {
190
+ for (const diff of diffs.slice(0, MAX_DIFF_CHILDREN_PER_PARENT)) {
191
+ renderChildDiff(diff, depth, lines);
192
+ }
193
+ if (diffs.length > MAX_DIFF_CHILDREN_PER_PARENT) {
194
+ const truncated = diffs.slice(MAX_DIFF_CHILDREN_PER_PARENT);
195
+ const prefix = diffPrefixForSummary(truncated);
196
+ lines.push(
197
+ `${prefix}${indent(depth)}${renderChildrenTruncationNotice(
198
+ diffSummaryChildren(truncated)
199
+ )}`
200
+ );
201
+ }
202
+ }
203
+ function renderChildDiff(diff, depth, lines) {
204
+ if (diff.kind === "text") {
205
+ if (diff.type === "added")
206
+ lines.push(renderTextNode(diff.node, depth, "+ "));
207
+ else if (diff.type === "removed")
208
+ lines.push(renderTextNode(diff.node, depth, "- "));
209
+ else {
210
+ lines.push(renderTextNode(diff.before, depth, "- "));
211
+ lines.push(renderTextNode(diff.after, depth, "+ "));
212
+ }
213
+ return;
214
+ }
215
+ renderNodeDiff(diff, depth, lines);
216
+ }
217
+ function renderNodeDiff(diff, depth, lines) {
218
+ if (diff.type === "added") {
219
+ renderNode(diff.node, depth, lines, "+ ");
220
+ } else if (diff.type === "removed") {
221
+ renderRemovedNode(diff.node, depth, lines);
222
+ } else if (diff.type === "modified") {
223
+ if (sameRef(diff.before, diff.after)) {
224
+ renderModifiedSameRefNode(diff, depth, lines);
225
+ } else {
226
+ renderRemovedNode(diff.before, depth, lines);
227
+ renderNode(diff.after, depth, lines, "+ ");
228
+ }
229
+ } else {
230
+ if (diff.node.children.length === 0) {
231
+ lines.push(
232
+ `${indent(depth)}${formatTag(diff.node.role, diff.node.attrs, false)}`
233
+ );
234
+ return;
235
+ }
236
+ lines.push(
237
+ `${indent(depth)}${formatTag(diff.node.role, diff.node.attrs, true)}`
238
+ );
239
+ if (diff.node.children.length > diff.children.length)
240
+ lines.push(`${indent(depth + 1)}...`);
241
+ renderChildDiffs(diff.children, depth + 1, lines);
242
+ lines.push(`${indent(depth)}</${diff.node.role}>`);
243
+ }
244
+ }
245
+ function renderModifiedSameRefNode(diff, depth, lines) {
246
+ if (diff.children.length === 0 || singleTextChild(diff.after) !== null) {
247
+ renderNode(diff.after, depth, lines, "~ ");
248
+ return;
249
+ }
250
+ if (diff.after.children.length === 0) {
251
+ lines.push(
252
+ `~ ${indent(depth)}${formatTag(diff.after.role, diff.after.attrs, false)}`
253
+ );
254
+ return;
255
+ }
256
+ lines.push(
257
+ `~ ${indent(depth)}${formatTag(diff.after.role, diff.after.attrs, true)}`
258
+ );
259
+ if (diff.after.children.length > diff.children.length)
260
+ lines.push(`~ ${indent(depth + 1)}...`);
261
+ renderChildDiffs(diff.children, depth + 1, lines);
262
+ lines.push(`~ ${indent(depth)}</${diff.after.role}>`);
263
+ }
264
+ function renderRemovedNode(node, depth, lines) {
265
+ const attrs = node.attrs.filter(([name]) => name === "ref");
266
+ if (node.children.length === 0) {
267
+ lines.push(`- ${indent(depth)}${formatTag(node.role, attrs, false)}`);
268
+ return;
269
+ }
270
+ lines.push(
271
+ `- ${indent(depth)}${formatTag(node.role, attrs, true)}...</${node.role}>`
272
+ );
273
+ }
274
+ function comparableFrame(frame) {
275
+ return JSON.stringify({
276
+ status: frame.status,
277
+ id: frame.id,
278
+ index: frame.index,
279
+ url: frame.url,
280
+ name: frame.name,
281
+ parentId: frame.parentId,
282
+ error: frame.status === "unavailable" ? frame.error : void 0
283
+ });
284
+ }
285
+ function comparableNode(node) {
286
+ return JSON.stringify({
287
+ role: node.role,
288
+ attrs: comparableAttrs(node.attrs)
289
+ });
290
+ }
291
+ function comparableAttrs(attrs) {
292
+ return attrs.flatMap(([name, value]) => {
293
+ if (LOW_SIGNAL_DIFF_ATTRS.has(name)) return [];
294
+ if (name === "href") return [[name, normalizeComparableHref(value)]];
295
+ return [[name, value]];
296
+ });
297
+ }
298
+ function sameRef(before, after) {
299
+ const beforeRef = attrValue(before, "ref");
300
+ return beforeRef !== null && beforeRef === attrValue(after, "ref");
301
+ }
302
+ function attrValue(node, name) {
303
+ return node.attrs.find(([attr]) => attr === name)?.[1] ?? null;
304
+ }
305
+ function singleTextChild(node) {
306
+ if (node.children.length !== 1) return null;
307
+ const child = node.children[0];
308
+ return child.kind === "text" && !child.block ? child.text : null;
309
+ }
310
+ function childFingerprint(child) {
311
+ if (child.kind === "text") return `text:${child.text}`;
312
+ return comparableNode(child);
313
+ }
314
+ function normalizeComparableHref(value) {
315
+ const withoutEllipsis = value.endsWith("\u2026") ? value.slice(0, -1) : value;
316
+ try {
317
+ const url = new URL(withoutEllipsis);
318
+ return `${url.protocol}//${url.host}${url.pathname}`;
319
+ } catch {
320
+ return withoutEllipsis.split(/[?#]/, 1)[0] ?? withoutEllipsis;
321
+ }
322
+ }
323
+ function firstNonEmpty(...values) {
324
+ for (const value of values) {
325
+ const normalized = normalizeRawText(value ?? "");
326
+ if (normalized) return truncate(normalized, MAX_LABEL_CHARS);
327
+ }
328
+ return null;
329
+ }
330
+ function normalizeText(value, maxChars) {
331
+ return truncate(value.replace(/\s+/g, " ").trim(), maxChars);
332
+ }
333
+ function normalizeRawText(value) {
334
+ return value.replace(/\s+/g, " ").trim();
335
+ }
336
+ function truncate(value, maxChars) {
337
+ return value.length > maxChars ? `${value.slice(0, maxChars - 1)}\u2026` : value;
338
+ }
339
+ function escapeText(value) {
340
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
341
+ }
342
+ function escapeAttribute(value) {
343
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
344
+ }
345
+ function diffPrefixForSummary(diffs) {
346
+ if (diffs.every((diff) => diff.type === "added")) return "+ ";
347
+ if (diffs.every((diff) => diff.type === "removed")) return "- ";
348
+ return "";
349
+ }
350
+ function diffSummaryChildren(diffs) {
351
+ return diffs.map(
352
+ (diff) => diff.type === "modified" ? diff.after : diff.node
353
+ );
354
+ }
355
+ export {
356
+ diffSnapshots,
357
+ renderSnapshotDiff
358
+ };
@@ -0,0 +1,39 @@
1
+ import { Snapshot } from './types.js';
2
+
3
+ type SnapshotTextNode = {
4
+ kind: "text";
5
+ text: string;
6
+ block?: boolean;
7
+ };
8
+ type RenderedSnapshotNode = {
9
+ kind: "node";
10
+ key: string;
11
+ role: string;
12
+ attrs: Array<[string, string]>;
13
+ children: RenderedSnapshotChild[];
14
+ };
15
+ type RenderedSnapshotChild = RenderedSnapshotNode | SnapshotTextNode;
16
+ type RenderedSnapshotFrame = {
17
+ status: "ok";
18
+ id: string;
19
+ index: number;
20
+ url: string;
21
+ name: string | null;
22
+ parentId: string | null;
23
+ roots: RenderedSnapshotNode[];
24
+ } | {
25
+ status: "unavailable";
26
+ id: string;
27
+ index: number;
28
+ url: string;
29
+ name: string | null;
30
+ parentId: string | null;
31
+ error: string;
32
+ };
33
+ declare function renderSnapshot(snapshot: Snapshot, refId?: string): string;
34
+ declare function renderSnapshotFrames(snapshot: Snapshot): RenderedSnapshotFrame[];
35
+ declare function renderChildrenTruncationNotice(children: RenderedSnapshotChild[]): string;
36
+ declare function renderFrame(frame: RenderedSnapshotFrame, depth: number, lines: string[], prefix?: string): void;
37
+ declare function renderNode(node: RenderedSnapshotNode, depth: number, lines: string[], prefix?: string): void;
38
+
39
+ export { type RenderedSnapshotChild, type RenderedSnapshotFrame, type RenderedSnapshotNode, renderChildrenTruncationNotice, renderFrame, renderNode, renderSnapshot, renderSnapshotFrames };