pi-revit 0.1.7 → 0.1.9
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/README.md +10 -10
- package/package.json +1 -1
- package/scripts/setup-workspace.ps1 +8 -11
- package/src/Revit/Tools/ExportDocuments.cs +37 -5
- package/src/Revit/Tools/SearchApiDocs.cs +93 -39
- package/workspace/AGENTS.md +25 -7
- package/workspace/pi-revit-global.cmd +12 -31
- package/workspace/project-AGENTS.md +0 -8
package/README.md
CHANGED
|
@@ -115,16 +115,16 @@ That's all. Pi starts with the Revit tools ready:
|
|
|
115
115
|
`pi` command itself. That folder is on your system PATH — which is exactly why *every* terminal
|
|
116
116
|
finds `pi-revit`, with no extra configuration. When you run it, it switches to your workspace at
|
|
117
117
|
`Documents\pi-revit` and starts Pi there, so your conventions file (`AGENTS.md`) loads
|
|
118
|
-
automatically and all Revit session history lives in one predictable place
|
|
119
|
-
themselves are installed globally in Pi, and the
|
|
120
|
-
inside Revit each time a session starts.
|
|
118
|
+
automatically and all Revit session history lives in one predictable place (`pi-revit -c`
|
|
119
|
+
continues the last session). The Revit tools themselves are installed globally in Pi, and the
|
|
120
|
+
extension discovers them live from the bridge inside Revit each time a session starts.
|
|
121
121
|
|
|
122
|
-
**Per
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
122
|
+
**Per model, automatically:** files sort themselves. Exports land in
|
|
123
|
+
`Documents\pi-revit\Models\<model title>\exports` — the add-in derives the folder from the
|
|
124
|
+
document being exported, so even a session that touches many models files every output under
|
|
125
|
+
the right one, with no naming decision from you or the AI. Each model folder carries a
|
|
126
|
+
`model.txt` recording the model's GUID and file path, so two models that share a title stay
|
|
127
|
+
distinguishable.
|
|
128
128
|
|
|
129
129
|
Plain `pi` from any folder also works; `pi-revit` just adds the right working folder on top.
|
|
130
130
|
|
|
@@ -142,7 +142,7 @@ Plain `pi` from any folder also works; `pi-revit` just adds the right working fo
|
|
|
142
142
|
| `search_api_docs` | Search the offline Revit API docs (works with no document open) |
|
|
143
143
|
| `execute_csharp` | Run a C# script in one auto-managed transaction — the escape hatch |
|
|
144
144
|
| `capture_view` | PNG snapshot of a view to a temp file (read the returned path to see it) |
|
|
145
|
-
| `export_documents` | PDF/DWG/PNG/IFC export of sheets and views |
|
|
145
|
+
| `export_documents` | PDF/DWG/PNG/IFC export of sheets and views — auto-sorted into `Models\<model>\exports` |
|
|
146
146
|
| `get_model_health` | Warnings grouped + worksets, phases, design options audit |
|
|
147
147
|
|
|
148
148
|
## Limitations — read before using on real projects
|
package/package.json
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
<#
|
|
3
3
|
Sets up the pi-revit user environment on this PC:
|
|
4
4
|
|
|
5
|
-
1. Workspace at Documents\pi-revit (AGENTS.md conventions,
|
|
6
|
-
double-click launcher).
|
|
5
|
+
1. Workspace at Documents\pi-revit (AGENTS.md conventions, Models\ output tree,
|
|
6
|
+
double-click launcher). An existing AGENTS.md is never overwritten.
|
|
7
7
|
2. Global `pi-revit` command installed next to the `pi` command, so any terminal can run:
|
|
8
8
|
pi-revit -> Pi in the workspace
|
|
9
|
-
pi-revit
|
|
10
|
-
|
|
9
|
+
pi-revit -c -> continue the last session
|
|
10
|
+
Model output sorts itself: the Revit tools file each export under
|
|
11
|
+
Models\<model title>\ automatically, keyed by the document it came from.
|
|
11
12
|
|
|
12
13
|
Idempotent — safe to re-run. Usage:
|
|
13
14
|
scripts\setup-workspace.ps1
|
|
@@ -20,18 +21,14 @@ param(
|
|
|
20
21
|
$ErrorActionPreference = 'Stop'
|
|
21
22
|
$templates = Join-Path (Split-Path $PSScriptRoot -Parent) 'workspace'
|
|
22
23
|
|
|
23
|
-
# 1. Workspace folders
|
|
24
|
-
New-Item -ItemType Directory -Force -Path (Join-Path $WorkspaceDir '
|
|
24
|
+
# 1. Workspace folders. Models\ is where the Revit tools file per-model output.
|
|
25
|
+
New-Item -ItemType Directory -Force -Path (Join-Path $WorkspaceDir 'Models') | Out-Null
|
|
25
26
|
|
|
26
27
|
# Conventions / notes: copy only when missing so user edits survive re-runs.
|
|
27
28
|
$workspaceAgents = Join-Path $WorkspaceDir 'AGENTS.md'
|
|
28
29
|
if (-not (Test-Path $workspaceAgents)) {
|
|
29
30
|
Copy-Item (Join-Path $templates 'AGENTS.md') $workspaceAgents
|
|
30
31
|
}
|
|
31
|
-
$projectAgents = Join-Path $WorkspaceDir 'Projects\sample\AGENTS.md'
|
|
32
|
-
if (-not (Test-Path $projectAgents)) {
|
|
33
|
-
Copy-Item (Join-Path $templates 'project-AGENTS.md') $projectAgents
|
|
34
|
-
}
|
|
35
32
|
|
|
36
33
|
# Launcher is code, not user data: always refresh.
|
|
37
34
|
Copy-Item (Join-Path $templates 'pi-revit-here.cmd') (Join-Path $WorkspaceDir 'pi-revit.cmd') -Force
|
|
@@ -77,7 +74,7 @@ if ($pi) {
|
|
|
77
74
|
# localized folder names) stay intact.
|
|
78
75
|
Set-Content -Path (Join-Path $binDir 'pi-revit.cmd') -Value $globalCmd -Encoding Oem
|
|
79
76
|
Write-Host "Global command installed: $(Join-Path $binDir 'pi-revit.cmd')" -ForegroundColor Green
|
|
80
|
-
Write-Host 'Run pi-revit from any terminal (pi-revit
|
|
77
|
+
Write-Host 'Run pi-revit from any terminal (pi-revit -c continues the last session).'
|
|
81
78
|
} else {
|
|
82
79
|
Write-Warning 'No permanent pi command found on PATH. Install Pi first (npm install -g --ignore-scripts @earendil-works/pi-coding-agent), then run npx.cmd -y pi-revit again (or re-run this script) to get the global pi-revit command.'
|
|
83
80
|
}
|
|
@@ -19,7 +19,7 @@ namespace RevitBridge.Tools
|
|
|
19
19
|
|
|
20
20
|
public string Name => "export_documents";
|
|
21
21
|
public string Label => "Export Documents";
|
|
22
|
-
public string Description => "Export documents from the open Revit model. format 'pdf'/'dwg'/'png' export the given sheet/view ids to files: pdf combines everything into one file by default (combine=false writes one PDF per sheet/view, named by Revit's naming rule); png renders 2048 px wide; ifc exports the whole model, or just what one given view shows. Files
|
|
22
|
+
public string Description => "Export documents from the open Revit model. format 'pdf'/'dwg'/'png' export the given sheet/view ids to files: pdf combines everything into one file by default (combine=false writes one PDF per sheet/view, named by Revit's naming rule); png renders 2048 px wide; ifc exports the whole model, or just what one given view shows. Files sort themselves per model: with output_dir omitted they land in Documents\\pi-revit\\Models\\<model title>\\exports, derived from the document being exported (pass output_dir only for a different explicit target); file_name_prefix sets the base file name (default: the document title; Revit appends view/sheet suffixes for multi-file exports). Returns the produced file paths with sizes. Find sheet/view ids with get_elements (category 'Sheets' or 'Views') first.";
|
|
23
23
|
public bool Write => true;
|
|
24
24
|
public string Tier => "advanced";
|
|
25
25
|
|
|
@@ -43,7 +43,7 @@ namespace RevitBridge.Tools
|
|
|
43
43
|
output_dir = new
|
|
44
44
|
{
|
|
45
45
|
type = "string",
|
|
46
|
-
description = "Output directory, created if missing. Default:
|
|
46
|
+
description = "Output directory, created if missing. Default: Documents\\pi-revit\\Models\\<model title>\\exports — files sort under the exported model automatically; omit unless the user names a different target.",
|
|
47
47
|
},
|
|
48
48
|
file_name_prefix = new
|
|
49
49
|
{
|
|
@@ -74,7 +74,7 @@ namespace RevitBridge.Tools
|
|
|
74
74
|
throw new ArgumentException($"Unknown format: {JsonArgs.GetString(args, "format")}. Supported: pdf, dwg, png, ifc.");
|
|
75
75
|
|
|
76
76
|
var views = ResolveViews(doc, args, format);
|
|
77
|
-
string outputDir = ResolveOutputDir(args);
|
|
77
|
+
string outputDir = ResolveOutputDir(args, doc);
|
|
78
78
|
string? prefixInput = JsonArgs.GetString(args, "file_name_prefix");
|
|
79
79
|
string baseName = SanitizeFileName(string.IsNullOrWhiteSpace(prefixInput) ? doc.Title : prefixInput.Trim());
|
|
80
80
|
bool combine = JsonArgs.GetBool(args, "combine", true);
|
|
@@ -236,16 +236,48 @@ namespace RevitBridge.Tools
|
|
|
236
236
|
return views;
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
-
private static string ResolveOutputDir(JsonElement args)
|
|
239
|
+
private static string ResolveOutputDir(JsonElement args, Document doc)
|
|
240
240
|
{
|
|
241
241
|
string? requested = JsonArgs.GetString(args, "output_dir");
|
|
242
242
|
string outputDir = string.IsNullOrWhiteSpace(requested)
|
|
243
|
-
? Path.Combine(
|
|
243
|
+
? Path.Combine(ModelFolder(doc), "exports")
|
|
244
244
|
: Path.GetFullPath(requested.Trim());
|
|
245
245
|
Directory.CreateDirectory(outputDir);
|
|
246
246
|
return outputDir;
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
+
/// <summary>Per-model folder under the pi-revit workspace:
|
|
250
|
+
/// Documents\pi-revit\Models\<model title>. The exporting tool is the one
|
|
251
|
+
/// component that knows with certainty which model a file belongs to, so the
|
|
252
|
+
/// sorting is automatic — never an agent or user decision. model.txt records
|
|
253
|
+
/// the model's identity so same-titled models stay distinguishable.</summary>
|
|
254
|
+
private static string ModelFolder(Document doc)
|
|
255
|
+
{
|
|
256
|
+
string workspace = Path.Combine(
|
|
257
|
+
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "pi-revit");
|
|
258
|
+
string title = SanitizeFileName(string.IsNullOrWhiteSpace(doc.Title) ? "untitled" : doc.Title);
|
|
259
|
+
string folder = Path.Combine(workspace, "Models", title);
|
|
260
|
+
Directory.CreateDirectory(folder);
|
|
261
|
+
TryRecordModelIdentity(folder, doc);
|
|
262
|
+
return folder;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
private static void TryRecordModelIdentity(string folder, Document doc)
|
|
266
|
+
{
|
|
267
|
+
try
|
|
268
|
+
{
|
|
269
|
+
string guid = doc.ProjectInformation?.UniqueId ?? string.Empty;
|
|
270
|
+
string line = $"{guid}\t{doc.PathName}";
|
|
271
|
+
string marker = Path.Combine(folder, "model.txt");
|
|
272
|
+
if (!File.Exists(marker) || !File.ReadAllLines(marker).Contains(line))
|
|
273
|
+
File.AppendAllLines(marker, new[] { line });
|
|
274
|
+
}
|
|
275
|
+
catch
|
|
276
|
+
{
|
|
277
|
+
// The identity record is best-effort; never block an export on it.
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
249
281
|
private static string SanitizeFileName(string name)
|
|
250
282
|
{
|
|
251
283
|
var invalid = Path.GetInvalidFileNameChars();
|
|
@@ -4,6 +4,7 @@ using System.Text.Json;
|
|
|
4
4
|
using System.Xml;
|
|
5
5
|
using System.Xml.Linq;
|
|
6
6
|
using Autodesk.Revit.DB;
|
|
7
|
+
using Autodesk.Revit.UI;
|
|
7
8
|
|
|
8
9
|
namespace RevitBridge.Tools
|
|
9
10
|
{
|
|
@@ -22,13 +23,14 @@ namespace RevitBridge.Tools
|
|
|
22
23
|
private const int MaxResultsCap = 50;
|
|
23
24
|
private const int MaxMarkdownChars = 6_000;
|
|
24
25
|
private const int MaxSummaryChars = 600;
|
|
26
|
+
private const int MaxRemarksChars = 600;
|
|
25
27
|
private const int MaxReturnsChars = 300;
|
|
26
28
|
private const int MaxParamDocChars = 240;
|
|
27
29
|
private const int MaxParamsPerMember = 10;
|
|
28
30
|
|
|
29
31
|
public string Name => "search_api_docs";
|
|
30
32
|
public string Label => "Search API Docs";
|
|
31
|
-
public string Description => "Search the offline Revit API documentation (the RevitAPI.xml and RevitAPIUI.xml files shipped with Revit) for types, methods, constructors, properties, fields
|
|
33
|
+
public string Description => "Search the offline Revit API documentation (the RevitAPI.xml and RevitAPIUI.xml files shipped with Revit) for types, methods, constructors, properties, fields, and events; every public API enum is fully searchable by value name (values the XML leaves undocumented are synthesized from the API assemblies). query is a single name or substring — e.g. 'FilteredElementCollector', 'Wall.Create', 'WALL_BASE_OFFSET' — ranked: exact name first, then prefix, then substring; dotted Type.Member queries match composites. Returns signatures with summary, remarks, parameter docs, return docs, and the Revit version a member was introduced in ('since'). Works with no document open. Use it to verify exact classes, members, and signatures before writing execute_csharp code. The first query builds the index (a few seconds); later queries are instant.";
|
|
32
34
|
|
|
33
35
|
public bool RequiresDocument => false;
|
|
34
36
|
|
|
@@ -90,6 +92,7 @@ namespace RevitBridge.Tools
|
|
|
90
92
|
["assembly"] = member.Assembly,
|
|
91
93
|
["since"] = member.Since,
|
|
92
94
|
["summary"] = member.Summary,
|
|
95
|
+
["remarks"] = member.Remarks,
|
|
93
96
|
["parameters"] = member.Parameters?
|
|
94
97
|
.Select(pair => new Dictionary<string, object?> { ["name"] = pair.Key, ["description"] = pair.Value })
|
|
95
98
|
.ToList(),
|
|
@@ -177,6 +180,8 @@ namespace RevitBridge.Tools
|
|
|
177
180
|
break;
|
|
178
181
|
}
|
|
179
182
|
markdown.Append(line);
|
|
183
|
+
if (i == 0)
|
|
184
|
+
AppendTopMatchDocs(markdown, member);
|
|
180
185
|
}
|
|
181
186
|
}
|
|
182
187
|
foreach (string warning in index.Warnings)
|
|
@@ -184,6 +189,27 @@ namespace RevitBridge.Tools
|
|
|
184
189
|
return markdown.ToString();
|
|
185
190
|
}
|
|
186
191
|
|
|
192
|
+
/// <summary>The model sees only this markdown — details.payload never reaches it —
|
|
193
|
+
/// so the top match carries its remarks, parameter, and return docs inline. Lines
|
|
194
|
+
/// that would blow the markdown budget are dropped individually; narrowing the
|
|
195
|
+
/// query promotes any other match to the top slot with its docs.</summary>
|
|
196
|
+
private static void AppendTopMatchDocs(StringBuilder markdown, ApiMember member)
|
|
197
|
+
{
|
|
198
|
+
var lines = new List<string>(3);
|
|
199
|
+
if (member.Remarks is { } remarks)
|
|
200
|
+
lines.Add($"\n remarks: {remarks}");
|
|
201
|
+
if (member.Parameters is { Count: > 0 } parameters)
|
|
202
|
+
lines.Add($"\n params: {string.Join("; ", parameters.Select(pair => $"{pair.Key} — {pair.Value}"))}");
|
|
203
|
+
if (member.Returns is { } returns)
|
|
204
|
+
lines.Add($"\n returns: {returns}");
|
|
205
|
+
foreach (string line in lines)
|
|
206
|
+
{
|
|
207
|
+
if (markdown.Length + line.Length > MaxMarkdownChars)
|
|
208
|
+
break;
|
|
209
|
+
markdown.Append(line);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
187
213
|
private static string KindLabel(ApiMember member) => member.IsConstructor ? "constructor" : member.Kind switch
|
|
188
214
|
{
|
|
189
215
|
'T' => "type",
|
|
@@ -237,6 +263,7 @@ namespace RevitBridge.Tools
|
|
|
237
263
|
public required string CompositeLower { get; init; }
|
|
238
264
|
public required string ShortNameLower { get; init; }
|
|
239
265
|
public string? Summary { get; init; }
|
|
266
|
+
public string? Remarks { get; init; }
|
|
240
267
|
public string? Returns { get; init; }
|
|
241
268
|
public string? Since { get; init; }
|
|
242
269
|
public IReadOnlyList<KeyValuePair<string, string>>? Parameters { get; init; }
|
|
@@ -259,7 +286,7 @@ namespace RevitBridge.Tools
|
|
|
259
286
|
var sources = new List<string>();
|
|
260
287
|
var warnings = new List<string>();
|
|
261
288
|
|
|
262
|
-
foreach (string path in CandidateXmlFiles())
|
|
289
|
+
foreach (string path in CandidateXmlFiles(warnings))
|
|
263
290
|
{
|
|
264
291
|
if (!File.Exists(path))
|
|
265
292
|
{
|
|
@@ -277,55 +304,77 @@ namespace RevitBridge.Tools
|
|
|
277
304
|
}
|
|
278
305
|
}
|
|
279
306
|
|
|
280
|
-
|
|
307
|
+
AddUndocumentedEnumValues(members, warnings);
|
|
281
308
|
|
|
282
309
|
return new DocIndex { Members = members, SourceFiles = sources, Warnings = warnings };
|
|
283
310
|
}
|
|
284
311
|
|
|
285
|
-
/// <summary>Autodesk's XML
|
|
286
|
-
///
|
|
287
|
-
///
|
|
288
|
-
|
|
312
|
+
/// <summary>Autodesk's XML leaves many public API enums partially or entirely
|
|
313
|
+
/// undocumented (measured on Revit 2025: 107 of 669, from BuiltInCategory's ~1200
|
|
314
|
+
/// values down to small flags). Synthesize the missing values from the loaded API
|
|
315
|
+
/// assemblies via reflection — pure metadata, safe off the Revit thread.</summary>
|
|
316
|
+
private static void AddUndocumentedEnumValues(List<ApiMember> members, List<string> warnings)
|
|
289
317
|
{
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
members
|
|
294
|
-
.Where(member => member.FullName.StartsWith("Autodesk.Revit.DB.BuiltInCategory.", StringComparison.Ordinal))
|
|
295
|
-
.Select(member => member.FullName),
|
|
296
|
-
StringComparer.Ordinal);
|
|
318
|
+
var existing = new HashSet<string>(
|
|
319
|
+
members.Where(member => member.Kind == 'F').Select(member => member.FullName),
|
|
320
|
+
StringComparer.Ordinal);
|
|
297
321
|
|
|
298
|
-
|
|
322
|
+
var assemblies = new (Func<System.Reflection.Assembly> Load, string Label)[]
|
|
323
|
+
{
|
|
324
|
+
(() => typeof(Document).Assembly, "RevitAPI"),
|
|
325
|
+
(() => typeof(UIApplication).Assembly, "RevitAPIUI"),
|
|
326
|
+
};
|
|
327
|
+
foreach (var (load, label) in assemblies)
|
|
328
|
+
{
|
|
329
|
+
try
|
|
299
330
|
{
|
|
300
|
-
|
|
301
|
-
if (!existing.Add(fullName))
|
|
302
|
-
continue;
|
|
303
|
-
|
|
304
|
-
string composite = "BuiltInCategory." + name;
|
|
305
|
-
members.Add(new ApiMember
|
|
331
|
+
foreach (var type in load().GetExportedTypes())
|
|
306
332
|
{
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
CompositeLower = composite.ToLowerInvariant(),
|
|
315
|
-
ShortNameLower = name.ToLowerInvariant(),
|
|
316
|
-
Summary = "BuiltInCategory enum value — usable as the 'category' argument of get_elements/get_element_types and with FilteredElementCollector.OfCategory in execute_csharp.",
|
|
317
|
-
});
|
|
333
|
+
if (type.IsEnum)
|
|
334
|
+
AddEnumValues(type, label, existing, members);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch (Exception ex)
|
|
338
|
+
{
|
|
339
|
+
warnings.Add($"Could not enumerate {label} enum values: {ex.Message}");
|
|
318
340
|
}
|
|
319
341
|
}
|
|
320
|
-
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/// <summary>Adds every value of one enum that the XML did not document itself.</summary>
|
|
345
|
+
private static void AddEnumValues(Type enumType, string assemblyName, HashSet<string> existing, List<ApiMember> members)
|
|
346
|
+
{
|
|
347
|
+
string typeName = enumType.Name;
|
|
348
|
+
string fullPrefix = (enumType.FullName ?? typeName).Replace('+', '.');
|
|
349
|
+
foreach (string name in Enum.GetNames(enumType))
|
|
321
350
|
{
|
|
322
|
-
|
|
351
|
+
string fullName = fullPrefix + "." + name;
|
|
352
|
+
if (!existing.Add(fullName))
|
|
353
|
+
continue;
|
|
354
|
+
|
|
355
|
+
string composite = typeName + "." + name;
|
|
356
|
+
members.Add(new ApiMember
|
|
357
|
+
{
|
|
358
|
+
Kind = 'F',
|
|
359
|
+
IsConstructor = false,
|
|
360
|
+
Assembly = assemblyName,
|
|
361
|
+
FullName = fullName,
|
|
362
|
+
Composite = composite,
|
|
363
|
+
Signature = composite,
|
|
364
|
+
FullNameLower = fullName.ToLowerInvariant(),
|
|
365
|
+
CompositeLower = composite.ToLowerInvariant(),
|
|
366
|
+
ShortNameLower = name.ToLowerInvariant(),
|
|
367
|
+
Summary = enumType == typeof(BuiltInCategory)
|
|
368
|
+
? "BuiltInCategory enum value — usable as the 'category' argument of get_elements/get_element_types and with FilteredElementCollector.OfCategory in execute_csharp."
|
|
369
|
+
: $"{typeName} enum value (not documented in the XML; synthesized from {assemblyName} metadata).",
|
|
370
|
+
});
|
|
323
371
|
}
|
|
324
372
|
}
|
|
325
373
|
|
|
326
|
-
/// <summary>RevitAPI.xml + RevitAPIUI.xml next to the loaded RevitAPI.dll
|
|
327
|
-
///
|
|
328
|
-
|
|
374
|
+
/// <summary>RevitAPI.xml + RevitAPIUI.xml next to the loaded RevitAPI.dll. When the
|
|
375
|
+
/// assembly location cannot be resolved, indexing is skipped with a warning instead
|
|
376
|
+
/// of guessing at an install directory for a Revit version that was never detected.</summary>
|
|
377
|
+
private static IEnumerable<string> CandidateXmlFiles(List<string> warnings)
|
|
329
378
|
{
|
|
330
379
|
string? installDir = null;
|
|
331
380
|
try
|
|
@@ -336,9 +385,13 @@ namespace RevitBridge.Tools
|
|
|
336
385
|
}
|
|
337
386
|
catch
|
|
338
387
|
{
|
|
339
|
-
//
|
|
388
|
+
// Handled below together with the empty-location case.
|
|
389
|
+
}
|
|
390
|
+
if (string.IsNullOrEmpty(installDir))
|
|
391
|
+
{
|
|
392
|
+
warnings.Add("Could not resolve the Revit install directory from the loaded RevitAPI.dll; documentation indexing skipped.");
|
|
393
|
+
yield break;
|
|
340
394
|
}
|
|
341
|
-
installDir = string.IsNullOrEmpty(installDir) ? @"C:\Program Files\Autodesk\Revit 2025" : installDir;
|
|
342
395
|
yield return Path.Combine(installDir, "RevitAPI.xml");
|
|
343
396
|
yield return Path.Combine(installDir, "RevitAPIUI.xml");
|
|
344
397
|
}
|
|
@@ -446,6 +499,7 @@ namespace RevitBridge.Tools
|
|
|
446
499
|
CompositeLower = composite.ToLowerInvariant(),
|
|
447
500
|
ShortNameLower = shortName.ToLowerInvariant(),
|
|
448
501
|
Summary = Cap(CleanDocText(element.Element("summary")), MaxSummaryChars),
|
|
502
|
+
Remarks = Cap(CleanDocText(element.Element("remarks")), MaxRemarksChars),
|
|
449
503
|
Returns = Cap(CleanDocText(element.Element("returns")), MaxReturnsChars),
|
|
450
504
|
Since = CleanDocText(element.Element("since")),
|
|
451
505
|
Parameters = parameters,
|
package/workspace/AGENTS.md
CHANGED
|
@@ -4,14 +4,32 @@ This folder tree is the working area for Pi + Revit sessions. The pi-revit tools
|
|
|
4
4
|
Revit bridge add-in; Revit 2025, 2026, or 2027 must be running with a project open
|
|
5
5
|
(only `ping` and `search_api_docs` work without a document).
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## File rules — where every file goes
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
|
|
9
|
+
Work sorts by model, automatically. The export tool files its output under the model it came
|
|
10
|
+
from — never a decision for you or the user to make:
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
Documents\pi-revit\
|
|
14
|
+
├─ AGENTS.md <- this file
|
|
15
|
+
├─ pi-revit.cmd <- double-click launcher
|
|
16
|
+
└─ Models\
|
|
17
|
+
└─ <model title>\ <- created automatically by the tools, one folder per Revit model
|
|
18
|
+
├─ model.txt <- the model's identity (GUID + file path), written by the add-in
|
|
19
|
+
├─ exports\ <- export_documents output (its default)
|
|
20
|
+
├─ captures\ <- view snapshots worth keeping
|
|
21
|
+
└─ scripts\ <- generated scripts and analysis for that model
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
1. **Let exports sort themselves**: call `export_documents` without `output_dir` — files land
|
|
25
|
+
in `Models\<model title>\exports` automatically, keyed to the exported document. Pass
|
|
26
|
+
`output_dir` only when the user names a different target.
|
|
27
|
+
2. **Anything else you produce about a model goes into that model's folder**: view captures the
|
|
28
|
+
user wants to keep in `Models\<model title>\captures` (`capture_view` writes to temp — copy
|
|
29
|
+
the PNG over; the model title comes from `get_model_overview`), scripts and analysis in
|
|
30
|
+
`Models\<model title>\scripts`. Create these subfolders on first use.
|
|
31
|
+
3. **Never create files loose in the workspace root.** The root holds `AGENTS.md`,
|
|
32
|
+
`pi-revit.cmd`, `Models\`, and Pi's own session data — nothing else, ever.
|
|
15
33
|
|
|
16
34
|
## Tool habits
|
|
17
35
|
|
|
@@ -1,31 +1,12 @@
|
|
|
1
|
-
@echo off
|
|
2
|
-
rem pi-revit: open Pi in the pi-revit workspace from anywhere.
|
|
3
|
-
rem
|
|
4
|
-
rem
|
|
5
|
-
rem
|
|
6
|
-
rem Installed next to the pi command by scripts\setup-workspace.ps1, which rewrites
|
|
7
|
-
rem the WORKSPACE line below to the chosen -WorkspaceDir.
|
|
8
|
-
|
|
9
|
-
set "WORKSPACE=%USERPROFILE%\Documents\pi-revit"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
pi
|
|
14
|
-
exit /b
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
if exist "%WORKSPACE%\Projects\%~1\" (
|
|
18
|
-
cd /d "%WORKSPACE%\Projects\%~1"
|
|
19
|
-
shift
|
|
20
|
-
) else (
|
|
21
|
-
cd /d "%WORKSPACE%"
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
set "ARGS="
|
|
25
|
-
:collect
|
|
26
|
-
if not "%~1"=="" (
|
|
27
|
-
set "ARGS=%ARGS% %1"
|
|
28
|
-
shift
|
|
29
|
-
goto collect
|
|
30
|
-
)
|
|
31
|
-
pi%ARGS%
|
|
1
|
+
@echo off
|
|
2
|
+
rem pi-revit: open Pi in the pi-revit workspace from anywhere. All arguments are
|
|
3
|
+
rem passed straight to pi (e.g. pi-revit -c continues the last session).
|
|
4
|
+
rem Model output needs no foldering decision: the Revit tools file each export
|
|
5
|
+
rem under Models\<model title>\ automatically, keyed by the document it came from.
|
|
6
|
+
rem Installed next to the pi command by scripts\setup-workspace.ps1, which rewrites
|
|
7
|
+
rem the WORKSPACE line below to the chosen -WorkspaceDir.
|
|
8
|
+
|
|
9
|
+
set "WORKSPACE=%USERPROFILE%\Documents\pi-revit"
|
|
10
|
+
|
|
11
|
+
cd /d "%WORKSPACE%"
|
|
12
|
+
pi %*
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
# Project: (name)
|
|
2
|
-
|
|
3
|
-
Notes for Pi sessions on this Revit project. Replace/extend as you learn the model.
|
|
4
|
-
|
|
5
|
-
- Model: (file name / what it is)
|
|
6
|
-
- Units: (metric/imperial)
|
|
7
|
-
- Naming conventions: (levels, views, sheets)
|
|
8
|
-
- Known quirks: (warnings to ignore, in-place families, etc.)
|