@snaptrude/plugin-core 0.8.0 → 0.9.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 (129) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/api-manifest.full.json +1350 -89
  3. package/api-manifest.json +1146 -48
  4. package/dist/api/analysis/daylight.d.ts +603 -0
  5. package/dist/api/analysis/daylight.d.ts.map +1 -0
  6. package/dist/api/analysis/heatmaps.d.ts +438 -14
  7. package/dist/api/analysis/heatmaps.d.ts.map +1 -1
  8. package/dist/api/analysis/index.d.ts +15 -0
  9. package/dist/api/analysis/index.d.ts.map +1 -1
  10. package/dist/api/analysis/solar.d.ts +249 -0
  11. package/dist/api/analysis/solar.d.ts.map +1 -0
  12. package/dist/api/analysis/weather.d.ts +193 -0
  13. package/dist/api/analysis/weather.d.ts.map +1 -0
  14. package/dist/api/core/camera/index.d.ts +37 -0
  15. package/dist/api/core/camera/index.d.ts.map +1 -1
  16. package/dist/api/core/geom/create/index.d.ts +318 -1
  17. package/dist/api/core/geom/create/index.d.ts.map +1 -1
  18. package/dist/api/core/index.d.ts +9 -0
  19. package/dist/api/core/index.d.ts.map +1 -1
  20. package/dist/api/core/io/export/index.d.ts +3 -1
  21. package/dist/api/core/io/export/index.d.ts.map +1 -1
  22. package/dist/api/core/io/import/index.d.ts +61 -0
  23. package/dist/api/core/io/import/index.d.ts.map +1 -1
  24. package/dist/api/core/io/terrain/index.d.ts +132 -0
  25. package/dist/api/core/io/terrain/index.d.ts.map +1 -1
  26. package/dist/api/core/mode/index.d.ts +99 -0
  27. package/dist/api/core/mode/index.d.ts.map +1 -0
  28. package/dist/api/core/storeys/index.d.ts +251 -0
  29. package/dist/api/core/storeys/index.d.ts.map +1 -0
  30. package/dist/api/core/tags.d.ts +24 -0
  31. package/dist/api/core/tags.d.ts.map +1 -1
  32. package/dist/api/core/zoom/index.d.ts +4 -0
  33. package/dist/api/core/zoom/index.d.ts.map +1 -1
  34. package/dist/api/design/create/index.d.ts +115 -4
  35. package/dist/api/design/create/index.d.ts.map +1 -1
  36. package/dist/api/design/delete/index.d.ts +3 -0
  37. package/dist/api/design/delete/index.d.ts.map +1 -1
  38. package/dist/api/design/query/geometry/index.d.ts +112 -0
  39. package/dist/api/design/query/geometry/index.d.ts.map +1 -1
  40. package/dist/api/design/query/index.d.ts +4 -0
  41. package/dist/api/design/query/index.d.ts.map +1 -1
  42. package/dist/api/design/query/referenceLines.d.ts +45 -0
  43. package/dist/api/design/query/referenceLines.d.ts.map +1 -0
  44. package/dist/api/design/query/spaces.d.ts +173 -0
  45. package/dist/api/design/query/spaces.d.ts.map +1 -1
  46. package/dist/api/design/transform/index.d.ts +12 -0
  47. package/dist/api/design/transform/index.d.ts.map +1 -1
  48. package/dist/api/design/update/index.d.ts +51 -1
  49. package/dist/api/design/update/index.d.ts.map +1 -1
  50. package/dist/api/entity/buildableEnvelope.d.ts +4 -0
  51. package/dist/api/entity/buildableEnvelope.d.ts.map +1 -1
  52. package/dist/api/entity/referenceLine.d.ts +8 -0
  53. package/dist/api/entity/referenceLine.d.ts.map +1 -1
  54. package/dist/api/entity/story.d.ts +20 -0
  55. package/dist/api/entity/story.d.ts.map +1 -1
  56. package/dist/api/index.d.ts +5 -0
  57. package/dist/api/index.d.ts.map +1 -1
  58. package/dist/api/presentation/annotate.d.ts +23 -4
  59. package/dist/api/presentation/annotate.d.ts.map +1 -1
  60. package/dist/api/presentation/diagrams.d.ts +64 -2
  61. package/dist/api/presentation/diagrams.d.ts.map +1 -1
  62. package/dist/api/presentation/export.d.ts +4 -0
  63. package/dist/api/presentation/export.d.ts.map +1 -1
  64. package/dist/api/presentation/import.d.ts +6 -0
  65. package/dist/api/presentation/import.d.ts.map +1 -1
  66. package/dist/api/presentation/index.d.ts +20 -1
  67. package/dist/api/presentation/index.d.ts.map +1 -1
  68. package/dist/api/presentation/placedViews.d.ts +1139 -0
  69. package/dist/api/presentation/placedViews.d.ts.map +1 -0
  70. package/dist/api/presentation/shapes.d.ts +481 -0
  71. package/dist/api/presentation/shapes.d.ts.map +1 -0
  72. package/dist/api/presentation/sheets.d.ts +42 -0
  73. package/dist/api/presentation/sheets.d.ts.map +1 -1
  74. package/dist/api/presentation/slideshow.d.ts +125 -0
  75. package/dist/api/presentation/slideshow.d.ts.map +1 -0
  76. package/dist/api/presentation/tables.d.ts +81 -0
  77. package/dist/api/presentation/tables.d.ts.map +1 -0
  78. package/dist/api/program/site.d.ts +260 -2
  79. package/dist/api/program/site.d.ts.map +1 -1
  80. package/dist/api/program/spreadsheet.d.ts +260 -28
  81. package/dist/api/program/spreadsheet.d.ts.map +1 -1
  82. package/dist/api/workspace/index.d.ts +505 -0
  83. package/dist/api/workspace/index.d.ts.map +1 -0
  84. package/dist/index.cjs +2904 -1761
  85. package/dist/index.cjs.map +1 -1
  86. package/dist/index.js +2762 -1761
  87. package/dist/index.js.map +1 -1
  88. package/package.json +3 -2
  89. package/scripts/generate-manifest.mjs +45 -0
  90. package/src/api/analysis/daylight.ts +470 -0
  91. package/src/api/analysis/heatmaps.ts +444 -17
  92. package/src/api/analysis/index.ts +15 -0
  93. package/src/api/analysis/solar.ts +237 -0
  94. package/src/api/analysis/weather.ts +179 -0
  95. package/src/api/core/camera/index.ts +39 -0
  96. package/src/api/core/geom/create/index.ts +344 -1
  97. package/src/api/core/index.ts +9 -0
  98. package/src/api/core/io/export/index.ts +3 -1
  99. package/src/api/core/io/import/index.ts +64 -0
  100. package/src/api/core/io/terrain/index.ts +143 -0
  101. package/src/api/core/mode/index.ts +96 -0
  102. package/src/api/core/storeys/index.ts +279 -0
  103. package/src/api/core/tags.ts +27 -0
  104. package/src/api/core/zoom/index.ts +4 -0
  105. package/src/api/design/create/index.ts +138 -1
  106. package/src/api/design/delete/index.ts +3 -0
  107. package/src/api/design/query/geometry/index.ts +125 -3
  108. package/src/api/design/query/index.ts +4 -0
  109. package/src/api/design/query/referenceLines.ts +52 -0
  110. package/src/api/design/query/spaces.ts +143 -0
  111. package/src/api/design/transform/index.ts +12 -0
  112. package/src/api/design/update/index.ts +66 -1
  113. package/src/api/entity/buildableEnvelope.ts +4 -0
  114. package/src/api/entity/referenceLine.ts +8 -0
  115. package/src/api/entity/story.ts +20 -0
  116. package/src/api/index.ts +5 -0
  117. package/src/api/presentation/annotate.ts +27 -2
  118. package/src/api/presentation/diagrams.ts +67 -2
  119. package/src/api/presentation/export.ts +4 -0
  120. package/src/api/presentation/import.ts +6 -0
  121. package/src/api/presentation/index.ts +20 -1
  122. package/src/api/presentation/placedViews.ts +1120 -0
  123. package/src/api/presentation/shapes.ts +274 -0
  124. package/src/api/presentation/sheets.ts +54 -0
  125. package/src/api/presentation/slideshow.ts +134 -0
  126. package/src/api/presentation/tables.ts +84 -0
  127. package/src/api/program/site.ts +205 -2
  128. package/src/api/program/spreadsheet.ts +251 -6
  129. package/src/api/workspace/index.ts +563 -0
