pi-revit 0.4.0 → 0.5.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.
- package/AGENTS.md +167 -0
- package/CHANGELOG.md +465 -430
- package/README.md +604 -548
- package/bin/pi-revit.js +9 -9
- package/docs/architecture.md +271 -0
- package/docs/evaluation.md +434 -0
- package/docs/invariants.json +147 -0
- package/extensions/pi-revit/completion-monitor.ts +55 -0
- package/extensions/pi-revit/contracts.ts +146 -0
- package/extensions/pi-revit/discovery.ts +93 -0
- package/extensions/pi-revit/index.ts +342 -255
- package/extensions/pi-revit/instance-router.ts +86 -86
- package/extensions/pi-revit/platform-prompt.ts +40 -0
- package/extensions/pi-revit/scope-monitor.ts +114 -0
- package/extensions/pi-revit/script-library.ts +144 -144
- package/extensions/pi-revit/tool-catalog.ts +113 -14
- package/extensions/pi-revit/tool-documentation.ts +72 -0
- package/extensions/pi-revit/tool-schema.ts +8 -0
- package/package.json +8 -2
- package/scripts/build.ps1 +9 -9
- package/scripts/check-sdk.ps1 +66 -66
- package/scripts/check-tool-documentation.mjs +287 -0
- package/scripts/deploy.ps1 +16 -16
- package/scripts/generate-contracts.mjs +80 -0
- package/scripts/lib/platform.mjs +226 -0
- package/scripts/test-extension.mjs +15 -0
- package/skills/pi-revit/SKILL.md +30 -218
- package/skills/pi-revit/contracts.generated.json +3524 -0
- package/skills/pi-revit/references/execution-rules.md +41 -0
- package/skills/pi-revit/references/model-audit-export.md +38 -27
- package/skills/pi-revit/references/operation-recovery.md +33 -0
- package/skills/pi-revit/references/room-documentation.md +37 -26
- package/skills/pi-revit/references/tool-index.md +89 -0
- package/skills/pi-revit/references/tools/capture_view.md +62 -0
- package/skills/pi-revit/references/tools/change_element_types.md +65 -0
- package/skills/pi-revit/references/tools/create_tags.md +85 -0
- package/skills/pi-revit/references/tools/delete_elements.md +66 -0
- package/skills/pi-revit/references/tools/execute_csharp.md +81 -0
- package/skills/pi-revit/references/tools/export_documents.md +75 -0
- package/skills/pi-revit/references/tools/find_revit_tools.md +96 -0
- package/skills/pi-revit/references/tools/get_element_details.md +66 -0
- package/skills/pi-revit/references/tools/get_element_relationships.md +61 -0
- package/skills/pi-revit/references/tools/get_element_types.md +67 -0
- package/skills/pi-revit/references/tools/get_elements.md +87 -0
- package/skills/pi-revit/references/tools/get_linked_elements.md +79 -0
- package/skills/pi-revit/references/tools/get_linked_models.md +57 -0
- package/skills/pi-revit/references/tools/get_model_coordinates.md +64 -0
- package/skills/pi-revit/references/tools/get_model_health.md +53 -0
- package/skills/pi-revit/references/tools/get_model_overview.md +57 -0
- package/skills/pi-revit/references/tools/get_revit_operation.md +54 -0
- package/skills/pi-revit/references/tools/get_schedule_fields.md +62 -0
- package/skills/pi-revit/references/tools/get_schedules.md +71 -0
- package/skills/pi-revit/references/tools/manage_element_sets.md +92 -0
- package/skills/pi-revit/references/tools/manage_revit_instances.md +63 -0
- package/skills/pi-revit/references/tools/manage_revit_scripts.md +109 -0
- package/skills/pi-revit/references/tools/manage_schedules.md +90 -0
- package/skills/pi-revit/references/tools/manage_selection.md +66 -0
- package/skills/pi-revit/references/tools/manage_sheet_placements.md +82 -0
- package/skills/pi-revit/references/tools/manage_sheets.md +71 -0
- package/skills/pi-revit/references/tools/manage_views.md +95 -0
- package/skills/pi-revit/references/tools/measure_geometry.md +71 -0
- package/skills/pi-revit/references/tools/open_view.md +59 -0
- package/skills/pi-revit/references/tools/ping.md +41 -0
- package/skills/pi-revit/references/tools/query_spatial_elements.md +74 -0
- package/skills/pi-revit/references/tools/read_revit_result.md +53 -0
- package/skills/pi-revit/references/tools/search_api_docs.md +65 -0
- package/skills/pi-revit/references/tools/set_parameters.md +75 -0
- package/skills/pi-revit/references/tools/summarize_elements.md +64 -0
- package/skills/pi-revit/references/tools/transform_elements.md +79 -0
- package/skills/pi-revit/references/visual-verification.md +36 -0
- package/skills/pi-revit/tool-manifest.json +338 -0
- package/src/Revit/BridgeServer.cs +93 -87
- package/src/Revit/OperationStore.cs +178 -178
- package/src/Revit/ToolRegistry.cs +88 -57
- package/src/Revit/Tools/CaptureView.cs +10 -2
- package/src/Revit/Tools/ChangeElementTypes.cs +74 -60
- package/src/Revit/Tools/ChangeSet.cs +39 -0
- package/src/Revit/Tools/CreateTags.cs +107 -95
- package/src/Revit/Tools/DeleteElements.cs +53 -44
- package/src/Revit/Tools/DocumentGuard.cs +74 -64
- package/src/Revit/Tools/ElementNames.cs +103 -0
- package/src/Revit/Tools/ElementQueryScope.cs +27 -27
- package/src/Revit/Tools/ElementTraits.cs +53 -0
- package/src/Revit/Tools/ExecuteCsharp.cs +54 -45
- package/src/Revit/Tools/ExportDocuments.cs +129 -121
- package/src/Revit/Tools/GetElementDetails.cs +37 -41
- package/src/Revit/Tools/GetElementRelationships.cs +82 -76
- package/src/Revit/Tools/GetElementTypes.cs +8 -0
- package/src/Revit/Tools/GetElements.cs +75 -86
- package/src/Revit/Tools/GetLinkedElements.cs +89 -82
- package/src/Revit/Tools/GetLinkedModels.cs +73 -66
- package/src/Revit/Tools/GetModelCoordinates.cs +56 -49
- package/src/Revit/Tools/GetModelHealth.cs +7 -0
- package/src/Revit/Tools/GetModelOverview.cs +185 -158
- package/src/Revit/Tools/GetScheduleFields.cs +44 -37
- package/src/Revit/Tools/GetSchedules.cs +96 -89
- package/src/Revit/Tools/InheritedState.Summary.cs +57 -0
- package/src/Revit/Tools/InheritedState.cs +144 -0
- package/src/Revit/Tools/ManageElementSets.cs +114 -106
- package/src/Revit/Tools/ManageSchedules.cs +174 -164
- package/src/Revit/Tools/ManageSelection.cs +45 -37
- package/src/Revit/Tools/ManageSheetPlacements.cs +113 -97
- package/src/Revit/Tools/ManageSheets.cs +72 -63
- package/src/Revit/Tools/ManageViews.cs +115 -100
- package/src/Revit/Tools/MeasureGeometry.cs +60 -54
- package/src/Revit/Tools/ModelChanges.cs +154 -0
- package/src/Revit/Tools/ModelEditBatch.cs +105 -102
- package/src/Revit/Tools/ModelEditInputs.cs +49 -49
- package/src/Revit/Tools/OpenView.cs +9 -2
- package/src/Revit/Tools/ParameterResolver.cs +94 -0
- package/src/Revit/Tools/QuerySpatialElements.cs +70 -63
- package/src/Revit/Tools/SearchApiDocs.cs +72 -4
- package/src/Revit/Tools/SetParameters.cs +60 -79
- package/src/Revit/Tools/SpatialBounds.cs +30 -30
- package/src/Revit/Tools/SummarizeElements.cs +94 -87
- package/src/Revit/Tools/ToolContract.cs +48 -0
- package/src/Revit/Tools/ToolSupport.cs +5 -1
- package/src/Revit/Tools/TransformElements.cs +72 -57
- package/workspace/AGENTS.md +26 -20
|
@@ -1,49 +1,56 @@
|
|
|
1
|
-
using System.Text.Json;
|
|
2
|
-
using Autodesk.Revit.DB;
|
|
3
|
-
|
|
4
|
-
namespace RevitBridge.Tools;
|
|
5
|
-
|
|
6
|
-
internal sealed class GetModelCoordinates : ITool
|
|
7
|
-
{
|
|
8
|
-
public string Name => "get_model_coordinates";
|
|
9
|
-
public string
|
|
10
|
-
public string
|
|
11
|
-
public
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
1
|
+
using System.Text.Json;
|
|
2
|
+
using Autodesk.Revit.DB;
|
|
3
|
+
|
|
4
|
+
namespace RevitBridge.Tools;
|
|
5
|
+
|
|
6
|
+
internal sealed class GetModelCoordinates : ITool
|
|
7
|
+
{
|
|
8
|
+
public string Name => "get_model_coordinates";
|
|
9
|
+
public IReadOnlyList<string> DocumentKinds => DocumentKind.ProjectOnly;
|
|
10
|
+
public IReadOnlyList<string> Keywords => new[] { "survey point", "project base point", "true north", "project north", "shared coordinates", "site location", "latitude", "longitude", "georeference", "elevation" };
|
|
11
|
+
public IReadOnlyList<ToolLimit> Limits => new[]
|
|
12
|
+
{
|
|
13
|
+
new ToolLimit("Identifying the datum, projection or EPSG code", "user", "Confirm the coordinate reference system with the surveyor or project standard"),
|
|
14
|
+
new ToolLimit("Changing coordinates or acquiring shared coordinates", "api", "ProjectLocation.SetProjectPosition; Document.AcquireCoordinates"),
|
|
15
|
+
};
|
|
16
|
+
public string Label => "Get Model Coordinates";
|
|
17
|
+
public string Tier => "advanced";
|
|
18
|
+
public string Description => "Read project/survey base points, active project location and site coordinates. Optionally report shared coordinates for up to 100 points expressed along document internal axes. Required unit applies to input points and every returned length; angles and latitude/longitude are degrees. The active location's Revit GetProjectPosition defines the shared mapping. List project locations with paging. Does not infer a GIS coordinate reference system or modify/acquire coordinates.";
|
|
19
|
+
public object ParametersSchema => new
|
|
20
|
+
{
|
|
21
|
+
type = "object", properties = new
|
|
22
|
+
{
|
|
23
|
+
unit = ModelEditInputs.LengthUnitSchema,
|
|
24
|
+
points = new { type = "array", maxItems = 100, items = ModelEditInputs.VectorSchema("Point along document internal axes, in unit.") },
|
|
25
|
+
offset = new { type = "integer", minimum = 0 }, limit = new { type = "integer", minimum = 1, maximum = 100 },
|
|
26
|
+
}, required = new[] { "unit" },
|
|
27
|
+
};
|
|
28
|
+
public object Execute(JsonElement args, ToolContext context)
|
|
29
|
+
{
|
|
30
|
+
var doc = context.Document ?? throw new NoActiveDocumentException();
|
|
31
|
+
if (doc.IsFamilyDocument) throw new ArgumentException("Project coordinates require a project document.");
|
|
32
|
+
double scale = ModelEditInputs.LengthScale(args);
|
|
33
|
+
var active = doc.ActiveProjectLocation;
|
|
34
|
+
object Position(ProjectPosition position) => new { east_west = position.EastWest / scale, north_south = position.NorthSouth / scale, elevation = position.Elevation / scale, angle_degrees = position.Angle * 180 / Math.PI };
|
|
35
|
+
object? Base(BasePoint? point) => point == null ? null : new { id = point.Id.Value, internal_position = SpatialBounds.Coordinates(point.Position, scale), shared_position = SpatialBounds.Coordinates(point.SharedPosition, scale) };
|
|
36
|
+
var points = new List<object>();
|
|
37
|
+
if (args.TryGetProperty("points", out var values))
|
|
38
|
+
{
|
|
39
|
+
if (values.ValueKind != JsonValueKind.Array || values.GetArrayLength() > 100) throw new ArgumentException("points must be an array of at most 100 XYZ points.");
|
|
40
|
+
foreach (var value in values.EnumerateArray())
|
|
41
|
+
{
|
|
42
|
+
var wrapper = JsonSerializer.SerializeToElement(new { point = value });
|
|
43
|
+
var point = ModelEditInputs.Vector(wrapper, "point").Multiply(scale);
|
|
44
|
+
points.Add(new { internal_position = SpatialBounds.Coordinates(point, scale), shared_position = Position(active.GetProjectPosition(point)) });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
var locations = doc.ProjectLocations.Cast<ProjectLocation>().OrderBy(x => x.Id.Value).ToList();
|
|
48
|
+
int offset = Math.Max(0, JsonArgs.GetInt(args, "offset", 0)), limit = Math.Clamp(JsonArgs.GetInt(args, "limit", 50), 1, 100);
|
|
49
|
+
var page = locations.Skip(offset).Take(limit).Select(x => new { id = x.Id.Value, name = x.Name, active = x.Id == active.Id, internal_origin_in_shared_coordinates = Position(x.GetProjectPosition(XYZ.Zero)) }).ToArray();
|
|
50
|
+
var site = doc.SiteLocation;
|
|
51
|
+
return new { unit = JsonArgs.GetString(args, "unit"), angle_unit = "degrees", point_input_coordinates = "document_internal", active_project_location = new { id = active.Id.Value, name = active.Name },
|
|
52
|
+
project_base_point = Base(BasePoint.GetProjectBasePoint(doc)), survey_point = Base(BasePoint.GetSurveyPoint(doc)),
|
|
53
|
+
site = new { name = site.Name, latitude_degrees = site.Latitude * 180 / Math.PI, longitude_degrees = site.Longitude * 180 / Math.PI, time_zone = site.TimeZone },
|
|
54
|
+
total_locations = locations.Count, offset, next_offset = offset + page.Length < locations.Count ? (int?)(offset + page.Length) : null, locations = page, points };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -16,6 +16,13 @@ namespace RevitBridge.Tools
|
|
|
16
16
|
private const int MaxElementsPerGroup = 20;
|
|
17
17
|
|
|
18
18
|
public string Name => "get_model_health";
|
|
19
|
+
public IReadOnlyList<string> DocumentKinds => DocumentKind.Both;
|
|
20
|
+
public IReadOnlyList<string> Keywords => new[] { "warnings", "errors", "audit", "model quality", "health check", "worksets", "phases", "design options", "in-place families" };
|
|
21
|
+
public IReadOnlyList<ToolLimit> Limits => new[]
|
|
22
|
+
{
|
|
23
|
+
new ToolLimit("Resolving warnings (report only)", "api", "Document.GetWarnings; resolve with dedicated edit tools or custom code within scope"),
|
|
24
|
+
new ToolLimit("Geometry, performance or standards-compliance audits", "api", "Custom inspection; verify members with search_api_docs"),
|
|
25
|
+
};
|
|
19
26
|
public string Label => "Get Model Health";
|
|
20
27
|
public string Description => "Audit the open Revit model: every document warning grouped by description (description, severity, occurrence count, failing element ids+names — the top 100 groups ordered by count, up to 20 elements each), plus structure counts: worksharing status with user worksets, phases, design options, in-place families, and the total element count. Read-only; use it to review model quality, e.g. before and after bulk edits.";
|
|
21
28
|
public string Tier => "advanced";
|
|
@@ -1,160 +1,187 @@
|
|
|
1
|
-
using System.Text.Json;
|
|
2
|
-
using Autodesk.Revit.DB;
|
|
3
|
-
|
|
4
|
-
namespace RevitBridge.Tools
|
|
5
|
-
{
|
|
6
|
-
internal sealed class GetModelOverview : ITool
|
|
7
|
-
{
|
|
8
|
-
public string Name => "get_model_overview";
|
|
9
|
-
public string
|
|
10
|
-
public string
|
|
11
|
-
public
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
["
|
|
27
|
-
["
|
|
28
|
-
["
|
|
29
|
-
["
|
|
30
|
-
["
|
|
31
|
-
["
|
|
32
|
-
["
|
|
33
|
-
["
|
|
34
|
-
["
|
|
35
|
-
["
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
var
|
|
47
|
-
|
|
1
|
+
using System.Text.Json;
|
|
2
|
+
using Autodesk.Revit.DB;
|
|
3
|
+
|
|
4
|
+
namespace RevitBridge.Tools
|
|
5
|
+
{
|
|
6
|
+
internal sealed class GetModelOverview : ITool
|
|
7
|
+
{
|
|
8
|
+
public string Name => "get_model_overview";
|
|
9
|
+
public IReadOnlyList<string> DocumentKinds => DocumentKind.Both;
|
|
10
|
+
public IReadOnlyList<string> Keywords => new[] { "project info", "model info", "units", "levels", "grids", "category counts", "summary", "document id", "identity", "document kind", "project or family", "family document" };
|
|
11
|
+
public IReadOnlyList<ToolLimit> Limits => new[]
|
|
12
|
+
{
|
|
13
|
+
new ToolLimit("Switching the active document or Revit session", "tool", "manage_revit_instances"),
|
|
14
|
+
};
|
|
15
|
+
public string Label => "Get Model Overview";
|
|
16
|
+
public string Description => "One-call orientation for the open Revit model: project metadata (title, name, number, client, address, file path, Revit version, display units), levels with elevations, grids, element counts for the major categories, and totals (elements, views, sheets). Use this first when starting work on a model.";
|
|
17
|
+
public object ParametersSchema => new { type = "object", properties = new { }, required = Array.Empty<string>() };
|
|
18
|
+
public string? PromptSnippet => "Get project info, units, levels, grids, and category counts for the open Revit model.";
|
|
19
|
+
public IReadOnlyList<string>? PromptGuidelines => new[]
|
|
20
|
+
{
|
|
21
|
+
"Call get_model_overview first when starting work on a Revit model; it covers project info, units, levels, grids, and per-category counts in one call.",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
private static readonly IReadOnlyDictionary<string, BuiltInCategory> MajorCategories = new Dictionary<string, BuiltInCategory>
|
|
25
|
+
{
|
|
26
|
+
["Walls"] = BuiltInCategory.OST_Walls,
|
|
27
|
+
["Doors"] = BuiltInCategory.OST_Doors,
|
|
28
|
+
["Windows"] = BuiltInCategory.OST_Windows,
|
|
29
|
+
["Floors"] = BuiltInCategory.OST_Floors,
|
|
30
|
+
["Rooms"] = BuiltInCategory.OST_Rooms,
|
|
31
|
+
["Areas"] = BuiltInCategory.OST_Areas,
|
|
32
|
+
["Ceilings"] = BuiltInCategory.OST_Ceilings,
|
|
33
|
+
["Roofs"] = BuiltInCategory.OST_Roofs,
|
|
34
|
+
["Columns"] = BuiltInCategory.OST_Columns,
|
|
35
|
+
["Structural Columns"] = BuiltInCategory.OST_StructuralColumns,
|
|
36
|
+
["Structural Framing"] = BuiltInCategory.OST_StructuralFraming,
|
|
37
|
+
["Stairs"] = BuiltInCategory.OST_Stairs,
|
|
38
|
+
["Furniture"] = BuiltInCategory.OST_Furniture,
|
|
39
|
+
["Generic Models"] = BuiltInCategory.OST_GenericModel,
|
|
40
|
+
["Pipes"] = BuiltInCategory.OST_PipeCurves,
|
|
41
|
+
["Ducts"] = BuiltInCategory.OST_DuctCurves,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
public object? Execute(JsonElement args, ToolContext context)
|
|
45
|
+
{
|
|
46
|
+
var doc = context.Document ?? throw new NoActiveDocumentException();
|
|
47
|
+
var info = doc.ProjectInformation;
|
|
48
|
+
var units = doc.GetUnits();
|
|
49
|
+
|
|
50
|
+
string system = doc.DisplayUnitSystem == DisplayUnit.IMPERIAL ? "imperial" : "metric";
|
|
51
|
+
string? lengthUnit = DisplayUnitName(units, SpecTypeId.Length);
|
|
52
|
+
var project = new Dictionary<string, object?>
|
|
53
|
+
{
|
|
48
54
|
["title"] = doc.Title,
|
|
49
55
|
["documentId"] = DocumentGuard.GetIdentity(doc),
|
|
50
|
-
["name"] = info?.Name,
|
|
51
|
-
["number"] = info?.Number,
|
|
52
|
-
["clientName"] = info?.ClientName,
|
|
53
|
-
["address"] = info?.Address,
|
|
54
|
-
["buildingName"] = info?.BuildingName,
|
|
55
|
-
["author"] = info?.Author,
|
|
56
|
-
["filePath"] = doc.PathName,
|
|
57
|
-
|
|
58
|
-
["
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
["
|
|
63
|
-
["
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
.
|
|
71
|
-
.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
["
|
|
76
|
-
["
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
.
|
|
84
|
-
.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
int
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
["
|
|
119
|
-
["
|
|
120
|
-
["
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
.
|
|
127
|
-
.
|
|
128
|
-
.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
56
|
+
["name"] = info?.Name,
|
|
57
|
+
["number"] = info?.Number,
|
|
58
|
+
["clientName"] = info?.ClientName,
|
|
59
|
+
["address"] = info?.Address,
|
|
60
|
+
["buildingName"] = info?.BuildingName,
|
|
61
|
+
["author"] = info?.Author,
|
|
62
|
+
["filePath"] = doc.PathName,
|
|
63
|
+
// Project or family: tools declare which kinds they work in, and the bridge refuses others.
|
|
64
|
+
["documentKind"] = DocumentGuard.KindOf(doc),
|
|
65
|
+
["revitVersion"] = doc.Application.VersionNumber,
|
|
66
|
+
["units"] = new Dictionary<string, object?>
|
|
67
|
+
{
|
|
68
|
+
["system"] = system,
|
|
69
|
+
["length"] = lengthUnit,
|
|
70
|
+
["area"] = DisplayUnitName(units, SpecTypeId.Area),
|
|
71
|
+
["volume"] = DisplayUnitName(units, SpecTypeId.Volume),
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
var levels = new FilteredElementCollector(doc)
|
|
76
|
+
.OfClass(typeof(Level))
|
|
77
|
+
.Cast<Level>()
|
|
78
|
+
.OrderBy(level => level.Elevation)
|
|
79
|
+
.Select(level => new Dictionary<string, object?>
|
|
80
|
+
{
|
|
81
|
+
["id"] = level.Id.Value,
|
|
82
|
+
["name"] = level.Name,
|
|
83
|
+
["elevation_ft"] = level.Elevation,
|
|
84
|
+
["elevation_display"] = FormatLength(units, level.Elevation),
|
|
85
|
+
})
|
|
86
|
+
.ToList();
|
|
87
|
+
|
|
88
|
+
var grids = new FilteredElementCollector(doc)
|
|
89
|
+
.OfClass(typeof(Grid))
|
|
90
|
+
.Cast<Grid>()
|
|
91
|
+
.OrderBy(grid => grid.Name, StringComparer.OrdinalIgnoreCase)
|
|
92
|
+
.Select(grid => new Dictionary<string, object?>
|
|
93
|
+
{
|
|
94
|
+
["id"] = grid.Id.Value,
|
|
95
|
+
["name"] = grid.Name,
|
|
96
|
+
})
|
|
97
|
+
.ToList();
|
|
98
|
+
|
|
99
|
+
var counts = new Dictionary<string, int>();
|
|
100
|
+
foreach (var (label, category) in MajorCategories)
|
|
101
|
+
{
|
|
102
|
+
try
|
|
103
|
+
{
|
|
104
|
+
counts[label] = new FilteredElementCollector(doc)
|
|
105
|
+
.OfCategory(category)
|
|
106
|
+
.WhereElementIsNotElementType()
|
|
107
|
+
.GetElementCount();
|
|
108
|
+
}
|
|
109
|
+
catch
|
|
110
|
+
{
|
|
111
|
+
counts[label] = 0;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
int totalElements = new FilteredElementCollector(doc).WhereElementIsNotElementType().GetElementCount();
|
|
116
|
+
int sheets = new FilteredElementCollector(doc).OfClass(typeof(ViewSheet)).GetElementCount();
|
|
117
|
+
int views = new FilteredElementCollector(doc)
|
|
118
|
+
.OfClass(typeof(View))
|
|
119
|
+
.Cast<View>()
|
|
120
|
+
.Count(view => !view.IsTemplate && view is not ViewSheet);
|
|
121
|
+
|
|
122
|
+
var totals = new Dictionary<string, int>
|
|
123
|
+
{
|
|
124
|
+
["elements"] = totalElements,
|
|
125
|
+
["views"] = views,
|
|
126
|
+
["sheets"] = sheets,
|
|
127
|
+
["levels"] = levels.Count,
|
|
128
|
+
["grids"] = grids.Count,
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
var topCategories = counts
|
|
132
|
+
.Where(pair => pair.Value > 0)
|
|
133
|
+
.OrderByDescending(pair => pair.Value)
|
|
134
|
+
.Take(5)
|
|
135
|
+
.Select(pair => $"{pair.Key} {pair.Value}")
|
|
136
|
+
.ToList();
|
|
137
|
+
string numberPart = string.IsNullOrWhiteSpace(info?.Number) ? string.Empty : $" (project {info!.Number})";
|
|
138
|
+
string compact = $"'{doc.Title}'{numberPart}: {totalElements} elements, {levels.Count} levels, {grids.Count} grids, {sheets} sheets, {views} views; units {system} ({lengthUnit})."
|
|
139
|
+
+ (topCategories.Count > 0 ? $" Top categories: {string.Join(", ", topCategories)}." : string.Empty);
|
|
140
|
+
|
|
141
|
+
if (doc.IsFamilyDocument) project["family"] = DescribeFamily(doc);
|
|
142
|
+
return new ToolOutput(new { project, levels, grids, counts, totals }, compact);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/// <summary>What a family document holds: its category, types and parameters (names only).</summary>
|
|
146
|
+
private static Dictionary<string, object?> DescribeFamily(Document doc)
|
|
147
|
+
{
|
|
148
|
+
var manager = doc.FamilyManager;
|
|
149
|
+
var category = doc.OwnerFamily?.FamilyCategory;
|
|
150
|
+
return new Dictionary<string, object?>
|
|
151
|
+
{
|
|
152
|
+
["category"] = category?.Name,
|
|
153
|
+
["builtInCategory"] = category?.BuiltInCategory.ToString(),
|
|
154
|
+
["currentType"] = manager.CurrentType?.Name,
|
|
155
|
+
["types"] = manager.Types.Cast<FamilyType>().Select(type => type.Name).OrderBy(name => name).ToList(),
|
|
156
|
+
["parameters"] = manager.Parameters.Cast<FamilyParameter>()
|
|
157
|
+
.Select(parameter => new { name = parameter.Definition.Name, instance = parameter.IsInstance, formula = parameter.Formula })
|
|
158
|
+
.OrderBy(parameter => parameter.name).ToList(),
|
|
159
|
+
["api"] = "Family types, parameters and formulas are edited through FamilyManager (" + DocumentKind.FamilyApi + ") with execute_csharp; project-only tools refuse this document.",
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private static string? DisplayUnitName(Units units, ForgeTypeId spec)
|
|
164
|
+
{
|
|
165
|
+
try
|
|
166
|
+
{
|
|
167
|
+
return UnitResolver.ShortName(units.GetFormatOptions(spec).GetUnitTypeId());
|
|
168
|
+
}
|
|
169
|
+
catch
|
|
170
|
+
{
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private static string? FormatLength(Units units, double value)
|
|
176
|
+
{
|
|
177
|
+
try
|
|
178
|
+
{
|
|
179
|
+
return UnitFormatUtils.Format(units, SpecTypeId.Length, value, false);
|
|
180
|
+
}
|
|
181
|
+
catch
|
|
182
|
+
{
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
@@ -1,37 +1,44 @@
|
|
|
1
|
-
using System.Text.Json;
|
|
2
|
-
using Autodesk.Revit.DB;
|
|
3
|
-
|
|
4
|
-
namespace RevitBridge.Tools;
|
|
5
|
-
|
|
6
|
-
internal sealed class GetScheduleFields : ITool
|
|
7
|
-
{
|
|
8
|
-
public string Name => "get_schedule_fields";
|
|
9
|
-
public string
|
|
10
|
-
public string
|
|
11
|
-
public
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
var
|
|
30
|
-
var
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
1
|
+
using System.Text.Json;
|
|
2
|
+
using Autodesk.Revit.DB;
|
|
3
|
+
|
|
4
|
+
namespace RevitBridge.Tools;
|
|
5
|
+
|
|
6
|
+
internal sealed class GetScheduleFields : ITool
|
|
7
|
+
{
|
|
8
|
+
public string Name => "get_schedule_fields";
|
|
9
|
+
public IReadOnlyList<string> DocumentKinds => DocumentKind.ProjectOnly;
|
|
10
|
+
public IReadOnlyList<string> Keywords => new[] { "schedule fields", "available fields", "add field", "schedulable parameters", "column" };
|
|
11
|
+
public IReadOnlyList<ToolLimit> Limits => new[]
|
|
12
|
+
{
|
|
13
|
+
new ToolLimit("Calculated (formula) fields", "revit_unsupported", "Revit 2025 API exposes ScheduleFieldType.Formula but no member to author a formula"),
|
|
14
|
+
new ToolLimit("Combined-parameter fields", "api", "ScheduleDefinition.InsertCombinedParameterField"),
|
|
15
|
+
};
|
|
16
|
+
public string Label => "Get Schedule Fields";
|
|
17
|
+
public string Tier => "advanced";
|
|
18
|
+
public string Description => "List fields eligible to be added to one existing schedule, with paging and localized-name filtering. A field is identified by the pair parameter_id + field_type; negative built-in parameter IDs are valid. These identities differ from schedule-local field_id values returned by get_schedules. Existing fields are marked included. Count may appear in the returned fields; manage_schedules accepts its discovered pair or field_type Count without a parameter_id. Calculated/combined fields are not exposed here.";
|
|
19
|
+
public object ParametersSchema => new
|
|
20
|
+
{
|
|
21
|
+
type = "object", properties = new
|
|
22
|
+
{
|
|
23
|
+
schedule_id = new { type = "integer", minimum = 1 }, name_filter = new { type = "string" },
|
|
24
|
+
offset = new { type = "integer", minimum = 0 }, limit = new { type = "integer", minimum = 1, maximum = 200 },
|
|
25
|
+
}, required = new[] { "schedule_id" },
|
|
26
|
+
};
|
|
27
|
+
public object Execute(JsonElement args, ToolContext context)
|
|
28
|
+
{
|
|
29
|
+
var doc = context.Document ?? throw new NoActiveDocumentException();
|
|
30
|
+
var schedule = doc.GetElement(new ElementId(JsonArgs.GetLong(args, "schedule_id") ?? 0)) as ViewSchedule ?? throw new ArgumentException("schedule_id is not a schedule.");
|
|
31
|
+
if (schedule.IsTemplate || schedule.IsTitleblockRevisionSchedule) throw new ArgumentException("Use a regular schedule, not a template or titleblock revision schedule.");
|
|
32
|
+
int offset = JsonArgs.GetInt(args, "offset", 0), limit = JsonArgs.GetInt(args, "limit", 100);
|
|
33
|
+
if (offset < 0 || limit is < 1 or > 200) throw new ArgumentException("Invalid paging range.");
|
|
34
|
+
string needle = JsonArgs.GetString(args, "name_filter") ?? "";
|
|
35
|
+
var definition = schedule.Definition;
|
|
36
|
+
var included = definition.GetFieldOrder().Select(id => definition.GetField(id)).Select(f => (f.ParameterId.Value, f.FieldType)).ToHashSet();
|
|
37
|
+
var fields = definition.GetSchedulableFields().Select(f => new
|
|
38
|
+
{
|
|
39
|
+
parameter_id = f.ParameterId.Value, field_type = f.FieldType.ToString(), name = f.GetName(doc), included = included.Contains((f.ParameterId.Value, f.FieldType)),
|
|
40
|
+
}).Where(f => f.name.Contains(needle, StringComparison.OrdinalIgnoreCase)).OrderBy(f => f.parameter_id).ThenBy(f => f.field_type, StringComparer.Ordinal).ToArray();
|
|
41
|
+
var page = fields.Skip(offset).Take(limit).ToArray();
|
|
42
|
+
return new { schedule_id = schedule.Id.Value, total_count = fields.Length, offset, returned_count = page.Length, next_offset = offset + page.Length < fields.Length ? (int?)(offset + page.Length) : null, fields = page };
|
|
43
|
+
}
|
|
44
|
+
}
|