@dev.fast/whiteboard 0.0.0-stage → 0.2.1-preview.20261005.98

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 (247) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +146 -2
  3. package/THIRD_PARTY_NOTICES.md +93 -0
  4. package/dist/account-alias-DOHN1RSH.js +973 -0
  5. package/dist/agent-cli-ChOq0ZuO.js +117 -0
  6. package/dist/agent-cli-DzWfZr6G.js +2 -0
  7. package/dist/agent-client-CPQo7iTI.js +305 -0
  8. package/dist/authoring-tools-Cr6Kpjsx.js +234 -0
  9. package/dist/build-info.json +1 -0
  10. package/dist/cli-hVgHcdsv.js +47 -0
  11. package/dist/cli-runner-D8y2_luU.js +5095 -0
  12. package/dist/cli.d.ts +1 -0
  13. package/dist/cli.js +128 -0
  14. package/dist/client-DFoh50W3.js +950 -0
  15. package/dist/desktop-discovery-DBO-PM2V.js +164 -0
  16. package/dist/error-message-OtiDonty.js +6 -0
  17. package/dist/fs-utils-BMPLt0cr.js +22 -0
  18. package/dist/fuzzy-match-BoAmcyak.js +30 -0
  19. package/dist/headless-host-BJxf4dUU.js +94 -0
  20. package/dist/input-error-OLgB_h31.js +11 -0
  21. package/dist/local-data-CxLk75rx.js +4491 -0
  22. package/dist/mcp-QeF8vkdf.js +140 -0
  23. package/dist/package-paths-B6-zxvIO.js +47 -0
  24. package/dist/process-error-telemetry-v9e5h6D7.js +3952 -0
  25. package/dist/profile-4ry2f3AM.js +76 -0
  26. package/dist/profile-Bh5FIrmf.js +2 -0
  27. package/dist/request-origin-D_4QIdoN.js +811 -0
  28. package/dist/review-agent-traces-DNJFYzc8.js +3866 -0
  29. package/dist/review-home-paths-6zZH-1c9.js +2560 -0
  30. package/dist/review-telemetry-DEFnQsQ2.js +1195 -0
  31. package/dist/runtime-CKiWhGrf.js +52 -0
  32. package/dist/runtime.d.ts +9 -0
  33. package/dist/runtime.js +2 -0
  34. package/dist/s3-SzLpeCG6.js +345 -0
  35. package/dist/s3-config-BgxkSoOy.js +2 -0
  36. package/dist/s3-config-CAxhO9u_.js +676 -0
  37. package/dist/server/desktop-host.d.ts +4 -0
  38. package/dist/server/desktop-host.js +1702 -0
  39. package/dist/server-discovery-Dbzn3w6Z.js +66 -0
  40. package/dist/sharing/index.d.ts +1977 -0
  41. package/dist/sharing/index.js +2 -0
  42. package/dist/src-CGP5ytbV.js +283 -0
  43. package/dist/src-CmdiBL20.js +3676 -0
  44. package/dist/src-DnwdaQ2r.js +865 -0
  45. package/dist/src-X9phtB2j.js +68 -0
  46. package/dist/stored-document-migration-DHeMpLMb.js +2671 -0
  47. package/dist/tool-failure-C8zB73HV.js +98 -0
  48. package/dist/tutorial-trace-DrBvkaeL.js +43 -0
  49. package/instructions/authoring.md +36 -0
  50. package/instructions/file-lenses.md +13 -0
  51. package/instructions/scratchpad.md +23 -0
  52. package/instructions/trace-archaeology.md +113 -0
  53. package/onboarding.md +8 -0
  54. package/package.json +106 -3
  55. package/src/agent-selection.ts +100 -0
  56. package/src/agent-session-ref.ts +80 -0
  57. package/src/ask/agents.ts +351 -0
  58. package/src/ask/checkout-files.ts +47 -0
  59. package/src/ask/file-refs.ts +111 -0
  60. package/src/ask/pi-mcp.ts +154 -0
  61. package/src/ask/protocol.ts +244 -0
  62. package/src/ask/thread-state.ts +350 -0
  63. package/src/ask/thread.ts +1400 -0
  64. package/src/ask/threads.ts +219 -0
  65. package/src/ask/watch.ts +79 -0
  66. package/src/cli-install.ts +1041 -0
  67. package/src/cli-runner.ts +1461 -0
  68. package/src/cli-runtime-info.ts +35 -0
  69. package/src/cli.ts +222 -0
  70. package/src/connect-prompts.ts +248 -0
  71. package/src/cursor-deeplink.ts +11 -0
  72. package/src/desktop-discovery.ts +355 -0
  73. package/src/diff-selection-migration.ts +63 -0
  74. package/src/embedded-posthog-key.ts +6 -0
  75. package/src/error-telemetry.ts +247 -0
  76. package/src/evidence.ts +14 -0
  77. package/src/exception-telemetry.ts +126 -0
  78. package/src/fixtures/blocks/call_stack_diff.json +27 -0
  79. package/src/fixtures/blocks/callout.json +11 -0
  80. package/src/fixtures/blocks/code.json +9 -0
  81. package/src/fixtures/blocks/code_peek.json +8 -0
  82. package/src/fixtures/blocks/database_lens.json +51 -0
  83. package/src/fixtures/blocks/divider.json +1 -0
  84. package/src/fixtures/blocks/fixtures.ts +33 -0
  85. package/src/fixtures/blocks/flow_diagram.json +36 -0
  86. package/src/fixtures/blocks/ids.ts +8 -0
  87. package/src/fixtures/blocks/image.json +9 -0
  88. package/src/fixtures/blocks/markdown.json +7 -0
  89. package/src/fixtures/blocks/section.json +11 -0
  90. package/src/fixtures/blocks/sequence.json +31 -0
  91. package/src/fixtures/blocks/software_map.json +7 -0
  92. package/src/fixtures/blocks/trace_quote.json +9 -0
  93. package/src/fixtures/blocks/tutorial.json +51 -0
  94. package/src/fs-utils.ts +32 -0
  95. package/src/fuzzy-match.ts +94 -0
  96. package/src/install.ts +29 -0
  97. package/src/legacy-skills.ts +133 -0
  98. package/src/lens-selection.ts +230 -0
  99. package/src/markdown-latex-math.ts +230 -0
  100. package/src/markdown.ts +81 -0
  101. package/src/package-paths.ts +53 -0
  102. package/src/posthog-capture-client.ts +610 -0
  103. package/src/review-api/README.md +295 -0
  104. package/src/review-api/activity.ts +340 -0
  105. package/src/review-api/agent-cli.ts +219 -0
  106. package/src/review-api/agent-client.ts +188 -0
  107. package/src/review-api/anchor-quotes.ts +88 -0
  108. package/src/review-api/ask-history.ts +242 -0
  109. package/src/review-api/authoring-tools.ts +211 -0
  110. package/src/review-api/blocks/call_stack_diff.ts +75 -0
  111. package/src/review-api/blocks/callout.ts +24 -0
  112. package/src/review-api/blocks/code.ts +9 -0
  113. package/src/review-api/blocks/code_peek.ts +13 -0
  114. package/src/review-api/blocks/database_lens.ts +150 -0
  115. package/src/review-api/blocks/definition.ts +40 -0
  116. package/src/review-api/blocks/divider.ts +6 -0
  117. package/src/review-api/blocks/flow_diagram.ts +111 -0
  118. package/src/review-api/blocks/image.ts +10 -0
  119. package/src/review-api/blocks/index.ts +90 -0
  120. package/src/review-api/blocks/markdown.ts +17 -0
  121. package/src/review-api/blocks/section.ts +24 -0
  122. package/src/review-api/blocks/sequence.ts +56 -0
  123. package/src/review-api/blocks/software_map.ts +9 -0
  124. package/src/review-api/blocks/trace_quote.ts +10 -0
  125. package/src/review-api/blocks/tutorial.ts +39 -0
  126. package/src/review-api/checkout-fs.ts +14 -0
  127. package/src/review-api/client.ts +1 -0
  128. package/src/review-api/comparison-coverage.ts +304 -0
  129. package/src/review-api/component-reference.ts +30 -0
  130. package/src/review-api/diff-lenses.ts +175 -0
  131. package/src/review-api/document-headings.ts +51 -0
  132. package/src/review-api/document-text.ts +200 -0
  133. package/src/review-api/document.ts +906 -0
  134. package/src/review-api/file-lenses.ts +100 -0
  135. package/src/review-api/http.ts +1877 -0
  136. package/src/review-api/image-decode.ts +29 -0
  137. package/src/review-api/input-error.ts +9 -0
  138. package/src/review-api/instructions.ts +89 -0
  139. package/src/review-api/lens-alignment.ts +52 -0
  140. package/src/review-api/local-data.ts +1837 -0
  141. package/src/review-api/map-input.ts +154 -0
  142. package/src/review-api/mcp-client-agent.ts +32 -0
  143. package/src/review-api/mcp.ts +240 -0
  144. package/src/review-api/origin.ts +43 -0
  145. package/src/review-api/profile.ts +146 -0
  146. package/src/review-api/public-tools.ts +102 -0
  147. package/src/review-api/pull-request.ts +389 -0
  148. package/src/review-api/read-schemas.ts +85 -0
  149. package/src/review-api/recovery.ts +2 -0
  150. package/src/review-api/request-origin.ts +33 -0
  151. package/src/review-api/review-progress.ts +382 -0
  152. package/src/review-api/status-tool.ts +10 -0
  153. package/src/review-api/store-schema.ts +22 -0
  154. package/src/review-api/store.ts +1647 -0
  155. package/src/review-api/tool-failure.ts +64 -0
  156. package/src/review-api/trace-schema.ts +13 -0
  157. package/src/review-api/traces.ts +119 -0
  158. package/src/review-api/unsupported-files.integration.ts +91 -0
  159. package/src/review-api/workspaces.ts +692 -0
  160. package/src/review-api/worktree-source.ts +170 -0
  161. package/src/review-api/worktree-structural.integration.ts +320 -0
  162. package/src/review-app-launcher.ts +432 -0
  163. package/src/review-app-picker.ts +168 -0
  164. package/src/review-app.ts +134 -0
  165. package/src/review-bundled-tools.ts +249 -0
  166. package/src/review-checkout-paths.ts +37 -0
  167. package/src/review-diff-files.ts +89 -0
  168. package/src/review-head-checkout.ts +300 -0
  169. package/src/review-home-paths.ts +73 -0
  170. package/src/review-info.ts +59 -0
  171. package/src/review-instances.ts +113 -0
  172. package/src/review-logger.ts +183 -0
  173. package/src/review-preferences.ts +88 -0
  174. package/src/review-prepare.ts +291 -0
  175. package/src/review-stack.ts +112 -0
  176. package/src/review-telemetry.ts +1066 -0
  177. package/src/runtime.ts +74 -0
  178. package/src/server/account-alias.ts +30 -0
  179. package/src/server/bounded-stream.ts +34 -0
  180. package/src/server/bug-report.ts +301 -0
  181. package/src/server/client-error-budget.ts +45 -0
  182. package/src/server/crash-report.ts +273 -0
  183. package/src/server/desktop-host-shutdown.ts +64 -0
  184. package/src/server/desktop-host.ts +190 -0
  185. package/src/server/desktop-server.ts +703 -0
  186. package/src/server/diffr-config.ts +509 -0
  187. package/src/server/diffr-languages.ts +97 -0
  188. package/src/server/global-verb-relay.ts +190 -0
  189. package/src/server/headless-host.ts +149 -0
  190. package/src/server/hono-http.ts +162 -0
  191. package/src/server/http-json.ts +24 -0
  192. package/src/server/json-review-reporting.ts +174 -0
  193. package/src/server/process-error-telemetry.ts +174 -0
  194. package/src/server/review-api-parsers.ts +90 -0
  195. package/src/server/review-lifecycle-telemetry.ts +73 -0
  196. package/src/server/review-open-watchdog.ts +46 -0
  197. package/src/server/review-server-core.ts +290 -0
  198. package/src/server/structural-comparisons.ts +153 -0
  199. package/src/server/structural-diff.ts +186 -0
  200. package/src/server/tutorial-service.ts +241 -0
  201. package/src/server/ui-telemetry.ts +198 -0
  202. package/src/server-discovery.ts +95 -0
  203. package/src/session-markers.ts +132 -0
  204. package/src/sharing/auth.ts +41 -0
  205. package/src/sharing/cli.ts +83 -0
  206. package/src/sharing/client.ts +334 -0
  207. package/src/sharing/export.ts +195 -0
  208. package/src/sharing/host.ts +316 -0
  209. package/src/sharing/import.ts +787 -0
  210. package/src/sharing/index.ts +16 -0
  211. package/src/sharing/repository.ts +145 -0
  212. package/src/sharing/routes.ts +34 -0
  213. package/src/slug.ts +23 -0
  214. package/src/software-map-diff-counts.ts +517 -0
  215. package/src/software-map-model.ts +1147 -0
  216. package/src/software-map-topology-diff.ts +260 -0
  217. package/src/source.ts +92 -0
  218. package/src/startup-trace.ts +232 -0
  219. package/src/stored-document-migration.ts +151 -0
  220. package/src/telemetry-clean-text.ts +257 -0
  221. package/src/telemetry-config.ts +298 -0
  222. package/src/telemetry-debug-sink.ts +38 -0
  223. package/src/telemetry.ts +13 -0
  224. package/src/trace-cli.ts +156 -0
  225. package/src/trace-storage-cli.ts +509 -0
  226. package/src/tutorial-conversation.ts +18 -0
  227. package/src/ui-telemetry-events.ts +765 -0
  228. package/src/unified-diff.ts +71 -0
  229. package/src/viewed-coverage.ts +259 -0
  230. package/src/windows-cli.ts +125 -0
  231. package/tutorial/document.json +275 -0
  232. package/tutorial/runtime-manifest.json +12 -0
  233. package/tutorial/sample-service/package.json +9 -0
  234. package/tutorial/sample-service/src/api/checkout-api.ts +17 -0
  235. package/tutorial/sample-service/src/app.ts +26 -0
  236. package/tutorial/sample-service/src/database/schema.ts +10 -0
  237. package/tutorial/sample-service/src/fulfillment/fulfillment-queue.ts +15 -0
  238. package/tutorial/sample-service/src/fulfillment/fulfillment-worker.ts +24 -0
  239. package/tutorial/sample-service/src/inventory/inventory-service.ts +11 -0
  240. package/tutorial/sample-service/src/orders/order-service.ts +34 -0
  241. package/tutorial/sample-service/src/orders/order.ts +21 -0
  242. package/tutorial/sample-service/src/orders/orders-repository.ts +24 -0
  243. package/tutorial/sample-service/src/payments/payment-gateway.ts +12 -0
  244. package/tutorial/sample-service/src/shipping/shipping-gateway.ts +15 -0
  245. package/tutorial/sample-service/tsconfig.json +12 -0
  246. package/tutorial/software-map.json +139 -0
  247. package/tutorial/trace.json +20 -0