@@ -0,0 +1,603 @@
1
+ import * as z from "zod";
2
+ import { PluginApiReturn } from "../../types";
3
+ /**
4
+ * Analysis daylight — standards-grade annual daylight metrics (IES LM-83).
5
+ *
6
+ * Runs an annual daylight simulation over per-space sensor grids and returns
7
+ * **numeric** per-sensor and aggregate metrics — no textures, no heatmap, no
8
+ * model mutation. Two metrics are supported: **ASE** (Annual Sunlight
9
+ * Exposure) and **sDA** (Spatial Daylight Autonomy, sDA300/50%).
10
+ *
11
+ * **Run semantics.** `metrics: ["ASE"]` runs **synchronously** — `compute`
12
+ * returns the full result directly, no `runId`. Any request including
13
+ * `"sDA"` (alone or with ASE) runs **asynchronously**: `compute` submits the
14
+ * job and immediately returns `{ status: "running", runId, sensors: [],
15
+ * aggregates: [] }`; call {@linkcode PluginAnalysisDaylightApi.poll} with the
16
+ * `runId` until `status` is `"complete"` (or `"failed"`).
17
+ *
18
+ * **Blind operation.** sDA is computed WITH dynamic blind operation per the
19
+ * IES LM-83 2% rule: windows are grouped by storey + facade orientation, and
20
+ * for every occupied hour blind groups close (default 5% diffuse
21
+ * transmittance) until no more than 2% of the analysis points receive direct
22
+ * sun. This API **operates the blinds for you** — sDA without blind operation
23
+ * is not LM-83-compliant, so there is no switch to turn it off. The run's
24
+ * `provenance.blinds` reports the groups, their closed hours, and any hours
25
+ * where no combination satisfies the rule.
26
+ *
27
+ * **Surface optics.** The optional `optics` arg overrides surface optics.
28
+ * Resolution order per surface: per-material (`optics.materials`, keyed by
29
+ * material **name** as shown in Snaptrude) → per-category
30
+ * (`optics.categories`) → LM-83/convention defaults:
31
+ *
32
+ * | Category | Default | Property |
33
+ * |---|---|---|
34
+ * | `wall` | `0.5` | reflectance |
35
+ * | `ceiling` | `0.7` | reflectance |
36
+ * | `floor` | `0.2` | reflectance |
37
+ * | `furniture` | `0.5` | reflectance |
38
+ * | `glazing` | `0.65` | transmittance (Tvis) |
39
+ * | `context` | `0.2` | reflectance |
40
+ * | blinds (closed) | `0.05` | diffuse transmittance |
41
+ *
42
+ * Glazing takes visible **transmittance** (Tvis) exactly as manufacturers
43
+ * quote it; the backend converts it to Radiance glass transmissivity
44
+ * internally.
45
+ *
46
+ * Every result carries a full `provenance` echo (weather file, thresholds,
47
+ * grid, location, resolved optics, blind operation, warnings, excluded
48
+ * spaces) plus `modelRevision` + `inputHash` for staleness. Positions are
49
+ * **world plan-space** coordinates.
50
+ *
51
+ * `compute` is write-gated and Pro-gated host-side, exactly like
52
+ * {@linkcode PluginAnalysisIlluminanceApi.compute}.
53
+ *
54
+ * Accessed via `snaptrude.analysis.daylight`.
55
+ */
56
+ export declare abstract class PluginAnalysisDaylightApi {
57
+ constructor();
58
+ /**
59
+ * Compute annual daylight metrics for the model's spaces.
60
+ *
61
+ * Sensors are laid out per-space from the `grid` spec; request the metrics
62
+ * you want in `metrics` (`["ASE"]`, `["sDA"]`, or both). ASE-only runs are
63
+ * **synchronous** and return the full result directly. Any run including
64
+ * `"sDA"` is **asynchronous**: this returns `{ status: "running", runId,
65
+ * sensors: [], aggregates: [] }` immediately — pass the `runId` to
66
+ * {@linkcode PluginAnalysisDaylightApi.poll} until the run completes.
67
+ * sDA is computed with LM-83 dynamic blind operation (see the class doc);
68
+ * pass `optics` to override surface reflectances / glazing transmittance.
69
+ *
70
+ * @param args - {@linkcode PluginDaylightComputeArgs}: the `standard`
71
+ * (`"IES-LM-83-23"`), the `metrics` to compute, an optional occupancy
72
+ * `schedule`, optional surface `optics` overrides, and the sensor `grid`
73
+ * spec.
74
+ * @returns A {@linkcode PluginDaylightResults} — per-sensor `sensors`,
75
+ * scope-rolled `aggregates`, the full `provenance` echo, `nextCursor`
76
+ * (`null` when all sensors fit in one page), and `runId` on
77
+ * asynchronous (sDA) runs.
78
+ * @throws When the workspace is not on a **Pro** plan.
79
+ * @throws When plugin writes are disabled.
80
+ * @throws When the project has no geo-located site (no location to compute
81
+ * daylight for) or no spaces to analyse.
82
+ *
83
+ * @examplePrompt Run an LM-83 ASE daylight analysis on all my spaces
84
+ * @examplePrompt Which rooms fail annual sunlight exposure?
85
+ * @examplePrompt Compute ASE with a 0.6m sensor grid at desk height
86
+ * @examplePrompt Run an LM-83 sDA analysis with blinds operated
87
+ * @examplePrompt Which spaces meet sDA300/50%?
88
+ * @examplePrompt Compute sDA with 70% reflective ceilings and Tvis 0.6 glazing
89
+ *
90
+ * # Example
91
+ * ```ts
92
+ * let res = await snaptrude.analysis.daylight.compute({
93
+ * standard: "IES-LM-83-23",
94
+ * metrics: ["sDA", "ASE"],
95
+ * grid: { spacingM: 0.6, workplaneHeightM: 0.76, boundaryOffsetM: 0.5 },
96
+ * optics: { materials: { "Glass - Clear": { transmittance: 0.6 } } },
97
+ * })
98
+ * const runId = res.runId
99
+ * while (res.status === "running" && runId) {
100
+ * await new Promise((r) => setTimeout(r, 5000))
101
+ * res = await snaptrude.analysis.daylight.poll({ runId })
102
+ * }
103
+ * const failing = res.aggregates.filter(
104
+ * (a) => a.scope === "space" && (a.sdaPercent ?? 0) < 55,
105
+ * )
106
+ * ```
107
+ */
108
+ abstract compute(args: PluginDaylightComputeArgs): PluginApiReturn<PluginDaylightResults>;
109
+ /**
110
+ * Poll an asynchronous daylight run started by
111
+ * {@linkcode PluginAnalysisDaylightApi.compute}.
112
+ *
113
+ * Returns the same {@linkcode PluginDaylightResults} shape as `compute`:
114
+ * `status: "running"` while the job is in flight (empty `sensors` /
115
+ * `aggregates`), `"complete"` with the full data once done. Poll every few
116
+ * seconds — an annual sDA simulation takes minutes, not milliseconds.
117
+ * Completed results page sensors exactly like a synchronous run: follow
118
+ * `nextCursor` via the `cursor` arg.
119
+ *
120
+ * @param args - {@linkcode PluginDaylightPollArgs}: the `runId` returned by
121
+ * `compute`, plus an optional sensor-page `cursor`.
122
+ * @returns A {@linkcode PluginDaylightResults} for the run.
123
+ * @throws When the `runId` is unknown, or when the run failed (surfaced as
124
+ * a typed `OPERATION_FAILED`).
125
+ *
126
+ * @examplePrompt Check whether my sDA run has finished
127
+ * @examplePrompt Get the results of the daylight run
128
+ */
129
+ abstract poll(args: PluginDaylightPollArgs): PluginApiReturn<PluginDaylightResults>;
130
+ }
131
+ /**
132
+ * A daylight metric to compute. `"ASE"` (Annual Sunlight Exposure) runs
133
+ * synchronously; any request including `"sDA"` (Spatial Daylight Autonomy,
134
+ * sDA300/50% with LM-83 dynamic blind operation) runs asynchronously —
135
+ * `compute` returns a `runId` to pass to
136
+ * {@linkcode PluginAnalysisDaylightApi.poll}.
137
+ */
138
+ export declare const PluginDaylightMetric: z.ZodEnum<{
139
+ ASE: "ASE";
140
+ sDA: "sDA";
141
+ }>;
142
+ export type PluginDaylightMetric = z.infer<typeof PluginDaylightMetric>;
143
+ /**
144
+ * Status of a daylight run. ASE-only runs are synchronous, so their result is
145
+ * `"complete"`; runs including sDA return `"running"` from `compute` and
146
+ * progress to `"complete"` (or `"failed"`) via
147
+ * {@linkcode PluginAnalysisDaylightApi.poll}.
148
+ */
149
+ export declare const PluginDaylightRunStatus: z.ZodEnum<{
150
+ complete: "complete";
151
+ failed: "failed";
152
+ running: "running";
153
+ cancelled: "cancelled";
154
+ }>;
155
+ export type PluginDaylightRunStatus = z.infer<typeof PluginDaylightRunStatus>;
156
+ /**
157
+ * Sensor-grid spec: spacing, workplane height, and boundary inset (all metres).
158
+ *
159
+ * | Property | Type | Description |
160
+ * |---|---|---|
161
+ * | `spacingM` | `number` | Sensor spacing |
162
+ * | `workplaneHeightM` | `number` | Sensor height above the floor |
163
+ * | `boundaryOffsetM` | `number` | Inset from the space boundary |
164
+ */
165
+ export declare const PluginDaylightGrid: z.ZodObject<{
166
+ spacingM: z.ZodNumber;
167
+ workplaneHeightM: z.ZodNumber;
168
+ boundaryOffsetM: z.ZodNumber;
169
+ }, z.core.$strip>;
170
+ export type PluginDaylightGrid = z.infer<typeof PluginDaylightGrid>;
171
+ /**
172
+ * Optional occupancy schedule (local hours). Defaults to the LM-83 default
173
+ * (8am–6pm) when omitted.
174
+ *
175
+ * | Property | Type | Description |
176
+ * |---|---|---|
177
+ * | `startHour` | `number` | Occupied-period start hour, local (`0`..`24`) |
178
+ * | `endHour` | `number` | Occupied-period end hour, local (`0`..`24`) |
179
+ */
180
+ export declare const PluginDaylightSchedule: z.ZodObject<{
181
+ startHour: z.ZodNumber;
182
+ endHour: z.ZodNumber;
183
+ }, z.core.$strip>;
184
+ export type PluginDaylightSchedule = z.infer<typeof PluginDaylightSchedule>;
185
+ /**
186
+ * Opaque surface optics: visible reflectance (`0`..`1`).
187
+ *
188
+ * | Property | Type | Description |
189
+ * |---|---|---|
190
+ * | `reflectance` | `number` | Visible reflectance (`0`..`1`) |
191
+ */
192
+ export declare const PluginDaylightOpaqueOptics: z.ZodObject<{
193
+ reflectance: z.ZodNumber;
194
+ }, z.core.$strip>;
195
+ export type PluginDaylightOpaqueOptics = z.infer<typeof PluginDaylightOpaqueOptics>;
196
+ /**
197
+ * Glazing optics: visible **transmittance** (Tvis, `0`..`1`) exactly as
198
+ * manufacturers quote it. The backend converts it to Radiance glass
199
+ * transmissivity internally — never pre-convert.
200
+ *
201
+ * | Property | Type | Description |
202
+ * |---|---|---|
203
+ * | `transmittance` | `number` | Visible transmittance Tvis (`0`..`1`) |
204
+ */
205
+ export declare const PluginDaylightGlazingOptics: z.ZodObject<{
206
+ transmittance: z.ZodNumber;
207
+ }, z.core.$strip>;
208
+ export type PluginDaylightGlazingOptics = z.infer<typeof PluginDaylightGlazingOptics>;
209
+ /**
210
+ * Optics for one material: {@linkcode PluginDaylightOpaqueOptics}
211
+ * (`reflectance`) for opaque surfaces, or
212
+ * {@linkcode PluginDaylightGlazingOptics} (`transmittance`) for glazing.
213
+ */
214
+ export declare const PluginDaylightMaterialOptics: z.ZodUnion<readonly [z.ZodObject<{
215
+ reflectance: z.ZodNumber;
216
+ }, z.core.$strip>, z.ZodObject<{
217
+ transmittance: z.ZodNumber;
218
+ }, z.core.$strip>]>;
219
+ export type PluginDaylightMaterialOptics = z.infer<typeof PluginDaylightMaterialOptics>;
220
+ /**
221
+ * Per-category optics overrides. Categories cover every surface in the
222
+ * model; omitted categories use the LM-83/convention defaults (wall `0.5`,
223
+ * ceiling `0.7`, floor `0.2`, furniture `0.5`, glazing Tvis `0.65`,
224
+ * context `0.2`).
225
+ *
226
+ * | Property | Type | Description |
227
+ * |---|---|---|
228
+ * | `wall` | {@linkcode PluginDaylightOpaqueOptics}? | Walls, columns, beams, doors, frames (default `0.5`) |
229
+ * | `ceiling` | {@linkcode PluginDaylightOpaqueOptics}? | Down-facing slab faces (default `0.7`) |
230
+ * | `floor` | {@linkcode PluginDaylightOpaqueOptics}? | Up-facing slab faces (default `0.2`) |
231
+ * | `furniture` | {@linkcode PluginDaylightOpaqueOptics}? | Furniture (default `0.5`) |
232
+ * | `glazing` | {@linkcode PluginDaylightGlazingOptics}? | Window/door glass (default Tvis `0.65`) |
233
+ * | `context` | {@linkcode PluginDaylightOpaqueOptics}? | Terrain / context masses (default `0.2`) |
234
+ */
235
+ export declare const PluginDaylightCategoryDefaults: z.ZodObject<{
236
+ wall: z.ZodOptional<z.ZodObject<{
237
+ reflectance: z.ZodNumber;
238
+ }, z.core.$strip>>;
239
+ ceiling: z.ZodOptional<z.ZodObject<{
240
+ reflectance: z.ZodNumber;
241
+ }, z.core.$strip>>;
242
+ floor: z.ZodOptional<z.ZodObject<{
243
+ reflectance: z.ZodNumber;
244
+ }, z.core.$strip>>;
245
+ furniture: z.ZodOptional<z.ZodObject<{
246
+ reflectance: z.ZodNumber;
247
+ }, z.core.$strip>>;
248
+ glazing: z.ZodOptional<z.ZodObject<{
249
+ transmittance: z.ZodNumber;
250
+ }, z.core.$strip>>;
251
+ context: z.ZodOptional<z.ZodObject<{
252
+ reflectance: z.ZodNumber;
253
+ }, z.core.$strip>>;
254
+ }, z.core.$strip>;
255
+ export type PluginDaylightCategoryDefaults = z.infer<typeof PluginDaylightCategoryDefaults>;
256
+ /**
257
+ * Closed-blind optics: diffuse transmittance of the closed state. Defaults to
258
+ * the LM-83 `0.05` (5% diffuse) when omitted.
259
+ *
260
+ * | Property | Type | Description |
261
+ * |---|---|---|
262
+ * | `transmittance` | `number` | Closed-blind diffuse transmittance (`0`..`1`) |
263
+ */
264
+ export declare const PluginDaylightBlindsOptics: z.ZodObject<{
265
+ transmittance: z.ZodNumber;
266
+ }, z.core.$strip>;
267
+ export type PluginDaylightBlindsOptics = z.infer<typeof PluginDaylightBlindsOptics>;
268
+ /**
269
+ * Surface-optics overrides for a daylight run. Resolution order per surface:
270
+ * `materials` (by material name) → `categories` → LM-83/convention defaults.
271
+ *
272
+ * | Property | Type | Description |
273
+ * |---|---|---|
274
+ * | `materials` | `Record<string,` {@linkcode PluginDaylightMaterialOptics}`>`? | Keyed by material **name** as shown in Snaptrude (the same names `design.query.geometry.getTriangulatedMeshes` returns in `materialIds`); applies wherever the material appears and wins over category defaults |
275
+ * | `categories` | {@linkcode PluginDaylightCategoryDefaults}? | Per-category defaults override |
276
+ * | `blinds` | {@linkcode PluginDaylightBlindsOptics}? | Closed-blind state (default `0.05` diffuse) |
277
+ */
278
+ export declare const PluginDaylightOptics: z.ZodObject<{
279
+ materials: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
280
+ reflectance: z.ZodNumber;
281
+ }, z.core.$strip>, z.ZodObject<{
282
+ transmittance: z.ZodNumber;
283
+ }, z.core.$strip>]>>>;
284
+ categories: z.ZodOptional<z.ZodObject<{
285
+ wall: z.ZodOptional<z.ZodObject<{
286
+ reflectance: z.ZodNumber;
287
+ }, z.core.$strip>>;
288
+ ceiling: z.ZodOptional<z.ZodObject<{
289
+ reflectance: z.ZodNumber;
290
+ }, z.core.$strip>>;
291
+ floor: z.ZodOptional<z.ZodObject<{
292
+ reflectance: z.ZodNumber;
293
+ }, z.core.$strip>>;
294
+ furniture: z.ZodOptional<z.ZodObject<{
295
+ reflectance: z.ZodNumber;
296
+ }, z.core.$strip>>;
297
+ glazing: z.ZodOptional<z.ZodObject<{
298
+ transmittance: z.ZodNumber;
299
+ }, z.core.$strip>>;
300
+ context: z.ZodOptional<z.ZodObject<{
301
+ reflectance: z.ZodNumber;
302
+ }, z.core.$strip>>;
303
+ }, z.core.$strip>>;
304
+ blinds: z.ZodOptional<z.ZodObject<{
305
+ transmittance: z.ZodNumber;
306
+ }, z.core.$strip>>;
307
+ }, z.core.$strip>;
308
+ export type PluginDaylightOptics = z.infer<typeof PluginDaylightOptics>;
309
+ /**
310
+ * Arguments for {@linkcode PluginAnalysisDaylightApi.compute}.
311
+ *
312
+ * | Property | Type | Description |
313
+ * |---|---|---|
314
+ * | `standard` | `"IES-LM-83-23"` | Daylight standard; only supported value |
315
+ * | `metrics` | {@linkcode PluginDaylightMetric}`[]` | Metrics to compute (`["ASE"]` synchronous; including `"sDA"` asynchronous) |
316
+ * | `schedule` | {@linkcode PluginDaylightSchedule}? | Occupancy hours (default 8am–6pm) |
317
+ * | `grid` | {@linkcode PluginDaylightGrid} | Sensor-grid spec |
318
+ * | `optics` | {@linkcode PluginDaylightOptics}? | Surface-optics overrides (per-material → per-category → LM-83 defaults) |
319
+ */
320
+ export declare const PluginDaylightComputeArgs: z.ZodObject<{
321
+ standard: z.ZodLiteral<"IES-LM-83-23">;
322
+ metrics: z.ZodArray<z.ZodEnum<{
323
+ ASE: "ASE";
324
+ sDA: "sDA";
325
+ }>>;
326
+ schedule: z.ZodOptional<z.ZodObject<{
327
+ startHour: z.ZodNumber;
328
+ endHour: z.ZodNumber;
329
+ }, z.core.$strip>>;
330
+ grid: z.ZodObject<{
331
+ spacingM: z.ZodNumber;
332
+ workplaneHeightM: z.ZodNumber;
333
+ boundaryOffsetM: z.ZodNumber;
334
+ }, z.core.$strip>;
335
+ optics: z.ZodOptional<z.ZodObject<{
336
+ materials: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
337
+ reflectance: z.ZodNumber;
338
+ }, z.core.$strip>, z.ZodObject<{
339
+ transmittance: z.ZodNumber;
340
+ }, z.core.$strip>]>>>;
341
+ categories: z.ZodOptional<z.ZodObject<{
342
+ wall: z.ZodOptional<z.ZodObject<{
343
+ reflectance: z.ZodNumber;
344
+ }, z.core.$strip>>;
345
+ ceiling: z.ZodOptional<z.ZodObject<{
346
+ reflectance: z.ZodNumber;
347
+ }, z.core.$strip>>;
348
+ floor: z.ZodOptional<z.ZodObject<{
349
+ reflectance: z.ZodNumber;
350
+ }, z.core.$strip>>;
351
+ furniture: z.ZodOptional<z.ZodObject<{
352
+ reflectance: z.ZodNumber;
353
+ }, z.core.$strip>>;
354
+ glazing: z.ZodOptional<z.ZodObject<{
355
+ transmittance: z.ZodNumber;
356
+ }, z.core.$strip>>;
357
+ context: z.ZodOptional<z.ZodObject<{
358
+ reflectance: z.ZodNumber;
359
+ }, z.core.$strip>>;
360
+ }, z.core.$strip>>;
361
+ blinds: z.ZodOptional<z.ZodObject<{
362
+ transmittance: z.ZodNumber;
363
+ }, z.core.$strip>>;
364
+ }, z.core.$strip>>;
365
+ }, z.core.$strip>;
366
+ export type PluginDaylightComputeArgs = z.infer<typeof PluginDaylightComputeArgs>;
367
+ /**
368
+ * Arguments for {@linkcode PluginAnalysisDaylightApi.poll}.
369
+ *
370
+ * | Property | Type | Description |
371
+ * |---|---|---|
372
+ * | `runId` | `string` | The run id returned by `compute` |
373
+ * | `cursor` | `string`? | Sensor-page cursor from a previous page's `nextCursor` |
374
+ */
375
+ export declare const PluginDaylightPollArgs: z.ZodObject<{
376
+ runId: z.ZodString;
377
+ cursor: z.ZodOptional<z.ZodString>;
378
+ }, z.core.$strip>;
379
+ export type PluginDaylightPollArgs = z.infer<typeof PluginDaylightPollArgs>;
380
+ /**
381
+ * One sensor's record. Positions are world plan-space `[x, y, z]`. Metric
382
+ * fields are present when the corresponding metric was requested: the ASE
383
+ * pair for `"ASE"`, `da300Percent`/`sdaPass` for `"sDA"`.
384
+ *
385
+ * | Property | Type | Description |
386
+ * |---|---|---|
387
+ * | `sensorId` | `string` | Sensor id |
388
+ * | `position` | `[number, number, number]` | World plan-space `[x, y, z]` |
389
+ * | `spaceId` | `string` | `ComponentHandle` id of the containing space |
390
+ * | `storeyId` | `string` | Storey the sensor is on |
391
+ * | `areaWeightM2` | `number` | Floor area this sensor represents (m²) |
392
+ * | `occupiedHours` | `number` | Occupied hours per the schedule |
393
+ * | `directSunHoursAtOrAbove1000Lux` | `number`? | ASE numerator (shades ignored per LM-83); present when ASE requested |
394
+ * | `aseFail` | `boolean`? | Direct-sun hours > 250 (fails ASE); present when ASE requested |
395
+ * | `da300Percent` | `number`? | % of occupied hours at or above 300 lux, blinds operated; present when sDA requested |
396
+ * | `sdaPass` | `boolean`? | `da300Percent >= 50`; present when sDA requested |
397
+ */
398
+ export declare const PluginDaylightSensorRecord: z.ZodObject<{
399
+ sensorId: z.ZodString;
400
+ position: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
401
+ spaceId: z.ZodString;
402
+ storeyId: z.ZodString;
403
+ areaWeightM2: z.ZodNumber;
404
+ occupiedHours: z.ZodNumber;
405
+ directSunHoursAtOrAbove1000Lux: z.ZodOptional<z.ZodNumber>;
406
+ aseFail: z.ZodOptional<z.ZodBoolean>;
407
+ da300Percent: z.ZodOptional<z.ZodNumber>;
408
+ sdaPass: z.ZodOptional<z.ZodBoolean>;
409
+ }, z.core.$strip>;
410
+ export type PluginDaylightSensorRecord = z.infer<typeof PluginDaylightSensorRecord>;
411
+ /**
412
+ * Scope of a rolled-up aggregate.
413
+ *
414
+ * | Value | Meaning |
415
+ * |---|---|
416
+ * | `"project"` | Whole project (aggregate `id` is `null`) |
417
+ * | `"storey"` | One storey (`id` = storey id) |
418
+ * | `"space"` | One space (`id` = space `ComponentHandle` id) |
419
+ */
420
+ export declare const PluginDaylightAggregateScope: z.ZodEnum<{
421
+ storey: "storey";
422
+ space: "space";
423
+ project: "project";
424
+ }>;
425
+ export type PluginDaylightAggregateScope = z.infer<typeof PluginDaylightAggregateScope>;
426
+ /**
427
+ * An area-weighted rollup for a scope. Metric fields are present when the
428
+ * corresponding metric was requested.
429
+ *
430
+ * | Property | Type | Description |
431
+ * |---|---|---|
432
+ * | `scope` | {@linkcode PluginDaylightAggregateScope} | `"project"` \| `"storey"` \| `"space"` |
433
+ * | `id` | `string \| null` | Scope id; `null` for project scope |
434
+ * | `analysisAreaM2` | `number` | Analysed floor area (m²) |
435
+ * | `asePercent` | `number`? | Area-weighted % of the analysis area failing ASE; present when ASE requested |
436
+ * | `sdaPercent` | `number`? | Area-weighted % of the analysis area passing sDA300/50%; present when sDA requested |
437
+ */
438
+ export declare const PluginDaylightAggregate: z.ZodObject<{
439
+ scope: z.ZodEnum<{
440
+ storey: "storey";
441
+ space: "space";
442
+ project: "project";
443
+ }>;
444
+ id: z.ZodNullable<z.ZodString>;
445
+ analysisAreaM2: z.ZodNumber;
446
+ asePercent: z.ZodOptional<z.ZodNumber>;
447
+ sdaPercent: z.ZodOptional<z.ZodNumber>;
448
+ }, z.core.$strip>;
449
+ export type PluginDaylightAggregate = z.infer<typeof PluginDaylightAggregate>;
450
+ /**
451
+ * Full provenance echo of a daylight run — a **loose** record: the known keys
452
+ * below are typed (all optional), and any additional backend-supplied keys pass
453
+ * through unmodified. `weather` is the resolved {@linkcode PluginWeatherSourceMeta}
454
+ * (or `null`); `surfaceReflectances` maps material/family-default key →
455
+ * reflectance so callers can tell per-material values from defaults.
456
+ */
457
+ export declare const PluginDaylightProvenance: z.ZodObject<{
458
+ engine: z.ZodOptional<z.ZodString>;
459
+ engineVersion: z.ZodOptional<z.ZodString>;
460
+ standardProfile: z.ZodOptional<z.ZodString>;
461
+ thresholds: z.ZodOptional<z.ZodObject<{
462
+ aseLux: z.ZodNumber;
463
+ aseHours: z.ZodNumber;
464
+ }, z.core.$loose>>;
465
+ weather: z.ZodOptional<z.ZodNullable<z.ZodObject<{
466
+ weatherFileId: z.ZodString;
467
+ station: z.ZodString;
468
+ sourceId: z.ZodString;
469
+ distanceKm: z.ZodNullable<z.ZodNumber>;
470
+ selectionMethod: z.ZodEnum<{
471
+ "nearest-station": "nearest-station";
472
+ "user-upload": "user-upload";
473
+ "project-override": "project-override";
474
+ }>;
475
+ checksum: z.ZodString;
476
+ windReferenceHeightM: z.ZodNumber;
477
+ }, z.core.$strip>>>;
478
+ occupancySchedule: z.ZodOptional<z.ZodObject<{
479
+ id: z.ZodString;
480
+ hoursPerYear: z.ZodNumber;
481
+ }, z.core.$loose>>;
482
+ grid: z.ZodOptional<z.ZodObject<{
483
+ spacingM: z.ZodNumber;
484
+ workplaneHeightM: z.ZodNumber;
485
+ boundaryOffsetM: z.ZodNumber;
486
+ }, z.core.$strip>>;
487
+ location: z.ZodOptional<z.ZodObject<{
488
+ latitude: z.ZodNumber;
489
+ longitude: z.ZodNumber;
490
+ timezone: z.ZodString;
491
+ trueNorthDeg: z.ZodNumber;
492
+ }, z.core.$loose>>;
493
+ surfaceReflectances: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
494
+ modelRevision: z.ZodOptional<z.ZodString>;
495
+ inputHash: z.ZodOptional<z.ZodString>;
496
+ warnings: z.ZodOptional<z.ZodArray<z.ZodString>>;
497
+ excludedSpaces: z.ZodOptional<z.ZodArray<z.ZodObject<{
498
+ spaceId: z.ZodString;
499
+ reason: z.ZodString;
500
+ }, z.core.$strip>>>;
501
+ failedGeometry: z.ZodOptional<z.ZodArray<z.ZodObject<{
502
+ componentId: z.ZodString;
503
+ reason: z.ZodString;
504
+ }, z.core.$strip>>>;
505
+ }, z.core.$loose>;
506
+ export type PluginDaylightProvenance = z.infer<typeof PluginDaylightProvenance>;
507
+ /**
508
+ * Result of {@linkcode PluginAnalysisDaylightApi.compute} and
509
+ * {@linkcode PluginAnalysisDaylightApi.poll}.
510
+ *
511
+ * | Property | Type | Description |
512
+ * |---|---|---|
513
+ * | `status` | {@linkcode PluginDaylightRunStatus} | `"complete"` on synchronous (ASE-only) runs; `"running"` then `"complete"`/`"failed"` on sDA runs |
514
+ * | `runId` | `string`? | Run id for {@linkcode PluginAnalysisDaylightApi.poll}; present on asynchronous (sDA) runs |
515
+ * | `sensors` | {@linkcode PluginDaylightSensorRecord}`[]` | Per-sensor records (paged; empty while `"running"`) |
516
+ * | `aggregates` | {@linkcode PluginDaylightAggregate}`[]` | Scope rollups (all scopes, not paged; empty while `"running"`) |
517
+ * | `provenance` | {@linkcode PluginDaylightProvenance} | Full run provenance echo |
518
+ * | `nextCursor` | `string \| null` | Next sensor page cursor; `null` = last page |
519
+ */
520
+ export declare const PluginDaylightResults: z.ZodObject<{
521
+ status: z.ZodEnum<{
522
+ complete: "complete";
523
+ failed: "failed";
524
+ running: "running";
525
+ cancelled: "cancelled";
526
+ }>;
527
+ runId: z.ZodOptional<z.ZodString>;
528
+ sensors: z.ZodArray<z.ZodObject<{
529
+ sensorId: z.ZodString;
530
+ position: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
531
+ spaceId: z.ZodString;
532
+ storeyId: z.ZodString;
533
+ areaWeightM2: z.ZodNumber;
534
+ occupiedHours: z.ZodNumber;
535
+ directSunHoursAtOrAbove1000Lux: z.ZodOptional<z.ZodNumber>;
536
+ aseFail: z.ZodOptional<z.ZodBoolean>;
537
+ da300Percent: z.ZodOptional<z.ZodNumber>;
538
+ sdaPass: z.ZodOptional<z.ZodBoolean>;
539
+ }, z.core.$strip>>;
540
+ aggregates: z.ZodArray<z.ZodObject<{
541
+ scope: z.ZodEnum<{
542
+ storey: "storey";
543
+ space: "space";
544
+ project: "project";
545
+ }>;
546
+ id: z.ZodNullable<z.ZodString>;
547
+ analysisAreaM2: z.ZodNumber;
548
+ asePercent: z.ZodOptional<z.ZodNumber>;
549
+ sdaPercent: z.ZodOptional<z.ZodNumber>;
550
+ }, z.core.$strip>>;
551
+ provenance: z.ZodObject<{
552
+ engine: z.ZodOptional<z.ZodString>;
553
+ engineVersion: z.ZodOptional<z.ZodString>;
554
+ standardProfile: z.ZodOptional<z.ZodString>;
555
+ thresholds: z.ZodOptional<z.ZodObject<{
556
+ aseLux: z.ZodNumber;
557
+ aseHours: z.ZodNumber;
558
+ }, z.core.$loose>>;
559
+ weather: z.ZodOptional<z.ZodNullable<z.ZodObject<{
560
+ weatherFileId: z.ZodString;
561
+ station: z.ZodString;
562
+ sourceId: z.ZodString;
563
+ distanceKm: z.ZodNullable<z.ZodNumber>;
564
+ selectionMethod: z.ZodEnum<{
565
+ "nearest-station": "nearest-station";
566
+ "user-upload": "user-upload";
567
+ "project-override": "project-override";
568
+ }>;
569
+ checksum: z.ZodString;
570
+ windReferenceHeightM: z.ZodNumber;
571
+ }, z.core.$strip>>>;
572
+ occupancySchedule: z.ZodOptional<z.ZodObject<{
573
+ id: z.ZodString;
574
+ hoursPerYear: z.ZodNumber;
575
+ }, z.core.$loose>>;
576
+ grid: z.ZodOptional<z.ZodObject<{
577
+ spacingM: z.ZodNumber;
578
+ workplaneHeightM: z.ZodNumber;
579
+ boundaryOffsetM: z.ZodNumber;
580
+ }, z.core.$strip>>;
581
+ location: z.ZodOptional<z.ZodObject<{
582
+ latitude: z.ZodNumber;
583
+ longitude: z.ZodNumber;
584
+ timezone: z.ZodString;
585
+ trueNorthDeg: z.ZodNumber;
586
+ }, z.core.$loose>>;
587
+ surfaceReflectances: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
588
+ modelRevision: z.ZodOptional<z.ZodString>;
589
+ inputHash: z.ZodOptional<z.ZodString>;
590
+ warnings: z.ZodOptional<z.ZodArray<z.ZodString>>;
591
+ excludedSpaces: z.ZodOptional<z.ZodArray<z.ZodObject<{
592
+ spaceId: z.ZodString;
593
+ reason: z.ZodString;
594
+ }, z.core.$strip>>>;
595
+ failedGeometry: z.ZodOptional<z.ZodArray<z.ZodObject<{
596
+ componentId: z.ZodString;
597
+ reason: z.ZodString;
598
+ }, z.core.$strip>>>;
599
+ }, z.core.$loose>;
600
+ nextCursor: z.ZodNullable<z.ZodString>;
601
+ }, z.core.$strip>;
602
+ export type PluginDaylightResults = z.infer<typeof PluginDaylightResults>;
603
+ //# sourceMappingURL=daylight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daylight.d.ts","sourceRoot":"","sources":["../../../src/api/analysis/daylight.ts"],"names":[],"mappings":"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"}