@thatopen/services 0.5.0 → 0.7.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 (72) hide show
  1. package/README.md +62 -62
  2. package/dist/built-in/index.d.ts +569 -0
  3. package/dist/cli.js +12 -23
  4. package/dist/index.cjs.js +2 -2
  5. package/dist/index.es.js +41 -49
  6. package/dist/vite-env.d.ts +1 -1
  7. package/docs/ai-quickstart.md +37 -0
  8. package/docs/builtin/paths.json +4 -0
  9. package/docs/cli/create.md +29 -29
  10. package/docs/cli/local-server.md +38 -38
  11. package/docs/cli/login.md +32 -32
  12. package/docs/cli/publish.md +31 -31
  13. package/docs/cli/run.md +26 -26
  14. package/docs/cli/serve.md +43 -43
  15. package/docs/cli/swap.md +30 -30
  16. package/docs/flow-architecture.md +389 -0
  17. package/docs/flow-plugin-guide.md +337 -0
  18. package/docs/platform-token.md +81 -0
  19. package/docs/revit-collab-quickstart.md +363 -173
  20. package/docs/rhino-interop-quickstart.md +391 -0
  21. package/package.json +1 -1
  22. package/resources/AGENTS.md +40 -40
  23. package/src/built-in/CDEManager/example.ts +214 -214
  24. package/src/built-in/CDEManager/examples/FileEditing/example.ts +226 -226
  25. package/src/built-in/CDEManager/examples/FileMoves/example.ts +186 -186
  26. package/src/built-in/CDEManager/examples/FileOperations/example.ts +295 -295
  27. package/src/built-in/CDEManager/examples/FileTransfers/example.ts +210 -210
  28. package/src/built-in/CDEManager/examples/FolderManagement/example.ts +230 -230
  29. package/src/built-in/CDEManager/examples/MetadataSchema/example.ts +230 -230
  30. package/src/built-in/CDEManager/examples/MetadataViews/example.ts +166 -166
  31. package/src/built-in/CDEManager/examples/ProjectConfig/example.ts +177 -177
  32. package/src/built-in/UIManager/src/app/example.ts +97 -97
  33. package/src/built-in/UIManager/src/app/examples/AppState/example.ts +140 -140
  34. package/src/built-in/UIManager/src/app/examples/Banner/example.ts +159 -159
  35. package/src/built-in/UIManager/src/app/examples/Contexts/example.ts +123 -123
  36. package/src/built-in/UIManager/src/app/examples/FileDrop/example.ts +124 -124
  37. package/src/built-in/UIManager/src/app/examples/FloatingLayout/example.ts +90 -90
  38. package/src/built-in/UIManager/src/app/examples/Modal/example.ts +163 -163
  39. package/src/built-in/UIManager/src/app/examples/Notifications/example.ts +133 -133
  40. package/src/built-in/UIManager/src/app/examples/ProjectFileStorage/example.ts +150 -150
  41. package/src/built-in/UIManager/src/app/examples/Sidebar/example.ts +102 -102
  42. package/src/built-in/UIManager/src/clashes-panel/example.ts +183 -183
  43. package/src/built-in/UIManager/src/git-history-panel/example.ts +70 -0
  44. package/src/built-in/UIManager/src/models-list/example.ts +122 -122
  45. package/src/built-in/UIManager/src/topics-panel/example.ts +170 -170
  46. package/src/built-in/index.ts +570 -0
  47. package/src/cli/templates/app/index.html +35 -35
  48. package/src/cli/templates/app/package.json +32 -32
  49. package/src/cli/templates/app/src/bim-components/CloudRunner/index.ts +95 -95
  50. package/src/cli/templates/app/src/bim-components/CloudRunner/src/index.ts +1 -1
  51. package/src/cli/templates/app/src/bim-components/CloudRunner/src/types.ts +5 -5
  52. package/src/cli/templates/app/src/bim-components/index.ts +1 -1
  53. package/src/cli/templates/app/src/globals.ts +1 -1
  54. package/src/cli/templates/app/src/ui-components/app-info-section/index.ts +26 -26
  55. package/src/cli/templates/app/src/ui-components/app-info-section/src/index.ts +1 -1
  56. package/src/cli/templates/app/src/ui-components/app-info-section/src/types.ts +15 -15
  57. package/src/cli/templates/app/src/ui-components/cloud-runner-section/index.ts +37 -37
  58. package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/index.ts +1 -1
  59. package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/types.ts +14 -14
  60. package/src/cli/templates/app/src/ui-components/index.ts +2 -2
  61. package/src/cli/templates/app/tsconfig.json +16 -16
  62. package/src/cli/templates/app/vite.config.js +57 -57
  63. package/src/cli/templates/cloud-component/README.md +205 -205
  64. package/src/cli/templates/cloud-component/_thatopen +5 -5
  65. package/src/cli/templates/cloud-component/declarations.json +4 -4
  66. package/src/cli/templates/cloud-component/package.json +21 -21
  67. package/src/cli/templates/cloud-component/src/main.ts +70 -70
  68. package/src/cli/templates/cloud-component/tsconfig.json +16 -16
  69. package/src/cli/templates/cloud-component/vite.config.js +46 -46
  70. package/src/cli/templates/shared/AGENTS.md +8 -8
  71. package/src/cli/templates/shared/CLAUDE.md +1 -1
  72. package/src/cli/templates/shared/_gitignore +5 -5
