@bendyline/docblocks 2.0.0 → 2.1.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.
Files changed (286) hide show
  1. package/dist/{chunk-J32GU3F3.js → chunk-6IYMTYMQ.js} +249 -221
  2. package/dist/chunk-6IYMTYMQ.js.map +1 -0
  3. package/dist/{chunk-75UUF6C4.js → chunk-B56KWCSE.js} +2 -2
  4. package/dist/{chunk-RVQHY3XU.js → chunk-BNKV7MTO.js} +1 -1
  5. package/dist/{chunk-RVQHY3XU.js.map → chunk-BNKV7MTO.js.map} +1 -1
  6. package/dist/chunk-BXMF5YQJ.js +149 -0
  7. package/dist/chunk-BXMF5YQJ.js.map +1 -0
  8. package/dist/{chunk-PGR7LK6D.js → chunk-COYQXQK3.js} +14 -5
  9. package/dist/chunk-COYQXQK3.js.map +1 -0
  10. package/dist/{chunk-RQJRQF46.js → chunk-DN7A33LL.js} +42 -49
  11. package/dist/chunk-DN7A33LL.js.map +1 -0
  12. package/dist/chunk-FA7UNOXK.js +20 -0
  13. package/dist/chunk-FA7UNOXK.js.map +1 -0
  14. package/dist/chunk-GM5YXU4L.js +29 -0
  15. package/dist/chunk-GM5YXU4L.js.map +1 -0
  16. package/dist/{chunk-SI2LU2RP.js → chunk-JS6XFWQK.js} +2 -1
  17. package/dist/chunk-JS6XFWQK.js.map +1 -0
  18. package/dist/{chunk-EGNDADXB.js → chunk-MNSZ7EZN.js} +2 -2
  19. package/dist/chunk-P3DVZQ6S.js +228 -0
  20. package/dist/chunk-P3DVZQ6S.js.map +1 -0
  21. package/dist/chunk-P4WATND4.js +52 -0
  22. package/dist/chunk-P4WATND4.js.map +1 -0
  23. package/dist/chunk-RVPGQBWR.js +169 -0
  24. package/dist/chunk-RVPGQBWR.js.map +1 -0
  25. package/dist/chunk-U722UUFN.js +9 -0
  26. package/dist/chunk-U722UUFN.js.map +1 -0
  27. package/dist/{chunk-GCPBEMMH.js → chunk-VTCSF7VS.js} +11 -21
  28. package/dist/chunk-VTCSF7VS.js.map +1 -0
  29. package/dist/{chunk-2D7Y4IR3.js → chunk-WJKYY5QR.js} +123 -66
  30. package/dist/chunk-WJKYY5QR.js.map +1 -0
  31. package/dist/{chunk-5MYAICRE.js → chunk-XUML3MKV.js} +44 -56
  32. package/dist/chunk-XUML3MKV.js.map +1 -0
  33. package/dist/document/index.d.ts +358 -6
  34. package/dist/document/index.js +24 -3
  35. package/dist/document/index.js.map +1 -1
  36. package/dist/filesystem/electron.d.ts +73 -4
  37. package/dist/filesystem/electron.js +16 -3
  38. package/dist/filesystem/electron.js.map +1 -1
  39. package/dist/filesystem/index.d.ts +228 -22
  40. package/dist/filesystem/index.js +133 -19
  41. package/dist/filesystem/index.js.map +1 -1
  42. package/dist/filesystem/indexeddb.d.ts +284 -5
  43. package/dist/filesystem/indexeddb.js +22 -4
  44. package/dist/filesystem/indexeddb.js.map +1 -1
  45. package/dist/filesystem/memory.d.ts +152 -4
  46. package/dist/filesystem/memory.js +12 -3
  47. package/dist/filesystem/memory.js.map +1 -1
  48. package/dist/filesystem/native.d.ts +136 -4
  49. package/dist/filesystem/native.js +27 -3
  50. package/dist/filesystem/native.js.map +1 -1
  51. package/dist/host/index.d.ts +32 -9
  52. package/dist/host/index.js +26 -29
  53. package/dist/host/index.js.map +1 -1
  54. package/dist/index.d.ts +14 -10
  55. package/dist/index.js +204 -9
  56. package/dist/index.js.map +1 -1
  57. package/dist/mcp/index.d.ts +33 -4
  58. package/dist/mcp/index.js +31 -3
  59. package/dist/mcp/index.js.map +1 -1
  60. package/dist/mcp/zod.d.ts +637 -635
  61. package/dist/mcp/zod.js +700 -884
  62. package/dist/mcp/zod.js.map +1 -1
  63. package/dist/share/index.d.ts +43 -0
  64. package/dist/share/index.js +13 -0
  65. package/dist/share/index.js.map +1 -0
  66. package/dist/{types-CsX6EN2t.d.ts → types-BEg5SQ1_.d.ts} +1 -1
  67. package/dist/{types-eOlt9J7n.d.ts → types-CueK0tvU.d.ts} +34 -11
  68. package/dist/vscode/index.d.ts +220 -3
  69. package/dist/vscode/index.js +382 -2
  70. package/dist/vscode/index.js.map +1 -1
  71. package/dist/workspace/index.d.ts +141 -4
  72. package/dist/workspace/index.js +28 -2
  73. package/dist/workspace/index.js.map +1 -1
  74. package/package.json +9 -5
  75. package/dist/chunk-2D7Y4IR3.js.map +0 -1
  76. package/dist/chunk-5MYAICRE.js.map +0 -1
  77. package/dist/chunk-AYZ4HN5M.js +0 -20
  78. package/dist/chunk-AYZ4HN5M.js.map +0 -1
  79. package/dist/chunk-GCPBEMMH.js.map +0 -1
  80. package/dist/chunk-J32GU3F3.js.map +0 -1
  81. package/dist/chunk-PGR7LK6D.js.map +0 -1
  82. package/dist/chunk-RQJRQF46.js.map +0 -1
  83. package/dist/chunk-SI2LU2RP.js.map +0 -1
  84. package/dist/chunk-W5UUUII5.js +0 -142
  85. package/dist/chunk-W5UUUII5.js.map +0 -1
  86. package/dist/document/document-session.d.ts +0 -127
  87. package/dist/document/document-session.d.ts.map +0 -1
  88. package/dist/document/document-session.js +0 -749
  89. package/dist/document/document-session.js.map +0 -1
  90. package/dist/document/filesystem-target.d.ts +0 -17
  91. package/dist/document/filesystem-target.d.ts.map +0 -1
  92. package/dist/document/filesystem-target.js +0 -70
  93. package/dist/document/filesystem-target.js.map +0 -1
  94. package/dist/document/index.d.ts.map +0 -1
  95. package/dist/document/recovery-journal.d.ts +0 -125
  96. package/dist/document/recovery-journal.d.ts.map +0 -1
  97. package/dist/document/recovery-journal.js +0 -385
  98. package/dist/document/recovery-journal.js.map +0 -1
  99. package/dist/document/types.d.ts +0 -89
  100. package/dist/document/types.d.ts.map +0 -1
  101. package/dist/document/types.js +0 -9
  102. package/dist/document/types.js.map +0 -1
  103. package/dist/filesystem/commit-lock.d.ts +0 -3
  104. package/dist/filesystem/commit-lock.d.ts.map +0 -1
  105. package/dist/filesystem/commit-lock.js +0 -20
  106. package/dist/filesystem/commit-lock.js.map +0 -1
  107. package/dist/filesystem/dbk-workspace.d.ts +0 -34
  108. package/dist/filesystem/dbk-workspace.d.ts.map +0 -1
  109. package/dist/filesystem/dbk-workspace.js +0 -85
  110. package/dist/filesystem/dbk-workspace.js.map +0 -1
  111. package/dist/filesystem/electron-provider-v2.d.ts +0 -36
  112. package/dist/filesystem/electron-provider-v2.d.ts.map +0 -1
  113. package/dist/filesystem/electron-provider-v2.js +0 -503
  114. package/dist/filesystem/electron-provider-v2.js.map +0 -1
  115. package/dist/filesystem/electron-provider.d.ts +0 -35
  116. package/dist/filesystem/electron-provider.d.ts.map +0 -1
  117. package/dist/filesystem/electron-provider.js +0 -69
  118. package/dist/filesystem/electron-provider.js.map +0 -1
  119. package/dist/filesystem/electron.d.ts.map +0 -1
  120. package/dist/filesystem/file-media-provider.d.ts +0 -23
  121. package/dist/filesystem/file-media-provider.d.ts.map +0 -1
  122. package/dist/filesystem/file-media-provider.js +0 -85
  123. package/dist/filesystem/file-media-provider.js.map +0 -1
  124. package/dist/filesystem/filesystem-content-container.d.ts +0 -24
  125. package/dist/filesystem/filesystem-content-container.d.ts.map +0 -1
  126. package/dist/filesystem/filesystem-content-container.js +0 -153
  127. package/dist/filesystem/filesystem-content-container.js.map +0 -1
  128. package/dist/filesystem/fs-error.d.ts +0 -46
  129. package/dist/filesystem/fs-error.d.ts.map +0 -1
  130. package/dist/filesystem/fs-error.js +0 -170
  131. package/dist/filesystem/fs-error.js.map +0 -1
  132. package/dist/filesystem/index.d.ts.map +0 -1
  133. package/dist/filesystem/indexeddb-content-container.d.ts +0 -22
  134. package/dist/filesystem/indexeddb-content-container.d.ts.map +0 -1
  135. package/dist/filesystem/indexeddb-content-container.js +0 -100
  136. package/dist/filesystem/indexeddb-content-container.js.map +0 -1
  137. package/dist/filesystem/indexeddb-provider-v2.d.ts +0 -96
  138. package/dist/filesystem/indexeddb-provider-v2.d.ts.map +0 -1
  139. package/dist/filesystem/indexeddb-provider-v2.js +0 -1241
  140. package/dist/filesystem/indexeddb-provider-v2.js.map +0 -1
  141. package/dist/filesystem/indexeddb-provider.d.ts +0 -39
  142. package/dist/filesystem/indexeddb-provider.d.ts.map +0 -1
  143. package/dist/filesystem/indexeddb-provider.js +0 -145
  144. package/dist/filesystem/indexeddb-provider.js.map +0 -1
  145. package/dist/filesystem/indexeddb-store.d.ts +0 -34
  146. package/dist/filesystem/indexeddb-store.d.ts.map +0 -1
  147. package/dist/filesystem/indexeddb-store.js +0 -165
  148. package/dist/filesystem/indexeddb-store.js.map +0 -1
  149. package/dist/filesystem/indexeddb.d.ts.map +0 -1
  150. package/dist/filesystem/legacy-v2-adapter.d.ts +0 -62
  151. package/dist/filesystem/legacy-v2-adapter.d.ts.map +0 -1
  152. package/dist/filesystem/legacy-v2-adapter.js +0 -499
  153. package/dist/filesystem/legacy-v2-adapter.js.map +0 -1
  154. package/dist/filesystem/memory-provider-v2.d.ts +0 -92
  155. package/dist/filesystem/memory-provider-v2.d.ts.map +0 -1
  156. package/dist/filesystem/memory-provider-v2.js +0 -615
  157. package/dist/filesystem/memory-provider-v2.js.map +0 -1
  158. package/dist/filesystem/memory-provider.d.ts +0 -54
  159. package/dist/filesystem/memory-provider.d.ts.map +0 -1
  160. package/dist/filesystem/memory-provider.js +0 -132
  161. package/dist/filesystem/memory-provider.js.map +0 -1
  162. package/dist/filesystem/memory.d.ts.map +0 -1
  163. package/dist/filesystem/move-entry.d.ts +0 -9
  164. package/dist/filesystem/move-entry.d.ts.map +0 -1
  165. package/dist/filesystem/move-entry.js +0 -103
  166. package/dist/filesystem/move-entry.js.map +0 -1
  167. package/dist/filesystem/move-error.d.ts +0 -53
  168. package/dist/filesystem/move-error.d.ts.map +0 -1
  169. package/dist/filesystem/move-error.js +0 -99
  170. package/dist/filesystem/move-error.js.map +0 -1
  171. package/dist/filesystem/native-provider-v2.d.ts +0 -75
  172. package/dist/filesystem/native-provider-v2.d.ts.map +0 -1
  173. package/dist/filesystem/native-provider-v2.js +0 -849
  174. package/dist/filesystem/native-provider-v2.js.map +0 -1
  175. package/dist/filesystem/native-provider.d.ts +0 -53
  176. package/dist/filesystem/native-provider.d.ts.map +0 -1
  177. package/dist/filesystem/native-provider.js +0 -471
  178. package/dist/filesystem/native-provider.js.map +0 -1
  179. package/dist/filesystem/native.d.ts.map +0 -1
  180. package/dist/filesystem/types.d.ts +0 -83
  181. package/dist/filesystem/types.d.ts.map +0 -1
  182. package/dist/filesystem/types.js +0 -16
  183. package/dist/filesystem/types.js.map +0 -1
  184. package/dist/filesystem/v2.d.ts +0 -172
  185. package/dist/filesystem/v2.d.ts.map +0 -1
  186. package/dist/filesystem/v2.js +0 -16
  187. package/dist/filesystem/v2.js.map +0 -1
  188. package/dist/filesystem/workspace-path.d.ts +0 -21
  189. package/dist/filesystem/workspace-path.d.ts.map +0 -1
  190. package/dist/filesystem/workspace-path.js +0 -80
  191. package/dist/filesystem/workspace-path.js.map +0 -1
  192. package/dist/host/filesystem-v2.d.ts +0 -45
  193. package/dist/host/filesystem-v2.d.ts.map +0 -1
  194. package/dist/host/filesystem-v2.js +0 -13
  195. package/dist/host/filesystem-v2.js.map +0 -1
  196. package/dist/host/git.d.ts +0 -200
  197. package/dist/host/git.d.ts.map +0 -1
  198. package/dist/host/git.js +0 -15
  199. package/dist/host/git.js.map +0 -1
  200. package/dist/host/index.d.ts.map +0 -1
  201. package/dist/host/types.d.ts +0 -232
  202. package/dist/host/types.d.ts.map +0 -1
  203. package/dist/host/types.js +0 -10
  204. package/dist/host/types.js.map +0 -1
  205. package/dist/host/wire-policy.d.ts +0 -22
  206. package/dist/host/wire-policy.d.ts.map +0 -1
  207. package/dist/host/wire-policy.js +0 -92
  208. package/dist/host/wire-policy.js.map +0 -1
  209. package/dist/index.d.ts.map +0 -1
  210. package/dist/mcp/index.d.ts.map +0 -1
  211. package/dist/mcp/types.d.ts +0 -466
  212. package/dist/mcp/types.d.ts.map +0 -1
  213. package/dist/mcp/types.js +0 -25
  214. package/dist/mcp/types.js.map +0 -1
  215. package/dist/mcp/wire.d.ts +0 -29
  216. package/dist/mcp/wire.d.ts.map +0 -1
  217. package/dist/mcp/wire.js +0 -1046
  218. package/dist/mcp/wire.js.map +0 -1
  219. package/dist/mcp/zod.d.ts.map +0 -1
  220. package/dist/vscode/index.d.ts.map +0 -1
  221. package/dist/vscode/messages.d.ts +0 -204
  222. package/dist/vscode/messages.d.ts.map +0 -1
  223. package/dist/vscode/messages.js +0 -494
  224. package/dist/vscode/messages.js.map +0 -1
  225. package/dist/workspace/index.d.ts.map +0 -1
  226. package/dist/workspace/reconcile-electron.d.ts +0 -19
  227. package/dist/workspace/reconcile-electron.d.ts.map +0 -1
  228. package/dist/workspace/reconcile-electron.js +0 -42
  229. package/dist/workspace/reconcile-electron.js.map +0 -1
  230. package/dist/workspace/types.d.ts +0 -69
  231. package/dist/workspace/types.d.ts.map +0 -1
  232. package/dist/workspace/types.js +0 -2
  233. package/dist/workspace/types.js.map +0 -1
  234. package/dist/workspace/workspace-manager.d.ts +0 -47
  235. package/dist/workspace/workspace-manager.d.ts.map +0 -1
  236. package/dist/workspace/workspace-manager.js +0 -126
  237. package/dist/workspace/workspace-manager.js.map +0 -1
  238. package/src/document/document-session.ts +0 -834
  239. package/src/document/filesystem-target.ts +0 -109
  240. package/src/document/index.ts +0 -41
  241. package/src/document/recovery-journal.ts +0 -536
  242. package/src/document/types.ts +0 -116
  243. package/src/filesystem/commit-lock.ts +0 -29
  244. package/src/filesystem/dbk-workspace.ts +0 -135
  245. package/src/filesystem/electron-provider-v2.ts +0 -630
  246. package/src/filesystem/electron-provider.ts +0 -99
  247. package/src/filesystem/electron.ts +0 -3
  248. package/src/filesystem/file-media-provider.ts +0 -103
  249. package/src/filesystem/filesystem-content-container.ts +0 -164
  250. package/src/filesystem/fs-error.ts +0 -234
  251. package/src/filesystem/index.ts +0 -143
  252. package/src/filesystem/indexeddb-content-container.ts +0 -112
  253. package/src/filesystem/indexeddb-provider-v2.ts +0 -1740
  254. package/src/filesystem/indexeddb-provider.ts +0 -171
  255. package/src/filesystem/indexeddb-store.ts +0 -207
  256. package/src/filesystem/indexeddb.ts +0 -12
  257. package/src/filesystem/legacy-v2-adapter.ts +0 -779
  258. package/src/filesystem/memory-provider-v2.ts +0 -896
  259. package/src/filesystem/memory-provider.ts +0 -180
  260. package/src/filesystem/memory.ts +0 -15
  261. package/src/filesystem/move-entry.ts +0 -142
  262. package/src/filesystem/move-error.ts +0 -159
  263. package/src/filesystem/native-provider-v2.ts +0 -1165
  264. package/src/filesystem/native-provider.ts +0 -537
  265. package/src/filesystem/native.ts +0 -16
  266. package/src/filesystem/types.ts +0 -114
  267. package/src/filesystem/v2.ts +0 -231
  268. package/src/filesystem/workspace-path.ts +0 -92
  269. package/src/host/filesystem-v2.ts +0 -104
  270. package/src/host/git.ts +0 -246
  271. package/src/host/index.ts +0 -93
  272. package/src/host/types.ts +0 -274
  273. package/src/host/wire-policy.ts +0 -103
  274. package/src/index.ts +0 -10
  275. package/src/mcp/index.ts +0 -3
  276. package/src/mcp/types.ts +0 -594
  277. package/src/mcp/wire.ts +0 -1280
  278. package/src/mcp/zod.ts +0 -1000
  279. package/src/vscode/index.ts +0 -2
  280. package/src/vscode/messages.ts +0 -704
  281. package/src/workspace/index.ts +0 -17
  282. package/src/workspace/reconcile-electron.ts +0 -65
  283. package/src/workspace/types.ts +0 -67
  284. package/src/workspace/workspace-manager.ts +0 -151
  285. /package/dist/{chunk-75UUF6C4.js.map → chunk-B56KWCSE.js.map} +0 -0
  286. /package/dist/{chunk-EGNDADXB.js.map → chunk-MNSZ7EZN.js.map} +0 -0
