pi-revit 0.3.0 → 0.3.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.
- package/CHANGELOG.md +6 -0
- package/README.md +12 -3
- package/bin/pi-revit.js +3 -5
- package/extensions/pi-revit/index.ts +95 -95
- package/package.json +4 -3
- package/scripts/build.ps1 +9 -3
- package/scripts/check-sdk.ps1 +66 -0
- package/scripts/deploy.ps1 +16 -4
- package/skills/pi-revit/SKILL.md +21 -21
- package/src/Revit/BridgeServer.cs +9 -9
- package/src/Revit/ToolRegistry.cs +32 -32
- package/src/Revit/Tools/DocumentGuard.cs +64 -64
- package/src/Revit/Tools/ExecuteCsharp.cs +22 -22
- package/src/Revit/Tools/ExportDocuments.cs +119 -119
- package/src/Revit/Tools/FailureGuard.cs +26 -26
- package/src/Revit/Tools/GetElementDetails.cs +10 -10
- package/src/Revit/Tools/GetElements.cs +17 -17
- package/src/Revit/Tools/GetModelOverview.cs +2 -2
- package/src/Revit/Tools/ManageSelection.cs +35 -35
- package/src/Revit/Tools/SetParameters.cs +14 -14
- package/src/Revit/Tools/ToolSupport.cs +1 -1
- package/workspace/AGENTS.md +45 -45
|
@@ -36,7 +36,7 @@ namespace RevitBridge.Tools
|
|
|
36
36
|
properties = new
|
|
37
37
|
{
|
|
38
38
|
parameters = new { type = "boolean", description = "Instance parameter values. Default true." },
|
|
39
|
-
type_parameters = new { type = "boolean", description = "Include the element type's parameters, marked isType=true, independently of the instance parameters flag. Default false." },
|
|
39
|
+
type_parameters = new { type = "boolean", description = "Include the element type's parameters, marked isType=true, independently of the instance parameters flag. Default false." },
|
|
40
40
|
location = new { type = "boolean", description = "Location point or curve (coordinates in internal feet). Default false." },
|
|
41
41
|
bounding_box = new { type = "boolean", description = "Model bounding box min/max (internal feet). Default false." },
|
|
42
42
|
materials = new { type = "boolean", description = "Material ids/names with area/volume (internal units). Default false." },
|
|
@@ -70,9 +70,9 @@ namespace RevitBridge.Tools
|
|
|
70
70
|
JsonElement include = args.TryGetProperty("include", out var includeElement) && includeElement.ValueKind == JsonValueKind.Object
|
|
71
71
|
? includeElement
|
|
72
72
|
: default;
|
|
73
|
-
bool withParameters = JsonArgs.GetBool(include, "parameters", true);
|
|
74
|
-
bool withTypeParameters = JsonArgs.GetBool(include, "type_parameters", false);
|
|
75
|
-
bool withAnyParameters = withParameters || withTypeParameters;
|
|
73
|
+
bool withParameters = JsonArgs.GetBool(include, "parameters", true);
|
|
74
|
+
bool withTypeParameters = JsonArgs.GetBool(include, "type_parameters", false);
|
|
75
|
+
bool withAnyParameters = withParameters || withTypeParameters;
|
|
76
76
|
bool withLocation = JsonArgs.GetBool(include, "location", false);
|
|
77
77
|
bool withBoundingBox = JsonArgs.GetBool(include, "bounding_box", false);
|
|
78
78
|
bool withMaterials = JsonArgs.GetBool(include, "materials", false);
|
|
@@ -103,11 +103,11 @@ namespace RevitBridge.Tools
|
|
|
103
103
|
|
|
104
104
|
int parameterCount = 0;
|
|
105
105
|
int parameterTotal = 0;
|
|
106
|
-
if (withAnyParameters)
|
|
107
|
-
{
|
|
108
|
-
var parameters = new List<Dictionary<string, object?>>();
|
|
109
|
-
if (withParameters)
|
|
110
|
-
parameterTotal += AppendParameters(doc, element, nameFilter, isType: false, parameters);
|
|
106
|
+
if (withAnyParameters)
|
|
107
|
+
{
|
|
108
|
+
var parameters = new List<Dictionary<string, object?>>();
|
|
109
|
+
if (withParameters)
|
|
110
|
+
parameterTotal += AppendParameters(doc, element, nameFilter, isType: false, parameters);
|
|
111
111
|
if (withTypeParameters && elementType != null)
|
|
112
112
|
parameterTotal += AppendParameters(doc, elementType, nameFilter, isType: true, parameters);
|
|
113
113
|
dto["parameters"] = parameters;
|
|
@@ -124,7 +124,7 @@ namespace RevitBridge.Tools
|
|
|
124
124
|
elements.Add(dto);
|
|
125
125
|
// With a name filter active, "0 params" is ambiguous (none matched vs none
|
|
126
126
|
// exist): report matched-of-total so a localization miss is visible.
|
|
127
|
-
string paramSummary = !withAnyParameters ? string.Empty
|
|
127
|
+
string paramSummary = !withAnyParameters ? string.Empty
|
|
128
128
|
: nameFilter != null ? $", {parameterCount} of {parameterTotal} params matched parameter_names"
|
|
129
129
|
: $", {parameterCount} params";
|
|
130
130
|
compactParts.Add($"'{element.Name}' (id {id}, {element.Category?.Name ?? "no category"}{paramSummary})");
|
|
@@ -21,7 +21,7 @@ namespace RevitBridge.Tools
|
|
|
21
21
|
|
|
22
22
|
public string Name => "get_elements";
|
|
23
23
|
public string Label => "Get Elements";
|
|
24
|
-
public string Description => "Query Revit elements: scope by category (display name like 'Walls' or enum name like 'OST_Walls'), element class, level, type id, or active view; filter by parameter rules; paginate with offset/limit or just count with count_only. Returns identity fields only (id, name, category, typeName, levelId) — read parameter values with get_element_details. Rules with an explicit BuiltInParameter or shared GUID can evaluate inside Revit's collector; display-name rules, regex rules, and unsupported quick filters run as a per-element scan. A display name can identify different parameters even within one category or class. Scope queries to reduce the scan, or use an explicit parameter identity when appropriate. Numeric rule values are interpreted in the document's display units for that parameter unless 'unit' is given.";
|
|
24
|
+
public string Description => "Query Revit elements: scope by category (display name like 'Walls' or enum name like 'OST_Walls'), element class, level, type id, or active view; filter by parameter rules; paginate with offset/limit or just count with count_only. Returns identity fields only (id, name, category, typeName, levelId) — read parameter values with get_element_details. Rules with an explicit BuiltInParameter or shared GUID can evaluate inside Revit's collector; display-name rules, regex rules, and unsupported quick filters run as a per-element scan. A display name can identify different parameters even within one category or class. Scope queries to reduce the scan, or use an explicit parameter identity when appropriate. Numeric rule values are interpreted in the document's display units for that parameter unless 'unit' is given.";
|
|
25
25
|
|
|
26
26
|
public object ParametersSchema => new
|
|
27
27
|
{
|
|
@@ -292,9 +292,9 @@ namespace RevitBridge.Tools
|
|
|
292
292
|
if (rules.Count == 0)
|
|
293
293
|
return (null, null, Array.Empty<string>());
|
|
294
294
|
|
|
295
|
-
// Probe a few in-scope elements for missing-name diagnostics and to find
|
|
296
|
-
// storage/spec exemplars for explicit parameter identities. A sample must
|
|
297
|
-
// never turn a display name into an assumed globally uniform identity.
|
|
295
|
+
// Probe a few in-scope elements for missing-name diagnostics and to find
|
|
296
|
+
// storage/spec exemplars for explicit parameter identities. A sample must
|
|
297
|
+
// never turn a display name into an assumed globally uniform identity.
|
|
298
298
|
var probes = new List<Element>(ProbeSize);
|
|
299
299
|
foreach (Element element in createBaseCollector())
|
|
300
300
|
{
|
|
@@ -326,19 +326,19 @@ namespace RevitBridge.Tools
|
|
|
326
326
|
}
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
-
foreach (var rule in rules)
|
|
330
|
-
{
|
|
331
|
-
if (rule.Op is RuleOp.Regex or RuleOp.IsEmpty or RuleOp.IsNotEmpty)
|
|
332
|
-
continue; // always post-scan (missing-parameter semantics)
|
|
333
|
-
// Category/class scope and unanimous samples do not establish a
|
|
334
|
-
// uniform parameter identity across later families. Resolve display
|
|
335
|
-
// names per element; only explicit identities may use a quick rule.
|
|
336
|
-
if (rule.BuiltIn is null && rule.SharedGuid is null)
|
|
337
|
-
continue;
|
|
338
|
-
var found = probes.Select(probe => FindParameter(probe, rule)).Where(parameter => parameter != null).ToList();
|
|
339
|
-
if (found.Count == 0)
|
|
340
|
-
continue;
|
|
341
|
-
rule.QuickRule = TryBuildQuickRule(doc, rule, found[0]!);
|
|
329
|
+
foreach (var rule in rules)
|
|
330
|
+
{
|
|
331
|
+
if (rule.Op is RuleOp.Regex or RuleOp.IsEmpty or RuleOp.IsNotEmpty)
|
|
332
|
+
continue; // always post-scan (missing-parameter semantics)
|
|
333
|
+
// Category/class scope and unanimous samples do not establish a
|
|
334
|
+
// uniform parameter identity across later families. Resolve display
|
|
335
|
+
// names per element; only explicit identities may use a quick rule.
|
|
336
|
+
if (rule.BuiltIn is null && rule.SharedGuid is null)
|
|
337
|
+
continue;
|
|
338
|
+
var found = probes.Select(probe => FindParameter(probe, rule)).Where(parameter => parameter != null).ToList();
|
|
339
|
+
if (found.Count == 0)
|
|
340
|
+
continue;
|
|
341
|
+
rule.QuickRule = TryBuildQuickRule(doc, rule, found[0]!);
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
var quickRules = rules.Where(rule => rule.QuickRule != null).ToList();
|
|
@@ -45,8 +45,8 @@ namespace RevitBridge.Tools
|
|
|
45
45
|
string? lengthUnit = DisplayUnitName(units, SpecTypeId.Length);
|
|
46
46
|
var project = new Dictionary<string, object?>
|
|
47
47
|
{
|
|
48
|
-
["title"] = doc.Title,
|
|
49
|
-
["documentId"] = DocumentGuard.GetIdentity(doc),
|
|
48
|
+
["title"] = doc.Title,
|
|
49
|
+
["documentId"] = DocumentGuard.GetIdentity(doc),
|
|
50
50
|
["name"] = info?.Name,
|
|
51
51
|
["number"] = info?.Number,
|
|
52
52
|
["clientName"] = info?.ClientName,
|
|
@@ -136,25 +136,25 @@ namespace RevitBridge.Tools
|
|
|
136
136
|
compactParts.Add($"ids not found: {string.Join(", ", notFound)}");
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
if (isolateInView)
|
|
140
|
-
{
|
|
141
|
-
var view = uiDocument.ActiveGraphicalView;
|
|
142
|
-
IReadOnlyList<string> warnings;
|
|
143
|
-
try
|
|
144
|
-
{
|
|
145
|
-
if (view is null)
|
|
146
|
-
throw new ArgumentException("isolate_in_view requires an active graphical view in Revit.");
|
|
147
|
-
warnings = ApplyTemporaryIsolate(doc, view, isolateTargets);
|
|
148
|
-
}
|
|
149
|
-
catch (Exception ex)
|
|
150
|
-
{
|
|
151
|
-
throw new InvalidOperationException($"Selection action '{action}' completed before temporary isolate failed: {ex.Message}. Selection/zoom changes were not rolled back.", ex);
|
|
152
|
-
}
|
|
153
|
-
if (warnings.Count > 0)
|
|
154
|
-
{
|
|
155
|
-
payload["commitWarnings"] = warnings;
|
|
156
|
-
compactParts.Add($"{warnings.Count} Revit warning(s) auto-dismissed (see commitWarnings)");
|
|
157
|
-
}
|
|
139
|
+
if (isolateInView)
|
|
140
|
+
{
|
|
141
|
+
var view = uiDocument.ActiveGraphicalView;
|
|
142
|
+
IReadOnlyList<string> warnings;
|
|
143
|
+
try
|
|
144
|
+
{
|
|
145
|
+
if (view is null)
|
|
146
|
+
throw new ArgumentException("isolate_in_view requires an active graphical view in Revit.");
|
|
147
|
+
warnings = ApplyTemporaryIsolate(doc, view, isolateTargets);
|
|
148
|
+
}
|
|
149
|
+
catch (Exception ex)
|
|
150
|
+
{
|
|
151
|
+
throw new InvalidOperationException($"Selection action '{action}' completed before temporary isolate failed: {ex.Message}. Selection/zoom changes were not rolled back.", ex);
|
|
152
|
+
}
|
|
153
|
+
if (warnings.Count > 0)
|
|
154
|
+
{
|
|
155
|
+
payload["commitWarnings"] = warnings;
|
|
156
|
+
compactParts.Add($"{warnings.Count} Revit warning(s) auto-dismissed (see commitWarnings)");
|
|
157
|
+
}
|
|
158
158
|
payload["viewId"] = view.Id.Value;
|
|
159
159
|
payload["viewName"] = view.Name;
|
|
160
160
|
if (isolateTargets.Count == 0)
|
|
@@ -203,28 +203,28 @@ namespace RevitBridge.Tools
|
|
|
203
203
|
/// only changes it inside an open transaction — so exactly this branch wraps
|
|
204
204
|
/// a small one while the tool stays Write = false.
|
|
205
205
|
/// </summary>
|
|
206
|
-
private static IReadOnlyList<string> ApplyTemporaryIsolate(Document doc, View view, ICollection<ElementId> elementIds)
|
|
207
|
-
{
|
|
208
|
-
using var transaction = new Transaction(doc, "manage_selection: temporary isolate");
|
|
209
|
-
if (transaction.Start() != TransactionStatus.Started)
|
|
210
|
-
throw new InvalidOperationException("Unable to start the temporary-isolate transaction.");
|
|
211
|
-
var failureGuard = FailureGuard.Attach(transaction);
|
|
206
|
+
private static IReadOnlyList<string> ApplyTemporaryIsolate(Document doc, View view, ICollection<ElementId> elementIds)
|
|
207
|
+
{
|
|
208
|
+
using var transaction = new Transaction(doc, "manage_selection: temporary isolate");
|
|
209
|
+
if (transaction.Start() != TransactionStatus.Started)
|
|
210
|
+
throw new InvalidOperationException("Unable to start the temporary-isolate transaction.");
|
|
211
|
+
var failureGuard = FailureGuard.Attach(transaction);
|
|
212
212
|
try
|
|
213
213
|
{
|
|
214
214
|
if (elementIds.Count == 0)
|
|
215
215
|
view.DisableTemporaryViewMode(TemporaryViewMode.TemporaryHideIsolate);
|
|
216
216
|
else
|
|
217
217
|
view.IsolateElementsTemporary(elementIds);
|
|
218
|
-
var status = transaction.Commit();
|
|
219
|
-
var finalStatus = transaction.GetStatus();
|
|
220
|
-
if (status != TransactionStatus.Committed || finalStatus != TransactionStatus.Committed)
|
|
221
|
-
throw new InvalidOperationException($"The temporary-isolate commit returned {status}; current transaction status is {finalStatus}." + failureGuard.DescribeErrors());
|
|
222
|
-
return failureGuard.Warnings;
|
|
223
|
-
}
|
|
224
|
-
catch (Exception ex)
|
|
225
|
-
{
|
|
226
|
-
throw new InvalidOperationException($"Temporary isolate in view '{view.Name}' failed: {ex.Message} {FailureGuard.RollBackAndDescribe(transaction)}", ex);
|
|
227
|
-
}
|
|
218
|
+
var status = transaction.Commit();
|
|
219
|
+
var finalStatus = transaction.GetStatus();
|
|
220
|
+
if (status != TransactionStatus.Committed || finalStatus != TransactionStatus.Committed)
|
|
221
|
+
throw new InvalidOperationException($"The temporary-isolate commit returned {status}; current transaction status is {finalStatus}." + failureGuard.DescribeErrors());
|
|
222
|
+
return failureGuard.Warnings;
|
|
223
|
+
}
|
|
224
|
+
catch (Exception ex)
|
|
225
|
+
{
|
|
226
|
+
throw new InvalidOperationException($"Temporary isolate in view '{view.Name}' failed: {ex.Message} {FailureGuard.RollBackAndDescribe(transaction)}", ex);
|
|
227
|
+
}
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
230
|
}
|
|
@@ -70,9 +70,9 @@ namespace RevitBridge.Tools
|
|
|
70
70
|
var failed = new List<Dictionary<string, object?>>();
|
|
71
71
|
|
|
72
72
|
using var transaction = new Transaction(doc, "set_parameters");
|
|
73
|
-
if (transaction.Start() != TransactionStatus.Started)
|
|
74
|
-
throw new InvalidOperationException("Unable to start the set_parameters transaction.");
|
|
75
|
-
var failureGuard = FailureGuard.Attach(transaction);
|
|
73
|
+
if (transaction.Start() != TransactionStatus.Started)
|
|
74
|
+
throw new InvalidOperationException("Unable to start the set_parameters transaction.");
|
|
75
|
+
var failureGuard = FailureGuard.Attach(transaction);
|
|
76
76
|
|
|
77
77
|
try
|
|
78
78
|
{
|
|
@@ -101,23 +101,23 @@ namespace RevitBridge.Tools
|
|
|
101
101
|
|
|
102
102
|
if (succeeded.Count > 0)
|
|
103
103
|
{
|
|
104
|
-
var status = transaction.Commit();
|
|
105
|
-
var finalStatus = transaction.GetStatus();
|
|
106
|
-
if (status != TransactionStatus.Committed || finalStatus != TransactionStatus.Committed)
|
|
107
|
-
throw new InvalidOperationException(
|
|
108
|
-
$"The set_parameters commit returned {status}; current transaction status is {finalStatus}."
|
|
104
|
+
var status = transaction.Commit();
|
|
105
|
+
var finalStatus = transaction.GetStatus();
|
|
106
|
+
if (status != TransactionStatus.Committed || finalStatus != TransactionStatus.Committed)
|
|
107
|
+
throw new InvalidOperationException(
|
|
108
|
+
$"The set_parameters commit returned {status}; current transaction status is {finalStatus}."
|
|
109
109
|
+ failureGuard.DescribeErrors());
|
|
110
110
|
}
|
|
111
111
|
else
|
|
112
112
|
{
|
|
113
|
-
var status = transaction.RollBack();
|
|
114
|
-
if (status != TransactionStatus.RolledBack || transaction.GetStatus() != TransactionStatus.RolledBack)
|
|
115
|
-
throw new InvalidOperationException($"The set_parameters rollback returned {status}.");
|
|
113
|
+
var status = transaction.RollBack();
|
|
114
|
+
if (status != TransactionStatus.RolledBack || transaction.GetStatus() != TransactionStatus.RolledBack)
|
|
115
|
+
throw new InvalidOperationException($"The set_parameters rollback returned {status}.");
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
|
-
catch (Exception ex)
|
|
119
|
-
{
|
|
120
|
-
throw new InvalidOperationException($"{ex.Message} {FailureGuard.RollBackAndDescribe(transaction)}", ex);
|
|
118
|
+
catch (Exception ex)
|
|
119
|
+
{
|
|
120
|
+
throw new InvalidOperationException($"{ex.Message} {FailureGuard.RollBackAndDescribe(transaction)}", ex);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
int elementCount = succeeded.Select(row => row["id"]).Distinct().Count();
|
package/workspace/AGENTS.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# pi-revit workspace
|
|
2
2
|
|
|
3
3
|
This folder tree is the working area for Pi + Revit sessions. The pi-revit tools talk to the
|
|
4
|
-
Revit bridge add-in, targeting Revit 2025, 2026, and 2027. The 0.3.0 changes were
|
|
5
|
-
tested live on Revit 2025. Bridge document tools require a project open; `ping` and
|
|
6
|
-
`search_api_docs` work without a document. `read_revit_result` reads saved local
|
|
7
|
-
results without contacting Revit.
|
|
4
|
+
Revit bridge add-in, targeting Revit 2025, 2026, and 2027. The 0.3.0 changes were
|
|
5
|
+
tested live on Revit 2025. Bridge document tools require a project open; `ping` and
|
|
6
|
+
`search_api_docs` work without a document. `read_revit_result` reads saved local
|
|
7
|
+
results without contacting Revit.
|
|
8
8
|
|
|
9
9
|
## File rules — where every file goes
|
|
10
10
|
|
|
@@ -16,57 +16,57 @@ Documents\pi-revit\
|
|
|
16
16
|
├─ AGENTS.md <- this file
|
|
17
17
|
├─ pi-revit.cmd <- double-click launcher
|
|
18
18
|
└─ Models\
|
|
19
|
-
└─ <model title>--<identity hash>\ <- selected automatically for the exported document
|
|
20
|
-
├─ model.txt <- document identity/path marker written by the add-in
|
|
19
|
+
└─ <model title>--<identity hash>\ <- selected automatically for the exported document
|
|
20
|
+
├─ model.txt <- document identity/path marker written by the add-in
|
|
21
21
|
├─ exports\ <- export_documents output (its default)
|
|
22
22
|
├─ captures\ <- view snapshots worth keeping
|
|
23
23
|
└─ scripts\ <- generated scripts and analysis for that model
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
1. **Let exports sort themselves**: call `export_documents` without `output_dir` — files land
|
|
27
|
-
in an identity-derived model folder automatically. Treat the returned `outputDir`
|
|
28
|
-
and file paths as authoritative; do not derive the hash from the model title or
|
|
29
|
-
opaque `project.documentId`. Save As can change the destination. Existing title-only
|
|
30
|
-
folders remain untouched. Pass
|
|
27
|
+
in an identity-derived model folder automatically. Treat the returned `outputDir`
|
|
28
|
+
and file paths as authoritative; do not derive the hash from the model title or
|
|
29
|
+
opaque `project.documentId`. Save As can change the destination. Existing title-only
|
|
30
|
+
folders remain untouched. Pass
|
|
31
31
|
`output_dir` only when the user names a different target.
|
|
32
32
|
2. **Anything else you produce about a model goes into that model's folder**: view captures the
|
|
33
|
-
user wants to keep in that verified model folder's `captures` subfolder
|
|
34
|
-
(`capture_view` writes to temp), and scripts and analysis in its `scripts`
|
|
35
|
-
subfolder. For a default export, the model folder is the parent of returned
|
|
36
|
-
`outputDir`. If no folder has been established, identify it from existing model
|
|
37
|
-
markers or choose an explicit destination for the task; do not trigger an
|
|
38
|
-
unnecessary export or guess a title-only folder. Create subfolders on first use.
|
|
33
|
+
user wants to keep in that verified model folder's `captures` subfolder
|
|
34
|
+
(`capture_view` writes to temp), and scripts and analysis in its `scripts`
|
|
35
|
+
subfolder. For a default export, the model folder is the parent of returned
|
|
36
|
+
`outputDir`. If no folder has been established, identify it from existing model
|
|
37
|
+
markers or choose an explicit destination for the task; do not trigger an
|
|
38
|
+
unnecessary export or guess a title-only folder. Create subfolders on first use.
|
|
39
39
|
3. **Never create files loose in the workspace root.** The root holds `AGENTS.md`,
|
|
40
40
|
`pi-revit.cmd`, `Models\`, and Pi's own session data — nothing else, ever.
|
|
41
41
|
|
|
42
42
|
## Tool habits
|
|
43
43
|
|
|
44
|
-
- Start unfamiliar models with `get_model_overview`; use `get_elements` for any listing or
|
|
45
|
-
counting; read parameter values with `get_element_details`.
|
|
46
|
-
- Copy the intended model's `project.documentId` unchanged into `expected_document_id`
|
|
47
|
-
for `set_parameters`, `execute_csharp`, `export_documents`, `open_view`, and
|
|
48
|
-
selection/zoom changes. Any `manage_selection` call with `isolate_in_view: true`
|
|
49
|
-
also requires it, including action `get`. Pure reads may omit it; supplied IDs
|
|
50
|
-
are checked. Legacy `expected_document` titles alone do not satisfy the guard.
|
|
51
|
-
After a rejection, verify the intended model before refreshing its ID. Closing
|
|
52
|
-
and reopening a model or restarting Revit invalidates earlier IDs.
|
|
53
|
-
- Before `execute_csharp`, verify unfamiliar API signatures with `search_api_docs`.
|
|
54
|
-
- Write tools (`set_parameters`, `execute_csharp`) change the real model — state clearly what
|
|
55
|
-
was changed. `set_parameters` commits partial successes: always check its `failed` list.
|
|
56
|
-
Inspect `commitWarnings` and the actual transaction outcome. A failed
|
|
57
|
-
`execute_csharp` attempts rollback; do not assume rollback succeeded. A
|
|
58
|
-
`returnValueError` can follow a committed edit. Earlier UI actions and created
|
|
59
|
-
files can persist after failure. Read reported effects before retrying.
|
|
60
|
-
- When a result returns `result_id`, use `read_revit_result` from offset zero and
|
|
61
|
-
follow `next_offset` until `has_more` is false. Join its `text` fragments in order;
|
|
62
|
-
offsets count UTF-16 code units. The returned absolute file path remains a
|
|
63
|
-
fallback for `read` after extension reload while the file exists. Tool query
|
|
64
|
-
pagination and limits still apply separately.
|
|
65
|
-
|
|
66
|
-
## Upgrade notes
|
|
67
|
-
|
|
68
|
-
After installing 0.3.0, deploy the matching add-in with Revit closed, restart Revit,
|
|
69
|
-
and start a fresh Pi session to load the new tool schemas. Obtain a new overview
|
|
70
|
-
before changing a document. Setup preserves existing `AGENTS.md`; older workspaces
|
|
71
|
-
need these exact-ID, saved-result, and identity-derived folder rules merged into
|
|
72
|
-
their existing instructions.
|
|
44
|
+
- Start unfamiliar models with `get_model_overview`; use `get_elements` for any listing or
|
|
45
|
+
counting; read parameter values with `get_element_details`.
|
|
46
|
+
- Copy the intended model's `project.documentId` unchanged into `expected_document_id`
|
|
47
|
+
for `set_parameters`, `execute_csharp`, `export_documents`, `open_view`, and
|
|
48
|
+
selection/zoom changes. Any `manage_selection` call with `isolate_in_view: true`
|
|
49
|
+
also requires it, including action `get`. Pure reads may omit it; supplied IDs
|
|
50
|
+
are checked. Legacy `expected_document` titles alone do not satisfy the guard.
|
|
51
|
+
After a rejection, verify the intended model before refreshing its ID. Closing
|
|
52
|
+
and reopening a model or restarting Revit invalidates earlier IDs.
|
|
53
|
+
- Before `execute_csharp`, verify unfamiliar API signatures with `search_api_docs`.
|
|
54
|
+
- Write tools (`set_parameters`, `execute_csharp`) change the real model — state clearly what
|
|
55
|
+
was changed. `set_parameters` commits partial successes: always check its `failed` list.
|
|
56
|
+
Inspect `commitWarnings` and the actual transaction outcome. A failed
|
|
57
|
+
`execute_csharp` attempts rollback; do not assume rollback succeeded. A
|
|
58
|
+
`returnValueError` can follow a committed edit. Earlier UI actions and created
|
|
59
|
+
files can persist after failure. Read reported effects before retrying.
|
|
60
|
+
- When a result returns `result_id`, use `read_revit_result` from offset zero and
|
|
61
|
+
follow `next_offset` until `has_more` is false. Join its `text` fragments in order;
|
|
62
|
+
offsets count UTF-16 code units. The returned absolute file path remains a
|
|
63
|
+
fallback for `read` after extension reload while the file exists. Tool query
|
|
64
|
+
pagination and limits still apply separately.
|
|
65
|
+
|
|
66
|
+
## Upgrade notes
|
|
67
|
+
|
|
68
|
+
After installing 0.3.0, deploy the matching add-in with Revit closed, restart Revit,
|
|
69
|
+
and start a fresh Pi session to load the new tool schemas. Obtain a new overview
|
|
70
|
+
before changing a document. Setup preserves existing `AGENTS.md`; older workspaces
|
|
71
|
+
need these exact-ID, saved-result, and identity-derived folder rules merged into
|
|
72
|
+
their existing instructions.
|