@@ -941,6 +941,575 @@ export type FileList = InstanceType<typeof _FileList>;
941
941
  export declare const FileList: typeof _FileList & {
942
942
  uuid: "b0b5e2a2-0b3a-4a6b-8b1c-0b1c4a6b8b1c";
943
943
  };
944
+ /** One element mutation inside a revit-flow commit. */
945
+ export interface RevitFlowChange {
946
+ /** create → element added, update → geometry/data changed, delete → removed. */
947
+ type: "create" | "update" | "delete" | string;
948
+ /** Revit UniqueId (GUID). Resolves to a fragments localId via getLocalIdsByGuids. */
949
+ uniqueId: string;
950
+ }
951
+ /** Per-commit change tallies, mirrored from the add-in's `counts` block. */
952
+ export interface RevitFlowCounts {
953
+ added: number;
954
+ modified: number;
955
+ removed: number;
956
+ }
957
+ /**
958
+ * A revit-flow commit — one push of changes from the Revit add-in. `id` is a
959
+ * monotonic integer; `parent` points at the previous commit (null for the
960
+ * root). The first commit is the baseline: its geometry IS the visible model
961
+ * file. Later commits carry only their delta geometry, in a HIDDEN .frag whose
962
+ * id is `deltaId`.
963
+ */
964
+ export interface RevitFlowCommit {
965
+ /**
966
+ * WHAT this commit is. Identity, minted by whoever wrote it, meaningful outside the model it
967
+ * belongs to — which the old integer was not: that was the platform's storage version, a number
968
+ * the CDE handed out. An application that does not push through a Revit central has no such
969
+ * number, and an integer sequence asserts one line of history, which Revit's central enforces and
970
+ * nothing else has to.
971
+ */
972
+ guid: string;
973
+ /**
974
+ * The commits this one was built on. Absent on a root.
975
+ *
976
+ * A LIST, because a history that can only ever be a line is a different thing from a graph. A
977
+ * fork was already expressible with a single parent — two commits naming the same one — but a
978
+ * MERGE means naming both lines, and that needs this. The first entry is the line the commit
979
+ * continues, which is what lets the panel lay out lanes without guessing which side is the trunk.
980
+ *
981
+ * Revit never writes more than one: its central IS a single line and it merges inside itself
982
+ * rather than in this graph. The list is for the applications that are not Revit.
983
+ */
984
+ parents?: string[] | null;
985
+ /**
986
+ * WHERE this landed in the CDE, when there is such a place. Data, never identity, and never shown
987
+ * as the commit's name. Absent for any application with no version counter.
988
+ */
989
+ version?: number;
990
+ /**
991
+ * Position in this model's history, computed from the parent chain when the commits are read.
992
+ *
993
+ * Order questions — "is this commit before the one on screen?" — used to be asked of the integer
994
+ * id, which meant every application had to produce a sequence to be understood. They are asked of
995
+ * this instead: derived from the graph, so an application that has no numbers still answers them.
996
+ */
997
+ ordinal: number;
998
+ /**
999
+ * What the author said this commit was for, in their own words. Absent when nobody said
1000
+ * anything, which is most commits.
1001
+ *
1002
+ * In Revit it comes from the Comment box in its own Synchronize with Central dialog, which
1003
+ * people have been typing into for years while it went nowhere. Free text: never parsed, never
1004
+ * relied on for structure.
1005
+ */
1006
+ message?: string;
1007
+ author: string;
1008
+ source: string;
1009
+ timestamp: string;
1010
+ changes: RevitFlowChange[];
1011
+ counts: RevitFlowCounts;
1012
+ /**
1013
+ * Hidden-file id of this commit's delta .frag (created+modified geometry).
1014
+ * Absent on the baseline/first commit and on geometry-less commits. The
1015
+ * platform's hidden-file API has no queryable name, so the delta is loaded by
1016
+ * this id, never by filename.
1017
+ */
1018
+ deltaId?: string;
1019
+ /**
1020
+ * Platform user id of the committer, recorded by the add-in from its API key. Lets the
1021
+ * UI resolve the author to a real project member (avatar + name) via getProjectData,
1022
+ * instead of deriving initials from the raw Revit username. Absent on history written
1023
+ * before this was recorded, or when the key isn't a readable JWT.
1024
+ */
1025
+ userId?: string;
1026
+ /**
1027
+ * Which loaded model this commit belongs to (the model file's id == the viewer's
1028
+ * modelId). Tagged in by the manager when it reads the history: commit ids are
1029
+ * per-model version numbers, so they repeat across models and can't identify a commit
1030
+ * on their own.
1031
+ */
1032
+ modelId?: string;
1033
+ /** The model's name AS SHOWN IN PROJECT FILES, for the cards and the model filter. */
1034
+ modelName?: string;
1035
+ /**
1036
+ * This commit re-exported the WHOLE model, so the project's visible .frag shows the
1037
+ * model as of here — what anyone opening it from Project Files gets, without the
1038
+ * history panel. True for the initial capture and for the periodic full exports the
1039
+ * team publishes; ordinary commits ship only their delta.
1040
+ */
1041
+ full?: boolean;
1042
+ /**
1043
+ * Interoperability operations this commit materialised. Present only when somebody in
1044
+ * Revit pulled a deferred edit: the commit is the native half of it, and this is the
1045
+ * link back to the operation that asked for it. Ordinary hand-authored commits, which
1046
+ * are nearly all of them, carry no such key at all.
1047
+ */
1048
+ appliedOps?: string[];
1049
+ /**
1050
+ * Set when this entry is NOT a commit but a deferred edit still waiting to be applied.
1051
+ *
1052
+ * Pending operations are surfaced commit-SHAPED rather than as a parallel kind of thing, so
1053
+ * they inherit search, the user and model filters, the change-kind chips and the
1054
+ * filter-by-selection behaviour instead of needing all of it reimplemented. It also means
1055
+ * one of them can be clicked and previewed: a `modify` or `delete` names elements that
1056
+ * already exist, which is exactly what the outline machinery consumes, so you can see what
1057
+ * a change will touch before anybody applies it. A `create` has nothing to show yet, which
1058
+ * is honest rather than missing.
1059
+ *
1060
+ * Everything that treats an entry as history must check this first: it has not happened.
1061
+ */
1062
+ pendingOp?: RevitFlowOp;
1063
+ }
1064
+ /** Shape of `revitflow_history.json`. */
1065
+ export interface RevitFlowHistory {
1066
+ model: string;
1067
+ commits: RevitFlowCommit[];
1068
+ }
1069
+ /**
1070
+ * One deferred edit waiting to be applied to a model.
1071
+ *
1072
+ * Operations are NOT commits and do not live in the graph: a commit is immutable past, an
1073
+ * operation is optional future. They sit above the model's HEAD until somebody opens the
1074
+ * model in Revit and applies one, at which point they become a commit and stop being
1075
+ * pending. Mirrors the add-in's `revitflow_ops.json`.
1076
+ */
1077
+ export interface RevitFlowOp {
1078
+ opId: string;
1079
+ /** Groups the operations one authored action produced across several models. */
1080
+ batchId?: string;
1081
+ /** Hidden-file id of the operation's .frag payload. */
1082
+ fragId?: string;
1083
+ title?: string;
1084
+ /** add | set | remove | mixed. Older queues say modify | create | delete. */
1085
+ verb?: string;
1086
+ author?: string;
1087
+ /**
1088
+ * Platform user id of whoever authored it. Resolved to a real project member exactly as a
1089
+ * commit's is, so the same person does not appear as "Antonio That Open" on their commits
1090
+ * and as their raw OS username on their operations.
1091
+ */
1092
+ userId?: string;
1093
+ createdAt?: string;
1094
+ /** The commit this operation was authored against. */
1095
+ /** The commit this was authored against, by guid. What a proposal actually refers to. */
1096
+ baseCommitGuid?: string;
1097
+ /** The platform version that commit landed in. Data, for reconciling with the CDE. */
1098
+ baseCommit?: number;
1099
+ /** How many elements it targets. */
1100
+ targets?: number;
1101
+ state?: "pending" | "applied" | "discarded" | string;
1102
+ /** The native commit that materialised it, once applied. */
1103
+ appliedInCommit?: number | null;
1104
+ /**
1105
+ * Native ids the operation actually touched or created, written by the add-in when it applied.
1106
+ * A FLAT list: it does not say which source object produced which result, because nothing in
1107
+ * this system ties an element to an element in another application.
1108
+ *
1109
+ * It is what lets an APPLIED proposal be selected and previewed like a commit, with no payload
1110
+ * fetch at all. Note which halves that leaves blind, because they are opposite ends:
1111
+ *
1112
+ * add pending → nothing exists yet · applied → these are what it made
1113
+ * set pending → its targets · applied → the same targets
1114
+ * remove pending → its targets · applied → nothing, they are gone
1115
+ *
1116
+ * So the only case still needing the payload is a PENDING set or remove, whose target ids live
1117
+ * in the operation's .frag rather than in this index.
1118
+ */
1119
+ affectedIds?: string[];
1120
+ /** Tagged in by the manager, exactly as commits are: which model this queue belongs to. */
1121
+ modelId?: string;
1122
+ modelName?: string;
1123
+ }
1124
+ /** Shape of `revitflow_ops.json`. */
1125
+ export interface RevitFlowOpsIndex {
1126
+ schema?: string;
1127
+ ops: RevitFlowOp[];
1128
+ }
1129
+ /** Dominant change type of a commit, used to color its timeline node. */
1130
+ export type DominantChange = "create" | "update" | "delete";
1131
+ /** What to do with elements outside the selected commit. */
1132
+ export type ContextMode = "default" | "hidden";
1133
+ /** The three kinds of change a commit can carry. */
1134
+ export type ChangeKind = "create" | "update" | "delete";
1135
+ /**
1136
+ * Stable id for a commit across models — which is now just its guid.
1137
+ *
1138
+ * It used to have to be `${model}:${id}`, because the id was a per-model version number and every
1139
+ * model had a commit 3. A guid needs no help being unique, and that is exactly what it was for.
1140
+ */
1141
+ export declare const commitKey: (c: {
1142
+ guid?: string;
1143
+ pendingOp?: {
1144
+ opId: string;
1145
+ };
1146
+ }) => string;
1147
+ /** How the commit is shown in 3D: review colours, or the model as it ended up. */
1148
+ export type HighlightMode = "colored" | "plain";
1149
+ /** Dominant change type of a commit: delete → create → update. */
1150
+ export declare function dominantChange(commit: RevitFlowCommit): DominantChange;
1151
+ /**
1152
+ * GitHistoryManager — headless engine for the revit-flow git-history built-in.
1153
+ *
1154
+ * Owns ALL viewer mutation for the change outlines. It does NOT load the model —
1155
+ * the user opens a model from the Project Files panel, and this manager reacts to
1156
+ * that load: it reads the model's hidden `revitflow_history.json` (if any) and
1157
+ * publishes the commit list. Showing a commit outlines its changed elements
1158
+ * (create → green, update → blue, delete → red) via three independently-colored
1159
+ * `OBF.Outliner` groups — a cheap post-process outline that never recolors the
1160
+ * fragment geometry. The Lit panel (`top-git-history`) is intent-only: it calls
1161
+ * these methods and subscribes to the events below.
1162
+ *
1163
+ * Data model, per loaded model (fileId == modelId), all HIDDEN children of it:
1164
+ * - revitflow_history.json — { model, commits: [{ id, parent, author, source,
1165
+ * timestamp, changes:[{type,uniqueId}], counts }] }. The first commit is the
1166
+ * INITIAL full-model capture (its geometry == the visible baseline file).
1167
+ * - revitflow_frag_<N>.frag — delta fragments for commit N (its created+modified
1168
+ * geometry), loaded on demand so created elements can be colored.
1169
+ */
1170
+ declare class _GitHistoryManager extends OBC.Component {
1171
+ static readonly uuid: "3f9c1a7e-6b2d-4e18-9a5c-7d0e2f4b6c81";
1172
+ enabled: boolean;
1173
+ readonly onCommitsChanged: OBC.Event<RevitFlowCommit[]>;
1174
+ /** {@link commitKey} of the highlighted commit, or null when cleared. */
1175
+ readonly onCommitChanged: OBC.Event<string | null>;
1176
+ readonly onLoadingChanged: OBC.Event<boolean>;
1177
+ readonly onError: OBC.Event<string>;
1178
+ /** The GUID currently selected in the 3D view (null when the selection is cleared). */
1179
+ readonly onSelectedGuidChanged: OBC.Event<string | null>;
1180
+ world?: OBC.World;
1181
+ /**
1182
+ * What happens to elements that are NOT part of the selected commit:
1183
+ * "default" — left as they are (the change outlines sit on the full model)
1184
+ * "hidden" — hidden entirely, isolating the commit's elements
1185
+ *
1186
+ * A dimmed ("ghost") middle ground was dropped: the fragments x-ray writes depth
1187
+ * from the pixels its screen door keeps, so dimmed geometry still occluded the very
1188
+ * elements under review — worse the denser the model in front. Fixing that properly
1189
+ * belongs in the renderer, not here, so this offers the two states that are exact.
1190
+ */
1191
+ contextMode: ContextMode;
1192
+ /**
1193
+ * Which change kinds to outline. All three by default; the panel's filter buttons
1194
+ * narrow it (e.g. only deletions) without reloading anything.
1195
+ */
1196
+ typeFilter: Set<ChangeKind>;
1197
+ /**
1198
+ * How many commits either side of the selected one to keep pre-loaded, so stepping
1199
+ * through the timeline is instant instead of fetching on every click. The window
1200
+ * slides with the selection and everything outside it is disposed, which bounds
1201
+ * memory no matter how long the history gets.
1202
+ */
1203
+ prefetchRadius: number;
1204
+ /**
1205
+ * How a commit is presented in 3D:
1206
+ * "colored" — outline created/edited/deleted in their colours (the review lens)
1207
+ * "plain" — no outlines: the model simply as it stood AFTER the commit, so the
1208
+ * deleted elements are hidden rather than painted red
1209
+ */
1210
+ highlightMode: HighlightMode;
1211
+ /** @deprecated kept so older callers still compile — maps onto contextMode. */
1212
+ get isolateChanges(): boolean;
1213
+ /** Green — created elements. */
1214
+ readonly COLOR_CREATED = "#22c55e";
1215
+ /** Golden yellow — modified elements. */
1216
+ readonly COLOR_MODIFIED = "#e3b341";
1217
+ /** Red — deleted elements. */
1218
+ readonly COLOR_DELETED = "#ef4444";
1219
+ readonly GROUP_CREATED = "revitflow-created";
1220
+ readonly GROUP_MODIFIED = "revitflow-modified";
1221
+ readonly GROUP_DELETED = "revitflow-deleted";
1222
+ private _client?;
1223
+ private _projectId?;
1224
+ /**
1225
+ * One entry per loaded revit-flow model. Commit ids are per-model version numbers, so
1226
+ * they collide across models — every commit is tagged with its modelId and a commit is
1227
+ * addressed by {@link commitKey}, never by id alone.
1228
+ */
1229
+ private _models;
1230
+ /** Which models the timeline shows. Empty = all of them. */
1231
+ private _selectedModels;
1232
+ /** `${modelId}:${id}` of the commit currently highlighted, or null. */
1233
+ private _currentKey;
1234
+ /** modelIds already probed for a sibling history (avoids re-probing). */
1235
+ private _probed;
1236
+ /** hiddenIds of delta frags this manager has loaded into the viewer. */
1237
+ private _loadedDeltas;
1238
+ /** Ghosted localIds per modelId, so isolate can be cleared/re-applied. */
1239
+ private _contextApplied;
1240
+ /** localIds hidden because the shown commit deleted them (plain mode). */
1241
+ private _hiddenDeleted;
1242
+ /** localIds hidden because a newer visible source supplies the same element. */
1243
+ private _hiddenSuperseded;
1244
+ /** True once the three named Outliner groups have been created. */
1245
+ private _groupsReady;
1246
+ private _loading;
1247
+ private _wired;
1248
+ constructor(components: OBC.Components);
1249
+ get ready(): boolean;
1250
+ get loading(): boolean;
1251
+ /**
1252
+ * Commits of the selected models, newest last, interleaved by time so a multi-model
1253
+ * timeline reads chronologically rather than model-by-model.
1254
+ */
1255
+ get commits(): RevitFlowCommit[];
1256
+ /** True when this entry is a proposal rather than something that happened. */
1257
+ isProposal(commit: RevitFlowCommit | null | undefined): boolean;
1258
+ /**
1259
+ * The entry a proposal/commit links to, in whichever direction applies: a commit points at
1260
+ * the proposal it materialised, a proposal at the commit that did it. Returns null when
1261
+ * there is no counterpart, which is the normal case for hand-authored work.
1262
+ */
1263
+ counterpart(commit: RevitFlowCommit): RevitFlowCommit | null;
1264
+ /**
1265
+ * Deferred edits still waiting to be applied, across the selected models, oldest first.
1266
+ *
1267
+ * Kept separate from {@link commits} on purpose. A commit is something that happened; a
1268
+ * pending operation is something that might. Merging them into one list would force every
1269
+ * consumer to keep asking which kind it was holding.
1270
+ */
1271
+ get pendingOps(): RevitFlowOp[];
1272
+ /** The loaded revit-flow models, for the panel's model filter. */
1273
+ get models(): Array<{
1274
+ modelId: string;
1275
+ name: string;
1276
+ commits: number;
1277
+ }>;
1278
+ get selectedModels(): Set<string>;
1279
+ get currentKey(): string | null;
1280
+ /** Name of the single loaded model, or "" when there are none/several. */
1281
+ get modelName(): string;
1282
+ /** The commit behind {@link currentKey}, or undefined when nothing is highlighted. */
1283
+ private _currentCommit;
1284
+ /** Restrict the timeline to these models (empty set = show all of them). */
1285
+ setSelectedModels(modelIds: Iterable<string>): Promise<void>;
1286
+ /** True when `commit` is its model's baseline (the full-model capture). */
1287
+ isBaseline(commit: RevitFlowCommit): boolean;
1288
+ /** True if `commit` has a hidden delta .frag to load. */
1289
+ hasFrag(commit: RevitFlowCommit): boolean;
1290
+ /**
1291
+ * Wire the platform client and subscribe to model loads. Does NOT load any
1292
+ * geometry: the manager only attaches to models the user opens from the Files
1293
+ * panel. Consumer panels call this once on connect.
1294
+ */
1295
+ init(client: PlatformClient): Promise<void>;
1296
+ /**
1297
+ * Follow the viewer's selection so the element view tracks whatever the user clicks in
1298
+ * 3D — no "trace this" button to press. The Highlighter's events appear asynchronously
1299
+ * (they're registered when the viewer sets it up), so retry briefly until they exist.
1300
+ */
1301
+ private _watchSelection;
1302
+ private _onModelSet;
1303
+ private _onModelDeleted;
1304
+ /**
1305
+ * Probe a loaded model for a sibling visible `revitflow_history.json` in its
1306
+ * folder. If present, adopt it as the active model and publish its commits.
1307
+ * Silent for non-revit models and for our own delta frags — only genuine
1308
+ * fetch/parse failures raise onError.
1309
+ */
1310
+ private _probeModel;
1311
+ /**
1312
+ * Read the model's deferred-edit queue, if it has one.
1313
+ *
1314
+ * Best effort by design: a model that has never been the target of an operation simply has
1315
+ * no queue, and that is the normal case rather than an error. A failure here must never
1316
+ * cost the user their history, which is why it cannot throw out of the probe.
1317
+ */
1318
+ private _readOps;
1319
+ /**
1320
+ * Re-scan every currently-loaded model for a hidden revit-flow history (the
1321
+ * panel's Refresh button). Clears the probe cache so models load-order edge
1322
+ * cases re-resolve.
1323
+ */
1324
+ loadHistory(): Promise<void>;
1325
+ /**
1326
+ * Show `commit`. The baseline geometry is the visible model the user already loaded, so
1327
+ * the baseline view just clears outlines. Any other commit pulls its hidden delta frag
1328
+ * in (so created elements exist) and outlines its changed elements. Fires
1329
+ * onCommitChanged. Takes the commit itself, not an id: ids repeat across models.
1330
+ */
1331
+ showCommit(commit: RevitFlowCommit): Promise<void>;
1332
+ /**
1333
+ * Keep the deltas of the commits around `centerId` loaded and drop the rest, so
1334
+ * stepping through the timeline never stalls and memory stays bounded: moving from
1335
+ * commit 10 to 11 fetches one delta and disposes one, instead of reloading a window.
1336
+ */
1337
+ private _slidePrefetchWindow;
1338
+ /**
1339
+ * Show the model as it stood AT `commit`: the visible baseline is the model at its
1340
+ * INITIAL commit, and everything created later lives in per-commit delta .frags loaded
1341
+ * as separate models. Those deltas stay loaded (the prefetch window keeps neighbours
1342
+ * warm), so stepping BACK has to hide the ones from later commits — otherwise a wall
1343
+ * added in commit 3 was still sitting there while you were looking at commit 2.
1344
+ * Only touches deltas of the commit's own model; other models keep their own state.
1345
+ */
1346
+ private _applyFutureVisibility;
1347
+ /** Which commit a loaded delta belongs to (deltas are keyed by their hidden id). */
1348
+ private _commitOfDelta;
1349
+ /** Make every loaded delta visible again (the model as of its latest commit). */
1350
+ private _showAllDeltas;
1351
+ /** Remove all revit-flow outlines + ghosting and reset the selection. */
1352
+ clear(): Promise<void>;
1353
+ /** Set what happens to non-commit elements; re-applies to the current commit. */
1354
+ setContextMode(mode: ContextMode): Promise<void>;
1355
+ /**
1356
+ * Every commit that touched `uniqueId`, oldest first, with what happened to it there.
1357
+ * The element's life story: created here, edited there, finally deleted.
1358
+ */
1359
+ elementHistory(uniqueId: string): Array<{
1360
+ commit: RevitFlowCommit;
1361
+ type: string;
1362
+ }>;
1363
+ /** Per-author totals across the (optionally date-filtered) history. */
1364
+ userActivity(since?: Date): Array<{
1365
+ author: string;
1366
+ userId?: string;
1367
+ commits: number;
1368
+ added: number;
1369
+ modified: number;
1370
+ removed: number;
1371
+ last: string;
1372
+ }>;
1373
+ /**
1374
+ * The GUID of whatever is currently selected in the viewer, so the element view can
1375
+ * follow the user's selection. Returns null when nothing (or something unresolvable)
1376
+ * is selected.
1377
+ */
1378
+ /** GUIDs of everything currently selected in the viewer (empty when nothing is). */
1379
+ selectedGuids(): Promise<string[]>;
1380
+ selectedGuid(): Promise<string | null>;
1381
+ /**
1382
+ * Select every element the commit touched, in the viewer's own selection — so the
1383
+ * usual tools (properties, isolate, zoom) work on it like any hand-made selection.
1384
+ * Honours the current type filter, so "only deletions" selects only those.
1385
+ * @returns how many elements ended up selected.
1386
+ */
1387
+ selectCommitElements(commit: RevitFlowCommit, zoom?: boolean): Promise<number>;
1388
+ /** Show/hide one kind of change; re-applies to the current commit. */
1389
+ setTypeVisible(kind: ChangeKind, on: boolean): Promise<void>;
1390
+ /** @deprecated use setContextMode. */
1391
+ setIsolateChanges(on: boolean): Promise<void>;
1392
+ /** The shared Outliner component (created on first access by the viewer). */
1393
+ private _outliner;
1394
+ /**
1395
+ * Create the three independently-colored outline groups once. The viewer
1396
+ * owns the Outliner's DEFAULT group (selection) — we only add our own named
1397
+ * groups and never touch "default".
1398
+ */
1399
+ private _ensureGroups;
1400
+ /** Clear our three outline groups only — leaves the viewer's default group. */
1401
+ private _clearOutlines;
1402
+ /**
1403
+ * Resolve each change bucket's GUIDs to localIds across every loaded model
1404
+ * and route them to the matching outline group.
1405
+ */
1406
+ private _outlineCommit;
1407
+ /**
1408
+ * Remove every localId that `_applySupersededVisibility` has hidden from a change map.
1409
+ * Returns a copy: the input maps come from `_buildMap` and are used elsewhere.
1410
+ */
1411
+ private _dropSuperseded;
1412
+ /**
1413
+ * Hide (or restore) the elements a commit deleted. Tracked separately from the context
1414
+ * modes so switching Colored↔Plain doesn't disturb ghosting or the rest of the model.
1415
+ */
1416
+ private _applyDeletedVisibility;
1417
+ /**
1418
+ * Show each element ONCE: from the newest source that supplies it.
1419
+ *
1420
+ * THE BUG THIS EXISTS FOR. The baseline .frag holds the whole model as of the first
1421
+ * commit, and every later commit ships a delta .frag with the geometry it created AND
1422
+ * the geometry it modified. Both stay in the scene. For a CREATED element that is
1423
+ * right — it exists in exactly one place. For a MODIFIED one it is not: the element is
1424
+ * in the baseline at its old shape and in the delta at its new one, and the viewer drew
1425
+ * both. Measured 2026-08-05 on a wall whose height Quim raised: the new wall stood
1426
+ * proud of the old one, with the coincident faces z-fighting into a dotted band.
1427
+ *
1428
+ * The rule is the obvious one once stated: for any element, only the newest VISIBLE
1429
+ * source may draw it. Deltas are walked newest-first, each guid is claimed by the first
1430
+ * source that has it, and every older copy — in an older delta or in the baseline — is
1431
+ * hidden. Deltas newer than the commit being shown are already hidden wholesale by
1432
+ * `_applyFutureVisibility`, so they never get to claim anything.
1433
+ *
1434
+ * Restores before it hides, like `_applyDeletedVisibility`, so stepping backwards
1435
+ * through the timeline brings the old geometry back rather than accumulating hidden
1436
+ * elements until the model is empty.
1437
+ */
1438
+ private _applySupersededVisibility;
1439
+ /** Switch between review colours and the plain post-commit model. */
1440
+ setHighlightMode(mode: HighlightMode): Promise<void>;
1441
+ /**
1442
+ * Make sure the geometry of `deleted` GUIDs is loaded. Anything already resolvable in
1443
+ * a loaded model (the usual case: the element shipped in the baseline) needs nothing;
1444
+ * for the rest, walk back through the history to the commit that CREATED each one and
1445
+ * load that commit's delta, which is the last place its geometry existed.
1446
+ */
1447
+ private _ensureDeletedGeometry;
1448
+ /** GUIDs → { modelId: Set<localId> } across the given models. */
1449
+ private _buildMap;
1450
+ private _mergeMaps;
1451
+ /**
1452
+ * Dim ("ghost") or hide every element that is NOT part of the shown commit, per the
1453
+ * chosen context mode. Best-effort per model: a model that doesn't support the call is
1454
+ * simply left alone — the outlines still convey the change.
1455
+ */
1456
+ private _applyContext;
1457
+ /** Undo whatever the context mode did: drop the ghost overlay and restore visibility. */
1458
+ private _clearContext;
1459
+ /**
1460
+ * Kept for the panel's connect hook. Prefetching is now driven by the SELECTION (see
1461
+ * _slidePrefetchWindow): nothing is downloaded until a commit is opened, and only its
1462
+ * neighbourhood is kept. Warming the newest N up front, as this used to do, spent
1463
+ * bandwidth on commits nobody had asked for and grew without bound.
1464
+ */
1465
+ warmDeltas(): void;
1466
+ /** Load a commit's hidden delta .frag (by its hidden id) into the viewer (modelId == hiddenId). */
1467
+ private _ensureDeltaLoaded;
1468
+ private _setLoading;
1469
+ private _firstWorld;
1470
+ }
1471
+ /**
1472
+ * GitHistoryManager — headless engine for the revit-flow git-history built-in.
1473
+ *
1474
+ * Owns ALL viewer mutation for the change outlines. It does NOT load the model —
1475
+ * the user opens a model from the Project Files panel, and this manager reacts to
1476
+ * that load: it reads the model's hidden `revitflow_history.json` (if any) and
1477
+ * publishes the commit list. Showing a commit outlines its changed elements
1478
+ * (create → green, update → blue, delete → red) via three independently-colored
1479
+ * `OBF.Outliner` groups — a cheap post-process outline that never recolors the
1480
+ * fragment geometry. The Lit panel (`top-git-history`) is intent-only: it calls
1481
+ * these methods and subscribes to the events below.
1482
+ *
1483
+ * Data model, per loaded model (fileId == modelId), all HIDDEN children of it:
1484
+ * - revitflow_history.json — { model, commits: [{ id, parent, author, source,
1485
+ * timestamp, changes:[{type,uniqueId}], counts }] }. The first commit is the
1486
+ * INITIAL full-model capture (its geometry == the visible baseline file).
1487
+ * - revitflow_frag_<N>.frag — delta fragments for commit N (its created+modified
1488
+ * geometry), loaded on demand so created elements can be colored.
1489
+ */
1490
+ export type GitHistoryManager = InstanceType<typeof _GitHistoryManager>;
1491
+ /**
1492
+ * GitHistoryManager — headless engine for the revit-flow git-history built-in.
1493
+ *
1494
+ * Owns ALL viewer mutation for the change outlines. It does NOT load the model —
1495
+ * the user opens a model from the Project Files panel, and this manager reacts to
1496
+ * that load: it reads the model's hidden `revitflow_history.json` (if any) and
1497
+ * publishes the commit list. Showing a commit outlines its changed elements
1498
+ * (create → green, update → blue, delete → red) via three independently-colored
1499
+ * `OBF.Outliner` groups — a cheap post-process outline that never recolors the
1500
+ * fragment geometry. The Lit panel (`top-git-history`) is intent-only: it calls
1501
+ * these methods and subscribes to the events below.
1502
+ *
1503
+ * Data model, per loaded model (fileId == modelId), all HIDDEN children of it:
1504
+ * - revitflow_history.json — { model, commits: [{ id, parent, author, source,
1505
+ * timestamp, changes:[{type,uniqueId}], counts }] }. The first commit is the
1506
+ * INITIAL full-model capture (its geometry == the visible baseline file).
1507
+ * - revitflow_frag_<N>.frag — delta fragments for commit N (its created+modified
1508
+ * geometry), loaded on demand so created elements can be colored.
1509
+ */
1510
+ export declare const GitHistoryManager: typeof _GitHistoryManager & {
1511
+ uuid: "3f9c1a7e-6b2d-4e18-9a5c-7d0e2f4b6c81";
1512
+ };
944
1513
  /**
945
1514
  * A simple test component to validate the built-in component pipeline.
946
1515
  * Replace this with real components once the infrastructure is verified.
package/dist/cli.js CHANGED
@@ -4205,8 +4205,8 @@ class BaseXHR extends Polling {
4205
4205
  /**
4206
4206
  * Sends data.
4207
4207
  *
4208
- * @param {String} data - data to send.
4209
- * @param {Function} fn - called upon flush.
4208
+ * @param {String} data to send.
4209
+ * @param {Function} called upon flush.
4210
4210
  * @private
4211
4211
  */
