@snaptrude/plugin-core 0.9.16 → 0.9.18-edgesetbacks-20261021.1

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 (221) hide show
  1. package/AGENTS.md +231 -231
  2. package/CHANGELOG.md +408 -402
  3. package/CLAUDE.md +11 -11
  4. package/api-manifest.json +1510 -701
  5. package/dist/api/analysis/daylight.d.ts +5 -5
  6. package/dist/api/analysis/solar.d.ts +2 -2
  7. package/dist/api/core/camera/index.d.ts +29 -0
  8. package/dist/api/core/camera/index.d.ts.map +1 -1
  9. package/dist/api/core/geom/create/index.d.ts +7 -1
  10. package/dist/api/core/geom/create/index.d.ts.map +1 -1
  11. package/dist/api/core/geom/update/contour.d.ts +8 -2
  12. package/dist/api/core/geom/update/contour.d.ts.map +1 -1
  13. package/dist/api/core/storeys/index.d.ts +5 -2
  14. package/dist/api/core/storeys/index.d.ts.map +1 -1
  15. package/dist/api/core/zoom/index.d.ts +13 -0
  16. package/dist/api/core/zoom/index.d.ts.map +1 -1
  17. package/dist/api/design/bim.d.ts +299 -0
  18. package/dist/api/design/bim.d.ts.map +1 -0
  19. package/dist/api/design/boolean/index.d.ts +2 -0
  20. package/dist/api/design/boolean/index.d.ts.map +1 -1
  21. package/dist/api/design/catalog.d.ts +320 -0
  22. package/dist/api/design/catalog.d.ts.map +1 -0
  23. package/dist/api/design/create/bulk-items.d.ts +65 -25
  24. package/dist/api/design/create/bulk-items.d.ts.map +1 -1
  25. package/dist/api/design/create/index.d.ts +299 -100
  26. package/dist/api/design/create/index.d.ts.map +1 -1
  27. package/dist/api/design/create/opening-fields.d.ts +13 -12
  28. package/dist/api/design/create/opening-fields.d.ts.map +1 -1
  29. package/dist/api/design/delete/index.d.ts +1 -0
  30. package/dist/api/design/delete/index.d.ts.map +1 -1
  31. package/dist/api/design/doors/index.d.ts +18 -24
  32. package/dist/api/design/doors/index.d.ts.map +1 -1
  33. package/dist/api/design/family.d.ts +813 -35
  34. package/dist/api/design/family.d.ts.map +1 -1
  35. package/dist/api/design/index.d.ts +16 -0
  36. package/dist/api/design/index.d.ts.map +1 -1
  37. package/dist/api/design/networks.d.ts +1703 -0
  38. package/dist/api/design/networks.d.ts.map +1 -0
  39. package/dist/api/design/query/grids.d.ts +2 -2
  40. package/dist/api/design/query/index.d.ts +42 -32
  41. package/dist/api/design/query/index.d.ts.map +1 -1
  42. package/dist/api/design/selection/index.d.ts +10 -10
  43. package/dist/api/design/types/index.d.ts +40 -24
  44. package/dist/api/design/types/index.d.ts.map +1 -1
  45. package/dist/api/design/update/index.d.ts +111 -6
  46. package/dist/api/design/update/index.d.ts.map +1 -1
  47. package/dist/api/design/windows/index.d.ts +8 -8
  48. package/dist/api/design/windows/index.d.ts.map +1 -1
  49. package/dist/api/entity/buildableEnvelope.d.ts +84 -2
  50. package/dist/api/entity/buildableEnvelope.d.ts.map +1 -1
  51. package/dist/api/presentation/aiInspiration.d.ts +10 -10
  52. package/dist/api/presentation/annotate.d.ts +38 -22
  53. package/dist/api/presentation/annotate.d.ts.map +1 -1
  54. package/dist/api/presentation/drawingContract.d.ts +32 -0
  55. package/dist/api/presentation/drawingContract.d.ts.map +1 -0
  56. package/dist/api/presentation/drawings.d.ts +3523 -0
  57. package/dist/api/presentation/drawings.d.ts.map +1 -0
  58. package/dist/api/presentation/export.d.ts +23 -5
  59. package/dist/api/presentation/export.d.ts.map +1 -1
  60. package/dist/api/presentation/index.d.ts +41 -12
  61. package/dist/api/presentation/index.d.ts.map +1 -1
  62. package/dist/api/presentation/placedViews.d.ts +106 -6
  63. package/dist/api/presentation/placedViews.d.ts.map +1 -1
  64. package/dist/api/presentation/sections.d.ts +461 -0
  65. package/dist/api/presentation/sections.d.ts.map +1 -0
  66. package/dist/api/presentation/shapes.d.ts +2 -2
  67. package/dist/api/presentation/sheets.d.ts +175 -19
  68. package/dist/api/presentation/sheets.d.ts.map +1 -1
  69. package/dist/api/presentation/viewPresets.d.ts +222 -0
  70. package/dist/api/presentation/viewPresets.d.ts.map +1 -0
  71. package/dist/api/presentation/views.d.ts +141 -8
  72. package/dist/api/presentation/views.d.ts.map +1 -1
  73. package/dist/api/presentation/walkthroughs.d.ts +6 -6
  74. package/dist/errors/codes.d.ts +3 -1
  75. package/dist/errors/codes.d.ts.map +1 -1
  76. package/dist/index.cjs +3883 -2385
  77. package/dist/index.cjs.map +1 -1
  78. package/dist/index.js +3744 -2385
  79. package/dist/index.js.map +1 -1
  80. package/package.json +1 -1
  81. package/scripts/check-dist-fresh.mjs +22 -22
  82. package/scripts/generate-manifest.mjs +243 -238
  83. package/scripts/generate-manifest.test.mjs +303 -303
  84. package/src/api/analysis/daylight.ts +470 -470
  85. package/src/api/analysis/heatmaps.ts +683 -683
  86. package/src/api/analysis/illuminance.ts +155 -155
  87. package/src/api/analysis/index.ts +61 -61
  88. package/src/api/analysis/shadows.ts +183 -183
  89. package/src/api/analysis/solar.ts +237 -237
  90. package/src/api/analysis/sunlightHours.ts +211 -211
  91. package/src/api/analysis/sunpath.ts +83 -83
  92. package/src/api/analysis/weather.ts +179 -179
  93. package/src/api/core/buildings.ts +485 -485
  94. package/src/api/core/camera/index.ts +696 -667
  95. package/src/api/core/comment/index.ts +376 -376
  96. package/src/api/core/geom/create/index.ts +2139 -2133
  97. package/src/api/core/geom/delete/index.ts +84 -84
  98. package/src/api/core/geom/index.ts +35 -35
  99. package/src/api/core/geom/query/arc.ts +169 -169
  100. package/src/api/core/geom/query/brep.ts +621 -621
  101. package/src/api/core/geom/query/circle.ts +404 -404
  102. package/src/api/core/geom/query/contour.ts +540 -540
  103. package/src/api/core/geom/query/curve.ts +1102 -1102
  104. package/src/api/core/geom/query/edge.ts +130 -130
  105. package/src/api/core/geom/query/face.ts +508 -508
  106. package/src/api/core/geom/query/halfedge.ts +210 -210
  107. package/src/api/core/geom/query/index.ts +63 -63
  108. package/src/api/core/geom/query/profile.ts +473 -473
  109. package/src/api/core/geom/query/vertex.ts +205 -205
  110. package/src/api/core/geom/update/contour.ts +323 -317
  111. package/src/api/core/geom/update/curve.ts +209 -209
  112. package/src/api/core/geom/update/index.ts +29 -29
  113. package/src/api/core/geom/update/profile.ts +379 -379
  114. package/src/api/core/groups.ts +521 -521
  115. package/src/api/core/handles/index.ts +234 -234
  116. package/src/api/core/history/index.ts +84 -84
  117. package/src/api/core/index.ts +99 -99
  118. package/src/api/core/io/export/index.ts +126 -126
  119. package/src/api/core/io/import/index.ts +504 -504
  120. package/src/api/core/io/index.ts +42 -42
  121. package/src/api/core/io/job/index.ts +140 -140
  122. package/src/api/core/io/query/index.ts +71 -71
  123. package/src/api/core/io/terrain/index.ts +360 -360
  124. package/src/api/core/io/underlay/index.ts +705 -705
  125. package/src/api/core/layers.ts +540 -540
  126. package/src/api/core/math/index.ts +20 -20
  127. package/src/api/core/math/quat.ts +172 -172
  128. package/src/api/core/math/vec3.ts +179 -179
  129. package/src/api/core/mode/index.ts +108 -108
  130. package/src/api/core/project/index.ts +479 -479
  131. package/src/api/core/proposals/index.ts +570 -570
  132. package/src/api/core/storeys/index.ts +311 -308
  133. package/src/api/core/storeys/layers.ts +339 -339
  134. package/src/api/core/tags.ts +911 -911
  135. package/src/api/core/units/index.ts +164 -164
  136. package/src/api/core/user.ts +46 -46
  137. package/src/api/core/zoom/index.ts +64 -51
  138. package/src/api/design/bim.ts +210 -0
  139. package/src/api/design/boolean/index.ts +181 -179
  140. package/src/api/design/catalog.ts +203 -0
  141. package/src/api/design/create/bulk-items.ts +294 -254
  142. package/src/api/design/create/grids.ts +137 -137
  143. package/src/api/design/create/index.ts +2178 -1980
  144. package/src/api/design/create/opening-fields.ts +40 -37
  145. package/src/api/design/delete/index.ts +75 -74
  146. package/src/api/design/dimensions.ts +453 -453
  147. package/src/api/design/doors/index.ts +516 -500
  148. package/src/api/design/edit/index.ts +54 -54
  149. package/src/api/design/erase/index.ts +151 -151
  150. package/src/api/design/family.ts +1342 -704
  151. package/src/api/design/furniture/index.ts +319 -319
  152. package/src/api/design/grids.ts +237 -237
  153. package/src/api/design/index.ts +304 -274
  154. package/src/api/design/lock.ts +69 -69
  155. package/src/api/design/materials/index.ts +608 -608
  156. package/src/api/design/networks.ts +607 -0
  157. package/src/api/design/query/geometry/index.ts +319 -319
  158. package/src/api/design/query/grids.ts +197 -197
  159. package/src/api/design/query/index.ts +1236 -1226
  160. package/src/api/design/query/referenceLines.ts +52 -52
  161. package/src/api/design/query/spaces.ts +275 -275
  162. package/src/api/design/selection/index.ts +273 -273
  163. package/src/api/design/shared.ts +40 -40
  164. package/src/api/design/transform/index.ts +254 -254
  165. package/src/api/design/types/index.ts +163 -156
  166. package/src/api/design/update/index.ts +1096 -983
  167. package/src/api/design/visibility.ts +143 -143
  168. package/src/api/design/windows/index.ts +351 -333
  169. package/src/api/entity/buildableEnvelope.ts +397 -322
  170. package/src/api/entity/index.ts +30 -30
  171. package/src/api/entity/referenceLine.ts +235 -235
  172. package/src/api/entity/space.ts +612 -612
  173. package/src/api/entity/story.ts +517 -517
  174. package/src/api/index.ts +47 -47
  175. package/src/api/presentation/aiInspiration.ts +1116 -1116
  176. package/src/api/presentation/annotate.ts +417 -385
  177. package/src/api/presentation/camera.ts +289 -289
  178. package/src/api/presentation/diagrams.ts +194 -194
  179. package/src/api/presentation/drawingContract.ts +70 -0
  180. package/src/api/presentation/drawings.ts +1179 -0
  181. package/src/api/presentation/export.ts +134 -108
  182. package/src/api/presentation/import.ts +159 -159
  183. package/src/api/presentation/index.ts +160 -126
  184. package/src/api/presentation/placedViews.ts +1211 -1120
  185. package/src/api/presentation/sections.ts +420 -0
  186. package/src/api/presentation/shapes.ts +274 -274
  187. package/src/api/presentation/sheets.ts +746 -585
  188. package/src/api/presentation/slideshow.ts +134 -134
  189. package/src/api/presentation/tables.ts +84 -84
  190. package/src/api/presentation/viewPresets.ts +241 -0
  191. package/src/api/presentation/views.ts +742 -673
  192. package/src/api/presentation/walkthroughs.ts +1201 -1201
  193. package/src/api/program/adjacency.ts +164 -164
  194. package/src/api/program/areas.ts +408 -408
  195. package/src/api/program/classification.ts +138 -138
  196. package/src/api/program/cores.ts +83 -83
  197. package/src/api/program/departments.ts +517 -517
  198. package/src/api/program/index.ts +73 -73
  199. package/src/api/program/labels.ts +332 -332
  200. package/src/api/program/layout.ts +422 -422
  201. package/src/api/program/metadata.ts +364 -364
  202. package/src/api/program/metrics.ts +120 -120
  203. package/src/api/program/site.ts +748 -748
  204. package/src/api/program/spreadsheet.ts +2698 -2698
  205. package/src/api/workspace/index.ts +612 -612
  206. package/src/errors/codes.ts +143 -136
  207. package/src/errors/envelope.ts +75 -75
  208. package/src/errors/index.ts +21 -21
  209. package/src/errors/plugin-error.ts +134 -134
  210. package/src/handles.ts +297 -297
  211. package/src/host-utils.ts +67 -67
  212. package/src/index.ts +7 -7
  213. package/src/massParameters.ops.ts +246 -246
  214. package/src/massParameters.ts +427 -427
  215. package/src/types.ts +16 -16
  216. package/test/drawingContract.test.mjs +288 -0
  217. package/test/errors.test.mjs +185 -184
  218. package/test/massParameters.test.mjs +952 -952
  219. package/test/presentationViewSettings.test.mjs +85 -0
  220. package/tsconfig.json +22 -22
  221. package/tsup.config.ts +12 -12
