Skip to content

v1.2.11 — Approve Before Keeping, Composite Profiles, Server Lockdown

Choose a tag to compare

@github-actions github-actions released this 20 Oct 16:39
· 50 commits to development since this release

Added — approve before keeping, preview, read-only runs (Settings → "Wijzigingen door de AI")

  • Plan 15, after pyRevit 7.0's agent runtime (2026-10-06). Off by default: auto keeps every
    answer exactly as it was. ask makes deletions and edits (delete, exec, set, join,
    unjoin, phase, and batches holding one) wait for the user: Revit isolates and selects what
    changed and a window shows the question, the command and the counts by category; Behouden
    keeps it as ONE undo step, Ongedaan maken (or Esc / closing) rolls everything back and tells
    the AI not to retry. "Deze Revit-sessie niet meer vragen" switches it off until Revit closes.
    New elements never ask. readonly refuses every change (READ_ONLY, with what it would have
    changed) — for colleagues who only look.
  • ?preview=1 on any modifying command or batch: it runs, says what it would add/modify/delete,
    and rolls everything back (an annotation it would re-host or remove is reported as -- preview:).
    ?readonly=1 (meant for exec/batch) fails (QUERY_MODIFIED_MODEL) instead of changing the model.
  • approvals lists this session's decisions; a decision a client missed (it waits up to 10 min,
    then APPROVAL_PENDING) appears once in the next model-state stamp. Discarded runs are journaled.
  • The file-based fallback (only used when the HTTP port could not open) cannot ask or roll back, so
    under ask or readonly it refuses changes instead of slipping past the setting.
  • IT can set it per machine: ChangeApproval in managed.json (locked in Settings); Diagnose names the
    source; build.ps1 -Approval ask for testing. Measured in Revit 2023: a window in 0.3–1.1 s, Keep is
    one Ctrl+Z (pile; floor + its spot elevation; an exec move), Discard leaves the edit counter as it was.

