@floless/app 0.48.0 → 0.48.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floless/app",
3
- "version": "0.48.0",
3
+ "version": "0.48.1",
4
4
  "type": "module",
5
5
  "description": "Thin localhost host for floless.app — serves web/ and shells the aware CLI. No engine, no LLM.",
6
6
  "bin": {
@@ -1,120 +0,0 @@
1
- ---
2
- name: floless-app-steel-from-drawings
3
- description: This skill should be used to turn a structural steel drawing into an interactive 3D model in floless.app — the "Steel from Drawings" reader. Triggers on a pending floless `rebake` request for the `steel-from-drawings` app (queued from its "Re-read & re-bake ▸" button), or asks like "read this framing plan into 3D", "turn this steel drawing into a model", "bake my drawing into steel-from-drawings". It teaches the host AI to READ a steel drawing (PDF/image) with its own vision, extract a schematic 3D scene (grids, members, sizes, takeoff) in the viewer-3d scene schema, bake it INLINE into the app's `view` node, recompile, and ask the user to approve — all at COMPOSE time (no model in the run path, no API key). Also bakes the same scene into the `steel-to-ifc` companion (universal IFC file) and the `steel-to-tekla` companion (native Tekla parts via the Open API, needs Tekla open). Triggers also on "export this to IFC", "bake to Tekla/SDS2/Revit", "bake into Tekla".
4
- metadata:
5
- version: 0.1.0
6
- ---
7
-
8
- # Steel from Drawings — read a steel drawing into an interactive 3D model
9
-
10
- ## What this is
11
-
12
- `steel-from-drawings` is a FloLess app that renders an interactive, **licence-free 3D model** of a
13
- steel frame (the `viewer-3d` agent) from a scene that **you, the terminal AI, bake from a drawing**.
14
- The drawing is read **at compose time** with your own vision — there is **no model in the run path
15
- and no AI API key**: the brain is you, in the terminal (the FloLess thin-UI contract). This is the
16
- **bake** strategy (`floless-app-rebake` is the generic version; this skill is the steel-specific one,
17
- and **for `steel-from-drawings` it supersedes the generic re-bake** — you bake the scene INLINE into
18
- the `.flo`'s `view` node, not into `config.yaml`).
19
-
20
- **Bake-out companions.** Two sibling apps consume the SAME scene: **`steel-to-ifc`** writes a
21
- universal **IFC** file (open in Tekla, SDS2, Revit, Navisworks; no Tekla needed), and
22
- **`steel-to-tekla`** creates **native Tekla members** directly via the Open API (needs Tekla open).
23
- When you bake a scene, bake the *identical* scene into whichever of these are installed (loop steps
24
- 6–7) so every output matches the 3D the user confirmed. The whole loop: **read the drawing → see it
25
- in 3D (`steel-from-drawings`) → bake it out (an IFC file and/or native Tekla parts) → finish in your tool.**
26
-
27
- > **Pasted a request?** If the user pastes a message beginning with a `[floless-request type=rebake
28
- > id=…]` marker, that's a request copied from the FloLess Dashboard — resolve it via
29
- > `GET /api/requests` (match the id), don't run the pasted line verbatim, and `DELETE` it when done.
30
-
31
- ## The loop
32
-
33
- 1. **Find the drawing.** From a `rebake` request: `GET http://localhost:<port>/api/requests` → the
34
- entry with `type:"rebake"` and `appId:"steel-from-drawings"` carries `snapshots: ["<abs path>"]`.
35
- (Or the user just attaches/points at a drawing in prose — same procedure, skip the lookup.)
36
- 2. **Read the drawing with your own vision.** Open the file (PDF or image) and READ it. If it's a
37
- large multi-sheet PDF, focus on one framing plan / GA sheet (say which). This is the compose-time
38
- extraction — your vision is the reader, not any API.
39
- 3. **Extract a schematic 3D scene** in the schema below (§ Scene schema), following § Reading a steel
40
- drawing. Aim for a complete, plausible stick model — the user confirms/nudges it in 3D.
41
- 4. **Bake it INLINE into the app.** Replace the entire `scene:` mapping under the `view` node's
42
- `config:` in the app's `.flo` with your extracted scene — in BOTH the installed copy
43
- `~/.aware/apps/steel-from-drawings/steel-from-drawings.flo` AND the editable
44
- `demos/steel-from-drawings/steel-from-drawings.flo` if present. Change ONLY the `scene:` block;
45
- leave `inputs`, `requires`, the node id/agent/command, and everything else identical.
46
- 5. **Recompile.** `aware app compile ~/.aware/apps/steel-from-drawings` → rewrites the `.lock`. The
47
- source-hash changes, so FloLess's Run gate disarms until the user approves. Copy the fresh `.lock`
48
- to `demos/steel-from-drawings/` if you keep the editable copy in sync.
49
- 6. **Bake the SAME scene into `steel-to-ifc` (the IFC bake-out), if it's installed.** Check
50
- `~/.aware/apps/steel-to-ifc/`. If present, replace the `scene:` mapping under that app's `bake-ifc`
51
- node `config` (the `ifc` agent's `scene` input — NOT `config.args`; the app now calls the host-free
52
- `ifc` AWARE agent, not an exec) with the IDENTICAL scene (the installed copy and `demos/steel-to-ifc/`
53
- if present), then `aware app compile ~/.aware/apps/steel-to-ifc`. This keeps the exported IFC matching
54
- the 3D the user confirmed. (`steel-to-ifc` writes a real IFC file — IfcColumn/IfcBeam on the grid —
55
- openable in Tekla, SDS2, Revit or Navisworks; it never touches a Tekla model, so no Tekla needed.)
56
- 7. **Bake the SAME scene into `steel-to-tekla` (native Tekla parts), if it's installed.** Check
57
- `~/.aware/apps/steel-to-tekla/`. If present, replace the `scene:` under that app's `bake-tekla` node
58
- `config` (the `tekla` `bake-scene` verb's `scene` input — NOT `config.args`; the app now calls the
59
- first-class `bake-scene` verb, not an exec) with the IDENTICAL scene (installed + `demos/steel-to-tekla/`), set `config.version`
60
- to the user's RUNNING Tekla version (e.g. "2026.0" — the Open API connects to a version-specific
61
- channel, so a wrong version silently finds no model), then `aware app compile
62
- ~/.aware/apps/steel-to-tekla`. It creates a real Tekla member per element via the Open API (mode:
63
- write, snapshot — Undo reverts the whole bake); needs Tekla OPEN with a model. Profiles fall back
64
- to a sized rectangular section when the environment lacks the drawing's catalogue profile.
65
- 8. **Hand the approval to the user.** Tell them what you read (e.g. "read 6 columns + 8 beams on grids
66
- A–C / 1–2, heights assumed 4.5 m — review in Inspect → Code, then Compile/Approve, then ▶ Run to
67
- see the 3D; run **steel-to-ifc** for an IFC file or **steel-to-tekla** for native Tekla parts").
68
- The human eyeballing the read in 3D **is the safety gate**. Never auto-run.
69
- 9. **Clear the request.** `DELETE http://localhost:<port>/api/requests/<id>` once done (if from one).
70
-
71
- ## Scene schema (the bake target — exactly what `viewer-3d` renders)
72
-
73
- ```yaml
74
- scene:
75
- meta: { name: "<sheet title / drawing no.>", units: mm, up: z }
76
- groups: # one per group you use; drives legend + colour
77
- - { key: column, label: Columns, color: "#60a5fa" }
78
- - { key: beam, label: Beams, color: "#94a3b8" }
79
- # rafter #38bdf8, brace #818cf8 — add others as needed
80
- elements: # one per member, kind: box (a from→to bar)
81
- - { id: COL-A1, group: column, kind: box, from: [x,y,z], to: [x,y,z],
82
- section: { w: 150, d: 150 }, meta: { profile: "HSS6x6x3/8", mark: "C1", grid: "A-1" } }
83
- grids: # grid labels placed just outside the framing
84
- - { label: A, at: [x,y,0] }
85
- panels: # generic side tables; build a Takeoff
86
- - title: Takeoff
87
- note: "<assumptions, e.g. heights assumed — plan view, H=4.5 m>"
88
- columns: [Section, "No.", Length]
89
- rows: [["HSS6x6x3/8", 6, "27.0 m"]]
90
- ```
91
-
92
- `from`/`to` are `[x,y,z]` in mm. `meta` is free-form (shown in the click-to-inspect panel) — put
93
- `profile`, `mark`, `grid` there. `section.w`/`d` are visual thickness only.
94
-
95
- ## Reading a steel drawing (the method)
96
-
97
- 1. **Grid.** Find the grid (A,B,C… one way, 1,2,3… the other, plus half-grids). Read the dimension
98
- strings to place grids in mm; if a spacing is unreadable, assume a regular ~6000 mm bay and say so.
99
- 2. **Sheet type & heights.** A PLAN view (top-down) shows no heights — pick one eave/storey height H
100
- (a level/height note if present, else ~4500 mm) and note it; columns run z:0→H, beams/rafters sit
101
- at z:H. An ELEVATION/SECTION gives real heights — read them.
102
- 3. **Members.** One `elements` entry per member, size label exactly as drawn. Columns → `column`,
103
- `from:[gx,gy,0] to:[gx,gy,H]`. Beams/rafters → `beam`/`rafter`, along the grid at z:H. Braces →
104
- `brace`, the diagonal. Put the size in `meta.profile`, the mark in `meta.mark`, the grid ref in
105
- `meta.grid`; approximate `section.w`/`d` from the profile (W12≈300×310, HSS6x6≈150×150, L≈90×90).
106
- 4. **Takeoff.** One row per distinct profile (count + total length in m). Assumptions in the note.
107
- 5. **meta.name** = the sheet title / drawing number. Never invent grids or members the drawing does
108
- not show; if a sheet has no readable steel framing, bake an empty `elements` with a note saying so.
109
-
110
- ## Guardrails
111
-
112
- - **Compose-time only.** The drawing is read HERE, by you, then baked. Never add a runtime node that
113
- reads the drawing — `aware app validate` rejects it and it breaks determinism.
114
- - **Scene, not logic.** Re-bake only the `view.scene` block. A different output (new columns, a
115
- schedule) is a workflow change — use `floless-app-workflows`, not this.
116
- - **Schematic + honest.** ~90% is the goal; the user tidies the last 10% in 3D. State your
117
- assumptions (heights, assumed bays) in the takeoff note. Don't fabricate sizes the drawing lacks.
118
- - **Thin-UI contract.** The browser only recorded intent + the drawing; the brain is you, in the
119
- terminal. The UI never reads the drawing and never bakes.
120
- - **Resolve the port** from the running floless.app the same way the other floless-app skills do.
@@ -1,73 +0,0 @@
1
- app: steel-from-drawings
2
- version: 0.1.0
3
- display-name: Steel from Drawings
4
- description: |
5
- Turn a structural steel drawing into an interactive, licence-free 3D model — no Tekla, no
6
- modelling, no AI API key. Your terminal AI (Claude Code / Codex) reads the drawing once and
7
- bakes a schematic 3D scene into this app; the viewer-3d agent renders it as an interactive
8
- document anyone can orbit, click to inspect, and take off (counts + length by section) — so an
9
- estimator, PM, fabricator or client can understand and price the steel before opening a seat.
10
-
11
- The reading is a COMPOSE-TIME act — the FloLess way: the app is the prompt in your terminal, so
12
- the brain is your AI terminal, never this server, and there is never a model in the run path.
13
- Attach a drawing and use "Re-read & re-bake ▸" (or just ask your terminal AI to read it). The AI
14
- reads the grids, members and sizes and bakes them straight into the `view` node's `scene` below
15
- (the viewer-3d scene schema), recompiles, and asks you to approve; the deterministic run then
16
- only renders the approved scene. Ships with a small example scene so it renders out of the box —
17
- the `floless-app-steel-from-drawings` skill teaches your terminal AI how to read your own drawing in.
18
- exposes-as-agent: false
19
- inputs:
20
- # BAKED at compose time: the terminal AI reads this drawing and writes the `view.scene` block
21
- # below (the run never reads the drawing). read-strategy: bake surfaces "Re-read & re-bake ▸" so
22
- # you can swap the drawing and have your AI re-read it. No runtime input node.
23
- drawing:
24
- type: image
25
- widget: file
26
- accept: [pdf, png, jpg]
27
- read-strategy: bake
28
- description: A structural steel drawing (framing plan / GA / elevation) — baked into the scene below; swap it to re-read & re-bake.
29
- requires:
30
- - viewer-3d@0.1.x
31
- layout: linear
32
- nodes:
33
- # The viewer-3d render node IS the terminal. Ships with a small EXAMPLE scene (a sample 3x2 bay
34
- # frame, schematic) so the app renders out of the box. Re-bake — or the
35
- # floless-app-steel-from-drawings skill — replaces this whole `scene` with a reading of YOUR drawing.
36
- - id: view
37
- agent: viewer-3d
38
- command: render
39
- config:
40
- scene:
41
- meta: { name: "Example — steel framing (sample, not your drawing)", units: mm, up: z }
42
- groups:
43
- - { key: column, label: "Columns (HSS6x6x3/8)", color: "#60a5fa" }
44
- - { key: beam, label: "Beams (W10x33)", color: "#94a3b8" }
45
- elements:
46
- # 6 columns (z 0 -> 4500) on a 3 x 2 grid
47
- - { id: COL-1A, group: column, kind: box, from: [0,0,0], to: [0,0,4500], section: { w: 150, d: 150 }, meta: { profile: "HSS6x6x3/8", grid: "1-A" } }
48
- - { id: COL-2A, group: column, kind: box, from: [6000,0,0], to: [6000,0,4500], section: { w: 150, d: 150 }, meta: { profile: "HSS6x6x3/8", grid: "2-A" } }
49
- - { id: COL-3A, group: column, kind: box, from: [12000,0,0], to: [12000,0,4500], section: { w: 150, d: 150 }, meta: { profile: "HSS6x6x3/8", grid: "3-A" } }
50
- - { id: COL-1B, group: column, kind: box, from: [0,6000,0], to: [0,6000,4500], section: { w: 150, d: 150 }, meta: { profile: "HSS6x6x3/8", grid: "1-B" } }
51
- - { id: COL-2B, group: column, kind: box, from: [6000,6000,0], to: [6000,6000,4500], section: { w: 150, d: 150 }, meta: { profile: "HSS6x6x3/8", grid: "2-B" } }
52
- - { id: COL-3B, group: column, kind: box, from: [12000,6000,0],to: [12000,6000,4500],section: { w: 150, d: 150 }, meta: { profile: "HSS6x6x3/8", grid: "3-B" } }
53
- # roof beams at z 4500 (W10x33): along each row, then tie beams along each grid line
54
- - { id: BM-12A, group: beam, kind: box, from: [0,0,4500], to: [6000,0,4500], section: { w: 150, d: 250 }, meta: { profile: "W10x33", grid: "A" } }
55
- - { id: BM-23A, group: beam, kind: box, from: [6000,0,4500], to: [12000,0,4500], section: { w: 150, d: 250 }, meta: { profile: "W10x33", grid: "A" } }
56
- - { id: BM-12B, group: beam, kind: box, from: [0,6000,4500], to: [6000,6000,4500], section: { w: 150, d: 250 }, meta: { profile: "W10x33", grid: "B" } }
57
- - { id: BM-23B, group: beam, kind: box, from: [6000,6000,4500],to: [12000,6000,4500], section: { w: 150, d: 250 }, meta: { profile: "W10x33", grid: "B" } }
58
- - { id: BM-1AB, group: beam, kind: box, from: [0,0,4500], to: [0,6000,4500], section: { w: 150, d: 250 }, meta: { profile: "W10x33", grid: "1" } }
59
- - { id: BM-2AB, group: beam, kind: box, from: [6000,0,4500], to: [6000,6000,4500], section: { w: 150, d: 250 }, meta: { profile: "W10x33", grid: "2" } }
60
- - { id: BM-3AB, group: beam, kind: box, from: [12000,0,4500], to: [12000,6000,4500], section: { w: 150, d: 250 }, meta: { profile: "W10x33", grid: "3" } }
61
- grids:
62
- - { label: "1", at: [0,-3000,0] }
63
- - { label: "2", at: [6000,-3000,0] }
64
- - { label: "3", at: [12000,-3000,0] }
65
- - { label: "A", at: [-3000,0,0] }
66
- - { label: "B", at: [-3000,6000,0] }
67
- panels:
68
- - title: Takeoff
69
- note: "EXAMPLE — not your drawing. A sample steel frame on a 1-3 x A-B grid; sizes & heights are illustrative. Use 'Re-read & re-bake ▸' (or ask your terminal AI) to read your own drawing."
70
- columns: [Section, "No.", Length]
71
- rows:
72
- - ["HSS6x6x3/8", 6, "27.0 m"]
73
- - ["W10x33", 7, "42.0 m"]
@@ -1,294 +0,0 @@
1
- app: steel-to-ifc
2
- version: 0.1.0
3
- display-name: Steel to IFC
4
- description: |
5
- Bake a read steel model OUT to a universal IFC file — open it in Tekla, SDS2, Revit or
6
- Navisworks. Companion to steel-from-drawings: that app reads a drawing into a 3D scene and shows
7
- it; this one writes the SAME scene to an IFC file (IfcColumn/IfcBeam as extruded sections on the
8
- real grid) so you can take the schematic model straight into your detailing tool and finish there.
9
-
10
- Same terminal-bake pattern — the FloLess way: your AI terminal bakes the scene inline
11
- (read-strategy: bake); a deterministic, MODEL-FREE exec node writes the .ifc (no Tekla needed to
12
- export — it never touches a Tekla model, just writes the file). Ships with the same EXAMPLE
13
- frame so it runs out of the box; the floless-app-steel-from-drawings skill bakes your drawing's
14
- scene into both apps so the IFC matches what you saw in 3D.
15
- exposes-as-agent: false
16
- inputs:
17
- # BAKED at compose time: the terminal AI reads this drawing and writes the `scene` block below
18
- # (the run never reads the drawing). read-strategy: bake surfaces "Re-read & re-bake ▸".
19
- drawing:
20
- type: image
21
- widget: file
22
- accept: [pdf, png, jpg]
23
- read-strategy: bake
24
- description: A structural steel drawing — baked into the scene below, then written out as IFC; swap it to re-read & re-bake.
25
- output_path:
26
- type: string
27
- default: steel-from-drawings.ifc
28
- description: Where to write the .ifc — FloLess fills this with your Downloads folder; editable per run.
29
- requires:
30
- - ifc@0.1.x
31
- layout: linear
32
- nodes:
33
- # Model-free exec: reads the baked `scene` and writes a valid IFC4 file (IfcColumn/IfcBeam as
34
- # extruded rectangle sections on the real grid), returning a summary report. NEVER derefs `model`
35
- # (no Tekla needed); writes the .ifc via System.IO to the user's Downloads (or home). Re-bake —
36
- # or the floless-app-steel-from-drawings skill — replaces `scene` with YOUR drawing's read.
37
- - id: bake-ifc
38
- agent: ifc
39
- command: write
40
- config:
41
- scene:
42
- meta:
43
- name: "Example \u2014 steel framing (sample, not your drawing)"
44
- units: mm
45
- up: z
46
- groups:
47
- - key: column
48
- label: Columns (HSS6x6x3/8)
49
- color: '#60a5fa'
50
- - key: beam
51
- label: Beams (W10x33)
52
- color: '#94a3b8'
53
- elements:
54
- - id: COL-1A
55
- group: column
56
- kind: box
57
- from:
58
- - 0
59
- - 0
60
- - 0
61
- to:
62
- - 0
63
- - 0
64
- - 4500
65
- section:
66
- w: 150
67
- d: 150
68
- meta:
69
- profile: HSS6x6x3/8
70
- grid: 1-A
71
- - id: COL-1B
72
- group: column
73
- kind: box
74
- from:
75
- - 0
76
- - 6000
77
- - 0
78
- to:
79
- - 0
80
- - 6000
81
- - 4500
82
- section:
83
- w: 150
84
- d: 150
85
- meta:
86
- profile: HSS6x6x3/8
87
- grid: 1-B
88
- - id: COL-2A
89
- group: column
90
- kind: box
91
- from:
92
- - 6000
93
- - 0
94
- - 0
95
- to:
96
- - 6000
97
- - 0
98
- - 4500
99
- section:
100
- w: 150
101
- d: 150
102
- meta:
103
- profile: HSS6x6x3/8
104
- grid: 2-A
105
- - id: COL-2B
106
- group: column
107
- kind: box
108
- from:
109
- - 6000
110
- - 6000
111
- - 0
112
- to:
113
- - 6000
114
- - 6000
115
- - 4500
116
- section:
117
- w: 150
118
- d: 150
119
- meta:
120
- profile: HSS6x6x3/8
121
- grid: 2-B
122
- - id: COL-3A
123
- group: column
124
- kind: box
125
- from:
126
- - 12000
127
- - 0
128
- - 0
129
- to:
130
- - 12000
131
- - 0
132
- - 4500
133
- section:
134
- w: 150
135
- d: 150
136
- meta:
137
- profile: HSS6x6x3/8
138
- grid: 3-A
139
- - id: COL-3B
140
- group: column
141
- kind: box
142
- from:
143
- - 12000
144
- - 6000
145
- - 0
146
- to:
147
- - 12000
148
- - 6000
149
- - 4500
150
- section:
151
- w: 150
152
- d: 150
153
- meta:
154
- profile: HSS6x6x3/8
155
- grid: 3-B
156
- - id: BM-12A
157
- group: beam
158
- kind: box
159
- from:
160
- - 0
161
- - 0
162
- - 4500
163
- to:
164
- - 6000
165
- - 0
166
- - 4500
167
- section:
168
- w: 150
169
- d: 250
170
- meta:
171
- profile: W10x33
172
- - id: BM-23A
173
- group: beam
174
- kind: box
175
- from:
176
- - 6000
177
- - 0
178
- - 4500
179
- to:
180
- - 12000
181
- - 0
182
- - 4500
183
- section:
184
- w: 150
185
- d: 250
186
- meta:
187
- profile: W10x33
188
- - id: BM-12B
189
- group: beam
190
- kind: box
191
- from:
192
- - 0
193
- - 6000
194
- - 4500
195
- to:
196
- - 6000
197
- - 6000
198
- - 4500
199
- section:
200
- w: 150
201
- d: 250
202
- meta:
203
- profile: W10x33
204
- - id: BM-23B
205
- group: beam
206
- kind: box
207
- from:
208
- - 6000
209
- - 6000
210
- - 4500
211
- to:
212
- - 12000
213
- - 6000
214
- - 4500
215
- section:
216
- w: 150
217
- d: 250
218
- meta:
219
- profile: W10x33
220
- - id: BM-1AB
221
- group: beam
222
- kind: box
223
- from:
224
- - 0
225
- - 0
226
- - 4500
227
- to:
228
- - 0
229
- - 6000
230
- - 4500
231
- section:
232
- w: 150
233
- d: 250
234
- meta:
235
- profile: W10x33
236
- - id: BM-2AB
237
- group: beam
238
- kind: box
239
- from:
240
- - 6000
241
- - 0
242
- - 4500
243
- to:
244
- - 6000
245
- - 6000
246
- - 4500
247
- section:
248
- w: 150
249
- d: 250
250
- meta:
251
- profile: W10x33
252
- - id: BM-3AB
253
- group: beam
254
- kind: box
255
- from:
256
- - 12000
257
- - 0
258
- - 4500
259
- to:
260
- - 12000
261
- - 6000
262
- - 4500
263
- section:
264
- w: 150
265
- d: 250
266
- meta:
267
- profile: W10x33
268
- grids:
269
- - label: '1'
270
- at:
271
- - 0
272
- - -3000
273
- - 0
274
- - label: '2'
275
- at:
276
- - 6000
277
- - -3000
278
- - 0
279
- - label: '3'
280
- at:
281
- - 12000
282
- - -3000
283
- - 0
284
- - label: A
285
- at:
286
- - -3000
287
- - 0
288
- - 0
289
- - label: B
290
- at:
291
- - -3000
292
- - 6000
293
- - 0
294
- output-path: "{{ inputs.output_path }}"