@world-engines/project-host 0.1.0-alpha.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 (218) hide show
  1. package/LICENSE +46 -0
  2. package/assets/gui/WELogo-title.svg +11 -0
  3. package/assets/gui/app.js +1326 -0
  4. package/assets/gui/index.html +118 -0
  5. package/assets/gui/local-preview-asset-urls.js +61 -0
  6. package/assets/gui/local-preview-bridge.js +393 -0
  7. package/assets/gui/spatial-template-panel.js +233 -0
  8. package/assets/gui/styles.css +115 -0
  9. package/assets/gui/terrain-render.js +120 -0
  10. package/assets/gui/workspace-status.css +17 -0
  11. package/assets/gui/workspace-status.js +255 -0
  12. package/assets/gui/world-map-globe.js +187 -0
  13. package/assets/gui/world-map-worker.js +62 -0
  14. package/assets/gui/world-map.css +30 -0
  15. package/assets/gui/world-map.js +2466 -0
  16. package/dist/account-model-proxy.d.ts +21 -0
  17. package/dist/account-model-proxy.js +470 -0
  18. package/dist/authoring-browser-runtime.d.ts +7 -0
  19. package/dist/authoring-browser-runtime.js +110 -0
  20. package/dist/authoring-ingestion.d.ts +38 -0
  21. package/dist/authoring-ingestion.js +410 -0
  22. package/dist/authoring-model-connection.d.ts +166 -0
  23. package/dist/authoring-model-connection.js +757 -0
  24. package/dist/chinese-lexical.d.ts +152 -0
  25. package/dist/chinese-lexical.js +555 -0
  26. package/dist/chromium-preview-browser-driver.d.ts +43 -0
  27. package/dist/chromium-preview-browser-driver.js +575 -0
  28. package/dist/cli/download.d.ts +12 -0
  29. package/dist/cli/download.js +50 -0
  30. package/dist/cli/dump.d.ts +32 -0
  31. package/dist/cli/dump.js +91 -0
  32. package/dist/cli/ingest.d.ts +49 -0
  33. package/dist/cli/ingest.js +225 -0
  34. package/dist/cli/review.d.ts +10 -0
  35. package/dist/cli/review.js +44 -0
  36. package/dist/cli/upload.d.ts +57 -0
  37. package/dist/cli/upload.js +112 -0
  38. package/dist/cli-command.d.ts +60 -0
  39. package/dist/cli-command.js +613 -0
  40. package/dist/cli.d.ts +2 -0
  41. package/dist/cli.js +182 -0
  42. package/dist/desktop-authoring-runtime.d.ts +88 -0
  43. package/dist/desktop-authoring-runtime.js +1602 -0
  44. package/dist/desktop-sidecar.d.ts +11 -0
  45. package/dist/desktop-sidecar.js +143 -0
  46. package/dist/document-dump.d.ts +113 -0
  47. package/dist/document-dump.js +431 -0
  48. package/dist/document-graph-extractor.d.ts +125 -0
  49. package/dist/document-graph-extractor.js +588 -0
  50. package/dist/document-ingestion-journal.d.ts +68 -0
  51. package/dist/document-ingestion-journal.js +471 -0
  52. package/dist/document-ingestion.d.ts +183 -0
  53. package/dist/document-ingestion.js +976 -0
  54. package/dist/document-query-path-proof.d.ts +30 -0
  55. package/dist/document-query-path-proof.js +34 -0
  56. package/dist/document-query-path-renderer.d.ts +50 -0
  57. package/dist/document-query-path-renderer.js +75 -0
  58. package/dist/document-query-proof-paths.d.ts +22 -0
  59. package/dist/document-query-proof-paths.js +71 -0
  60. package/dist/document-query.d.ts +97 -0
  61. package/dist/document-query.js +1106 -0
  62. package/dist/document-relation-role.d.ts +14 -0
  63. package/dist/document-relation-role.js +86 -0
  64. package/dist/document-source.d.ts +107 -0
  65. package/dist/document-source.js +255 -0
  66. package/dist/embedding-cache.d.ts +35 -0
  67. package/dist/embedding-cache.js +317 -0
  68. package/dist/frozen-review-local-pipeline.d.ts +88 -0
  69. package/dist/frozen-review-local-pipeline.js +609 -0
  70. package/dist/frozen-review-source-capture.d.ts +15 -0
  71. package/dist/frozen-review-source-capture.js +551 -0
  72. package/dist/frozen-review-wasm-encryptor.d.ts +16 -0
  73. package/dist/frozen-review-wasm-encryptor.js +72 -0
  74. package/dist/frozen-review.d.ts +131 -0
  75. package/dist/frozen-review.js +802 -0
  76. package/dist/graph-traversal.d.ts +23 -0
  77. package/dist/graph-traversal.js +100 -0
  78. package/dist/gui/graph-layout-worker.js +1 -0
  79. package/dist/gui/graph-layout.wasm +0 -0
  80. package/dist/gui/graph.css +1 -0
  81. package/dist/gui/graph.js +76 -0
  82. package/dist/gui/plane-generation.js +112 -0
  83. package/dist/gui/plane-generator.js +310 -0
  84. package/dist/gui/plane-generator_bg.wasm +0 -0
  85. package/dist/gui/procedural-city.js +595 -0
  86. package/dist/gui/road-generation.js +129 -0
  87. package/dist/gui/road-parcels.js +1584 -0
  88. package/dist/gui/score.css +1 -0
  89. package/dist/gui/score.js +54 -0
  90. package/dist/gui/spatial-runtime.js +1231 -0
  91. package/dist/gui/spatial-templates.js +200 -0
  92. package/dist/gui/trigger.css +1 -0
  93. package/dist/gui/trigger.js +142 -0
  94. package/dist/harness-callback-transport.d.ts +17 -0
  95. package/dist/harness-callback-transport.js +128 -0
  96. package/dist/harness-document-ingestion.d.ts +77 -0
  97. package/dist/harness-document-ingestion.js +343 -0
  98. package/dist/index.d.ts +43 -0
  99. package/dist/index.js +43 -0
  100. package/dist/ingestion-source-reconciliation.d.ts +88 -0
  101. package/dist/ingestion-source-reconciliation.js +253 -0
  102. package/dist/ladybug-runtime.d.ts +117 -0
  103. package/dist/ladybug-runtime.js +886 -0
  104. package/dist/local-account-embedding.d.ts +34 -0
  105. package/dist/local-account-embedding.js +294 -0
  106. package/dist/local-gallery.d.ts +35 -0
  107. package/dist/local-gallery.js +227 -0
  108. package/dist/local-gui-auth.d.ts +96 -0
  109. package/dist/local-gui-auth.js +703 -0
  110. package/dist/local-gui-contract.d.ts +53 -0
  111. package/dist/local-gui-contract.js +5 -0
  112. package/dist/local-gui-image-assets.d.ts +17 -0
  113. package/dist/local-gui-image-assets.js +96 -0
  114. package/dist/local-gui-preview-client.d.ts +3 -0
  115. package/dist/local-gui-preview-client.js +111 -0
  116. package/dist/local-gui-score.d.ts +72 -0
  117. package/dist/local-gui-score.js +184 -0
  118. package/dist/local-gui-server.d.ts +10 -0
  119. package/dist/local-gui-server.js +987 -0
  120. package/dist/local-gui-version.d.ts +17 -0
  121. package/dist/local-gui-version.js +147 -0
  122. package/dist/local-gui-workspace.d.ts +14 -0
  123. package/dist/local-gui-workspace.js +171 -0
  124. package/dist/local-model-settings.d.ts +28 -0
  125. package/dist/local-model-settings.js +124 -0
  126. package/dist/local-preview-assets.d.ts +28 -0
  127. package/dist/local-preview-assets.js +124 -0
  128. package/dist/local-preview-bound-resources.d.ts +12 -0
  129. package/dist/local-preview-bound-resources.js +80 -0
  130. package/dist/local-preview-message-store.d.ts +63 -0
  131. package/dist/local-preview-message-store.js +214 -0
  132. package/dist/local-preview-player-read-models.d.ts +47 -0
  133. package/dist/local-preview-player-read-models.js +90 -0
  134. package/dist/local-preview-projections.d.ts +61 -0
  135. package/dist/local-preview-projections.js +117 -0
  136. package/dist/local-preview-runtime.d.ts +105 -0
  137. package/dist/local-preview-runtime.js +553 -0
  138. package/dist/local-preview-session.d.ts +73 -0
  139. package/dist/local-preview-session.js +395 -0
  140. package/dist/local-preview-source.d.ts +40 -0
  141. package/dist/local-preview-source.js +192 -0
  142. package/dist/local-preview-view-events.d.ts +101 -0
  143. package/dist/local-preview-view-events.js +179 -0
  144. package/dist/local-preview-view-state-sqlite.d.ts +24 -0
  145. package/dist/local-preview-view-state-sqlite.js +263 -0
  146. package/dist/local-preview-view-state.d.ts +93 -0
  147. package/dist/local-preview-view-state.js +108 -0
  148. package/dist/local-preview-vite-config.d.ts +6 -0
  149. package/dist/local-preview-vite-config.js +122 -0
  150. package/dist/local-preview-world-effects.d.ts +9 -0
  151. package/dist/local-preview-world-effects.js +55 -0
  152. package/dist/local-preview-worldline-store.d.ts +47 -0
  153. package/dist/local-preview-worldline-store.js +282 -0
  154. package/dist/local-preview-worldlines.d.ts +95 -0
  155. package/dist/local-preview-worldlines.js +136 -0
  156. package/dist/mcp-async-dispatcher.d.ts +3 -0
  157. package/dist/mcp-async-dispatcher.js +129 -0
  158. package/dist/mcp-line-queue.d.ts +14 -0
  159. package/dist/mcp-line-queue.js +184 -0
  160. package/dist/mcp-pipe-internal.d.ts +6 -0
  161. package/dist/mcp-pipe-internal.js +151 -0
  162. package/dist/mcp-pipe-response.d.ts +14 -0
  163. package/dist/mcp-pipe-response.js +50 -0
  164. package/dist/mcp-stdio-response.d.ts +12 -0
  165. package/dist/mcp-stdio-response.js +27 -0
  166. package/dist/mcp.d.ts +27 -0
  167. package/dist/mcp.js +194 -0
  168. package/dist/prepared-embedding-cache.d.ts +38 -0
  169. package/dist/prepared-embedding-cache.js +238 -0
  170. package/dist/preview-browser-adapter.d.ts +53 -0
  171. package/dist/preview-browser-adapter.js +171 -0
  172. package/dist/preview-runtime.d.ts +67 -0
  173. package/dist/preview-runtime.js +460 -0
  174. package/dist/project-auth-transport.d.ts +27 -0
  175. package/dist/project-auth-transport.js +121 -0
  176. package/dist/project-auth.d.ts +51 -0
  177. package/dist/project-auth.js +108 -0
  178. package/dist/project-git-capture-recovery.d.ts +16 -0
  179. package/dist/project-git-capture-recovery.js +347 -0
  180. package/dist/project-git-cli.d.ts +5 -0
  181. package/dist/project-git-cli.js +40 -0
  182. package/dist/project-git-scenario-source.d.ts +10 -0
  183. package/dist/project-git-scenario-source.js +240 -0
  184. package/dist/project-git-view-source.d.ts +13 -0
  185. package/dist/project-git-view-source.js +134 -0
  186. package/dist/project-git.d.ts +97 -0
  187. package/dist/project-git.js +656 -0
  188. package/dist/project-host.d.ts +59 -0
  189. package/dist/project-host.js +471 -0
  190. package/dist/project-writer-lease.d.ts +18 -0
  191. package/dist/project-writer-lease.js +430 -0
  192. package/dist/public-error.d.ts +7 -0
  193. package/dist/public-error.js +61 -0
  194. package/dist/retrieval-benchmark.d.ts +46 -0
  195. package/dist/retrieval-benchmark.js +58 -0
  196. package/dist/safe-project-path.d.ts +8 -0
  197. package/dist/safe-project-path.js +93 -0
  198. package/dist/scenario-writer.d.ts +32 -0
  199. package/dist/scenario-writer.js +191 -0
  200. package/dist/transfer/download.d.ts +159 -0
  201. package/dist/transfer/download.js +598 -0
  202. package/dist/transfer/transport.d.ts +26 -0
  203. package/dist/transfer/transport.js +1 -0
  204. package/dist/transfer/upload.d.ts +162 -0
  205. package/dist/transfer/upload.js +354 -0
  206. package/dist/transfer-types.d.ts +95 -0
  207. package/dist/transfer-types.js +1 -0
  208. package/dist/transfer.d.ts +18 -0
  209. package/dist/transfer.js +273 -0
  210. package/dist/trigger-runtime.d.ts +121 -0
  211. package/dist/trigger-runtime.js +153 -0
  212. package/dist/vendor/wasm-core/asset-hashes.json +5 -0
  213. package/dist/vendor/wasm-core/wasm_core.d.ts +490 -0
  214. package/dist/vendor/wasm-core/wasm_core.js +1 -0
  215. package/dist/vendor/wasm-core/wasm_core_bg.wasm +0 -0
  216. package/dist/view-watcher.d.ts +9 -0
  217. package/dist/view-watcher.js +34 -0
  218. package/package.json +110 -0