4212
4212
  doWrite(data, fn) {
@@ -4959,7 +4959,7 @@ class SocketWithoutUpgrade extends Emitter {
4959
4959
  /**
4960
4960
  * Sends a packet.
4961
4961
  *
4962
- * @param {String} type - packet type.
4962
+ * @param {String} type: packet type.
4963
4963
  * @param {String} data.
4964
4964
  * @param {Object} options.
4965
4965
  * @param {Function} fn - callback function.
@@ -5194,12 +5194,11 @@ class SocketWithUpgrade extends SocketWithoutUpgrade {
5194
5194
  }
5195
5195
  let Socket$1 = class Socket extends SocketWithUpgrade {
5196
5196
  constructor(uri, opts = {}) {
5197
- const isOptionsOnly = typeof uri === "object";
5198
- const o = isOptionsOnly ? { ...uri } : { ...opts };
5197
+ const o = typeof uri === "object" ? uri : opts;
5199
5198
  if (!o.transports || o.transports && typeof o.transports[0] === "string") {
5200
5199
  o.transports = (o.transports || ["polling", "websocket", "webtransport"]).map((transportName) => transports[transportName]).filter((t) => !!t);
5201
5200
  }
5202
- super(isOptionsOnly ? o : uri, o);
5201
+ super(uri, o);
5203
5202
  }
5204
5203
  };
5205
5204
  function url(uri, path2 = "", loc) {
@@ -5420,13 +5419,12 @@ class Encoder {
5420
5419
  class Decoder extends Emitter {
5421
5420
  /**
5422
5421
  * Decoder constructor
5422
+ *
5423
+ * @param {function} reviver - custom reviver to pass down to JSON.stringify
5423
5424
  */
5424
- constructor(opts) {
5425
+ constructor(reviver) {
5425
5426
  super();
5426
- this.opts = Object.assign({
5427
- reviver: void 0,
5428
- maxAttachments: 10
5429
- }, typeof opts === "function" ? { reviver: opts } : opts);
5427
+ this.reviver = reviver;
5430
5428
  }
5431
5429
  /**
5432
5430
  * Decodes an encoded packet string into packet JSON.
@@ -5486,13 +5484,7 @@ class Decoder extends Emitter {
5486
5484
  if (buf != Number(buf) || str.charAt(i) !== "-") {
5487
5485
  throw new Error("Illegal attachments");
5488
5486
  }
5489
- const n = Number(buf);
5490
- if (!isInteger(n) || n < 0) {
5491
- throw new Error("Illegal attachments");
5492
- } else if (n > this.opts.maxAttachments) {
5493
- throw new Error("too many attachments");
5494
- }
5495
- p.attachments = n;
5487
+ p.attachments = Number(buf);
5496
5488
  }
5497
5489
  if ("/" === str.charAt(i + 1)) {
5498
5490
  const start = i + 1;
@@ -5533,7 +5525,7 @@ class Decoder extends Emitter {
5533
5525
  }
5534
5526
  tryParse(str) {
5535
5527
  try {
5536
- return JSON.parse(str, this.opts.reviver);
5528
+ return JSON.parse(str, this.reviver);
5537
5529
  } catch (e) {
5538
5530
  return false;
5539
5531
  }
@@ -5595,9 +5587,6 @@ class BinaryReconstructor {
5595
5587
  this.buffers = [];
5596
5588
  }
5597
5589
  }
5598
- const isInteger = Number.isInteger || function(value2) {
5599
- return typeof value2 === "number" && isFinite(value2) && Math.floor(value2) === value2;
5600
- };
5601
5590
  function isObject(value2) {
5602
5591
  return Object.prototype.toString.call(value2) === "[object Object]";
5603
5592
  }
@@ -8227,7 +8216,7 @@ Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/js
8227
8216
  JSZip uses the library pako released under the MIT license :
8228
8217
  https://github.com/nodeca/pako/blob/main/LICENSE
8229
8218
  */
8230
- (function(module2, exports) {
8219
+ (function(module2, exports$1) {
8231
8220
  !function(e) {
8232
8221
  module2.exports = e();
8233
8222
  }(function() {