@@ -1,3 +1,383 @@
1
- /** Runtime-validated VS Code host/webview wire protocol. */
2
- export * from './messages.js';
1
+ import {
2
+ HOST_WIRE_LIMITS,
3
+ isBoundedString
4
+ } from "../chunk-FNW556FN.js";
5
+
6
+ // src/vscode/messages.ts
7
+ var MAX_REQUEST_ID = 2147483647;
8
+ var DOCBLOCKS_ACCENT_COLORS = [
9
+ "brown",
10
+ "green",
11
+ "blue",
12
+ "purple",
13
+ "maroon",
14
+ "orange",
15
+ "gray"
16
+ ];
17
+ var DOCBLOCKS_WRITE_CANVAS_TEXT_SIZE_MIN = 12;
18
+ var DOCBLOCKS_WRITE_CANVAS_TEXT_SIZE_MAX = 32;
19
+ var DOCBLOCKS_WRITE_CANVAS_LINE_SPACING_MIN = 1.2;
20
+ var DOCBLOCKS_WRITE_CANVAS_LINE_SPACING_MAX = 2.4;
21
+ var DEFAULT_VSCODE_WRITE_CANVAS_SETTINGS = {
22
+ textSize: 16,
23
+ lineSpacing: 1.7
24
+ };
25
+ function parseWebviewToExtensionMessage(value) {
26
+ if (!isRecord(value) || typeof value.type !== "string") return null;
27
+ switch (value.type) {
28
+ case "ready":
29
+ return hasOnlyKeys(value, ["type"]) ? { type: "ready" } : null;
30
+ case "setAutoSave":
31
+ return hasOnlyKeys(value, ["type", "enabled"]) && typeof value.enabled === "boolean" ? { type: "setAutoSave", enabled: value.enabled } : null;
32
+ case "setAccentColor":
33
+ return hasOnlyKeys(value, ["type", "accentColor"]) && isDocBlocksAccentColor(value.accentColor) ? { type: "setAccentColor", accentColor: value.accentColor } : null;
34
+ case "setWriteCanvasSettings": {
35
+ if (!hasOnlyKeys(value, ["type", "settings"])) return null;
36
+ const settings = parseVscodeWriteCanvasSettings(value.settings);
37
+ return settings ? { type: "setWriteCanvasSettings", settings } : null;
38
+ }
39
+ case "edit":
40
+ return hasOnlyKeys(value, [
41
+ "type",
42
+ "content",
43
+ "sessionId",
44
+ "clientRevision",
45
+ "baseDocumentVersion"
46
+ ]) && hasBoundedString(value, "content", HOST_WIRE_LIMITS.documentCharacters) && isSessionEnvelope(value) ? {
47
+ type: "edit",
48
+ content: value.content,
49
+ sessionId: value.sessionId,
50
+ clientRevision: value.clientRevision,
51
+ baseDocumentVersion: value.baseDocumentVersion
52
+ } : null;
53
+ case "save":
54
+ return hasOnlyKeys(value, [
55
+ "type",
56
+ "sessionId",
57
+ "requestId",
58
+ "clientRevision",
59
+ "baseDocumentVersion"
60
+ ]) && isSessionEnvelope(value) && hasRequestId(value) ? {
61
+ type: "save",
62
+ sessionId: value.sessionId,
63
+ requestId: value.requestId,
64
+ clientRevision: value.clientRevision,
65
+ baseDocumentVersion: value.baseDocumentVersion
66
+ } : null;
67
+ case "resolveConflict":
68
+ return hasOnlyKeys(value, ["type", "sessionId", "choice"]) && hasBoundedString(value, "sessionId", HOST_WIRE_LIMITS.identifierCharacters, 1) && (value.choice === "use-local" || value.choice === "use-external") ? { type: "resolveConflict", sessionId: value.sessionId, choice: value.choice } : null;
69
+ case "resolveMedia":
70
+ return hasOnlyKeys(value, ["type", "requestId", "ref"]) && hasRequestId(value) && hasBoundedString(value, "ref", HOST_WIRE_LIMITS.pathCharacters, 1) ? { type: "resolveMedia", requestId: value.requestId, ref: value.ref } : null;
71
+ case "listMedia":
72
+ return hasOnlyKeys(value, ["type", "requestId"]) && hasRequestId(value) ? { type: "listMedia", requestId: value.requestId } : null;
73
+ case "addMedia":
74
+ return hasOnlyKeys(value, ["type", "requestId", "name", "dataBase64", "mimeType"]) && hasRequestId(value) && hasBoundedString(value, "name", HOST_WIRE_LIMITS.pathCharacters, 1) && hasBoundedString(value, "dataBase64", HOST_WIRE_LIMITS.base64Characters) && hasMimeType(value, "mimeType") ? {
75
+ type: "addMedia",
76
+ requestId: value.requestId,
77
+ name: value.name,
78
+ dataBase64: value.dataBase64,
79
+ mimeType: value.mimeType
80
+ } : null;
81
+ case "removeMedia":
82
+ return hasOnlyKeys(value, ["type", "requestId", "ref"]) && hasRequestId(value) && hasBoundedString(value, "ref", HOST_WIRE_LIMITS.pathCharacters, 1) ? { type: "removeMedia", requestId: value.requestId, ref: value.ref } : null;
83
+ case "saveExport":
84
+ return hasOnlyKeys(value, [
85
+ "type",
86
+ "requestId",
87
+ "filename",
88
+ "dataBase64",
89
+ "mimeType",
90
+ "grantId"
91
+ ]) && hasRequestId(value) && hasSafeFilename(value, "filename") && hasBoundedString(value, "dataBase64", HOST_WIRE_LIMITS.base64Characters) && hasMimeType(value, "mimeType") && hasNullableBoundedString(value, "grantId", HOST_WIRE_LIMITS.identifierCharacters, 1) ? {
92
+ type: "saveExport",
93
+ requestId: value.requestId,
94
+ filename: value.filename,
95
+ dataBase64: value.dataBase64,
96
+ mimeType: value.mimeType,
97
+ grantId: value.grantId
98
+ } : null;
99
+ case "resolveExportTarget":
100
+ return hasOnlyKeys(value, ["type", "requestId", "filename"]) && hasRequestId(value) && hasSafeFilename(value, "filename") ? { type: "resolveExportTarget", requestId: value.requestId, filename: value.filename } : null;
101
+ case "pickExportTarget":
102
+ return hasOnlyKeys(value, ["type", "requestId", "filename", "currentGrantId"]) && hasRequestId(value) && hasSafeFilename(value, "filename") && hasNullableBoundedString(value, "currentGrantId", HOST_WIRE_LIMITS.identifierCharacters, 1) ? {
103
+ type: "pickExportTarget",
104
+ requestId: value.requestId,
105
+ filename: value.filename,
106
+ currentGrantId: value.currentGrantId
107
+ } : null;
108
+ case "readWorkspaceFile":
109
+ return hasOnlyKeys(value, ["type", "requestId", "path"]) && hasRequestId(value) && hasBoundedString(value, "path", HOST_WIRE_LIMITS.pathCharacters, 1) ? { type: "readWorkspaceFile", requestId: value.requestId, path: value.path } : null;
110
+ default:
111
+ return null;
112
+ }
113
+ }
114
+ function parseExtensionToWebviewMessage(value) {
115
+ if (!isRecord(value) || typeof value.type !== "string") return null;
116
+ switch (value.type) {
117
+ case "setContent":
118
+ return hasOnlyKeys(value, [
119
+ "type",
120
+ "content",
121
+ "documentVersion",
122
+ "fileName",
123
+ "sessionId",
124
+ "sessionRevision",
125
+ "acknowledgedClientRevision"
126
+ ]) && hasBoundedString(value, "content", HOST_WIRE_LIMITS.documentCharacters) && hasNonNegativeInteger(value, "documentVersion") && hasBoundedString(value, "fileName", HOST_WIRE_LIMITS.pathCharacters, 1) && hasBoundedString(value, "sessionId", HOST_WIRE_LIMITS.identifierCharacters, 1) && hasNonNegativeInteger(value, "sessionRevision") && hasNonNegativeInteger(value, "acknowledgedClientRevision") ? {
127
+ type: "setContent",
128
+ content: value.content,
129
+ documentVersion: value.documentVersion,
130
+ fileName: value.fileName,
131
+ sessionId: value.sessionId,
132
+ sessionRevision: value.sessionRevision,
133
+ acknowledgedClientRevision: value.acknowledgedClientRevision
134
+ } : null;
135
+ case "editAcknowledged":
136
+ return hasOnlyKeys(value, [
137
+ "type",
138
+ "sessionId",
139
+ "clientRevision",
140
+ "sessionRevision",
141
+ "accepted",
142
+ "message"
143
+ ]) && hasBoundedString(value, "sessionId", HOST_WIRE_LIMITS.identifierCharacters, 1) && hasNonNegativeInteger(value, "clientRevision") && hasNonNegativeInteger(value, "sessionRevision") && typeof value.accepted === "boolean" && hasNullableBoundedString(value, "message", HOST_WIRE_LIMITS.messageCharacters) ? {
144
+ type: "editAcknowledged",
145
+ sessionId: value.sessionId,
146
+ clientRevision: value.clientRevision,
147
+ sessionRevision: value.sessionRevision,
148
+ accepted: value.accepted,
149
+ message: value.message
150
+ } : null;
151
+ case "sessionState": {
152
+ if (!hasOnlyKeys(value, [
153
+ "type",
154
+ "sessionId",
155
+ "status",
156
+ "revision",
157
+ "persistedRevision",
158
+ "acknowledgedClientRevision",
159
+ "documentVersion",
160
+ "error",
161
+ "conflict"
162
+ ]) || !hasBoundedString(value, "sessionId", HOST_WIRE_LIMITS.identifierCharacters, 1) || !isDocumentSessionMessageStatus(value.status) || !hasNonNegativeInteger(value, "revision") || !hasNonNegativeInteger(value, "persistedRevision") || value.persistedRevision > value.revision || !hasNonNegativeInteger(value, "acknowledgedClientRevision") || !hasNonNegativeInteger(value, "documentVersion") || !hasNullableBoundedString(value, "error", HOST_WIRE_LIMITS.messageCharacters)) {
163
+ return null;
164
+ }
165
+ const conflict = parseDocumentConflictDetails(value.conflict);
166
+ if (conflict === void 0 || value.status === "conflict" && conflict === null || value.status !== "conflict" && conflict !== null) {
167
+ return null;
168
+ }
169
+ return {
170
+ type: "sessionState",
171
+ sessionId: value.sessionId,
172
+ status: value.status,
173
+ revision: value.revision,
174
+ persistedRevision: value.persistedRevision,
175
+ acknowledgedClientRevision: value.acknowledgedClientRevision,
176
+ documentVersion: value.documentVersion,
177
+ error: value.error,
178
+ conflict
179
+ };
180
+ }
181
+ case "saveResult":
182
+ return hasOnlyKeys(value, [
183
+ "type",
184
+ "sessionId",
185
+ "requestId",
186
+ "ok",
187
+ "revision",
188
+ "persistedRevision",
189
+ "documentVersion",
190
+ "message"
191
+ ]) && hasBoundedString(value, "sessionId", HOST_WIRE_LIMITS.identifierCharacters, 1) && hasRequestId(value) && typeof value.ok === "boolean" && hasNonNegativeInteger(value, "revision") && hasNonNegativeInteger(value, "persistedRevision") && value.persistedRevision <= value.revision && hasNonNegativeInteger(value, "documentVersion") && hasNullableBoundedString(value, "message", HOST_WIRE_LIMITS.messageCharacters) ? {
192
+ type: "saveResult",
193
+ sessionId: value.sessionId,
194
+ requestId: value.requestId,
195
+ ok: value.ok,
196
+ revision: value.revision,
197
+ persistedRevision: value.persistedRevision,
198
+ documentVersion: value.documentVersion,
199
+ message: value.message
200
+ } : null;
201
+ case "themeChange":
202
+ return hasOnlyKeys(value, ["type", "theme"]) && (value.theme === "light" || value.theme === "dark") ? { type: "themeChange", theme: value.theme } : null;
203
+ case "editorSettings": {
204
+ if (!hasOnlyKeys(value, ["type", "settings"])) return null;
205
+ const settings = parseVscodeEditorSettings(value.settings);
206
+ return settings ? { type: "editorSettings", settings } : null;
207
+ }
208
+ case "mediaResolved":
209
+ return hasOnlyKeys(value, ["type", "requestId", "url"]) && hasRequestId(value) && isBoundedMediaDataUrl(value.url) ? { type: "mediaResolved", requestId: value.requestId, url: value.url } : null;
210
+ case "mediaListed": {
211
+ if (!hasOnlyKeys(value, ["type", "requestId", "entries"]) || !hasRequestId(value)) {
212
+ return null;
213
+ }
214
+ const entries = parseMediaEntries(value.entries);
215
+ return entries ? { type: "mediaListed", requestId: value.requestId, entries } : null;
216
+ }
217
+ case "mediaAdded":
218
+ return hasOnlyKeys(value, ["type", "requestId", "path"]) && hasRequestId(value) && hasBoundedString(value, "path", HOST_WIRE_LIMITS.pathCharacters, 1) ? { type: "mediaAdded", requestId: value.requestId, path: value.path } : null;
219
+ case "mediaRemoved":
220
+ return hasOnlyKeys(value, ["type", "requestId"]) && hasRequestId(value) ? { type: "mediaRemoved", requestId: value.requestId } : null;
221
+ case "mediaError":
222
+ case "exportError":
223
+ case "workspaceFileError":
224
+ return hasOnlyKeys(value, ["type", "requestId", "message"]) && hasRequestId(value) && hasBoundedString(value, "message", HOST_WIRE_LIMITS.messageCharacters, 1) ? { type: value.type, requestId: value.requestId, message: value.message } : null;
225
+ case "exportSaved":
226
+ case "exportTargetResolved":
227
+ case "exportTargetPicked": {
228
+ if (!hasOnlyKeys(value, ["type", "requestId", "target"]) || !hasRequestId(value)) {
229
+ return null;
230
+ }
231
+ const target = parseExportTargetGrant(value.target);
232
+ return target !== void 0 ? { type: value.type, requestId: value.requestId, target } : null;
233
+ }
234
+ case "workspaceFileRead":
235
+ return hasOnlyKeys(value, ["type", "requestId", "dataBase64"]) && hasRequestId(value) && hasNullableBoundedString(value, "dataBase64", HOST_WIRE_LIMITS.base64Characters) ? { type: "workspaceFileRead", requestId: value.requestId, dataBase64: value.dataBase64 } : null;
236
+ default:
237
+ return null;
238
+ }
239
+ }
240
+ function parseExportTargetGrant(value) {
241
+ if (value === null) return null;
242
+ if (!isRecord(value) || !hasOnlyKeys(value, ["grantId", "displayLabel"]) || !hasBoundedString(value, "grantId", HOST_WIRE_LIMITS.identifierCharacters, 1) || !hasBoundedString(value, "displayLabel", HOST_WIRE_LIMITS.pathCharacters, 1)) {
243
+ return void 0;
244
+ }
245
+ return { grantId: value.grantId, displayLabel: value.displayLabel };
246
+ }
247
+ function parseDocumentConflictDetails(value) {
248
+ if (value === null) return null;
249
+ if (!isRecord(value) || !hasOnlyKeys(value, [
250
+ "localBaseDocumentVersion",
251
+ "externalDocumentVersion",
252
+ "localBytes",
253
+ "externalBytes",
254
+ "localEditedAt",
255
+ "externalObservedAt",
256
+ "externalIsDirty"
257
+ ]) || !hasNonNegativeInteger(value, "localBaseDocumentVersion") || !hasNonNegativeInteger(value, "externalDocumentVersion") || !hasNonNegativeInteger(value, "localBytes") || !isNullableNonNegativeInteger(value.externalBytes) || !isNullableNonNegativeInteger(value.localEditedAt) || !isNullableNonNegativeInteger(value.externalObservedAt) || value.externalIsDirty !== null && typeof value.externalIsDirty !== "boolean") {
258
+ return void 0;
259
+ }
260
+ return {
261
+ localBaseDocumentVersion: value.localBaseDocumentVersion,
262
+ externalDocumentVersion: value.externalDocumentVersion,
263
+ localBytes: value.localBytes,
264
+ externalBytes: value.externalBytes,
265
+ localEditedAt: value.localEditedAt,
266
+ externalObservedAt: value.externalObservedAt,
267
+ externalIsDirty: value.externalIsDirty
268
+ };
269
+ }
270
+ function parseVscodeEditorSettings(value) {
271
+ if (!isRecord(value) || !hasOnlyKeys(value, ["autoSave", "accentColor", "writeCanvasSettings"]) || typeof value.autoSave !== "boolean" || !isDocBlocksAccentColor(value.accentColor)) {
272
+ return null;
273
+ }
274
+ const writeCanvasSettings = parseVscodeWriteCanvasSettings(value.writeCanvasSettings);
275
+ return writeCanvasSettings ? { autoSave: value.autoSave, accentColor: value.accentColor, writeCanvasSettings } : null;
276
+ }
277
+ function isDocBlocksAccentColor(value) {
278
+ return DOCBLOCKS_ACCENT_COLORS.some((color) => color === value);
279
+ }
280
+ function isDocBlocksWriteCanvasTextSize(value) {
281
+ return numberInRange(
282
+ value,
283
+ DOCBLOCKS_WRITE_CANVAS_TEXT_SIZE_MIN,
284
+ DOCBLOCKS_WRITE_CANVAS_TEXT_SIZE_MAX
285
+ );
286
+ }
287
+ function isDocBlocksWriteCanvasLineSpacing(value) {
288
+ return numberInRange(
289
+ value,
290
+ DOCBLOCKS_WRITE_CANVAS_LINE_SPACING_MIN,
291
+ DOCBLOCKS_WRITE_CANVAS_LINE_SPACING_MAX
292
+ );
293
+ }
294
+ function parseVscodeWriteCanvasSettings(value) {
295
+ return isRecord(value) && hasOnlyKeys(value, ["textSize", "lineSpacing"]) && isDocBlocksWriteCanvasTextSize(value.textSize) && isDocBlocksWriteCanvasLineSpacing(value.lineSpacing) ? { textSize: value.textSize, lineSpacing: value.lineSpacing } : null;
296
+ }
297
+ function numberInRange(value, min, max) {
298
+ return typeof value === "number" && Number.isFinite(value) && value >= min && value <= max;
299
+ }
300
+ function parseMediaEntries(value) {
301
+ if (!Array.isArray(value) || value.length > HOST_WIRE_LIMITS.arrayEntries) return null;
302
+ const entries = [];
303
+ for (const entry of value) {
304
+ if (!isRecord(entry) || !hasOnlyKeys(entry, ["name", "mimeType", "size"]) || !hasBoundedString(entry, "name", HOST_WIRE_LIMITS.pathCharacters, 1) || !hasMimeType(entry, "mimeType") || !hasNonNegativeInteger(entry, "size") || entry.size > HOST_WIRE_LIMITS.binaryBytes) {
305
+ return null;
306
+ }
307
+ entries.push({ name: entry.name, mimeType: entry.mimeType, size: entry.size });
308
+ }
309
+ return entries;
310
+ }
311
+ function isBoundedMediaDataUrl(value) {
312
+ if (!isBoundedString(value, HOST_WIRE_LIMITS.base64Characters + 512, 1)) return false;
313
+ if (!value.startsWith("data:")) return false;
314
+ const separator = value.indexOf(";base64,");
315
+ return separator > 5 && separator <= HOST_WIRE_LIMITS.identifierCharacters;
316
+ }
317
+ function isDocumentSessionMessageStatus(value) {
318
+ return value === "idle" || value === "saved" || value === "dirty" || value === "saving" || value === "error" || value === "conflict" || value === "closed";
319
+ }
320
+ function isSessionEnvelope(value) {
321
+ return hasBoundedString(value, "sessionId", HOST_WIRE_LIMITS.identifierCharacters, 1) && hasNonNegativeInteger(value, "clientRevision") && hasNonNegativeInteger(value, "baseDocumentVersion");
322
+ }
323
+ function hasRequestId(value) {
324
+ return hasNonNegativeInteger(value, "requestId") && value.requestId <= MAX_REQUEST_ID;
325
+ }
326
+ function hasBoundedString(value, key, maximumCharacters, minimumCharacters = 0) {
327
+ return isBoundedString(value[key], maximumCharacters, minimumCharacters);
328
+ }
329
+ function hasNullableBoundedString(value, key, maximumCharacters, minimumCharacters = 0) {
330
+ return value[key] === null || isBoundedString(value[key], maximumCharacters, minimumCharacters);
331
+ }
332
+ function hasNonNegativeInteger(value, key) {
333
+ const entry = value[key];
334
+ return typeof entry === "number" && Number.isSafeInteger(entry) && entry >= 0;
335
+ }
336
+ function isNullableNonNegativeInteger(value) {
337
+ return value === null || typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
338
+ }
339
+ function isRecord(value) {
340
+ return typeof value === "object" && value !== null && !Array.isArray(value);
341
+ }
342
+ function hasOnlyKeys(value, keys) {
343
+ const expected = new Set(keys);
344
+ const actual = Object.keys(value);
345
+ return actual.length === expected.size && actual.every((key) => expected.has(key));
346
+ }
347
+ function hasSafeFilename(value, key) {
348
+ return isSafeExportFilename(value[key]);
349
+ }
350
+ function isSafeExportFilename(value) {
351
+ return isBoundedString(value, 255, 1) && value.trim() === value && !/[\\/:*?"<>|]/.test(value) && !hasControlCharacter(value) && value !== "." && value !== ".." && !value.endsWith(".") && !value.endsWith(" ");
352
+ }
353
+ function hasControlCharacter(value) {
354
+ for (let index = 0; index < value.length; index += 1) {
355
+ const code = value.charCodeAt(index);
356
+ if (code <= 31 || code === 127) return true;
357
+ }
358
+ return false;
359
+ }
360
+ function hasMimeType(value, key) {
361
+ return isSafeMimeType(value[key]);
362
+ }
363
+ function isSafeMimeType(value) {
364
+ return isBoundedString(value, HOST_WIRE_LIMITS.identifierCharacters, 1) && /^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+(?:\s*;\s*[A-Za-z0-9!#$&^_.+-]+=[^;\r\n]+)*$/.test(
365
+ value
366
+ );
367
+ }
368
+ export {
369
+ DEFAULT_VSCODE_WRITE_CANVAS_SETTINGS,
370
+ DOCBLOCKS_ACCENT_COLORS,
371
+ DOCBLOCKS_WRITE_CANVAS_LINE_SPACING_MAX,
372
+ DOCBLOCKS_WRITE_CANVAS_LINE_SPACING_MIN,
373
+ DOCBLOCKS_WRITE_CANVAS_TEXT_SIZE_MAX,
374
+ DOCBLOCKS_WRITE_CANVAS_TEXT_SIZE_MIN,
375
+ isDocBlocksAccentColor,
376
+ isDocBlocksWriteCanvasLineSpacing,
377
+ isDocBlocksWriteCanvasTextSize,
378
+ isSafeExportFilename,
379
+ isSafeMimeType,
380
+ parseExtensionToWebviewMessage,
381
+ parseWebviewToExtensionMessage
382
+ };
3
383
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vscode/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,cAAc,eAAe,CAAC"}
1
+ {"version":3,"sources":["../../src/vscode/messages.ts"],"sourcesContent":["/**\n * Typed message protocol between the extension host and webview.\n */\n\nimport { HOST_WIRE_LIMITS, isBoundedString } from '../host/wire-policy.js';\n\nconst MAX_REQUEST_ID = 2_147_483_647;\n\nexport type DocumentSessionMessageStatus =\n | 'idle'\n | 'saved'\n | 'dirty'\n | 'saving'\n | 'error'\n | 'conflict'\n | 'closed';\n\nexport type DocumentConflictChoice = 'use-local' | 'use-external';\n\n/** Host-observed details that help a user distinguish two text branches. */\nexport interface DocumentConflictDetailsMessage {\n /** VS Code document version on which the DocBlocks draft was based. */\n localBaseDocumentVersion: number;\n /** Current VS Code document version observed outside the DocBlocks edit pipeline. */\n externalDocumentVersion: number;\n /** UTF-8 encoded sizes of the complete text snapshots. */\n localBytes: number;\n externalBytes: number | null;\n /** Times are extension-host observations, not filesystem-authoritative mtimes. */\n localEditedAt: number | null;\n externalObservedAt: number | null;\n /** Whether VS Code reported the external document snapshot as not yet saved. */\n externalIsDirty: boolean | null;\n}\n\nexport const DOCBLOCKS_ACCENT_COLORS = [\n 'brown',\n 'green',\n 'blue',\n 'purple',\n 'maroon',\n 'orange',\n 'gray',\n] as const;\n\nexport type DocBlocksAccentColor = (typeof DOCBLOCKS_ACCENT_COLORS)[number];\n\nexport const DOCBLOCKS_WRITE_CANVAS_TEXT_SIZE_MIN = 12;\nexport const DOCBLOCKS_WRITE_CANVAS_TEXT_SIZE_MAX = 32;\nexport const DOCBLOCKS_WRITE_CANVAS_LINE_SPACING_MIN = 1.2;\nexport const DOCBLOCKS_WRITE_CANVAS_LINE_SPACING_MAX = 2.4;\n\nexport interface VscodeWriteCanvasSettings {\n textSize: number;\n lineSpacing: number;\n}\n\nexport const DEFAULT_VSCODE_WRITE_CANVAS_SETTINGS: Readonly<VscodeWriteCanvasSettings> = {\n textSize: 16,\n lineSpacing: 1.7,\n};\n\nexport interface VscodeEditorSettings {\n autoSave: boolean;\n accentColor: DocBlocksAccentColor;\n writeCanvasSettings: VscodeWriteCanvasSettings;\n}\n\n/**\n * An opaque, one-shot authority to write one host-owned export target.\n * The label is presentation-only and must never be interpreted as a path.\n */\nexport interface ExportTargetGrantMessage {\n grantId: string;\n displayLabel: string;\n}\n\n/** Messages sent from the extension host to the webview. */\nexport type ExtensionToWebviewMessage =\n | {\n type: 'setContent';\n content: string;\n documentVersion: number;\n fileName: string;\n sessionId: string;\n sessionRevision: number;\n acknowledgedClientRevision: number;\n }\n | {\n type: 'editAcknowledged';\n sessionId: string;\n clientRevision: number;\n sessionRevision: number;\n accepted: boolean;\n message: string | null;\n }\n | {\n type: 'sessionState';\n sessionId: string;\n status: DocumentSessionMessageStatus;\n revision: number;\n persistedRevision: number;\n acknowledgedClientRevision: number;\n documentVersion: number;\n error: string | null;\n conflict: DocumentConflictDetailsMessage | null;\n }\n | {\n type: 'saveResult';\n sessionId: string;\n requestId: number;\n ok: boolean;\n revision: number;\n persistedRevision: number;\n documentVersion: number;\n message: string | null;\n }\n | { type: 'themeChange'; theme: 'light' | 'dark' }\n | { type: 'editorSettings'; settings: VscodeEditorSettings }\n | { type: 'mediaResolved'; requestId: number; url: string }\n | { type: 'mediaListed'; requestId: number; entries: MediaEntryMessage[] }\n | { type: 'mediaAdded'; requestId: number; path: string }\n | { type: 'mediaRemoved'; requestId: number }\n | { type: 'mediaError'; requestId: number; message: string }\n | { type: 'exportSaved'; requestId: number; target: ExportTargetGrantMessage | null }\n | { type: 'exportError'; requestId: number; message: string }\n | { type: 'exportTargetResolved'; requestId: number; target: ExportTargetGrantMessage | null }\n | { type: 'exportTargetPicked'; requestId: number; target: ExportTargetGrantMessage | null }\n | { type: 'workspaceFileRead'; requestId: number; dataBase64: string | null }\n | { type: 'workspaceFileError'; requestId: number; message: string };\n\n/** Messages sent from the webview to the extension host. */\nexport type WebviewToExtensionMessage =\n | { type: 'ready' }\n | { type: 'setAutoSave'; enabled: boolean }\n | { type: 'setAccentColor'; accentColor: DocBlocksAccentColor }\n | { type: 'setWriteCanvasSettings'; settings: VscodeWriteCanvasSettings }\n | {\n type: 'edit';\n content: string;\n sessionId: string;\n clientRevision: number;\n baseDocumentVersion: number;\n }\n | {\n type: 'save';\n sessionId: string;\n requestId: number;\n clientRevision: number;\n baseDocumentVersion: number;\n }\n | { type: 'resolveConflict'; sessionId: string; choice: DocumentConflictChoice }\n | { type: 'resolveMedia'; requestId: number; ref: string }\n | { type: 'listMedia'; requestId: number }\n | { type: 'addMedia'; requestId: number; name: string; dataBase64: string; mimeType: string }\n | { type: 'removeMedia'; requestId: number; ref: string }\n | {\n type: 'saveExport';\n requestId: number;\n filename: string;\n dataBase64: string;\n mimeType: string;\n grantId: string | null;\n }\n | { type: 'resolveExportTarget'; requestId: number; filename: string }\n | {\n type: 'pickExportTarget';\n requestId: number;\n filename: string;\n currentGrantId: string | null;\n }\n | { type: 'readWorkspaceFile'; requestId: number; path: string };\n\nexport interface MediaEntryMessage {\n name: string;\n mimeType: string;\n size: number;\n}\n\n/**\n * The webview boundary is untrusted at runtime. Keep malformed or stale\n * messages out of the document session instead of relying on a TypeScript\n * assertion in the extension host.\n */\nexport function parseWebviewToExtensionMessage(value: unknown): WebviewToExtensionMessage | null {\n if (!isRecord(value) || typeof value.type !== 'string') return null;\n\n switch (value.type) {\n case 'ready':\n return hasOnlyKeys(value, ['type']) ? { type: 'ready' } : null;\n case 'setAutoSave':\n return hasOnlyKeys(value, ['type', 'enabled']) && typeof value.enabled === 'boolean'\n ? { type: 'setAutoSave', enabled: value.enabled }\n : null;\n case 'setAccentColor':\n return hasOnlyKeys(value, ['type', 'accentColor']) &&\n isDocBlocksAccentColor(value.accentColor)\n ? { type: 'setAccentColor', accentColor: value.accentColor }\n : null;\n case 'setWriteCanvasSettings': {\n if (!hasOnlyKeys(value, ['type', 'settings'])) return null;\n const settings = parseVscodeWriteCanvasSettings(value.settings);\n return settings ? { type: 'setWriteCanvasSettings', settings } : null;\n }\n case 'edit':\n return hasOnlyKeys(value, [\n 'type',\n 'content',\n 'sessionId',\n 'clientRevision',\n 'baseDocumentVersion',\n ]) &&\n hasBoundedString(value, 'content', HOST_WIRE_LIMITS.documentCharacters) &&\n isSessionEnvelope(value)\n ? {\n type: 'edit',\n content: value.content,\n sessionId: value.sessionId,\n clientRevision: value.clientRevision,\n baseDocumentVersion: value.baseDocumentVersion,\n }\n : null;\n case 'save':\n return hasOnlyKeys(value, [\n 'type',\n 'sessionId',\n 'requestId',\n 'clientRevision',\n 'baseDocumentVersion',\n ]) &&\n isSessionEnvelope(value) &&\n hasRequestId(value)\n ? {\n type: 'save',\n sessionId: value.sessionId,\n requestId: value.requestId,\n clientRevision: value.clientRevision,\n baseDocumentVersion: value.baseDocumentVersion,\n }\n : null;\n case 'resolveConflict':\n return hasOnlyKeys(value, ['type', 'sessionId', 'choice']) &&\n hasBoundedString(value, 'sessionId', HOST_WIRE_LIMITS.identifierCharacters, 1) &&\n (value.choice === 'use-local' || value.choice === 'use-external')\n ? { type: 'resolveConflict', sessionId: value.sessionId, choice: value.choice }\n : null;\n case 'resolveMedia':\n return hasOnlyKeys(value, ['type', 'requestId', 'ref']) &&\n hasRequestId(value) &&\n hasBoundedString(value, 'ref', HOST_WIRE_LIMITS.pathCharacters, 1)\n ? { type: 'resolveMedia', requestId: value.requestId, ref: value.ref }\n : null;\n case 'listMedia':\n return hasOnlyKeys(value, ['type', 'requestId']) && hasRequestId(value)\n ? { type: 'listMedia', requestId: value.requestId }\n : null;\n case 'addMedia':\n return hasOnlyKeys(value, ['type', 'requestId', 'name', 'dataBase64', 'mimeType']) &&\n hasRequestId(value) &&\n hasBoundedString(value, 'name', HOST_WIRE_LIMITS.pathCharacters, 1) &&\n hasBoundedString(value, 'dataBase64', HOST_WIRE_LIMITS.base64Characters) &&\n hasMimeType(value, 'mimeType')\n ? {\n type: 'addMedia',\n requestId: value.requestId,\n name: value.name,\n dataBase64: value.dataBase64,\n mimeType: value.mimeType,\n }\n : null;\n case 'removeMedia':\n return hasOnlyKeys(value, ['type', 'requestId', 'ref']) &&\n hasRequestId(value) &&\n hasBoundedString(value, 'ref', HOST_WIRE_LIMITS.pathCharacters, 1)\n ? { type: 'removeMedia', requestId: value.requestId, ref: value.ref }\n : null;\n case 'saveExport':\n return hasOnlyKeys(value, [\n 'type',\n 'requestId',\n 'filename',\n 'dataBase64',\n 'mimeType',\n 'grantId',\n ]) &&\n hasRequestId(value) &&\n hasSafeFilename(value, 'filename') &&\n hasBoundedString(value, 'dataBase64', HOST_WIRE_LIMITS.base64Characters) &&\n hasMimeType(value, 'mimeType') &&\n hasNullableBoundedString(value, 'grantId', HOST_WIRE_LIMITS.identifierCharacters, 1)\n ? {\n type: 'saveExport',\n requestId: value.requestId,\n filename: value.filename,\n dataBase64: value.dataBase64,\n mimeType: value.mimeType,\n grantId: value.grantId,\n }\n : null;\n case 'resolveExportTarget':\n return hasOnlyKeys(value, ['type', 'requestId', 'filename']) &&\n hasRequestId(value) &&\n hasSafeFilename(value, 'filename')\n ? { type: 'resolveExportTarget', requestId: value.requestId, filename: value.filename }\n : null;\n case 'pickExportTarget':\n return hasOnlyKeys(value, ['type', 'requestId', 'filename', 'currentGrantId']) &&\n hasRequestId(value) &&\n hasSafeFilename(value, 'filename') &&\n hasNullableBoundedString(value, 'currentGrantId', HOST_WIRE_LIMITS.identifierCharacters, 1)\n ? {\n type: 'pickExportTarget',\n requestId: value.requestId,\n filename: value.filename,\n currentGrantId: value.currentGrantId,\n }\n : null;\n case 'readWorkspaceFile':\n return hasOnlyKeys(value, ['type', 'requestId', 'path']) &&\n hasRequestId(value) &&\n hasBoundedString(value, 'path', HOST_WIRE_LIMITS.pathCharacters, 1)\n ? { type: 'readWorkspaceFile', requestId: value.requestId, path: value.path }\n : null;\n default:\n return null;\n }\n}\n\n/**\n * Validate host responses before they influence webview state. This protects\n * the browser side from protocol drift and from messages injected by another\n * script in the webview document; a TypeScript MessageEvent annotation is not\n * runtime validation.\n */\nexport function parseExtensionToWebviewMessage(value: unknown): ExtensionToWebviewMessage | null {\n if (!isRecord(value) || typeof value.type !== 'string') return null;\n\n switch (value.type) {\n case 'setContent':\n return hasOnlyKeys(value, [\n 'type',\n 'content',\n 'documentVersion',\n 'fileName',\n 'sessionId',\n 'sessionRevision',\n 'acknowledgedClientRevision',\n ]) &&\n hasBoundedString(value, 'content', HOST_WIRE_LIMITS.documentCharacters) &&\n hasNonNegativeInteger(value, 'documentVersion') &&\n hasBoundedString(value, 'fileName', HOST_WIRE_LIMITS.pathCharacters, 1) &&\n hasBoundedString(value, 'sessionId', HOST_WIRE_LIMITS.identifierCharacters, 1) &&\n hasNonNegativeInteger(value, 'sessionRevision') &&\n hasNonNegativeInteger(value, 'acknowledgedClientRevision')\n ? {\n type: 'setContent',\n content: value.content,\n documentVersion: value.documentVersion,\n fileName: value.fileName,\n sessionId: value.sessionId,\n sessionRevision: value.sessionRevision,\n acknowledgedClientRevision: value.acknowledgedClientRevision,\n }\n : null;\n case 'editAcknowledged':\n return hasOnlyKeys(value, [\n 'type',\n 'sessionId',\n 'clientRevision',\n 'sessionRevision',\n 'accepted',\n 'message',\n ]) &&\n hasBoundedString(value, 'sessionId', HOST_WIRE_LIMITS.identifierCharacters, 1) &&\n hasNonNegativeInteger(value, 'clientRevision') &&\n hasNonNegativeInteger(value, 'sessionRevision') &&\n typeof value.accepted === 'boolean' &&\n hasNullableBoundedString(value, 'message', HOST_WIRE_LIMITS.messageCharacters)\n ? {\n type: 'editAcknowledged',\n sessionId: value.sessionId,\n clientRevision: value.clientRevision,\n sessionRevision: value.sessionRevision,\n accepted: value.accepted,\n message: value.message,\n }\n : null;\n case 'sessionState': {\n if (\n !hasOnlyKeys(value, [\n 'type',\n 'sessionId',\n 'status',\n 'revision',\n 'persistedRevision',\n 'acknowledgedClientRevision',\n 'documentVersion',\n 'error',\n 'conflict',\n ]) ||\n !hasBoundedString(value, 'sessionId', HOST_WIRE_LIMITS.identifierCharacters, 1) ||\n !isDocumentSessionMessageStatus(value.status) ||\n !hasNonNegativeInteger(value, 'revision') ||\n !hasNonNegativeInteger(value, 'persistedRevision') ||\n value.persistedRevision > value.revision ||\n !hasNonNegativeInteger(value, 'acknowledgedClientRevision') ||\n !hasNonNegativeInteger(value, 'documentVersion') ||\n !hasNullableBoundedString(value, 'error', HOST_WIRE_LIMITS.messageCharacters)\n ) {\n return null;\n }\n const conflict = parseDocumentConflictDetails(value.conflict);\n if (\n conflict === undefined ||\n (value.status === 'conflict' && conflict === null) ||\n (value.status !== 'conflict' && conflict !== null)\n ) {\n return null;\n }\n return {\n type: 'sessionState',\n sessionId: value.sessionId,\n status: value.status,\n revision: value.revision,\n persistedRevision: value.persistedRevision,\n acknowledgedClientRevision: value.acknowledgedClientRevision,\n documentVersion: value.documentVersion,\n error: value.error,\n conflict,\n };\n }\n case 'saveResult':\n return hasOnlyKeys(value, [\n 'type',\n 'sessionId',\n 'requestId',\n 'ok',\n 'revision',\n 'persistedRevision',\n 'documentVersion',\n 'message',\n ]) &&\n hasBoundedString(value, 'sessionId', HOST_WIRE_LIMITS.identifierCharacters, 1) &&\n hasRequestId(value) &&\n typeof value.ok === 'boolean' &&\n hasNonNegativeInteger(value, 'revision') &&\n hasNonNegativeInteger(value, 'persistedRevision') &&\n value.persistedRevision <= value.revision &&\n hasNonNegativeInteger(value, 'documentVersion') &&\n hasNullableBoundedString(value, 'message', HOST_WIRE_LIMITS.messageCharacters)\n ? {\n type: 'saveResult',\n sessionId: value.sessionId,\n requestId: value.requestId,\n ok: value.ok,\n revision: value.revision,\n persistedRevision: value.persistedRevision,\n documentVersion: value.documentVersion,\n message: value.message,\n }\n : null;\n case 'themeChange':\n return hasOnlyKeys(value, ['type', 'theme']) &&\n (value.theme === 'light' || value.theme === 'dark')\n ? { type: 'themeChange', theme: value.theme }\n : null;\n case 'editorSettings': {\n if (!hasOnlyKeys(value, ['type', 'settings'])) return null;\n const settings = parseVscodeEditorSettings(value.settings);\n return settings ? { type: 'editorSettings', settings } : null;\n }\n case 'mediaResolved':\n return hasOnlyKeys(value, ['type', 'requestId', 'url']) &&\n hasRequestId(value) &&\n isBoundedMediaDataUrl(value.url)\n ? { type: 'mediaResolved', requestId: value.requestId, url: value.url }\n : null;\n case 'mediaListed': {\n if (!hasOnlyKeys(value, ['type', 'requestId', 'entries']) || !hasRequestId(value)) {\n return null;\n }\n const entries = parseMediaEntries(value.entries);\n return entries ? { type: 'mediaListed', requestId: value.requestId, entries } : null;\n }\n case 'mediaAdded':\n return hasOnlyKeys(value, ['type', 'requestId', 'path']) &&\n hasRequestId(value) &&\n hasBoundedString(value, 'path', HOST_WIRE_LIMITS.pathCharacters, 1)\n ? { type: 'mediaAdded', requestId: value.requestId, path: value.path }\n : null;\n case 'mediaRemoved':\n return hasOnlyKeys(value, ['type', 'requestId']) && hasRequestId(value)\n ? { type: 'mediaRemoved', requestId: value.requestId }\n : null;\n case 'mediaError':\n case 'exportError':\n case 'workspaceFileError':\n return hasOnlyKeys(value, ['type', 'requestId', 'message']) &&\n hasRequestId(value) &&\n hasBoundedString(value, 'message', HOST_WIRE_LIMITS.messageCharacters, 1)\n ? { type: value.type, requestId: value.requestId, message: value.message }\n : null;\n case 'exportSaved':\n case 'exportTargetResolved':\n case 'exportTargetPicked': {\n if (!hasOnlyKeys(value, ['type', 'requestId', 'target']) || !hasRequestId(value)) {\n return null;\n }\n const target = parseExportTargetGrant(value.target);\n return target !== undefined ? { type: value.type, requestId: value.requestId, target } : null;\n }\n case 'workspaceFileRead':\n return hasOnlyKeys(value, ['type', 'requestId', 'dataBase64']) &&\n hasRequestId(value) &&\n hasNullableBoundedString(value, 'dataBase64', HOST_WIRE_LIMITS.base64Characters)\n ? { type: 'workspaceFileRead', requestId: value.requestId, dataBase64: value.dataBase64 }\n : null;\n default:\n return null;\n }\n}\n\nfunction parseExportTargetGrant(value: unknown): ExportTargetGrantMessage | null | undefined {\n if (value === null) return null;\n if (\n !isRecord(value) ||\n !hasOnlyKeys(value, ['grantId', 'displayLabel']) ||\n !hasBoundedString(value, 'grantId', HOST_WIRE_LIMITS.identifierCharacters, 1) ||\n !hasBoundedString(value, 'displayLabel', HOST_WIRE_LIMITS.pathCharacters, 1)\n ) {\n return undefined;\n }\n return { grantId: value.grantId, displayLabel: value.displayLabel };\n}\n\nfunction parseDocumentConflictDetails(\n value: unknown,\n): DocumentConflictDetailsMessage | null | undefined {\n if (value === null) return null;\n if (\n !isRecord(value) ||\n !hasOnlyKeys(value, [\n 'localBaseDocumentVersion',\n 'externalDocumentVersion',\n 'localBytes',\n 'externalBytes',\n 'localEditedAt',\n 'externalObservedAt',\n 'externalIsDirty',\n ]) ||\n !hasNonNegativeInteger(value, 'localBaseDocumentVersion') ||\n !hasNonNegativeInteger(value, 'externalDocumentVersion') ||\n !hasNonNegativeInteger(value, 'localBytes') ||\n !isNullableNonNegativeInteger(value.externalBytes) ||\n !isNullableNonNegativeInteger(value.localEditedAt) ||\n !isNullableNonNegativeInteger(value.externalObservedAt) ||\n (value.externalIsDirty !== null && typeof value.externalIsDirty !== 'boolean')\n ) {\n return undefined;\n }\n return {\n localBaseDocumentVersion: value.localBaseDocumentVersion,\n externalDocumentVersion: value.externalDocumentVersion,\n localBytes: value.localBytes,\n externalBytes: value.externalBytes,\n localEditedAt: value.localEditedAt,\n externalObservedAt: value.externalObservedAt,\n externalIsDirty: value.externalIsDirty,\n };\n}\n\nfunction parseVscodeEditorSettings(value: unknown): VscodeEditorSettings | null {\n if (\n !isRecord(value) ||\n !hasOnlyKeys(value, ['autoSave', 'accentColor', 'writeCanvasSettings']) ||\n typeof value.autoSave !== 'boolean' ||\n !isDocBlocksAccentColor(value.accentColor)\n ) {\n return null;\n }\n const writeCanvasSettings = parseVscodeWriteCanvasSettings(value.writeCanvasSettings);\n return writeCanvasSettings\n ? { autoSave: value.autoSave, accentColor: value.accentColor, writeCanvasSettings }\n : null;\n}\n\nexport function isDocBlocksAccentColor(value: unknown): value is DocBlocksAccentColor {\n return DOCBLOCKS_ACCENT_COLORS.some((color) => color === value);\n}\n\nexport function isDocBlocksWriteCanvasTextSize(value: unknown): value is number {\n return numberInRange(\n value,\n DOCBLOCKS_WRITE_CANVAS_TEXT_SIZE_MIN,\n DOCBLOCKS_WRITE_CANVAS_TEXT_SIZE_MAX,\n );\n}\n\nexport function isDocBlocksWriteCanvasLineSpacing(value: unknown): value is number {\n return numberInRange(\n value,\n DOCBLOCKS_WRITE_CANVAS_LINE_SPACING_MIN,\n DOCBLOCKS_WRITE_CANVAS_LINE_SPACING_MAX,\n );\n}\n\nfunction parseVscodeWriteCanvasSettings(value: unknown): VscodeWriteCanvasSettings | null {\n return isRecord(value) &&\n hasOnlyKeys(value, ['textSize', 'lineSpacing']) &&\n isDocBlocksWriteCanvasTextSize(value.textSize) &&\n isDocBlocksWriteCanvasLineSpacing(value.lineSpacing)\n ? { textSize: value.textSize, lineSpacing: value.lineSpacing }\n : null;\n}\n\nfunction numberInRange(value: unknown, min: number, max: number): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value >= min && value <= max;\n}\n\nfunction parseMediaEntries(value: unknown): MediaEntryMessage[] | null {\n if (!Array.isArray(value) || value.length > HOST_WIRE_LIMITS.arrayEntries) return null;\n const entries: MediaEntryMessage[] = [];\n for (const entry of value) {\n if (\n !isRecord(entry) ||\n !hasOnlyKeys(entry, ['name', 'mimeType', 'size']) ||\n !hasBoundedString(entry, 'name', HOST_WIRE_LIMITS.pathCharacters, 1) ||\n !hasMimeType(entry, 'mimeType') ||\n !hasNonNegativeInteger(entry, 'size') ||\n entry.size > HOST_WIRE_LIMITS.binaryBytes\n ) {\n return null;\n }\n entries.push({ name: entry.name, mimeType: entry.mimeType, size: entry.size });\n }\n return entries;\n}\n\nfunction isBoundedMediaDataUrl(value: unknown): value is string {\n if (!isBoundedString(value, HOST_WIRE_LIMITS.base64Characters + 512, 1)) return false;\n if (!value.startsWith('data:')) return false;\n const separator = value.indexOf(';base64,');\n return separator > 5 && separator <= HOST_WIRE_LIMITS.identifierCharacters;\n}\n\nfunction isDocumentSessionMessageStatus(value: unknown): value is DocumentSessionMessageStatus {\n return (\n value === 'idle' ||\n value === 'saved' ||\n value === 'dirty' ||\n value === 'saving' ||\n value === 'error' ||\n value === 'conflict' ||\n value === 'closed'\n );\n}\n\nfunction isSessionEnvelope(value: Record<string, unknown>): value is Record<string, unknown> & {\n sessionId: string;\n clientRevision: number;\n baseDocumentVersion: number;\n} {\n return (\n hasBoundedString(value, 'sessionId', HOST_WIRE_LIMITS.identifierCharacters, 1) &&\n hasNonNegativeInteger(value, 'clientRevision') &&\n hasNonNegativeInteger(value, 'baseDocumentVersion')\n );\n}\n\nfunction hasRequestId(\n value: Record<string, unknown>,\n): value is Record<string, unknown> & { requestId: number } {\n return hasNonNegativeInteger(value, 'requestId') && value.requestId <= MAX_REQUEST_ID;\n}\n\nfunction hasBoundedString<K extends string>(\n value: Record<string, unknown>,\n key: K,\n maximumCharacters: number,\n minimumCharacters = 0,\n): value is Record<string, unknown> & Record<K, string> {\n return isBoundedString(value[key], maximumCharacters, minimumCharacters);\n}\n\nfunction hasNullableBoundedString<K extends string>(\n value: Record<string, unknown>,\n key: K,\n maximumCharacters: number,\n minimumCharacters = 0,\n): value is Record<string, unknown> & Record<K, string | null> {\n return value[key] === null || isBoundedString(value[key], maximumCharacters, minimumCharacters);\n}\n\nfunction hasNonNegativeInteger<K extends string>(\n value: Record<string, unknown>,\n key: K,\n): value is Record<string, unknown> & Record<K, number> {\n const entry = value[key];\n return typeof entry === 'number' && Number.isSafeInteger(entry) && entry >= 0;\n}\n\nfunction isNullableNonNegativeInteger(value: unknown): value is number | null {\n return value === null || (typeof value === 'number' && Number.isSafeInteger(value) && value >= 0);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction hasOnlyKeys(value: Record<string, unknown>, keys: readonly string[]): boolean {\n const expected = new Set(keys);\n const actual = Object.keys(value);\n return actual.length === expected.size && actual.every((key) => expected.has(key));\n}\n\nfunction hasSafeFilename<K extends string>(\n value: Record<string, unknown>,\n key: K,\n): value is Record<string, unknown> & Record<K, string> {\n return isSafeExportFilename(value[key]);\n}\n\nexport function isSafeExportFilename(value: unknown): value is string {\n return (\n isBoundedString(value, 255, 1) &&\n value.trim() === value &&\n !/[\\\\/:*?\"<>|]/.test(value) &&\n !hasControlCharacter(value) &&\n value !== '.' &&\n value !== '..' &&\n !value.endsWith('.') &&\n !value.endsWith(' ')\n );\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 0x1f || code === 0x7f) return true;\n }\n return false;\n}\n\nfunction hasMimeType<K extends string>(\n value: Record<string, unknown>,\n key: K,\n): value is Record<string, unknown> & Record<K, string> {\n return isSafeMimeType(value[key]);\n}\n\nexport function isSafeMimeType(value: unknown): value is string {\n return (\n isBoundedString(value, HOST_WIRE_LIMITS.identifierCharacters, 1) &&\n /^[A-Za-z0-9!#$&^_.+-]+\\/[A-Za-z0-9!#$&^_.+-]+(?:\\s*;\\s*[A-Za-z0-9!#$&^_.+-]+=[^;\\r\\n]+)*$/.test(\n value,\n )\n );\n}\n"],"mappings":";;;;;;AAMA,IAAM,iBAAiB;AA6BhB,IAAM,0BAA0B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIO,IAAM,uCAAuC;AAC7C,IAAM,uCAAuC;AAC7C,IAAM,0CAA0C;AAChD,IAAM,0CAA0C;AAOhD,IAAM,uCAA4E;AAAA,EACvF,UAAU;AAAA,EACV,aAAa;AACf;AA4HO,SAAS,+BAA+B,OAAkD;AAC/F,MAAI,CAAC,SAAS,KAAK,KAAK,OAAO,MAAM,SAAS,SAAU,QAAO;AAE/D,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,QAAQ,IAAI;AAAA,IAC5D,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,SAAS,CAAC,KAAK,OAAO,MAAM,YAAY,YACvE,EAAE,MAAM,eAAe,SAAS,MAAM,QAAQ,IAC9C;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,aAAa,CAAC,KAC/C,uBAAuB,MAAM,WAAW,IACtC,EAAE,MAAM,kBAAkB,aAAa,MAAM,YAAY,IACzD;AAAA,IACN,KAAK,0BAA0B;AAC7B,UAAI,CAAC,YAAY,OAAO,CAAC,QAAQ,UAAU,CAAC,EAAG,QAAO;AACtD,YAAM,WAAW,+BAA+B,MAAM,QAAQ;AAC9D,aAAO,WAAW,EAAE,MAAM,0BAA0B,SAAS,IAAI;AAAA,IACnE;AAAA,IACA,KAAK;AACH,aAAO,YAAY,OAAO;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC,KACC,iBAAiB,OAAO,WAAW,iBAAiB,kBAAkB,KACtE,kBAAkB,KAAK,IACrB;AAAA,QACE,MAAM;AAAA,QACN,SAAS,MAAM;AAAA,QACf,WAAW,MAAM;AAAA,QACjB,gBAAgB,MAAM;AAAA,QACtB,qBAAqB,MAAM;AAAA,MAC7B,IACA;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC,KACC,kBAAkB,KAAK,KACvB,aAAa,KAAK,IAChB;AAAA,QACE,MAAM;AAAA,QACN,WAAW,MAAM;AAAA,QACjB,WAAW,MAAM;AAAA,QACjB,gBAAgB,MAAM;AAAA,QACtB,qBAAqB,MAAM;AAAA,MAC7B,IACA;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,aAAa,QAAQ,CAAC,KACvD,iBAAiB,OAAO,aAAa,iBAAiB,sBAAsB,CAAC,MAC5E,MAAM,WAAW,eAAe,MAAM,WAAW,kBAChD,EAAE,MAAM,mBAAmB,WAAW,MAAM,WAAW,QAAQ,MAAM,OAAO,IAC5E;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,aAAa,KAAK,CAAC,KACpD,aAAa,KAAK,KAClB,iBAAiB,OAAO,OAAO,iBAAiB,gBAAgB,CAAC,IAC/D,EAAE,MAAM,gBAAgB,WAAW,MAAM,WAAW,KAAK,MAAM,IAAI,IACnE;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,WAAW,CAAC,KAAK,aAAa,KAAK,IAClE,EAAE,MAAM,aAAa,WAAW,MAAM,UAAU,IAChD;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,aAAa,QAAQ,cAAc,UAAU,CAAC,KAC/E,aAAa,KAAK,KAClB,iBAAiB,OAAO,QAAQ,iBAAiB,gBAAgB,CAAC,KAClE,iBAAiB,OAAO,cAAc,iBAAiB,gBAAgB,KACvE,YAAY,OAAO,UAAU,IAC3B;AAAA,QACE,MAAM;AAAA,QACN,WAAW,MAAM;AAAA,QACjB,MAAM,MAAM;AAAA,QACZ,YAAY,MAAM;AAAA,QAClB,UAAU,MAAM;AAAA,MAClB,IACA;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,aAAa,KAAK,CAAC,KACpD,aAAa,KAAK,KAClB,iBAAiB,OAAO,OAAO,iBAAiB,gBAAgB,CAAC,IAC/D,EAAE,MAAM,eAAe,WAAW,MAAM,WAAW,KAAK,MAAM,IAAI,IAClE;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC,KACC,aAAa,KAAK,KAClB,gBAAgB,OAAO,UAAU,KACjC,iBAAiB,OAAO,cAAc,iBAAiB,gBAAgB,KACvE,YAAY,OAAO,UAAU,KAC7B,yBAAyB,OAAO,WAAW,iBAAiB,sBAAsB,CAAC,IACjF;AAAA,QACE,MAAM;AAAA,QACN,WAAW,MAAM;AAAA,QACjB,UAAU,MAAM;AAAA,QAChB,YAAY,MAAM;AAAA,QAClB,UAAU,MAAM;AAAA,QAChB,SAAS,MAAM;AAAA,MACjB,IACA;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,aAAa,UAAU,CAAC,KACzD,aAAa,KAAK,KAClB,gBAAgB,OAAO,UAAU,IAC/B,EAAE,MAAM,uBAAuB,WAAW,MAAM,WAAW,UAAU,MAAM,SAAS,IACpF;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,aAAa,YAAY,gBAAgB,CAAC,KAC3E,aAAa,KAAK,KAClB,gBAAgB,OAAO,UAAU,KACjC,yBAAyB,OAAO,kBAAkB,iBAAiB,sBAAsB,CAAC,IACxF;AAAA,QACE,MAAM;AAAA,QACN,WAAW,MAAM;AAAA,QACjB,UAAU,MAAM;AAAA,QAChB,gBAAgB,MAAM;AAAA,MACxB,IACA;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,aAAa,MAAM,CAAC,KACrD,aAAa,KAAK,KAClB,iBAAiB,OAAO,QAAQ,iBAAiB,gBAAgB,CAAC,IAChE,EAAE,MAAM,qBAAqB,WAAW,MAAM,WAAW,MAAM,MAAM,KAAK,IAC1E;AAAA,IACN;AACE,aAAO;AAAA,EACX;AACF;AAQO,SAAS,+BAA+B,OAAkD;AAC/F,MAAI,CAAC,SAAS,KAAK,KAAK,OAAO,MAAM,SAAS,SAAU,QAAO;AAE/D,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO,YAAY,OAAO;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC,KACC,iBAAiB,OAAO,WAAW,iBAAiB,kBAAkB,KACtE,sBAAsB,OAAO,iBAAiB,KAC9C,iBAAiB,OAAO,YAAY,iBAAiB,gBAAgB,CAAC,KACtE,iBAAiB,OAAO,aAAa,iBAAiB,sBAAsB,CAAC,KAC7E,sBAAsB,OAAO,iBAAiB,KAC9C,sBAAsB,OAAO,4BAA4B,IACvD;AAAA,QACE,MAAM;AAAA,QACN,SAAS,MAAM;AAAA,QACf,iBAAiB,MAAM;AAAA,QACvB,UAAU,MAAM;AAAA,QAChB,WAAW,MAAM;AAAA,QACjB,iBAAiB,MAAM;AAAA,QACvB,4BAA4B,MAAM;AAAA,MACpC,IACA;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC,KACC,iBAAiB,OAAO,aAAa,iBAAiB,sBAAsB,CAAC,KAC7E,sBAAsB,OAAO,gBAAgB,KAC7C,sBAAsB,OAAO,iBAAiB,KAC9C,OAAO,MAAM,aAAa,aAC1B,yBAAyB,OAAO,WAAW,iBAAiB,iBAAiB,IAC3E;AAAA,QACE,MAAM;AAAA,QACN,WAAW,MAAM;AAAA,QACjB,gBAAgB,MAAM;AAAA,QACtB,iBAAiB,MAAM;AAAA,QACvB,UAAU,MAAM;AAAA,QAChB,SAAS,MAAM;AAAA,MACjB,IACA;AAAA,IACN,KAAK,gBAAgB;AACnB,UACE,CAAC,YAAY,OAAO;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC,KACD,CAAC,iBAAiB,OAAO,aAAa,iBAAiB,sBAAsB,CAAC,KAC9E,CAAC,+BAA+B,MAAM,MAAM,KAC5C,CAAC,sBAAsB,OAAO,UAAU,KACxC,CAAC,sBAAsB,OAAO,mBAAmB,KACjD,MAAM,oBAAoB,MAAM,YAChC,CAAC,sBAAsB,OAAO,4BAA4B,KAC1D,CAAC,sBAAsB,OAAO,iBAAiB,KAC/C,CAAC,yBAAyB,OAAO,SAAS,iBAAiB,iBAAiB,GAC5E;AACA,eAAO;AAAA,MACT;AACA,YAAM,WAAW,6BAA6B,MAAM,QAAQ;AAC5D,UACE,aAAa,UACZ,MAAM,WAAW,cAAc,aAAa,QAC5C,MAAM,WAAW,cAAc,aAAa,MAC7C;AACA,eAAO;AAAA,MACT;AACA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,WAAW,MAAM;AAAA,QACjB,QAAQ,MAAM;AAAA,QACd,UAAU,MAAM;AAAA,QAChB,mBAAmB,MAAM;AAAA,QACzB,4BAA4B,MAAM;AAAA,QAClC,iBAAiB,MAAM;AAAA,QACvB,OAAO,MAAM;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,IACA,KAAK;AACH,aAAO,YAAY,OAAO;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC,KACC,iBAAiB,OAAO,aAAa,iBAAiB,sBAAsB,CAAC,KAC7E,aAAa,KAAK,KAClB,OAAO,MAAM,OAAO,aACpB,sBAAsB,OAAO,UAAU,KACvC,sBAAsB,OAAO,mBAAmB,KAChD,MAAM,qBAAqB,MAAM,YACjC,sBAAsB,OAAO,iBAAiB,KAC9C,yBAAyB,OAAO,WAAW,iBAAiB,iBAAiB,IAC3E;AAAA,QACE,MAAM;AAAA,QACN,WAAW,MAAM;AAAA,QACjB,WAAW,MAAM;AAAA,QACjB,IAAI,MAAM;AAAA,QACV,UAAU,MAAM;AAAA,QAChB,mBAAmB,MAAM;AAAA,QACzB,iBAAiB,MAAM;AAAA,QACvB,SAAS,MAAM;AAAA,MACjB,IACA;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,OAAO,CAAC,MACxC,MAAM,UAAU,WAAW,MAAM,UAAU,UAC1C,EAAE,MAAM,eAAe,OAAO,MAAM,MAAM,IAC1C;AAAA,IACN,KAAK,kBAAkB;AACrB,UAAI,CAAC,YAAY,OAAO,CAAC,QAAQ,UAAU,CAAC,EAAG,QAAO;AACtD,YAAM,WAAW,0BAA0B,MAAM,QAAQ;AACzD,aAAO,WAAW,EAAE,MAAM,kBAAkB,SAAS,IAAI;AAAA,IAC3D;AAAA,IACA,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,aAAa,KAAK,CAAC,KACpD,aAAa,KAAK,KAClB,sBAAsB,MAAM,GAAG,IAC7B,EAAE,MAAM,iBAAiB,WAAW,MAAM,WAAW,KAAK,MAAM,IAAI,IACpE;AAAA,IACN,KAAK,eAAe;AAClB,UAAI,CAAC,YAAY,OAAO,CAAC,QAAQ,aAAa,SAAS,CAAC,KAAK,CAAC,aAAa,KAAK,GAAG;AACjF,eAAO;AAAA,MACT;AACA,YAAM,UAAU,kBAAkB,MAAM,OAAO;AAC/C,aAAO,UAAU,EAAE,MAAM,eAAe,WAAW,MAAM,WAAW,QAAQ,IAAI;AAAA,IAClF;AAAA,IACA,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,aAAa,MAAM,CAAC,KACrD,aAAa,KAAK,KAClB,iBAAiB,OAAO,QAAQ,iBAAiB,gBAAgB,CAAC,IAChE,EAAE,MAAM,cAAc,WAAW,MAAM,WAAW,MAAM,MAAM,KAAK,IACnE;AAAA,IACN,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,WAAW,CAAC,KAAK,aAAa,KAAK,IAClE,EAAE,MAAM,gBAAgB,WAAW,MAAM,UAAU,IACnD;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,aAAa,SAAS,CAAC,KACxD,aAAa,KAAK,KAClB,iBAAiB,OAAO,WAAW,iBAAiB,mBAAmB,CAAC,IACtE,EAAE,MAAM,MAAM,MAAM,WAAW,MAAM,WAAW,SAAS,MAAM,QAAQ,IACvE;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,sBAAsB;AACzB,UAAI,CAAC,YAAY,OAAO,CAAC,QAAQ,aAAa,QAAQ,CAAC,KAAK,CAAC,aAAa,KAAK,GAAG;AAChF,eAAO;AAAA,MACT;AACA,YAAM,SAAS,uBAAuB,MAAM,MAAM;AAClD,aAAO,WAAW,SAAY,EAAE,MAAM,MAAM,MAAM,WAAW,MAAM,WAAW,OAAO,IAAI;AAAA,IAC3F;AAAA,IACA,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,aAAa,YAAY,CAAC,KAC3D,aAAa,KAAK,KAClB,yBAAyB,OAAO,cAAc,iBAAiB,gBAAgB,IAC7E,EAAE,MAAM,qBAAqB,WAAW,MAAM,WAAW,YAAY,MAAM,WAAW,IACtF;AAAA,IACN;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,uBAAuB,OAA6D;AAC3F,MAAI,UAAU,KAAM,QAAO;AAC3B,MACE,CAAC,SAAS,KAAK,KACf,CAAC,YAAY,OAAO,CAAC,WAAW,cAAc,CAAC,KAC/C,CAAC,iBAAiB,OAAO,WAAW,iBAAiB,sBAAsB,CAAC,KAC5E,CAAC,iBAAiB,OAAO,gBAAgB,iBAAiB,gBAAgB,CAAC,GAC3E;AACA,WAAO;AAAA,EACT;AACA,SAAO,EAAE,SAAS,MAAM,SAAS,cAAc,MAAM,aAAa;AACpE;AAEA,SAAS,6BACP,OACmD;AACnD,MAAI,UAAU,KAAM,QAAO;AAC3B,MACE,CAAC,SAAS,KAAK,KACf,CAAC,YAAY,OAAO;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC,KACD,CAAC,sBAAsB,OAAO,0BAA0B,KACxD,CAAC,sBAAsB,OAAO,yBAAyB,KACvD,CAAC,sBAAsB,OAAO,YAAY,KAC1C,CAAC,6BAA6B,MAAM,aAAa,KACjD,CAAC,6BAA6B,MAAM,aAAa,KACjD,CAAC,6BAA6B,MAAM,kBAAkB,KACrD,MAAM,oBAAoB,QAAQ,OAAO,MAAM,oBAAoB,WACpE;AACA,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,0BAA0B,MAAM;AAAA,IAChC,yBAAyB,MAAM;AAAA,IAC/B,YAAY,MAAM;AAAA,IAClB,eAAe,MAAM;AAAA,IACrB,eAAe,MAAM;AAAA,IACrB,oBAAoB,MAAM;AAAA,IAC1B,iBAAiB,MAAM;AAAA,EACzB;AACF;AAEA,SAAS,0BAA0B,OAA6C;AAC9E,MACE,CAAC,SAAS,KAAK,KACf,CAAC,YAAY,OAAO,CAAC,YAAY,eAAe,qBAAqB,CAAC,KACtE,OAAO,MAAM,aAAa,aAC1B,CAAC,uBAAuB,MAAM,WAAW,GACzC;AACA,WAAO;AAAA,EACT;AACA,QAAM,sBAAsB,+BAA+B,MAAM,mBAAmB;AACpF,SAAO,sBACH,EAAE,UAAU,MAAM,UAAU,aAAa,MAAM,aAAa,oBAAoB,IAChF;AACN;AAEO,SAAS,uBAAuB,OAA+C;AACpF,SAAO,wBAAwB,KAAK,CAAC,UAAU,UAAU,KAAK;AAChE;AAEO,SAAS,+BAA+B,OAAiC;AAC9E,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,kCAAkC,OAAiC;AACjF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,+BAA+B,OAAkD;AACxF,SAAO,SAAS,KAAK,KACnB,YAAY,OAAO,CAAC,YAAY,aAAa,CAAC,KAC9C,+BAA+B,MAAM,QAAQ,KAC7C,kCAAkC,MAAM,WAAW,IACjD,EAAE,UAAU,MAAM,UAAU,aAAa,MAAM,YAAY,IAC3D;AACN;AAEA,SAAS,cAAc,OAAgB,KAAa,KAA8B;AAChF,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,SAAS,OAAO,SAAS;AACzF;AAEA,SAAS,kBAAkB,OAA4C;AACrE,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,iBAAiB,aAAc,QAAO;AAClF,QAAM,UAA+B,CAAC;AACtC,aAAW,SAAS,OAAO;AACzB,QACE,CAAC,SAAS,KAAK,KACf,CAAC,YAAY,OAAO,CAAC,QAAQ,YAAY,MAAM,CAAC,KAChD,CAAC,iBAAiB,OAAO,QAAQ,iBAAiB,gBAAgB,CAAC,KACnE,CAAC,YAAY,OAAO,UAAU,KAC9B,CAAC,sBAAsB,OAAO,MAAM,KACpC,MAAM,OAAO,iBAAiB,aAC9B;AACA,aAAO;AAAA,IACT;AACA,YAAQ,KAAK,EAAE,MAAM,MAAM,MAAM,UAAU,MAAM,UAAU,MAAM,MAAM,KAAK,CAAC;AAAA,EAC/E;AACA,SAAO;AACT;AAEA,SAAS,sBAAsB,OAAiC;AAC9D,MAAI,CAAC,gBAAgB,OAAO,iBAAiB,mBAAmB,KAAK,CAAC,EAAG,QAAO;AAChF,MAAI,CAAC,MAAM,WAAW,OAAO,EAAG,QAAO;AACvC,QAAM,YAAY,MAAM,QAAQ,UAAU;AAC1C,SAAO,YAAY,KAAK,aAAa,iBAAiB;AACxD;AAEA,SAAS,+BAA+B,OAAuD;AAC7F,SACE,UAAU,UACV,UAAU,WACV,UAAU,WACV,UAAU,YACV,UAAU,WACV,UAAU,cACV,UAAU;AAEd;AAEA,SAAS,kBAAkB,OAIzB;AACA,SACE,iBAAiB,OAAO,aAAa,iBAAiB,sBAAsB,CAAC,KAC7E,sBAAsB,OAAO,gBAAgB,KAC7C,sBAAsB,OAAO,qBAAqB;AAEtD;AAEA,SAAS,aACP,OAC0D;AAC1D,SAAO,sBAAsB,OAAO,WAAW,KAAK,MAAM,aAAa;AACzE;AAEA,SAAS,iBACP,OACA,KACA,mBACA,oBAAoB,GACkC;AACtD,SAAO,gBAAgB,MAAM,GAAG,GAAG,mBAAmB,iBAAiB;AACzE;AAEA,SAAS,yBACP,OACA,KACA,mBACA,oBAAoB,GACyC;AAC7D,SAAO,MAAM,GAAG,MAAM,QAAQ,gBAAgB,MAAM,GAAG,GAAG,mBAAmB,iBAAiB;AAChG;AAEA,SAAS,sBACP,OACA,KACsD;AACtD,QAAM,QAAQ,MAAM,GAAG;AACvB,SAAO,OAAO,UAAU,YAAY,OAAO,cAAc,KAAK,KAAK,SAAS;AAC9E;AAEA,SAAS,6BAA6B,OAAwC;AAC5E,SAAO,UAAU,QAAS,OAAO,UAAU,YAAY,OAAO,cAAc,KAAK,KAAK,SAAS;AACjG;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,YAAY,OAAgC,MAAkC;AACrF,QAAM,WAAW,IAAI,IAAI,IAAI;AAC7B,QAAM,SAAS,OAAO,KAAK,KAAK;AAChC,SAAO,OAAO,WAAW,SAAS,QAAQ,OAAO,MAAM,CAAC,QAAQ,SAAS,IAAI,GAAG,CAAC;AACnF;AAEA,SAAS,gBACP,OACA,KACsD;AACtD,SAAO,qBAAqB,MAAM,GAAG,CAAC;AACxC;AAEO,SAAS,qBAAqB,OAAiC;AACpE,SACE,gBAAgB,OAAO,KAAK,CAAC,KAC7B,MAAM,KAAK,MAAM,SACjB,CAAC,eAAe,KAAK,KAAK,KAC1B,CAAC,oBAAoB,KAAK,KAC1B,UAAU,OACV,UAAU,QACV,CAAC,MAAM,SAAS,GAAG,KACnB,CAAC,MAAM,SAAS,GAAG;AAEvB;AAEA,SAAS,oBAAoB,OAAwB;AACnD,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,QAAQ,MAAQ,SAAS,IAAM,QAAO;AAAA,EAC5C;AACA,SAAO;AACT;AAEA,SAAS,YACP,OACA,KACsD;AACtD,SAAO,eAAe,MAAM,GAAG,CAAC;AAClC;AAEO,SAAS,eAAe,OAAiC;AAC9D,SACE,gBAAgB,OAAO,iBAAiB,sBAAsB,CAAC,KAC/D,4FAA4F;AAAA,IAC1F;AAAA,EACF;AAEJ;","names":[]}
@@ -1,4 +1,141 @@
1
- export type { WorkspaceDescriptor, TransientOrigin } from './types.js';
2
- export { listWorkspaces, getWorkspace, saveWorkspace, removeWorkspace, touchWorkspace, ensureDefaultWorkspace, registerTransientWorkspace, getTransientWorkspace, unregisterTransientWorkspace, } from './workspace-manager.js';
3
- export { reconcileElectronWorkspaceDescriptors, type ElectronWorkspaceReconciliation, } from './reconcile-electron.js';
4
- //# sourceMappingURL=index.d.ts.map
1
+ import { q as FileSystemProvider } from '../types-BEg5SQ1_.js';
2
+ import { k as ElectronWorkspaceInfo, B as HostEnvironment } from '../types-CueK0tvU.js';
3
+ import '../workspace-path-CWVrcuPL.js';
4
+
5
+ /**
6
+ * Origin of a transient workspace — records where its contents came from and
7
+ * how to save them back. Set only on `type: 'transient'` workspaces.
8
+ * - 'loose-file' — a single markdown file opened from the OS (Electron);
9
+ * edits write back through an owner-scoped `resourceId` grant.
10
+ * - 'dbk' — a `.dbk`/zip bundle unpacked into memory (Electron); edits are
11
+ * re-zipped and written back through an owner-scoped resource grant.
12
+ * - 'web-file' — a single markdown file launched into the installed web app
13
+ * (File Handling API); edits write back through `handle`.
14
+ * - 'web-dbk' — a `.dbk`/zip bundle launched into the installed web app;
15
+ * edits are re-zipped and written back through `handle`.
16
+ *
17
+ * The web variants hold a live `FileSystemFileHandle`. That is safe because
18
+ * transient descriptors are never persisted — they live only in the
19
+ * in-memory registry (see workspace-manager) for the current page session.
20
+ */
21
+ type TransientOrigin = {
22
+ kind: 'loose-file';
23
+ resourceId: string;
24
+ } | {
25
+ kind: 'dbk';
26
+ resourceId: string;
27
+ /** SHA-256 of the last bundle version acknowledged by the host. */
28
+ version: string | null;
29
+ } | {
30
+ kind: 'web-file';
31
+ handle: FileSystemFileHandle;
32
+ name: string;
33
+ } | {
34
+ kind: 'web-dbk';
35
+ handle: FileSystemFileHandle;
36
+ name: string;
37
+ /** SHA-256 of the last bundle version observed on disk. */
38
+ version: string | null;
39
+ };
40
+ /**
41
+ * Workspace — a named binding to a FileSystemProvider, representing
42
+ * the user's current working context (a folder of markdown files).
43
+ */
44
+ interface WorkspaceDescriptor {
45
+ /** Unique stable identifier (persisted in IndexedDB). */
46
+ id: string;
47
+ /** User-visible label. */
48
+ name: string;
49
+ /**
50
+ * Provider kind:
51
+ * - 'indexeddb' — browser-local storage (web only)
52
+ * - 'native' — File System Access API (web Chrome/Edge only)
53
+ * - 'electron-native' — Electron main-process native filesystem
54
+ * - 'transient' — session-only, in-memory (a loose file/`.dbk` opened from
55
+ * the OS, or a document copied from a shared URL). Never persisted; its
56
+ * provider lives in an in-memory registry (see workspace-manager). An
57
+ * `origin` is present only when changes can be saved back externally.
58
+ */
59
+ type: 'indexeddb' | 'native' | 'electron-native' | 'transient';
60
+ /** ISO timestamp of last access. */
61
+ lastOpened: string;
62
+ /** Absolute filesystem path for 'electron-native' workspaces. */
63
+ rootPath?: string;
64
+ /** For 'transient' workspaces: where the contents came from / save back to. */
65
+ origin?: TransientOrigin;
66
+ /**
67
+ * Per-workspace override for the global versioning preference. When
68
+ * `'inherit'` (or absent), the global preference applies. `'on'` /
69
+ * `'off'` force the corresponding behavior regardless of the global
70
+ * setting. See `resolveVersioningEnabled` in the preferences module.
71
+ */
72
+ versioningOverride?: 'inherit' | 'on' | 'off';
73
+ }
74
+
75
+ /** Parse the complete persisted workspace list before it reaches startup code. */
76
+ declare function parsePersistedWorkspaceList(value: unknown): WorkspaceDescriptor[];
77
+
78
+ /**
79
+ * WorkspaceManager — manages the list of known workspaces in IndexedDB
80
+ * and provides helpers for creating / switching / removing them.
81
+ *
82
+ * The actual FileSystemProvider instances are created by the caller
83
+ * (since native providers need a DirectoryHandle from user interaction).
84
+ */
85
+
86
+ /** Register a transient workspace and its (already-built) provider. */
87
+ declare function registerTransientWorkspace(descriptor: WorkspaceDescriptor, provider: FileSystemProvider): void;
88
+ /** Look up a transient workspace (descriptor + provider) by id, if any. */
89
+ declare function getTransientWorkspace(id: string): {
90
+ descriptor: WorkspaceDescriptor;
91
+ provider: FileSystemProvider;
92
+ } | null;
93
+ /** Forget a transient workspace (e.g. when it is closed). */
94
+ declare function unregisterTransientWorkspace(id: string): Promise<void>;
95
+ /**
96
+ * Get all known workspace descriptors — persisted plus any session-only
97
+ * transient ones (so they show in the picker and resolve for the session).
98
+ */
99
+ declare function listWorkspaces(): Promise<WorkspaceDescriptor[]>;
100
+ /**
101
+ * Get a specific workspace descriptor by id (transient or persisted).
102
+ */
103
+ declare function getWorkspace(id: string): Promise<WorkspaceDescriptor | null>;
104
+ /**
105
+ * Add or update a workspace descriptor. If a workspace with the same id
106
+ * already exists, it is replaced. Transient workspaces are never persisted.
107
+ */
108
+ declare function saveWorkspace(workspace: WorkspaceDescriptor): Promise<void>;
109
+ /**
110
+ * Remove a workspace descriptor by id (transient or persisted).
111
+ */
112
+ declare function removeWorkspace(id: string): Promise<void>;
113
+ /**
114
+ * Touch the lastOpened timestamp on a workspace. For transient workspaces this
115
+ * updates the in-memory descriptor only (nothing is persisted).
116
+ */
117
+ declare function touchWorkspace(id: string): Promise<void>;
118
+ /**
119
+ * Ensure a default IndexedDB workspace exists. Called on app startup.
120
+ * Returns the descriptor.
121
+ */
122
+ declare function ensureDefaultWorkspace(): Promise<WorkspaceDescriptor>;
123
+
124
+ interface ElectronWorkspaceReconciliation {
125
+ /** Obsolete renderer descriptors to remove before attempting restoration. */
126
+ readonly removeIds: readonly string[];
127
+ /** Canonical main-authorized descriptors to insert or replace. */
128
+ readonly upsert: readonly WorkspaceDescriptor[];
129
+ /** Safe navigation migration for a local descriptor matched by root. */
130
+ readonly idRemap: Readonly<Record<string, string>>;
131
+ }
132
+ /**
133
+ * Reconcile renderer IndexedDB metadata with the main process authority list.
134
+ * `hostWorkspaces` is authoritative: local Electron descriptors absent from
135
+ * it cannot be opened safely and are removed. Root-path matching carries user
136
+ * metadata across an id migration without treating that display path as
137
+ * authority.
138
+ */
139
+ declare function reconcileElectronWorkspaceDescriptors(local: readonly WorkspaceDescriptor[], hostWorkspaces: readonly ElectronWorkspaceInfo[], platform: HostEnvironment['platform'], now: string): ElectronWorkspaceReconciliation;
140
+
141
+ export { type ElectronWorkspaceReconciliation, type TransientOrigin, type WorkspaceDescriptor, ensureDefaultWorkspace, getTransientWorkspace, getWorkspace, listWorkspaces, parsePersistedWorkspaceList, reconcileElectronWorkspaceDescriptors, registerTransientWorkspace, removeWorkspace, saveWorkspace, touchWorkspace, unregisterTransientWorkspace };