@@ -0,0 +1,64 @@
1
+ import type {
2
+ ReviewTelemetryErrorCategory,
3
+ ReviewTelemetryErrorName,
4
+ } from "@review/review-telemetry.js";
5
+
6
+ import { ReviewApiError } from "./client.js";
7
+ import { ReviewInputError } from "./input-error.js";
8
+
9
+ export interface ToolFailure {
10
+ errorName: ReviewTelemetryErrorName;
11
+ errorCategory: ReviewTelemetryErrorCategory;
12
+ }
13
+
14
+ /**
15
+ * Sort a failed agent tool call into the CLI's closed error vocabulary, so
16
+ * telemetry can tell an agent's bad input from a broken host. `connect`
17
+ * covers reaching the host and reading its catalog; `call` is the tool itself.
18
+ */
19
+ export function toolFailure(
20
+ // oxlint-disable-next-line anti-slop/no-unknown-parameters -- Catch boundary: sorts whatever a tool call threw by its class.
21
+ error: unknown,
22
+ phase: "connect" | "call",
23
+ ): ToolFailure {
24
+ const status =
25
+ error instanceof ReviewApiError || error instanceof ReviewInputError
26
+ ? error.status
27
+ : undefined;
28
+
29
+ if (status === 400)
30
+ return { errorName: "usage_error", errorCategory: "user_input" };
31
+
32
+ if (status === 401)
33
+ return {
34
+ errorName: "desktop_connection_error",
35
+ errorCategory: "dependency",
36
+ };
37
+
38
+ if (status === 404)
39
+ return { errorName: "review_not_found", errorCategory: "local_state" };
40
+
41
+ if (status === 409)
42
+ return { errorName: "review_state_error", errorCategory: "local_state" };
43
+
44
+ if (status !== undefined)
45
+ return { errorName: "unexpected_error", errorCategory: "internal" };
46
+
47
+ if (phase === "connect")
48
+ return {
49
+ errorName: "desktop_connection_error",
50
+ errorCategory: "dependency",
51
+ };
52
+
53
+ // fetch rejects with a TypeError; a command whose reply was lost is rewrapped
54
+ // with that rejection as its cause; an abort is the agent canceling the call.
55
+ if (
56
+ error instanceof Error &&
57
+ (error instanceof TypeError ||
58
+ error.name === "AbortError" ||
59
+ error.cause !== undefined)
60
+ )
61
+ return { errorName: "network_error", errorCategory: "transport" };
62
+
63
+ return { errorName: "unexpected_error", errorCategory: "internal" };
64
+ }
@@ -0,0 +1,13 @@
1
+ import { z } from "zod";
2
+
3
+ export const traceSchema = z.strictObject({
4
+ label: z.string(),
5
+ events: z.array(
6
+ z.strictObject({
7
+ id: z.string().min(1),
8
+ role: z.enum(["user", "assistant", "tool"]),
9
+ text: z.string(),
10
+ }),
11
+ ),
12
+ provenance: z.enum(["client_supplied", "legacy_import"]).optional(),
13
+ });
@@ -0,0 +1,119 @@
1
+ import {
2
+ TraceConfigurationError,
3
+ TraceStorageDeniedError,
4
+ type TraceStorageKind,
5
+ isS3MockMode,
6
+ isTraceStorageConfigured,
7
+ listReviewTraceSessions,
8
+ loadReviewAgentTrace,
9
+ resolveTraceStorage,
10
+ selectTraceStorage,
11
+ } from "@dev.fast/trace-core";
12
+
13
+ import type { Pins } from "./document.js";
14
+
15
+ export async function listPinnedTraces(
16
+ cwd: string,
17
+ pins: Pins,
18
+ override?: TraceStorageKind,
19
+ ) {
20
+ const selection = selectTraceStorage();
21
+ const sources: TraceStorageKind[] = [];
22
+
23
+ if (selection.s3?.credentials || isS3MockMode()) sources.push("s3");
24
+
25
+ if (selection.hosted) sources.push("hosted");
26
+
27
+ const result = {
28
+ ok: true as const,
29
+ configured: isTraceStorageConfigured(),
30
+ storage: override ?? selection.mode,
31
+ sources,
32
+ };
33
+
34
+ try {
35
+ if (selection.error)
36
+ return { ...result, storageError: selection.error, sessions: [] };
37
+ const storage = await resolveTraceStorage({ cwd, override });
38
+
39
+ if (!storage && (override ?? selection.mode) === "hosted")
40
+ return {
41
+ ...result,
42
+ storageError:
43
+ "The hosted trace store has no login on this machine. Run `whiteboard login` and open the review again.",
44
+ sessions: [],
45
+ };
46
+
47
+ return {
48
+ ...result,
49
+ sessions: await listReviewTraceSessions({
50
+ rootPath: cwd,
51
+ baseCommit: pins.base,
52
+ headCommit: pins.head,
53
+ storage,
54
+ }),
55
+ };
56
+ } catch (error) {
57
+ if (
58
+ error instanceof TraceStorageDeniedError ||
59
+ error instanceof TraceConfigurationError
60
+ )
61
+ return { ...result, storageError: error.message, sessions: [] };
62
+ throw error;
63
+ }
64
+ }
65
+
66
+ export async function readStoredTrace(
67
+ cwd: string,
68
+ sessionId: string,
69
+ trace?: string,
70
+ override?: TraceStorageKind,
71
+ ) {
72
+ try {
73
+ const storage = await resolveTraceStorage({ cwd, override });
74
+
75
+ const loaded = await loadReviewAgentTrace({
76
+ cwd,
77
+ sessionId,
78
+ trace,
79
+ storage,
80
+ });
81
+
82
+ if (!loaded)
83
+ return {
84
+ ok: false as const,
85
+ status: 404 as const,
86
+ error: `Trace not found for session ${sessionId}.`,
87
+ };
88
+
89
+ return {
90
+ ok: true as const,
91
+ parserVersion: loaded.parserVersion,
92
+ session: loaded.descriptor,
93
+ trace: loaded.traceName,
94
+ cacheStatus: loaded.cacheStatus,
95
+ subagents: loaded.subagents,
96
+ title: loaded.trace.title,
97
+ startedAt: loaded.trace.startedAt,
98
+ endedAt: loaded.trace.endedAt,
99
+ activeMs: loaded.trace.activeMs,
100
+ userTurns: loaded.trace.userTurns,
101
+ toolCalls: loaded.trace.toolCalls,
102
+ events: loaded.trace.events,
103
+ };
104
+ } catch (error) {
105
+ if (
106
+ error instanceof TraceStorageDeniedError ||
107
+ error instanceof TraceConfigurationError
108
+ )
109
+ return {
110
+ ok: false as const,
111
+ status:
112
+ error instanceof TraceStorageDeniedError
113
+ ? (403 as const)
114
+ : (400 as const),
115
+ error: error.message,
116
+ };
117
+ throw error;
118
+ }
119
+ }
@@ -0,0 +1,91 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import {
3
+ mkdtempSync,
4
+ rmSync,
5
+ symlinkSync,
6
+ unlinkSync,
7
+ writeFileSync,
8
+ } from "node:fs";
9
+ import { tmpdir } from "node:os";
10
+ import path from "node:path";
11
+
12
+ import { coverageProgress } from "@review/viewed-coverage";
13
+ import { expect, it } from "vitest";
14
+
15
+ import { createReviewApi } from "./http";
16
+ import { openLocalReviewStore } from "./local-data";
17
+
18
+ it.each([false, true])(
19
+ "omits unsupported files from progress, with text changes=%s",
20
+ async (textChanged) => {
21
+ const root = mkdtempSync(path.join(tmpdir(), "unsupported-files-"));
22
+
23
+ const git = (...args: string[]) =>
24
+ execFileSync("git", ["-C", root, ...args], { encoding: "utf8" }).trim();
25
+
26
+ const commit = () => {
27
+ git(
28
+ "-c",
29
+ "user.name=Test",
30
+ "-c",
31
+ "user.email=test@example.invalid",
32
+ "commit",
33
+ "-qm",
34
+ "Fixture",
35
+ );
36
+
37
+ return git("rev-parse", "HEAD");
38
+ };
39
+
40
+ const local = openLocalReviewStore(path.join(root, "reviews.db"));
41
+
42
+ try {
43
+ git("init", "-q", "-b", "main");
44
+ writeFileSync(path.join(root, "value.ts"), "export const value = 1;\n");
45
+ git("add", "value.ts");
46
+ const first = commit();
47
+ git("update-index", "--add", "--cacheinfo", `160000,${first},module`);
48
+ symlinkSync("value.ts", path.join(root, "link"));
49
+ git("add", "link");
50
+ const base = commit();
51
+
52
+ git("update-index", "--cacheinfo", `160000,${base},module`);
53
+ unlinkSync(path.join(root, "link"));
54
+ symlinkSync("other.ts", path.join(root, "link"));
55
+
56
+ if (textChanged)
57
+ writeFileSync(path.join(root, "value.ts"), "export const value = 2;\n");
58
+ git("add", "value.ts", "link");
59
+ const head = commit();
60
+ const { id } = await local.data.register(root);
61
+
62
+ const { reviewId } = await local.store.execute({
63
+ operation: {
64
+ type: "create",
65
+ title: "Unsupported files",
66
+ target: { kind: "commits", repositoryId: id, base, head },
67
+ },
68
+ });
69
+
70
+ const app = createReviewApi(local.store, local.data);
71
+
72
+ const response = await app.request(
73
+ `/${reviewId}/progress?mode=structural`,
74
+ );
75
+
76
+ expect(response.status).toBe(200);
77
+ const progress = await response.json();
78
+ expect(progress.files.map((file: { path: string }) => file.path)).toEqual(
79
+ textChanged ? ["value.ts"] : [],
80
+ );
81
+ expect(coverageProgress(progress.files).total).toEqual({
82
+ additions: textChanged ? 1 : 0,
83
+ deletions: textChanged ? 1 : 0,
84
+ });
85
+ } finally {
86
+ await local.data.close();
87
+ await local.store.close();
88
+ rmSync(root, { recursive: true, force: true });
89
+ }
90
+ },
91
+ );