@@ -1,376 +1,376 @@
1
- import * as z from "zod"
2
- import { PluginApiReturn } from "../../../types"
3
- import { Vec3Handle, ComponentHandle, Vec3Components } from "../../../handles"
4
-
5
- /**
6
- * Comments — create, edit, resolve, tag, and list scene/project comments.
7
- *
8
- * A comment is an opaque {@link CommentHandle} (its server id). Comments may be
9
- * anchored to a component at a 3D point, carry @mentions (by email) and emojis,
10
- * and be resolved / reopened. Accessed via `snaptrude.core.comment`.
11
- */
12
- export abstract class PluginCommentApi {
13
- constructor() {}
14
-
15
- /**
16
- * Create a comment in the project — optionally pinned to a component at a 3D
17
- * point — with optional @mentions that notify teammates by email.
18
- *
19
- * @param message - Comment text (emojis = plain unicode).
20
- * @param component - Optional component to anchor the comment to.
21
- * @param position - Optional pin point; defaults to the component's center.
22
- * @param mentions - Optional user emails to @mention (appended as real @mention tags).
23
- * @returns the new {@link CommentHandle}.
24
- *
25
- * @examplePrompt Add a comment on this wall saying the height looks wrong
26
- * @examplePrompt Leave a note on the selected room for the design team
27
- * @examplePrompt Comment "verify the door swing" and tag alex@acme.com
28
- * @examplePrompt Pin a review note at this point on the slab
29
- *
30
- * # Example
31
- * ```ts
32
- * const c = await snaptrude.core.comment.create(
33
- * "Check this wall 🎉",
34
- * spaceId,
35
- * undefined,
36
- * ["alex@acme.com"],
37
- * )
38
- * ```
39
- */
40
- public abstract create(
41
- message: string,
42
- component?: ComponentHandle,
43
- position?: Vec3Handle,
44
- mentions?: string[],
45
- ): PluginApiReturn<CommentHandle>
46
-
47
- /**
48
- * Edit a comment's message (and optional @mentions).
49
- *
50
- * @param comment - The comment to edit.
51
- * @param message - New message text.
52
- * @param mentions - Optional user emails to @mention.
53
- *
54
- * @examplePrompt Edit my comment to say the beam depth is 600mm
55
- * @examplePrompt Change the text of this comment
56
- * @examplePrompt Update the note on the wall and mention priya@studio.com
57
- * @examplePrompt Reword the comment I just added
58
- *
59
- * # Example
60
- * ```ts
61
- * const c = await snaptrude.core.comment.create("Beam depth TBD")
62
- * await snaptrude.core.comment.update(c, "Beam depth is 600mm", ["priya@studio.com"])
63
- * ```
64
- */
65
- public abstract update(
66
- comment: CommentHandle,
67
- message: string,
68
- mentions?: string[],
69
- ): PluginApiReturn<boolean>
70
-
71
- /**
72
- * Mark a comment resolved. Paired with {@link PluginCommentApi.reopen}.
73
- *
74
- * @param comment - The target comment.
75
- *
76
- * @examplePrompt Mark this comment as resolved
77
- * @examplePrompt Resolve the comment about the staircase
78
- * @examplePrompt Close out this review note
79
- * @examplePrompt Set that comment to done
80
- *
81
- * # Example
82
- * ```ts
83
- * const c = await snaptrude.core.comment.create("Verify the door swing")
84
- * await snaptrude.core.comment.resolve(c)
85
- * ```
86
- */
87
- public abstract resolve(comment: CommentHandle): PluginApiReturn<boolean>
88
-
89
- /**
90
- * Reopen a resolved comment. Paired with {@link PluginCommentApi.resolve}.
91
- *
92
- * @param comment - The target comment.
93
- *
94
- * @examplePrompt Reopen this resolved comment
95
- * @examplePrompt Mark the comment as unresolved again
96
- * @examplePrompt Bring back the closed note about the window heights
97
- * @examplePrompt Un-resolve that comment so we can keep discussing it
98
- *
99
- * # Example
100
- * ```ts
101
- * const [comment] = await snaptrude.core.comment.list()
102
- * await snaptrude.core.comment.reopen(comment)
103
- * ```
104
- */
105
- public abstract reopen(comment: CommentHandle): PluginApiReturn<boolean>
106
-
107
- /**
108
- * Check whether a comment has been marked resolved.
109
- *
110
- * @param comment - The target comment.
111
- *
112
- * @examplePrompt Is this comment resolved yet?
113
- * @examplePrompt Check if the note about the roof has been closed
114
- * @examplePrompt Has my comment been resolved?
115
- * @examplePrompt Tell me whether that comment is still open
116
- *
117
- * # Example
118
- * ```ts
119
- * const [comment] = await snaptrude.core.comment.list()
120
- * const resolved = await snaptrude.core.comment.isResolved(comment)
121
- * console.log(resolved ? "resolved" : "still open")
122
- * ```
123
- */
124
- public abstract isResolved(comment: CommentHandle): PluginApiReturn<boolean>
125
-
126
- /**
127
- * Tag (mention) a user on an existing comment, by email.
128
- *
129
- * @param comment - The comment to add a mention to.
130
- * @param email - The user's email to @mention.
131
- *
132
- * @examplePrompt Tag alex@acme.com on this comment
133
- * @examplePrompt Mention the structural engineer in that note
134
- * @examplePrompt Add priya@studio.com to the comment about the lobby
135
- * @examplePrompt Notify a teammate about an existing comment
136
- *
137
- * # Example
138
- * ```ts
139
- * const [comment] = await snaptrude.core.comment.list()
140
- * await snaptrude.core.comment.tag(comment, "alex@acme.com")
141
- * ```
142
- */
143
- public abstract tag(
144
- comment: CommentHandle,
145
- email: string,
146
- ): PluginApiReturn<boolean>
147
-
148
- /**
149
- * Permanently remove a comment from the project.
150
- *
151
- * @param comment - The target comment.
152
- *
153
- * @examplePrompt Delete this comment
154
- * @examplePrompt Remove the note about the old layout
155
- * @examplePrompt Get rid of my last comment
156
- * @examplePrompt Clear that resolved comment off the wall
157
- *
158
- * # Example
159
- * ```ts
160
- * const [comment] = await snaptrude.core.comment.list()
161
- * await snaptrude.core.comment.delete(comment)
162
- * ```
163
- */
164
- public abstract delete(comment: CommentHandle): PluginApiReturn<boolean>
165
-
166
- /**
167
- * List every comment in the project (deleted ones are excluded), returned as
168
- * comment handles you can pass to the other comment methods.
169
- *
170
- * @examplePrompt List all the comments in this project
171
- * @examplePrompt How many comments are on this model?
172
- * @examplePrompt Show every note in the file
173
- * @examplePrompt Get all comments so I can check which are resolved
174
- *
175
- * # Example
176
- * ```ts
177
- * const comments = await snaptrude.core.comment.list()
178
- * console.log(`${comments.length} comments in the project`)
179
- * ```
180
- */
181
- public abstract list(): PluginApiReturn<CommentHandle[]>
182
-
183
- /**
184
- * Read a comment's full detail — its text, author, pin location, resolved
185
- * state, and reply thread. Comments are otherwise write-only; this is the read
186
- * side. Pass a top-level comment handle or a reply handle (a reply has an empty
187
- * `thread`). Returns `null` if the handle doesn't match a live comment.
188
- *
189
- * @param comment - The comment (or reply) to read.
190
- * @returns the {@link PluginCommentDetails}, or `null` if not found.
191
- *
192
- * @examplePrompt Read the comment on this wall and tell me what it says
193
- * @examplePrompt Who left this comment and where is it pinned?
194
- * @examplePrompt Show me the full thread for this comment
195
- * @examplePrompt Get the text and author of the selected comment
196
- *
197
- * # Example
198
- * ```ts
199
- * const [first] = await snaptrude.core.comment.list()
200
- * const details = await snaptrude.core.comment.get(first)
201
- * console.log(details?.content, "by", details?.author?.name)
202
- * console.log(`${details?.thread.length ?? 0} replies`)
203
- * ```
204
- */
205
- public abstract get(
206
- comment: CommentHandle,
207
- ): PluginApiReturn<PluginCommentDetails | null>
208
-
209
- /**
210
- * Reply to a comment — posts a new comment threaded under `comment` (which must
211
- * be a top-level comment, not itself a reply). Notifies the thread's
212
- * participants, mirroring the sidebar Reply action.
213
- *
214
- * @param comment - The top-level comment to reply to.
215
- * @param text - The reply text (emojis = plain unicode).
216
- * @returns the new reply's {@link CommentHandle}.
217
- *
218
- * @examplePrompt Reply to this comment saying I fixed the wall height
219
- * @examplePrompt Add a reply to the review note confirming it's done
220
- * @examplePrompt Respond to the comment about the door with "looks good now"
221
- * @examplePrompt Post a follow-up on the selected comment thread
222
- *
223
- * # Example
224
- * ```ts
225
- * const [thread] = await snaptrude.core.comment.list()
226
- * const reply = await snaptrude.core.comment.reply(thread, "Fixed 👍")
227
- * ```
228
- */
229
- public abstract reply(
230
- comment: CommentHandle,
231
- text: string,
232
- ): PluginApiReturn<CommentHandle>
233
- }
234
-
235
- /**
236
- * Opaque handle to a comment — its server-assigned id (entity-style: a raw,
237
- * persistable string resolved live, not a registry-minted value handle).
238
- */
239
- export type CommentHandle = string & { readonly __handle: "comment" }
240
- export const CommentHandle = z
241
- .string()
242
- .min(1)
243
- .transform((s) => s as CommentHandle)
244
-
245
- /** `ComponentHandle` is defined in `handles.ts` (imported above) and exported from the
246
- * package root via `export * from "./handles"`. Not re-exported here to avoid an
247
- * ambiguous double `export *` at the barrel. */
248
-
249
- /**
250
- * Arguments for {@link PluginCommentApi.create}.
251
- *
252
- * | Property | Type | Description |
253
- * |---|---|---|
254
- * | `component` | {@link ComponentHandle}? | Component to anchor the comment to |
255
- * | `position` | {@link Vec3Handle}? | Pin point; defaults to the component's center |
256
- * | `message` | `string` | Comment text (emojis = unicode) |
257
- * | `mentions` | `string[]`? | User emails to @mention |
258
- */
259
- export const PluginCommentCreateArgs = z.object({
260
- component: ComponentHandle.optional(),
261
- position: Vec3Handle.optional(),
262
- message: z.string(),
263
- mentions: z.array(z.string()).optional(),
264
- })
265
-
266
- export type PluginCommentCreateArgs = z.infer<typeof PluginCommentCreateArgs>
267
-
268
- /**
269
- * Arguments for {@link PluginCommentApi.update}.
270
- *
271
- * | Property | Type | Description |
272
- * |---|---|---|
273
- * | `comment` | {@link CommentHandle} | The comment to edit |
274
- * | `message` | `string` | New message text |
275
- * | `mentions` | `string[]`? | User emails to @mention |
276
- */
277
- export const PluginCommentUpdateArgs = z.object({
278
- comment: CommentHandle,
279
- message: z.string(),
280
- mentions: z.array(z.string()).optional(),
281
- })
282
-
283
- export type PluginCommentUpdateArgs = z.infer<typeof PluginCommentUpdateArgs>
284
-
285
- /**
286
- * Arguments for {@link PluginCommentApi.resolve} / {@link PluginCommentApi.reopen}
287
- * / {@link PluginCommentApi.isResolved} / {@link PluginCommentApi.delete}.
288
- *
289
- * | Property | Type | Description |
290
- * |---|---|---|
291
- * | `comment` | {@link CommentHandle} | The target comment |
292
- */
293
- export const PluginCommentRefArgs = z.object({
294
- comment: CommentHandle,
295
- })
296
-
297
- export type PluginCommentRefArgs = z.infer<typeof PluginCommentRefArgs>
298
-
299
- /**
300
- * Arguments for {@link PluginCommentApi.tag}.
301
- *
302
- * | Property | Type | Description |
303
- * |---|---|---|
304
- * | `comment` | {@link CommentHandle} | The comment to add a mention to |
305
- * | `email` | `string` | The user's email to @mention |
306
- */
307
- export const PluginCommentTagArgs = z.object({
308
- comment: CommentHandle,
309
- email: z.string(),
310
- })
311
-
312
- export type PluginCommentTagArgs = z.infer<typeof PluginCommentTagArgs>
313
-
314
- /**
315
- * Arguments for {@link PluginCommentApi.reply}.
316
- *
317
- * | Property | Type | Description |
318
- * |---|---|---|
319
- * | `comment` | {@link CommentHandle} | The top-level comment to reply to |
320
- * | `text` | `string` | The reply text (emojis = unicode) |
321
- */
322
- export const PluginCommentReplyArgs = z.object({
323
- comment: CommentHandle,
324
- text: z.string(),
325
- })
326
-
327
- export type PluginCommentReplyArgs = z.infer<typeof PluginCommentReplyArgs>
328
-
329
- /**
330
- * The author of a comment or reply — the display name and email of the teammate
331
- * who posted it. `null` on the rare comment with no recorded author.
332
- */
333
- export interface PluginCommentAuthor {
334
- /** The author's display name (falls back to their email). */
335
- name: string
336
- /** The author's email. */
337
- email: string
338
- }
339
-
340
- /**
341
- * One reply in a comment's thread (returned by {@link PluginCommentApi.get}).
342
- */
343
- export interface PluginCommentReply {
344
- /** The reply's own {@link CommentHandle}. */
345
- id: CommentHandle
346
- /** The reply text. */
347
- content: string
348
- /** Who posted the reply. */
349
- author: PluginCommentAuthor | null
350
- /** ISO-8601 timestamp of when the reply was posted (empty if unknown). */
351
- createdAt: string
352
- }
353
-
354
- /**
355
- * The read model of a comment — returned by {@link PluginCommentApi.get}. The
356
- * inverse of {@link PluginCommentApi.create}: `content`/`component`/`position`
357
- * echo what was posted, plus the resolved state and reply `thread`.
358
- */
359
- export interface PluginCommentDetails {
360
- /** The comment's {@link CommentHandle}. */
361
- id: CommentHandle
362
- /** The comment text. */
363
- content: string
364
- /** Who posted the comment. */
365
- author: PluginCommentAuthor | null
366
- /** The pin point (engine world coordinates), or `null` if un-anchored. */
367
- position: Vec3Components | null
368
- /** The component the comment is anchored to, or `null` if un-anchored. */
369
- component: ComponentHandle | null
370
- /** Whether the comment has been marked resolved. */
371
- isResolved: boolean
372
- /** ISO-8601 timestamp of when the comment was posted (empty if unknown). */
373
- createdAt: string
374
- /** The reply thread, oldest first. Empty for a comment with no replies. */
375
- thread: PluginCommentReply[]
376
- }
1
+ import * as z from "zod"
2
+ import { PluginApiReturn } from "../../../types"
3
+ import { Vec3Handle, ComponentHandle, Vec3Components } from "../../../handles"
4
+
5
+ /**
6
+ * Comments — create, edit, resolve, tag, and list scene/project comments.
7
+ *
8
+ * A comment is an opaque {@link CommentHandle} (its server id). Comments may be
9
+ * anchored to a component at a 3D point, carry @mentions (by email) and emojis,
10
+ * and be resolved / reopened. Accessed via `snaptrude.core.comment`.
11
+ */
12
+ export abstract class PluginCommentApi {
13
+ constructor() {}
14
+
15
+ /**
16
+ * Create a comment in the project — optionally pinned to a component at a 3D
17
+ * point — with optional @mentions that notify teammates by email.
18
+ *
19
+ * @param message - Comment text (emojis = plain unicode).
20
+ * @param component - Optional component to anchor the comment to.
21
+ * @param position - Optional pin point; defaults to the component's center.
22
+ * @param mentions - Optional user emails to @mention (appended as real @mention tags).
23
+ * @returns the new {@link CommentHandle}.
24
+ *
25
+ * @examplePrompt Add a comment on this wall saying the height looks wrong
26
+ * @examplePrompt Leave a note on the selected room for the design team
27
+ * @examplePrompt Comment "verify the door swing" and tag alex@acme.com
28
+ * @examplePrompt Pin a review note at this point on the slab
29
+ *
30
+ * # Example
31
+ * ```ts
32
+ * const c = await snaptrude.core.comment.create(
33
+ * "Check this wall 🎉",
34
+ * spaceId,
35
+ * undefined,
36
+ * ["alex@acme.com"],
37
+ * )
38
+ * ```
39
+ */
40
+ public abstract create(
41
+ message: string,
42
+ component?: ComponentHandle,
43
+ position?: Vec3Handle,
44
+ mentions?: string[],
45
+ ): PluginApiReturn<CommentHandle>
46
+
47
+ /**
48
+ * Edit a comment's message (and optional @mentions).
49
+ *
50
+ * @param comment - The comment to edit.
51
+ * @param message - New message text.
52
+ * @param mentions - Optional user emails to @mention.
53
+ *
54
+ * @examplePrompt Edit my comment to say the beam depth is 600mm
55
+ * @examplePrompt Change the text of this comment
56
+ * @examplePrompt Update the note on the wall and mention priya@studio.com
57
+ * @examplePrompt Reword the comment I just added
58
+ *
59
+ * # Example
60
+ * ```ts
61
+ * const c = await snaptrude.core.comment.create("Beam depth TBD")
62
+ * await snaptrude.core.comment.update(c, "Beam depth is 600mm", ["priya@studio.com"])
63
+ * ```
64
+ */
65
+ public abstract update(
66
+ comment: CommentHandle,
67
+ message: string,
68
+ mentions?: string[],
69
+ ): PluginApiReturn<boolean>
70
+
71
+ /**
72
+ * Mark a comment resolved. Paired with {@link PluginCommentApi.reopen}.
73
+ *
74
+ * @param comment - The target comment.
75
+ *
76
+ * @examplePrompt Mark this comment as resolved
77
+ * @examplePrompt Resolve the comment about the staircase
78
+ * @examplePrompt Close out this review note
79
+ * @examplePrompt Set that comment to done
80
+ *
81
+ * # Example
82
+ * ```ts
83
+ * const c = await snaptrude.core.comment.create("Verify the door swing")
84
+ * await snaptrude.core.comment.resolve(c)
85
+ * ```
86
+ */
87
+ public abstract resolve(comment: CommentHandle): PluginApiReturn<boolean>
88
+
89
+ /**
90
+ * Reopen a resolved comment. Paired with {@link PluginCommentApi.resolve}.
91
+ *
92
+ * @param comment - The target comment.
93
+ *
94
+ * @examplePrompt Reopen this resolved comment
95
+ * @examplePrompt Mark the comment as unresolved again
96
+ * @examplePrompt Bring back the closed note about the window heights
97
+ * @examplePrompt Un-resolve that comment so we can keep discussing it
98
+ *
99
+ * # Example
100
+ * ```ts
101
+ * const [comment] = await snaptrude.core.comment.list()
102
+ * await snaptrude.core.comment.reopen(comment)
103
+ * ```
104
+ */
105
+ public abstract reopen(comment: CommentHandle): PluginApiReturn<boolean>
106
+
107
+ /**
108
+ * Check whether a comment has been marked resolved.
109
+ *
110
+ * @param comment - The target comment.
111
+ *
112
+ * @examplePrompt Is this comment resolved yet?
113
+ * @examplePrompt Check if the note about the roof has been closed
114
+ * @examplePrompt Has my comment been resolved?
115
+ * @examplePrompt Tell me whether that comment is still open
116
+ *
117
+ * # Example
118
+ * ```ts
119
+ * const [comment] = await snaptrude.core.comment.list()
120
+ * const resolved = await snaptrude.core.comment.isResolved(comment)
121
+ * console.log(resolved ? "resolved" : "still open")
122
+ * ```
123
+ */
124
+ public abstract isResolved(comment: CommentHandle): PluginApiReturn<boolean>
125
+
126
+ /**
127
+ * Tag (mention) a user on an existing comment, by email.
128
+ *
129
+ * @param comment - The comment to add a mention to.
130
+ * @param email - The user's email to @mention.
131
+ *
132
+ * @examplePrompt Tag alex@acme.com on this comment
133
+ * @examplePrompt Mention the structural engineer in that note
134
+ * @examplePrompt Add priya@studio.com to the comment about the lobby
135
+ * @examplePrompt Notify a teammate about an existing comment
136
+ *
137
+ * # Example
138
+ * ```ts
139
+ * const [comment] = await snaptrude.core.comment.list()
140
+ * await snaptrude.core.comment.tag(comment, "alex@acme.com")
141
+ * ```
142
+ */
143
+ public abstract tag(
144
+ comment: CommentHandle,
145
+ email: string,
146
+ ): PluginApiReturn<boolean>
147
+
148
+ /**
149
+ * Permanently remove a comment from the project.
150
+ *
151
+ * @param comment - The target comment.
152
+ *
153
+ * @examplePrompt Delete this comment
154
+ * @examplePrompt Remove the note about the old layout
155
+ * @examplePrompt Get rid of my last comment
156
+ * @examplePrompt Clear that resolved comment off the wall
157
+ *
158
+ * # Example
159
+ * ```ts
160
+ * const [comment] = await snaptrude.core.comment.list()
161
+ * await snaptrude.core.comment.delete(comment)
162
+ * ```
163
+ */
164
+ public abstract delete(comment: CommentHandle): PluginApiReturn<boolean>
165
+
166
+ /**
167
+ * List every comment in the project (deleted ones are excluded), returned as
168
+ * comment handles you can pass to the other comment methods.
169
+ *
170
+ * @examplePrompt List all the comments in this project
171
+ * @examplePrompt How many comments are on this model?
172
+ * @examplePrompt Show every note in the file
173
+ * @examplePrompt Get all comments so I can check which are resolved
174
+ *
175
+ * # Example
176
+ * ```ts
177
+ * const comments = await snaptrude.core.comment.list()
178
+ * console.log(`${comments.length} comments in the project`)
179
+ * ```
180
+ */
181
+ public abstract list(): PluginApiReturn<CommentHandle[]>
182
+
183
+ /**
184
+ * Read a comment's full detail — its text, author, pin location, resolved
185
+ * state, and reply thread. Comments are otherwise write-only; this is the read
186
+ * side. Pass a top-level comment handle or a reply handle (a reply has an empty
187
+ * `thread`). Returns `null` if the handle doesn't match a live comment.
188
+ *
189
+ * @param comment - The comment (or reply) to read.
190
+ * @returns the {@link PluginCommentDetails}, or `null` if not found.
191
+ *
192
+ * @examplePrompt Read the comment on this wall and tell me what it says
193
+ * @examplePrompt Who left this comment and where is it pinned?
194
+ * @examplePrompt Show me the full thread for this comment
195
+ * @examplePrompt Get the text and author of the selected comment
196
+ *
197
+ * # Example
198
+ * ```ts
199
+ * const [first] = await snaptrude.core.comment.list()
200
+ * const details = await snaptrude.core.comment.get(first)
201
+ * console.log(details?.content, "by", details?.author?.name)
202
+ * console.log(`${details?.thread.length ?? 0} replies`)
203
+ * ```
204
+ */
205
+ public abstract get(
206
+ comment: CommentHandle,
207
+ ): PluginApiReturn<PluginCommentDetails | null>
208
+
209
+ /**
210
+ * Reply to a comment — posts a new comment threaded under `comment` (which must
211
+ * be a top-level comment, not itself a reply). Notifies the thread's
212
+ * participants, mirroring the sidebar Reply action.
213
+ *
214
+ * @param comment - The top-level comment to reply to.
215
+ * @param text - The reply text (emojis = plain unicode).
216
+ * @returns the new reply's {@link CommentHandle}.
217
+ *
218
+ * @examplePrompt Reply to this comment saying I fixed the wall height
219
+ * @examplePrompt Add a reply to the review note confirming it's done
220
+ * @examplePrompt Respond to the comment about the door with "looks good now"
221
+ * @examplePrompt Post a follow-up on the selected comment thread
222
+ *
223
+ * # Example
224
+ * ```ts
225
+ * const [thread] = await snaptrude.core.comment.list()
226
+ * const reply = await snaptrude.core.comment.reply(thread, "Fixed 👍")
227
+ * ```
228
+ */
229
+ public abstract reply(
230
+ comment: CommentHandle,
231
+ text: string,
232
+ ): PluginApiReturn<CommentHandle>
233
+ }
234
+
235
+ /**
236
+ * Opaque handle to a comment — its server-assigned id (entity-style: a raw,
237
+ * persistable string resolved live, not a registry-minted value handle).
238
+ */
239
+ export type CommentHandle = string & { readonly __handle: "comment" }
240
+ export const CommentHandle = z
241
+ .string()
242
+ .min(1)
243
+ .transform((s) => s as CommentHandle)
244
+
245
+ /** `ComponentHandle` is defined in `handles.ts` (imported above) and exported from the
246
+ * package root via `export * from "./handles"`. Not re-exported here to avoid an
247
+ * ambiguous double `export *` at the barrel. */
248
+
249
+ /**
250
+ * Arguments for {@link PluginCommentApi.create}.
251
+ *
252
+ * | Property | Type | Description |
253
+ * |---|---|---|
254
+ * | `component` | {@link ComponentHandle}? | Component to anchor the comment to |
255
+ * | `position` | {@link Vec3Handle}? | Pin point; defaults to the component's center |
256
+ * | `message` | `string` | Comment text (emojis = unicode) |
257
+ * | `mentions` | `string[]`? | User emails to @mention |
258
+ */
259
+ export const PluginCommentCreateArgs = z.object({
260
+ component: ComponentHandle.optional(),
261
+ position: Vec3Handle.optional(),
262
+ message: z.string(),
263
+ mentions: z.array(z.string()).optional(),
264
+ })
265
+
266
+ export type PluginCommentCreateArgs = z.infer<typeof PluginCommentCreateArgs>
267
+
268
+ /**
269
+ * Arguments for {@link PluginCommentApi.update}.
270
+ *
271
+ * | Property | Type | Description |
272
+ * |---|---|---|
273
+ * | `comment` | {@link CommentHandle} | The comment to edit |
274
+ * | `message` | `string` | New message text |
275
+ * | `mentions` | `string[]`? | User emails to @mention |
276
+ */
277
+ export const PluginCommentUpdateArgs = z.object({
278
+ comment: CommentHandle,
279
+ message: z.string(),
280
+ mentions: z.array(z.string()).optional(),
281
+ })
282
+
283
+ export type PluginCommentUpdateArgs = z.infer<typeof PluginCommentUpdateArgs>
284
+
285
+ /**
286
+ * Arguments for {@link PluginCommentApi.resolve} / {@link PluginCommentApi.reopen}
287
+ * / {@link PluginCommentApi.isResolved} / {@link PluginCommentApi.delete}.
288
+ *
289
+ * | Property | Type | Description |
290
+ * |---|---|---|
291
+ * | `comment` | {@link CommentHandle} | The target comment |
292
+ */
293
+ export const PluginCommentRefArgs = z.object({
294
+ comment: CommentHandle,
295
+ })
296
+
297
+ export type PluginCommentRefArgs = z.infer<typeof PluginCommentRefArgs>
298
+
299
+ /**
300
+ * Arguments for {@link PluginCommentApi.tag}.
301
+ *
302
+ * | Property | Type | Description |
303
+ * |---|---|---|
304
+ * | `comment` | {@link CommentHandle} | The comment to add a mention to |
305
+ * | `email` | `string` | The user's email to @mention |
306
+ */
307
+ export const PluginCommentTagArgs = z.object({
308
+ comment: CommentHandle,
309
+ email: z.string(),
310
+ })
311
+
312
+ export type PluginCommentTagArgs = z.infer<typeof PluginCommentTagArgs>
313
+
314
+ /**
315
+ * Arguments for {@link PluginCommentApi.reply}.
316
+ *
317
+ * | Property | Type | Description |
318
+ * |---|---|---|
319
+ * | `comment` | {@link CommentHandle} | The top-level comment to reply to |
320
+ * | `text` | `string` | The reply text (emojis = unicode) |
321
+ */
322
+ export const PluginCommentReplyArgs = z.object({
323
+ comment: CommentHandle,
324
+ text: z.string(),
325
+ })
326
+
327
+ export type PluginCommentReplyArgs = z.infer<typeof PluginCommentReplyArgs>
328
+
329
+ /**
330
+ * The author of a comment or reply — the display name and email of the teammate
331
+ * who posted it. `null` on the rare comment with no recorded author.
332
+ */
333
+ export interface PluginCommentAuthor {
334
+ /** The author's display name (falls back to their email). */
335
+ name: string
336
+ /** The author's email. */
337
+ email: string
338
+ }
339
+
340
+ /**
341
+ * One reply in a comment's thread (returned by {@link PluginCommentApi.get}).
342
+ */
343
+ export interface PluginCommentReply {
344
+ /** The reply's own {@link CommentHandle}. */
345
+ id: CommentHandle
346
+ /** The reply text. */
347
+ content: string
348
+ /** Who posted the reply. */
349
+ author: PluginCommentAuthor | null
350
+ /** ISO-8601 timestamp of when the reply was posted (empty if unknown). */
351
+ createdAt: string
352
+ }
353
+
354
+ /**
355
+ * The read model of a comment — returned by {@link PluginCommentApi.get}. The
356
+ * inverse of {@link PluginCommentApi.create}: `content`/`component`/`position`
357
+ * echo what was posted, plus the resolved state and reply `thread`.
358
+ */
359
+ export interface PluginCommentDetails {
360
+ /** The comment's {@link CommentHandle}. */
361
+ id: CommentHandle
362
+ /** The comment text. */
363
+ content: string
364
+ /** Who posted the comment. */
365
+ author: PluginCommentAuthor | null
366
+ /** The pin point (engine world coordinates), or `null` if un-anchored. */
367
+ position: Vec3Components | null
368
+ /** The component the comment is anchored to, or `null` if un-anchored. */
369
+ component: ComponentHandle | null
370
+ /** Whether the comment has been marked resolved. */
371
+ isResolved: boolean
372
+ /** ISO-8601 timestamp of when the comment was posted (empty if unknown). */
373
+ createdAt: string
374
+ /** The reply thread, oldest first. Empty for a comment with no replies. */
375
+ thread: PluginCommentReply[]
376
+ }