Added — apilookup: the Revit API of this Revit, for exec

  • Plan 16, after pyRevit's lookup_revit_api. apilookup Wall, apilookup Wall.Create,
    apilookup FilteredElementCollector --filter Where: namespace (and the full name to write in exec
    when exec does not import it), how to get one (the collector line goes through a base class for
    Room, ModelLine and the other classes Revit's class filter refuses), properties, methods by overload, enum values and
    [Obsolete] with Revit's own replacement advice — reflected from the RevitAPI of the running year.
    Unknown names give the closest ones. 0.28 s the first time, then 0.01–0.03 s.
  • A failed exec compile now appends the matching lookup (Hint: apilookup Wall.Widht … Closest: Wall.Width) — matched by error number, so the Dutch compiler messages work too.

Added — exec stops runaway loops

  • Plan 17. An endless loop in an exec snippet froze Revit until it was killed. Every loop body
    written with { } now checks a deadline: after 25 s (?timeout=<s>, up to 300) the snippet stops,
    its transaction is rolled back and exec answers EXEC_TIMEOUT — measured 25.1 s, Revit answered
    the next command at once, no measurable overhead on normal loops. Brace-less loops, recursion and a
    single long Revit call are still not interruptible (the timeout message says so).

Added — quay walls, capstones and curved runs as real families (profile, extrude, sweep, lwall)

  • Plan 12 phase 1. A composite cross-section used to be an exec DirectShape: no family or type,
    no Volume in a schedule, join refused. Four commands now generate a real Revit family on the
    fly, load it and place it as ONE undo step (also inside batch, atomic included):
    • lwall x1 y1 x2 y2 --stem 600x4000 --foot 2500x800 [--toe] [--side left|right] [--slope] — an
      L-shaped quay wall on one parametric line-based Generic Model (VM_L-wand, or … SF with
      --category foundation): stem and foot sizes are type parameters on locked reference planes, each
      size combination becomes a type named from its sizes, an existing type is reused. The line is the
      stem's front face, the heel lies left of the line unless --side right.
    • profile <name> --points u,v … — a named section stored as a Revit Profile family (also usable in
      Revit's own Wall Sweep / Slab Edge tools) with its points in VM_Profile; profile <name> prints
      points, area, box and centroid; profile lists them.
    • extrude <profile | --points …> --along <line/wall id | x1 y1 x2 y2> — line-based Generic Model
      (--category foundation = point-based Structural Foundation with Wall length, framing = a beam);
      extrude … --vertical <height> --at <x y> stands a plan profile up (Height is a type parameter).
    • sweep <profile> --along <id,id,…> — along a chain of lines and arcs (any order) or a wall; the
      path is fixed in the family and the response says so.
  • Profiles are mm, u = left of the run direction (the side section looks to), v = up; outlines are
    closed, cleaned and checked (a crossing outline names its segments).
  • Every generated family schedules by type with a correct Volume and a shared VM_Length (fixed
    GUID, so all of them share one schedule column); Material is a type parameter (--material, or
    the pack's default). The new element is joined with the walls, floors and generated elements it
    overlaps (--no-join to skip; library families such as piles are never joined), gets the office
    phase (--phase), runs the post-command check and is journaled with the .rfa it wrote.
  • Re-running updates instead of adding "(2)": the same profile reuses the loaded family, a changed one
    is regenerated and reloaded keeping the project's type values; a family edited by hand in Revit
    since (or one VibeModel did not make) is refused until --replace. Live-checked in Revit 2023
    (docs/verify/plan12-live-2026-10-16.md): a reused family is not opened, so its hand edits show
    up as a WARN when Revit's volume differs from profile area × length; --replace regenerates
    even with unchanged points.
  • The .rfa files go to <project folder>\VibeModel\families\ (3 s deadline; offline → a local copy,
    said in the response). Revit's shared-parameter file setting is swapped for the build and always
    restored.
  • Office packs get an optional profiles block (prefix, category per kind, templates, folder,
    shared parameters, materials, type-name pattern) and the example pack a kadeconstructie topic
    sheet: the questions an office answers about its quay walls, without values.

Security — the local server only answers the user's own tools

A brainstorm review (2026-10-15) found that any web page the user had open could drive Revit: the
server never looked at Host or Origin, and the token was off unless VIBEMODEL_TOKEN was set —
<img src="http://127.0.0.1:18884/exec?args=…"> ran C# inside Revit, and a domain resolving to
127.0.0.1 could also read readdoc/memory. See the new SECURITY.md.

  • Browser requests are refused (403 forbidden, before /health too): any request with an
    Origin header, a Sec-Fetch-Site other than none/same-origin, a cross-site Sec-Fetch-Mode,
    or a Host that is not 127.0.0.1, localhost or [::1] (bare or with the server's own port).
    curl, the chat backends and the Claude Code CLI send none of these — nothing legitimate changes.
  • A token on every call, by default. Without VIBEMODEL_TOKEN the server now generates a random
    per-session token and publishes it in the per-user %LOCALAPPDATA%\VibeModel\servers\<port>.json
    (token field). The chat pane reads it in-process, the Claude Code CLI gets it as VIBEMODEL_TOKEN;
    terminal one-liners for bash and PowerShell are in CLAUDE.md/README. An explicit VIBEMODEL_TOKEN
    still wins. "OpenServer": true (managed.json or settings.json) restores the open server for
    scripts; Diagnose shows which mode is active, and a 401's hint names the servers file.
  • managed.json must be IT's. %ProgramData%\VibeModel\managed.json is only trusted when file and
    folder are owned by Administrators or SYSTEM and give ordinary users no write access (Windows lets
    users create folders under ProgramData); otherwise it is ignored, logged once and named in Diagnose.
    docs/deployment.md shows the icacls commands.

Fixed

  • POST /batch: a multi-byte character (°, m², ë) that straddled a 4 KB read boundary was
    decoded as two broken characters and changed the body's byte count. The request is now read as
    bytes against Content-Length and decoded once; Expect: 100-continue (curl, bodies over 1 KB) is
    answered before the body is awaited.
  • scripts/sign.ps1 signed silently without a timestamp when the timestamp server was unreachable
    (such a signature dies with the certificate). It is now an error unless -NoTimestamp is passed.
  • poll-health.ps1 and the build summary use 127.0.0.1 instead of localhost (IPv6 stall).

Full Changelog: v1.2.10...v1.2.11