@@ -0,0 +1,129 @@
1
+ export const ROAD_GENERATION_PROFILE = "terrain-roads-v1";
2
+ /**
3
+ * 绑定路径搜索、桥隧门户、地形采样和地块图语义的 canonical 规则字节。
4
+ * 任一语义变更都必须更新这份 JSON 并发布新 identity。
5
+ */
6
+ export const LEGACY_V6_ROAD_GENERATION_RULES_CANONICAL = '{"algorithm":"direction-state-a-star-v2;32-coprime-neighbors;stable-heap-tie-order;route-edge-cache-v1","anchor":"city-guide-anchor-once;whole-candidate-single-connectors;no-grid-exact-grid-pair-foldback-v3","bridge":"complete-dry-portal-water-span-v1;linear-deck-3d-length-at-most-maxBridgeLengthMeters;all-water-interior;no-shortcut-or-split-v2","cityAccess":"surface-street-node-short-connect-v1;radius-over-block-times-1.5-ceil-4to12;candidate-distance-0.75to3-block;target-1.7-block;stable-city-seed-node-pair-sort;surface-only-existing-nodes;actual-sampler-direct-or-bounded-astar;complete-portal-no-acute-boundary-containment;access-unreachable-domain-v1","cityBoundary":"radial-budget-v2;world-seed-city-seed-city-id-fnv1a-xor;24to128-rays;step-at-most10m;phase-smooth-three-harmonics-radius-0.85to1.15;actual-sampler-surface-or-complete-classify-edge-portal;surface-abs-grade-integral-ds-times-1-plus-0.6-normalized-grade-over-one-minus-normalized;normalized-grade-at-least-0.995-reject;bounded-ccw-nonclosed-3to128|unbuildable-empty;city-road-continuous-points-inside-boundary;intercity-unclipped","cityField":"seeded-radial-terrain-contour-guide-v1","direction":"heading-dot-at-least-zero;interior-angle-at-least90deg;all-assembled-route-final-gate-v2","elevation":"relative-height-times-elevationScaleMeters-v1","limits":"maxGrade-roadWidthMeters-maxBridgeLengthMeters-maxTunnelLengthMeters-v1","parcelFace":"road-parcels-v4-boundary-highway;cityId-exact-arterial-local-street-surface-only;quantized-strict-xy-intersection-split;dcel-left-turn;positive-inside-concave-boundary;oriented-length-weighted-second-moment-principal-axis;canonical-longest-edge-isotropic-fallback;projection-midline-clip;area22500-recursion-depth8;inset-half-widest-road-plus-setback;triangulated-max-square-safe-bounds-v4","parcelFrontage":"face-plus-uncovered-frontage-v1;cityId-exact-arterial-local-street-surface-elementary-run;polyline-slice-16to42m;two-sided-offset;depth-clamp-blockSize-times-0.18-10to20;source-and-road-corridor-clear;face-first-frontage-positive-area-nonoverlap-stable-id-greedy-v1","parcelGraph":"road-parcels-v4-boundary-highway","parcelIdentity":"boundary-token-sorted-hash-worldSeed-citySeed-cityId;oriented-split-normal-token;frontage-side-and-ordinal;weighted-land-use;id-sort-v3","parcelTerrain":"polygon-touching-cells-dry-finite;adjacent-touching-cell-slope-at-most-settings-maxSlope;grid-at-most257-v1","portalLookahead":"complete-portal-before-partial-surface-v1;exact-dry-grid-portal-preserved-v1;off-grid-origin-requires-validated-surface-connector-v1;connector-budget-cost-required-v1","repair":"same-core-segment-splice;10m-grid;at-most8-attempts;min-margin200m-v1","roadClass":"required-kind-intercity-arterial-local;required-class-street-motorway;intercity-motorway-else-street;all-intercity-motorway-and-city-nonbuildable-roads-forbidden-corridor;centerline-no-intersection-or-containment;clearance-half-width-plus-setback-v1","shortcut":"surface-run-control-edge-boundaries;candidates-i-to-j-j-at-most-i-plus24-or-last;actual-sampler-water-grade-step-at-most10m;reverse-sparse-dag-heading-compatible-dot-epsilon1e-12;no-accumulated-cost;farthest-reachable-stable-descending;retain-original-if-no-complete-chain;whole-road-stable-branch-unreachable-if-final-acute;bridge-tunnel-excluded-v3","terrain":"canonical-plane-hydrology-fixed-sampling;global-long-axis257;city-long-axis65to257;actual-finite-sampler-step10m;no-sub10m-obstacle-guarantee-v1","tunnel":"covered-dry-portal-bore;actual-cover-at-least1m;3d-length-at-most-maxTunnelLengthMeters;no-shortcut-or-split;no-water-interior;roadWidth-surface-abutment-v2","version":6}';
7
+ /**
8
+ * 该字符串绑定 profile、算法版本与上方 canonical 规则字节的 SHA-256。
9
+ * 道路语义变化时必须发布新 identity,禁止让旧世界静默重算为不同结果。
10
+ */
11
+ export const LEGACY_V6_IDENTITY = "chat.worldengine.terrain-roads/v1;rules-sha256=9dc32e6e3f5e63fbf378d6b83dfa67c2e9d62dabfebe5b432956f7ff0fdb8443";
12
+ export const STRUCTURED_V8_ROAD_GENERATION_RULES_CANONICAL = '{"version":8,"algorithm":"direction-state-a-star-v2;32-coprime-neighbors;stable-heap-tie-order;route-edge-cache-v1","cityField":"structured-two-family-seeded-skeleton-v8;candidate-only-actual-terrain-router-required","cityCandidateBudget":"boundary-polygon-shoelace-abs-area-m2;ceil-sqrt-area-over-block-times-0.42-per-family;clamp6to15;not-nominal-radius-area;not-feasible-terrain-mask","cityCandidateFamilies":"six-arterial-rays-from-center-four-collinear-points;arterial-base-seeded-angle-plus-sixth-turn-plus-seeded-jitter;two-transverse-families-base-and-base-plus-pi-over-two-plus-seeded-0.18rad;collector-and-local;four-point-parabolic-sweeps;seeded-bend-block-times-0.32;actual-terrain-and-boundary-gates","cityBoundary":"radial-budget-v2;world-seed-city-seed-city-id-fnv1a-xor;24to128-rays;step-at-most10m;phase-smooth-three-harmonics-radius-0.85to1.15;actual-sampler-surface-or-complete-classify-edge-portal;surface-abs-grade-integral-ds-times-1-plus-0.6-normalized-grade-over-one-minus-normalized;normalized-grade-at-least-0.995-reject;bounded-ccw-nonclosed-3to128|unbuildable-empty;city-road-continuous-points-inside-boundary;intercity-unclipped","cityStructuredClip":"v8-nonarterial-all-exact-boundary-inside-runs;candidate-segment-boundary-intersections;boundary-inclusive;rooted-run-nearest-original-sweep-midpoint-else-inside-run-nearest-midpoint;arterial-uses-legacy-origin-first-exit-clip;final-route-sample-boundary-verify-at-most10m","cityStructuredRoot":"v8-transverse-same-city-surface-strict-internal-xy-intersection;parallel-collinear-endpoint-near-end-reject-epsilon1e-9;nearest-original-sweep-midpoint-then-stable-road-segment-point-pair-tie-order;root-z-actual-terrain-sample;both-old-surface-halves-revalidate-before-noding","cityRootArms":"root-left-right-independent-anchor-direct-or-bounded-astar-finish-and-boundary-check;both-concatenate|one-commit-valid-arm-and-record-other-unreachable|none-reject;assembled-root-route-no-acute-final-gate;preserve-root-xy","citySurfaceNoding":"v8-same-city-nonintercity-surface-only;strict-internal-xy-crossing-with-nonfinite-reject-and-dimensionless-interior-epsilon1e-9|positive-collinear-xy-overlap-line-distance-at-most1e-7;canonical-overlap-endpoints-xy-round-1e-7m-and-z-actual-terrain-sample;all-four-half-edges-or-local-endpoint-replacement-surface-revalidate;stable-road-segment-original-edge-index-descending-and-t-descending-insert-order;not-cross-city-bridge-tunnel-or-general-grade-separation","cityExactSurfaceReuse":"after-same-city-surface-noding-and-common-overlap-endpoint-rewrite;same-city-nonintercity-contiguous-all-surface-normalized-run-only-without-crossing-bridge-or-tunnel;undirected-exact-xyz-bit-elementary-key;arterial-then-local-then-lexical-road-id-owner;partial-overlap-reuse-removes-nonowner-exact-pieces-retains-continuous-chains;single-retained-chain-keeps-parent-id|multiple-retained-chains-child-id-parent-plus-retained-child-first-last-xy-IEEE-bits-and-reuse-purpose-no-ordinal;refresh-sorted-layout-ids;no-reuse-status-output;not-near-or-unvalidated-overlap-reuse","cityAccess":"legacy-v6-only:surface-street-node-short-connect-v1;radius-over-block-times-1.5-ceil-4to12;candidate-distance-0.75to3-block;target-1.7-block;stable-city-seed-node-pair-sort;surface-only-existing-nodes;actual-sampler-direct-or-bounded-astar;complete-portal-no-acute-boundary-containment;access-unreachable-domain-v1","parcelFace":"structured-v8-convex-closed-face-with-every-simplified-edge-matched-to-real-ordinary-street-elementary-frontage-only;per-edge-inward-half-plane-offset-before-split;clearance-max-matching-edge-half-width-plus-nonnegative-setback;mixed-width-collinear-match-uses-max-conservative-clearance;nonconvex-unmatched-or-invalid-offset-closed-face-reject-no-topology-guess","parcelSplit":"structured-v8-projection-midline-clip-area-settings-maxFaceAreaMeters-default22500-recursion-depth8;each-child-needs-longest-continuous-collinear-overlap-with-inset-real-street-frontage-at-least-max-10-min-20-widest-road;not-fragment-sum;on-failure-retain-parent-unsplit;cut-edge-is-not-frontage","parcelFrontage":"face-plus-uncovered-frontage-v1;open-area-only-real-surface-ordinary-street-segment-run;polyline-slice-min16-max42-except-unsplittable-first-edge-may-exceed42;two-sided-offset;inner-road-corridor-clearance-plus-0.01;source-run-clearance-recheck-at-least-clearance-minus0.2;depth-clamp-blockSize-times-0.18-10to20;source-and-road-corridor-clear;face-first-frontage-positive-area-nonoverlap-stable-id-greedy-v1;no-entrance-or-navigation-reachability-claim","legacyParcel":"legacy-v6-undefined-or-explicit-legacy-uses-prior-split-and-centroid-inset-path;v8-only-convex-offset-and-child-frontage-rule;shared-invalid-algorithm-fail-closed","parcelGraph":"road-parcels-v4-boundary-highway","parcelIdentity":"boundary-token-sorted-hash-worldSeed-citySeed-cityId;oriented-split-normal-token;frontage-side-and-ordinal;weighted-land-use;id-sort-v3","parcelTerrain":"polygon-touching-cells-dry-finite;adjacent-touching-cell-slope-at-most-settings-maxSlope;grid-at-most257-v1","roadClass":"required-kind-intercity-arterial-local;required-class-street-motorway;intercity-motorway-else-street;all-intercity-motorway-and-city-nonbuildable-roads-forbidden-corridor;centerline-no-intersection-or-containment;clearance-half-width-plus-setback-v1","direction":"heading-dot-at-least-zero;interior-angle-at-least90deg;all-assembled-route-final-gate-v2","limits":"maxGrade-roadWidthMeters-maxBridgeLengthMeters-maxTunnelLengthMeters-v1","elevation":"relative-height-times-elevationScaleMeters-v1","terrain":"canonical-plane-hydrology-fixed-sampling;global-long-axis257;city-long-axis65to257;actual-finite-sampler-step10m;no-sub10m-obstacle-guarantee-v1","portalLookahead":"complete-portal-before-partial-surface-v1;exact-dry-grid-portal-preserved-v1;off-grid-origin-requires-validated-surface-connector-v1;connector-budget-cost-required-v1","bridge":"complete-dry-portal-water-span-v1;linear-deck-3d-length-at-most-maxBridgeLengthMeters;all-water-interior;no-shortcut-or-split-v2","tunnel":"covered-dry-portal-bore;actual-cover-at-least1m;3d-length-at-most-maxTunnelLengthMeters;no-shortcut-or-split;no-water-interior;roadWidth-surface-abutment-v2","shortcut":"surface-run-control-edge-boundaries;candidates-i-to-j-j-at-most-i-plus24-or-last;actual-sampler-water-grade-step-at-most10m;reverse-sparse-dag-heading-compatible-dot-epsilon1e-12;no-accumulated-cost;farthest-reachable-stable-descending;retain-original-if-no-complete-chain;whole-road-stable-branch-unreachable-if-final-acute;bridge-tunnel-excluded-v3","repair":"same-core-segment-splice;10m-grid;at-most8-attempts;min-margin200m-v1"}';
13
+ export const STRUCTURED_V8_IDENTITY = "chat.worldengine.terrain-roads/v1;rules-sha256=03ab0544e8fdfc741045dccac18a946eb95b76bc10e9880012cba50060b29b4f";
14
+ export const FRONTAGE_BALANCED_V9_ROAD_GENERATION_RULES_CANONICAL = '{"version":9,"algorithm":"direction-state-a-star-v2;32-coprime-neighbors;stable-heap-tie-order;route-edge-cache-v1","cityField":"structured-two-family-seeded-skeleton-v8;candidate-only-actual-terrain-router-required","cityCandidateBudget":"boundary-polygon-shoelace-abs-area-m2;ceil-sqrt-area-over-block-times-0.42-per-family;clamp6to15;not-nominal-radius-area;not-feasible-terrain-mask","cityCandidateFamilies":"six-arterial-rays-from-center-four-collinear-points;arterial-base-seeded-angle-plus-sixth-turn-plus-seeded-jitter;two-transverse-families-base-and-base-plus-pi-over-two-plus-seeded-0.18rad;collector-and-local;four-point-parabolic-sweeps;seeded-bend-block-times-0.32;actual-terrain-and-boundary-gates","cityBoundary":"radial-budget-v2;world-seed-city-seed-city-id-fnv1a-xor;24to128-rays;step-at-most10m;phase-smooth-three-harmonics-radius-0.85to1.15;actual-sampler-surface-or-complete-classify-edge-portal;surface-abs-grade-integral-ds-times-1-plus-0.6-normalized-grade-over-one-minus-normalized;normalized-grade-at-least-0.995-reject;bounded-ccw-nonclosed-3to128|unbuildable-empty;city-road-continuous-points-inside-boundary;intercity-unclipped","cityStructuredClip":"v8-nonarterial-all-exact-boundary-inside-runs;candidate-segment-boundary-intersections;boundary-inclusive;rooted-run-nearest-original-sweep-midpoint-else-inside-run-nearest-midpoint;arterial-uses-legacy-origin-first-exit-clip;final-route-sample-boundary-verify-at-most10m","cityStructuredRoot":"v8-transverse-same-city-surface-strict-internal-xy-intersection;parallel-collinear-endpoint-near-end-reject-epsilon1e-9;nearest-original-sweep-midpoint-then-stable-road-segment-point-pair-tie-order;root-z-actual-terrain-sample;both-old-surface-halves-revalidate-before-noding","cityRootArms":"root-left-right-independent-anchor-direct-or-bounded-astar-finish-and-boundary-check;both-concatenate|one-commit-valid-arm-and-record-other-unreachable|none-reject;assembled-root-route-no-acute-final-gate;preserve-root-xy","citySurfaceNoding":"v8-same-city-nonintercity-surface-only;strict-internal-xy-crossing-with-nonfinite-reject-and-dimensionless-interior-epsilon1e-9|positive-collinear-xy-overlap-line-distance-at-most1e-7;canonical-overlap-endpoints-xy-round-1e-7m-and-z-actual-terrain-sample;all-four-half-edges-or-local-endpoint-replacement-surface-revalidate;stable-road-segment-original-edge-index-descending-and-t-descending-insert-order;not-cross-city-bridge-tunnel-or-general-grade-separation","cityExactSurfaceReuse":"after-same-city-surface-noding-and-common-overlap-endpoint-rewrite;same-city-nonintercity-contiguous-all-surface-normalized-run-only-without-crossing-bridge-or-tunnel;undirected-exact-xyz-bit-elementary-key;arterial-then-local-then-lexical-road-id-owner;partial-overlap-reuse-removes-nonowner-exact-pieces-retains-continuous-chains;single-retained-chain-keeps-parent-id|multiple-retained-chains-child-id-parent-plus-retained-child-first-last-xy-IEEE-bits-and-reuse-purpose-no-ordinal;refresh-sorted-layout-ids;no-reuse-status-output;not-near-or-unvalidated-overlap-reuse","cityAccess":"legacy-v6-only:surface-street-node-short-connect-v1;radius-over-block-times-1.5-ceil-4to12;candidate-distance-0.75to3-block;target-1.7-block;stable-city-seed-node-pair-sort;surface-only-existing-nodes;actual-sampler-direct-or-bounded-astar;complete-portal-no-acute-boundary-containment;access-unreachable-domain-v1","parcelAlgorithm":"identity-bound-v1;v6=legacy-v6-road-core-and-parcels;v8=structured-v8-road-core-and-parcels;v9=structured-v8-road-core-plus-frontage-balanced-v9-parcels;v9-vs-v8-selects-parcel-only;no-load-time-upgrade","parcelFace":"structured-v8-convex-closed-face-with-every-simplified-edge-matched-to-real-ordinary-street-elementary-frontage-only;per-edge-inward-half-plane-offset-before-split;clearance-max-matching-edge-half-width-plus-nonnegative-setback;mixed-width-collinear-match-uses-max-conservative-clearance;nonconvex-unmatched-or-invalid-offset-closed-face-reject-no-topology-guess","parcelSplit":"frontage-balanced-v9-primary-structured-v8-projection-midline-clip-area-settings-maxFaceAreaMeters-default22500;each-child-needs-longest-continuous-collinear-overlap-with-inset-real-street-frontage-at-least-max-10-min-20-widest-road;not-fragment-sum;when-primary-area-frontage-invalid-try-real-inset-frontage-overlap-cuts-length-desc-edge-id-normal-key;canonical-positive-frontage-tangent-normal;cut-overlap-midpoint-projection;dedup-normal-and-cut;first-area-frontage-valid-candidate;recursive-split-depth8;emitted-children-pass-existing-final-terrain-corridor-nonoverlap-gates;no-retry-after-final-rejection;on-all-area-frontage-failure-retain-parent-unsplit;cut-edge-is-not-frontage","parcelFrontage":"face-plus-uncovered-frontage-v1;open-area-only-real-surface-ordinary-street-segment-run;polyline-slice-min16-max42-except-unsplittable-first-edge-may-exceed42;two-sided-offset;inner-road-corridor-clearance-plus-0.01;source-run-clearance-recheck-at-least-clearance-minus0.2;depth-clamp-blockSize-times-0.18-10to20;source-and-road-corridor-clear;face-first-frontage-positive-area-nonoverlap-stable-id-greedy-v1;no-entrance-or-navigation-reachability-claim","legacyParcel":"legacy-v6-undefined-or-explicit-legacy-uses-prior-split-and-centroid-inset-path;structured-v8-uses-convex-offset-and-primary-child-frontage-rule;frontage-balanced-v9-keeps-v8-road-core-face-inset-and-primary-split-plus-stable-frontage-cut-fallback;shared-invalid-algorithm-fail-closed","parcelGraph":"road-parcels-v4-boundary-highway","parcelIdentity":"boundary-token-sorted-hash-worldSeed-citySeed-cityId;oriented-split-normal-token;frontage-side-and-ordinal;weighted-land-use;id-sort-v3","parcelTerrain":"polygon-touching-cells-dry-finite;adjacent-touching-cell-slope-at-most-settings-maxSlope;grid-at-most257-v1","roadClass":"required-kind-intercity-arterial-local;required-class-street-motorway;intercity-motorway-else-street;all-intercity-motorway-and-city-nonbuildable-roads-forbidden-corridor;centerline-no-intersection-or-containment;clearance-half-width-plus-setback-v1","direction":"heading-dot-at-least-zero;interior-angle-at-least90deg;all-assembled-route-final-gate-v2","limits":"maxGrade-roadWidthMeters-maxBridgeLengthMeters-maxTunnelLengthMeters-v1","elevation":"relative-height-times-elevationScaleMeters-v1","terrain":"canonical-plane-hydrology-fixed-sampling;global-long-axis257;city-long-axis65to257;actual-finite-sampler-step10m;no-sub10m-obstacle-guarantee-v1","portalLookahead":"complete-portal-before-partial-surface-v1;exact-dry-grid-portal-preserved-v1;off-grid-origin-requires-validated-surface-connector-v1;connector-budget-cost-required-v1","bridge":"complete-dry-portal-water-span-v1;linear-deck-3d-length-at-most-maxBridgeLengthMeters;all-water-interior;no-shortcut-or-split-v2","tunnel":"covered-dry-portal-bore;actual-cover-at-least1m;3d-length-at-most-maxTunnelLengthMeters;no-shortcut-or-split;no-water-interior;roadWidth-surface-abutment-v2","shortcut":"surface-run-control-edge-boundaries;candidates-i-to-j-j-at-most-i-plus24-or-last;actual-sampler-water-grade-step-at-most10m;reverse-sparse-dag-heading-compatible-dot-epsilon1e-12;no-accumulated-cost;farthest-reachable-stable-descending;retain-original-if-no-complete-chain;whole-road-stable-branch-unreachable-if-final-acute;bridge-tunnel-excluded-v3","repair":"same-core-segment-splice;10m-grid;at-most8-attempts;min-margin200m-v1"}';
15
+ export const FRONTAGE_BALANCED_V9_IDENTITY = "chat.worldengine.terrain-roads/v1;rules-sha256=671b01df50d378c85208f910ba10e63ff5b03d3787619898c8de60453329b38b";
16
+ export const ROAD_GENERATION_RULES_CANONICAL = '{"version":10,"algorithm":"direction-state-a-star-v2;32-coprime-neighbors;stable-heap-tie-order;route-edge-cache-v1","cityField":"structured-two-family-seeded-skeleton-v8;candidate-only-actual-terrain-router-required","cityCandidateBudget":"boundary-polygon-shoelace-abs-area-m2;ceil-sqrt-area-over-block-times-0.42-per-family;clamp6to15;not-nominal-radius-area;not-feasible-terrain-mask","cityCandidateFamilies":"six-arterial-rays-from-center-four-collinear-points;arterial-base-seeded-angle-plus-sixth-turn-plus-seeded-jitter;two-transverse-families-base-and-base-plus-pi-over-two-plus-seeded-0.18rad;collector-and-local;four-point-parabolic-sweeps;seeded-bend-block-times-0.32;actual-terrain-and-boundary-gates","cityBoundary":"radial-budget-v2;world-seed-city-seed-city-id-fnv1a-xor;24to128-rays;step-at-most10m;phase-smooth-three-harmonics-radius-0.85to1.15;actual-sampler-surface-or-complete-classify-edge-portal;surface-abs-grade-integral-ds-times-1-plus-0.6-normalized-grade-over-one-minus-normalized;normalized-grade-at-least-0.995-reject;bounded-ccw-nonclosed-3to128|unbuildable-empty;city-road-continuous-points-inside-boundary;intercity-unclipped","cityStructuredClip":"v8-nonarterial-all-exact-boundary-inside-runs;candidate-segment-boundary-intersections;boundary-inclusive;rooted-run-nearest-original-sweep-midpoint-else-inside-run-nearest-midpoint;arterial-uses-legacy-origin-first-exit-clip;final-route-sample-boundary-verify-at-most10m","cityStructuredRoot":"v8-transverse-same-city-surface-strict-internal-xy-intersection;parallel-collinear-endpoint-near-end-reject-epsilon1e-9;nearest-original-sweep-midpoint-then-stable-road-segment-point-pair-tie-order;root-z-actual-terrain-sample;both-old-surface-halves-revalidate-before-noding","cityRootArms":"root-left-right-independent-anchor-direct-or-bounded-astar-finish-and-boundary-check;both-concatenate|one-commit-valid-arm-and-record-other-unreachable|none-reject;assembled-root-route-no-acute-final-gate;preserve-root-xy","citySurfaceNoding":"v8-same-city-nonintercity-surface-only;strict-internal-xy-crossing-with-nonfinite-reject-and-dimensionless-interior-epsilon1e-9|positive-collinear-xy-overlap-line-distance-at-most1e-7;canonical-overlap-endpoints-xy-round-1e-7m-and-z-actual-terrain-sample;all-four-half-edges-or-local-endpoint-replacement-surface-revalidate;stable-road-segment-original-edge-index-descending-and-t-descending-insert-order;not-cross-city-bridge-tunnel-or-general-grade-separation","cityExactSurfaceReuse":"after-same-city-surface-noding-and-common-overlap-endpoint-rewrite;same-city-nonintercity-contiguous-all-surface-normalized-run-only-without-crossing-bridge-or-tunnel;undirected-exact-xyz-bit-elementary-key;arterial-then-local-then-lexical-road-id-owner;partial-overlap-reuse-removes-nonowner-exact-pieces-retains-continuous-chains;single-retained-chain-keeps-parent-id|multiple-retained-chains-child-id-parent-plus-retained-child-first-last-xy-IEEE-bits-and-reuse-purpose-no-ordinal;refresh-sorted-layout-ids;no-reuse-status-output;not-near-or-unvalidated-overlap-reuse","cityAccess":"legacy-v6-only:surface-street-node-short-connect-v1;radius-over-block-times-1.5-ceil-4to12;candidate-distance-0.75to3-block;target-1.7-block;stable-city-seed-node-pair-sort;surface-only-existing-nodes;actual-sampler-direct-or-bounded-astar;complete-portal-no-acute-boundary-containment;access-unreachable-domain-v1","parcelAlgorithm":"identity-bound-v1;v6=legacy-v6-road-core-and-parcels;v8=structured-v8-road-core-and-parcels;v9=structured-v8-road-core-plus-frontage-balanced-v9-parcels;v10=structured-v8-road-core-plus-shape-filled-v10-parcels;v10-vs-v9-selects-parcel-only;no-load-time-upgrade","parcelFace":"shape-filled-v10-simple-single-ring-closed-face;real-ordinary-street-elementary-frontage-only;collinear-ring-simplify;per-edge-inward-offset-max-matching-real-road-half-width-plus-nonnegative-setback-plus-4epsilon-quantization-guard;inset-must-stay-within-source-and-strict-road-clearance;self-cross-reject;concave-ear-clip-then-stable-convex-merge;internal-chords-have-no-offset-and-no-frontage;unsupported-complex-or-hole-face-reject-no-topology-guess","parcelSplit":"shape-filled-v10-long-axis-oriented-bounds-primary-then-stable-face-axis;projection-midline-clip-targets-settings-maxFaceAreaMeters-default22500-not-terminal-hard-limit;shape-context-cut-children-inset-by-4epsilon-per-side-leaving-8epsilon-artificial-nonroad-gap-to-prevent-quantized-shared-edge-positive-overlap;no-distance-or-overlap-gate-relaxation;both-children-area-at-least-settings-minParcelAreaMeters-default36;each-child-needs-longest-continuous-real-inset-street-frontage-at-least-max-10-min-20-widest-road;shape-node-and-recursive-output-hard-gates;pair-atomic-no-single-child-commit;frontage-balanced-real-inset-frontage-cut-fallback;recursive-depth8;at-depth-or-no-valid-cut-shape-valid-parent-may-remain-even-over-max-area;at-depth-or-no-valid-cut-invalid-shape-reject;cut-edge-is-not-frontage","parcelFrontage":"shape-filled-v10-face-first-then-uncovered-frontage-only;closed-valid-inset-faces-fill-before-open-street;real-surface-ordinary-street-run-resampled-at-at-most-min-10-maxSliceLength;two-sided-offset;depth-at-least-blockSize-times-0.18-and-at-least-minShortSide-times-sqrt2-plus1;maxSliceLength-max-requiredStripDimension-plus10-only-when-requiredStripDimension-over42-and-min-42-maxAspectRatio-times-depth-so-minShortSide-override-remains-sliceable;slice-at-least-minShortSide-times-sqrt2-plus1;shape-safe-bounds-and-ratio-hard-gates;source-and-all-road-corridor-boundary-terrain-clear;positive-area-nonoverlap-stable-id-greedy;no-entrance-or-navigation-reachability-claim","legacyParcel":"legacy-v6-undefined-or-explicit-legacy-uses-prior-split-and-centroid-inset-path;structured-v8-uses-convex-offset-and-primary-child-frontage-rule;frontage-balanced-v9-keeps-v8-road-core-face-inset-and-primary-split-plus-stable-frontage-cut-fallback;shape-filled-v10-keeps-v8-road-core-and-uses-simple-ring-inset-concave-decomposition-shape-hard-gates-and-uncovered-frontage-only;shared-invalid-algorithm-fail-closed","parcelGraph":"road-parcels-v4-boundary-highway","parcelIdentity":"boundary-token-sorted-hash-worldSeed-citySeed-cityId;oriented-split-normal-token;frontage-side-and-ordinal;weighted-land-use;id-sort-v3;shape-filled-v10-canonical-ring-ear-clip-first-valid-vertex-order-then-first-pair-convex-merge-loop;decomposed-piece-traversal-order-is-explicit-root-c-pieceIndex-and-affects-stable-id","parcelTerrain":"polygon-touching-cells-dry-finite;adjacent-touching-cell-slope-at-most-settings-maxSlope;grid-at-most257-v1","roadClass":"required-kind-intercity-arterial-local;required-class-street-motorway;intercity-motorway-else-street;all-intercity-motorway-and-city-nonbuildable-roads-forbidden-corridor;centerline-no-intersection-or-containment;clearance-half-width-plus-setback-v1","direction":"heading-dot-at-least-zero;interior-angle-at-least90deg;all-assembled-route-final-gate-v2","limits":"maxGrade-roadWidthMeters-maxBridgeLengthMeters-maxTunnelLengthMeters-v1","elevation":"relative-height-times-elevationScaleMeters-v1","terrain":"canonical-plane-hydrology-fixed-sampling;global-long-axis257;city-long-axis65to257;actual-finite-sampler-step10m;no-sub10m-obstacle-guarantee-v1","portalLookahead":"complete-portal-before-partial-surface-v1;exact-dry-grid-portal-preserved-v1;off-grid-origin-requires-validated-surface-connector-v1;connector-budget-cost-required-v1","bridge":"complete-dry-portal-water-span-v1;linear-deck-3d-length-at-most-maxBridgeLengthMeters;all-water-interior;no-shortcut-or-split-v2","tunnel":"covered-dry-portal-bore;actual-cover-at-least1m;3d-length-at-most-maxTunnelLengthMeters;no-shortcut-or-split;no-water-interior;roadWidth-surface-abutment-v2","shortcut":"surface-run-control-edge-boundaries;candidates-i-to-j-j-at-most-i-plus24-or-last;actual-sampler-water-grade-step-at-most10m;reverse-sparse-dag-heading-compatible-dot-epsilon1e-12;no-accumulated-cost;farthest-reachable-stable-descending;retain-original-if-no-complete-chain;whole-road-stable-branch-unreachable-if-final-acute;bridge-tunnel-excluded-v3","repair":"same-core-segment-splice;10m-grid;at-most8-attempts;min-margin200m-v1","parcelShape":"coordinates-round-decimal6-epsilon1e-6;minimum-oriented-convex-hull-edge-aligned-bounds;settings-maxAspectRatio-finite-at-least1-default4;settings-minShortSideMeters-finite-at-least26-default26;short-side-at-least-minShortSideMeters;long-side-at-most-short-side-times-maxAspectRatio;safe-axis-aligned-square-inside-polygon-width-and-height-at-least-minShortSideMeters;all-partition-nodes-and-emitted-parcels-terrain-boundary-corridor-clear"}';
17
+ export const ROAD_GENERATION_IDENTITY = "chat.worldengine.terrain-roads/v1;rules-sha256=58fc51cfe9986a8da0cc6931c8600cf4c1afbbcda80f58e00038b76f982aec5b";
18
+ /**
19
+ * 已发布 identity 的精确 allowlist。新算法必须先有冻结的 rules digest,才能加入这里;
20
+ * 不得以“当前默认值”替换已保存 source 的 identity。
21
+ */
22
+ export const SUPPORTED_ROAD_GENERATION_IDENTITIES = Object.freeze([
23
+ LEGACY_V6_IDENTITY,
24
+ STRUCTURED_V8_IDENTITY,
25
+ FRONTAGE_BALANCED_V9_IDENTITY,
26
+ ROAD_GENERATION_IDENTITY,
27
+ ]);
28
+ export function roadGenerationAlgorithm(identity) {
29
+ switch (identity) {
30
+ case LEGACY_V6_IDENTITY:
31
+ return "legacy-v6";
32
+ case STRUCTURED_V8_IDENTITY:
33
+ case FRONTAGE_BALANCED_V9_IDENTITY:
34
+ case ROAD_GENERATION_IDENTITY:
35
+ return "structured-v8";
36
+ }
37
+ }
38
+ /** 已保存 identity 独立选择 parcel 语义;V9 仍复用已发布 V8 道路 core。 */
39
+ export function roadParcelAlgorithm(identity) {
40
+ switch (identity) {
41
+ case LEGACY_V6_IDENTITY:
42
+ return "legacy-v6";
43
+ case STRUCTURED_V8_IDENTITY:
44
+ return "structured-v8";
45
+ case FRONTAGE_BALANCED_V9_IDENTITY:
46
+ return "frontage-balanced-v9";
47
+ case ROAD_GENERATION_IDENTITY:
48
+ return "shape-filled-v10";
49
+ }
50
+ }
51
+ /**
52
+ * 只有已冻结的后继 identity 才能令旧 source 出现显式升级预览入口。
53
+ * 加载或保存绝不能据此静默升级。
54
+ */
55
+ export function roadGenerationUpgradeTarget(identity) {
56
+ return identity === LEGACY_V6_IDENTITY
57
+ || identity === STRUCTURED_V8_IDENTITY
58
+ || identity === FRONTAGE_BALANCED_V9_IDENTITY
59
+ ? ROAD_GENERATION_IDENTITY
60
+ : undefined;
61
+ }
62
+ export const DEFAULT_ROAD_GENERATION = Object.freeze({
63
+ profile: ROAD_GENERATION_PROFILE,
64
+ identity: ROAD_GENERATION_IDENTITY,
65
+ allowBridges: true,
66
+ allowTunnels: false,
67
+ maxBridgeLengthMeters: 300,
68
+ maxTunnelLengthMeters: 1_000,
69
+ maxGrade: 0.15,
70
+ roadWidthMeters: 8,
71
+ elevationScaleMeters: 3_000,
72
+ });
73
+ const ROAD_GENERATION_KEYS = new Set([
74
+ "profile",
75
+ "identity",
76
+ "allowBridges",
77
+ "allowTunnels",
78
+ "maxBridgeLengthMeters",
79
+ "maxTunnelLengthMeters",
80
+ "maxGrade",
81
+ "roadWidthMeters",
82
+ "elevationScaleMeters",
83
+ ]);
84
+ function isRecord(value) {
85
+ return typeof value === "object" && value !== null && !Array.isArray(value);
86
+ }
87
+ function boundedNumber(value, field, minimum, maximum) {
88
+ if (typeof value !== "number" || !Number.isFinite(value))
89
+ throw new TypeError(`${field} 必须是有限数`);
90
+ if (value < minimum || value > maximum)
91
+ throw new RangeError(`${field} 必须位于 ${minimum}..${maximum}`);
92
+ return value;
93
+ }
94
+ function boolean(value, field) {
95
+ if (typeof value !== "boolean")
96
+ throw new TypeError(`${field} 必须是 boolean`);
97
+ return value;
98
+ }
99
+ function supportedIdentity(value) {
100
+ if (typeof value !== "string" || !SUPPORTED_ROAD_GENERATION_IDENTITIES.includes(value)) {
101
+ throw new TypeError(`identity 必须为 ${SUPPORTED_ROAD_GENERATION_IDENTITIES.join(" 或 ")}`);
102
+ }
103
+ return value;
104
+ }
105
+ /** 严格验证桥隧道路设置,拒绝未知字段并返回不可变 canonical 副本。 */
106
+ export function validateRoadGeneration(input) {
107
+ if (!isRecord(input))
108
+ throw new TypeError("RoadGenerationV1 必须是对象");
109
+ const unknown = Object.keys(input).filter((key) => !ROAD_GENERATION_KEYS.has(key));
110
+ if (unknown.length > 0)
111
+ throw new TypeError(`RoadGenerationV1 包含未知字段:${unknown.join(", ")}`);
112
+ const missing = [...ROAD_GENERATION_KEYS].filter((key) => !Object.hasOwn(input, key));
113
+ if (missing.length > 0)
114
+ throw new TypeError(`RoadGenerationV1 缺少字段:${missing.join(", ")}`);
115
+ if (input.profile !== ROAD_GENERATION_PROFILE)
116
+ throw new TypeError(`profile 必须为 ${ROAD_GENERATION_PROFILE}`);
117
+ const identity = supportedIdentity(input.identity);
118
+ return Object.freeze({
119
+ profile: ROAD_GENERATION_PROFILE,
120
+ identity,
121
+ allowBridges: boolean(input.allowBridges, "allowBridges"),
122
+ allowTunnels: boolean(input.allowTunnels, "allowTunnels"),
123
+ maxBridgeLengthMeters: boundedNumber(input.maxBridgeLengthMeters, "maxBridgeLengthMeters", 1, 1_000_000),
124
+ maxTunnelLengthMeters: boundedNumber(input.maxTunnelLengthMeters, "maxTunnelLengthMeters", 1, 1_000_000),
125
+ maxGrade: boundedNumber(input.maxGrade, "maxGrade", 0.01, 1),
126
+ roadWidthMeters: boundedNumber(input.roadWidthMeters, "roadWidthMeters", 3, 40),
127
+ elevationScaleMeters: boundedNumber(input.elevationScaleMeters, "elevationScaleMeters", 1, 100_000),
128
+ });
129
+ }