lineadraw 0.9.0 → 0.11.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/README.md +154 -20
- package/bin/lineadraw.mjs +60 -10
- package/dist/bridge.d.ts +1 -0
- package/dist/bridge.js +1 -1
- package/dist/{chunk-BQCSFVAF.js → chunk-7UFXC7OI.js} +5570 -1174
- package/dist/chunk-7UFXC7OI.js.map +1 -0
- package/dist/chunk-FDLANLIC.js +1161 -0
- package/dist/chunk-FDLANLIC.js.map +1 -0
- package/dist/chunk-M3EDRSHW.js +81 -0
- package/dist/chunk-M3EDRSHW.js.map +1 -0
- package/dist/chunk-MYP7RUYK.js +9 -0
- package/dist/chunk-MYP7RUYK.js.map +1 -0
- package/dist/{chunk-L2CWZAKW.js → chunk-RNA2RDGL.js} +13 -6
- package/dist/chunk-RNA2RDGL.js.map +1 -0
- package/dist/dist-56K6CNML.js +188 -0
- package/dist/dist-56K6CNML.js.map +1 -0
- package/dist/dist-IEN64QSV.js +10 -0
- package/dist/dist-IEN64QSV.js.map +1 -0
- package/dist/emscripten-module-Q67P5WYC-ITCU5LXL.js +2424 -0
- package/dist/emscripten-module-Q67P5WYC-ITCU5LXL.js.map +1 -0
- package/dist/{exportDxf-T2RTSTH5.js → exportDxf-6XTXQ4XN.js} +2 -2
- package/dist/ffi-SHMEF5YV.js +82 -0
- package/dist/ffi-SHMEF5YV.js.map +1 -0
- package/dist/module-ES6BEMUI-BJFWC656.js +14 -0
- package/dist/module-ES6BEMUI-BJFWC656.js.map +1 -0
- package/dist/module-asyncify-2EFITU5U-7F5WZXRA.js +9 -0
- package/dist/module-asyncify-2EFITU5U-7F5WZXRA.js.map +1 -0
- package/dist/sdk.d.ts +1118 -128
- package/dist/sdk.js +742 -620
- package/dist/sdk.js.map +1 -1
- package/lineadraw.d.ts +666 -44
- package/package.json +1 -1
- package/templates/README.md +6 -4
- package/dist/chunk-BQCSFVAF.js.map +0 -1
- package/dist/chunk-L2CWZAKW.js.map +0 -1
- /package/dist/{exportDxf-T2RTSTH5.js.map → exportDxf-6XTXQ4XN.js.map} +0 -0
package/README.md
CHANGED
|
@@ -59,9 +59,13 @@ await doc.exportPdf("plan.pdf");
|
|
|
59
59
|
its objects; an object's own `opacity` overrides it. Paints across canvas,
|
|
60
60
|
SVG, and PDF; DXF/DWG export drops it (no direct mapping).
|
|
61
61
|
- **Annotation scale is per-object**: for a 1:N drawing set the top-level
|
|
62
|
-
`scale: N` on text, dimensions, and hatches, keeping
|
|
63
|
-
paper size (2.5 body / 3.5 / 5 titles). `scale` is NOT a
|
|
64
|
-
key; `add`/`update` reject it there.
|
|
62
|
+
`scale: N` on text, dimensions, and hatches, keeping the text height
|
|
63
|
+
at paper size (2.5 body / 3.5 / 5 titles). `scale` is NOT a
|
|
64
|
+
`styleOverride` key; `add`/`update` reject it there.
|
|
65
|
+
- **One shape per field.** Style keys of a text, table or dimension
|
|
66
|
+
(`textHeight`, `font`, `bold`, `arrowSize`, …) live in `styleOverride`
|
|
67
|
+
(or a named style via `styleId`), never at the top level; a hidden layer
|
|
68
|
+
is `visible: false`. Unknown fields throw, naming where they belong.
|
|
65
69
|
- **Reads are detached snapshots**: `doc.document`, `doc.objects`,
|
|
66
70
|
`getObject`, `listObjects()` return deep clones — mutating them does nothing.
|
|
67
71
|
- **New documents are layout-less**; `exportPdf` of a layout-less document
|
|
@@ -113,7 +117,9 @@ appended when missing):
|
|
|
113
117
|
configuration, never written to the file.
|
|
114
118
|
- **Scripts**: `await runScript(source, inputs?, params?)` runs a
|
|
115
119
|
`defineCommand` module (the same one the editor palette runs) headlessly
|
|
116
|
-
as ONE undo step — its declared `inputs`
|
|
120
|
+
as ONE undo step — its declared `inputs` are supplied up front (by name
|
|
121
|
+
for an inputs table: `{ origin: [0, 0], doors: [id] }`; points in order
|
|
122
|
+
for labels),
|
|
117
123
|
its declared `params` by name (`{ count: 3 }`; omitted ones take their
|
|
118
124
|
defaults, unknown names and wrong types throw); `runUserCommand(id, inputs?,
|
|
119
125
|
params?)` runs one of the document's own commands. Returns the script's
|
|
@@ -144,7 +150,10 @@ Full parameter docs are in the bundled `dist/sdk.d.ts` JSDoc.
|
|
|
144
150
|
|
|
145
151
|
`line` (a, b) · `polyline` (points with optional bulge, closed) · `circle` ·
|
|
146
152
|
`arc` (CCW start→end) · `ellipse` (center, majorAxis vector, ratio) ·
|
|
147
|
-
`point` (p) · `hatch` (loops — outer + holes, even-odd;
|
|
153
|
+
`point` (p) · `hatch` (loops — outer + holes, even-odd; each loop a closed
|
|
154
|
+
chain of `edges`: `line`, `arc`, `ellipse` or `spline`, with the fields of that
|
|
155
|
+
object type — a circle, ellipse or closed spline is one edge; `hatchLoop(points)`
|
|
156
|
+
builds a polygon / bulged loop; fill solid/pattern/lines) ·
|
|
148
157
|
`text` (position, content; **default alignment center/center**; optional
|
|
149
158
|
leaderLines with the arrowhead at index 0) · `dimension` (linear/angular/
|
|
150
159
|
radial/diameter; linear: `offset` is the signed distance of the dimension
|
|
@@ -260,16 +269,32 @@ export default defineBlock({
|
|
|
260
269
|
params: [
|
|
261
270
|
{ name: "kind", type: "enum", default: "rock", options: ["rock", "ground"] },
|
|
262
271
|
],
|
|
263
|
-
|
|
264
|
-
|
|
272
|
+
// What the user picks at insertion, read by name in `draw`.
|
|
273
|
+
inputs: [
|
|
274
|
+
{ name: "start", type: "point", label: "Start point" },
|
|
275
|
+
{ name: "end", type: "point", label: "End point" },
|
|
276
|
+
],
|
|
277
|
+
draw: ({ params, inputs: { start, end } }) => {
|
|
265
278
|
params.kind; // "rock" | "ground" — inferred from the params table
|
|
266
279
|
return [{ type: "line", a: start, b: end }];
|
|
267
280
|
},
|
|
268
281
|
});
|
|
269
282
|
```
|
|
270
283
|
|
|
271
|
-
|
|
272
|
-
`
|
|
284
|
+
Input kinds: `point`; `points` — a chain picked until Enter (`min`,
|
|
285
|
+
`max`, `closed` for a polygon) arriving as `Vec2[]`; `object` / `objects`
|
|
286
|
+
— picked objects filtered by `types` (`["line", "polyline"]`), arriving in
|
|
287
|
+
`draw` as the objects themselves (re-evaluated when they change; a
|
|
288
|
+
deleted one is `null` / dropped). `point` and `object` may be `optional`
|
|
289
|
+
(Enter skips). The first point is the pivot. Instances store their inputs
|
|
290
|
+
by name, so reordering or adding inputs never breaks placed instances —
|
|
291
|
+
removing or renaming one does. (The older `place: ["Start", "End"]` labels
|
|
292
|
+
form, with `draw` reading `inputs` as an array, still works.)
|
|
293
|
+
|
|
294
|
+
Notable optional members: `place` — an interactive
|
|
295
|
+
`({ params, pickPoint, pickPoints, pickObject, pickObjects })` function run
|
|
296
|
+
once at insertion, for conditional or chained picks; with an `inputs`
|
|
297
|
+
table it returns the inputs by name;
|
|
273
298
|
`dependencies` lists ids of blocks your `draw` emits instances of (installs
|
|
274
299
|
pull them along); `paramVisibility({ params })` hides property rows;
|
|
275
300
|
`previewInputs` curates the inputs used for thumbnails. Units are
|
|
@@ -294,6 +319,26 @@ Parameter types (the same rows serve a command's `params`):
|
|
|
294
319
|
- `label` — a section heading (no value); `row` — 2–3 compact params on one
|
|
295
320
|
panel row (`items`, each label a short prefix like "W"); its items are
|
|
296
321
|
ordinary flat params (`params.w`).
|
|
322
|
+
- `data` — structured data the block owns: any JSON value, typed by its
|
|
323
|
+
default (`default: {} as Record<string, Wall>`). It has no Properties row;
|
|
324
|
+
handles, handle menus and actions edit it (agents set it like any param).
|
|
325
|
+
|
|
326
|
+
Geometry helpers come from `"lineadraw/helpers"` — vector math
|
|
327
|
+
(`add`, `sub`, `scale`, `rotate`, `polar`, …) and polygon booleans:
|
|
328
|
+
`union(...polygons)`, `difference(subject, ...clips)`,
|
|
329
|
+
`intersection(...polygons)`. A polygon is a ring of points, or rings with
|
|
330
|
+
holes (first the outer boundary). The result is a flat list of rings,
|
|
331
|
+
ready for closed polylines or ONE hatch, which fills even-odd so holes
|
|
332
|
+
stay holes:
|
|
333
|
+
|
|
334
|
+
```ts
|
|
335
|
+
const solid = union(...walls.map(wallRect)); // overlapping walls → clean outlines
|
|
336
|
+
return [
|
|
337
|
+
{ type: "hatch", loops: solid.map(hatchLoop), // a ring → line edges
|
|
338
|
+
fill: { kind: "pattern", name: "ANSI31", angle: 0, scale: 20 } },
|
|
339
|
+
...solid.map((points) => ({ type: "polyline", points, closed: true })),
|
|
340
|
+
];
|
|
341
|
+
```
|
|
297
342
|
|
|
298
343
|
Every param may carry a `hint` (the label's tooltip). An instance that
|
|
299
344
|
overrides a param shows "Reset" beside it in Properties, back to your
|
|
@@ -302,10 +347,94 @@ default. `draw` also receives
|
|
|
302
347
|
empty or unknown id → the first), for blocks that lay out with real text
|
|
303
348
|
sizes.
|
|
304
349
|
|
|
350
|
+
#### Hosted blocks
|
|
351
|
+
|
|
352
|
+
A block can LIVE ON another instance: a door on a floor plan. Give it a
|
|
353
|
+
`host` input; it then draws in the host's frame (moving, rotating and
|
|
354
|
+
copying with it, and deleted with it), and the two talk through
|
|
355
|
+
`expose`, JSON each publishes from its OWN params:
|
|
356
|
+
|
|
357
|
+
```ts
|
|
358
|
+
// The plan publishes its walls and cuts them where its openings say.
|
|
359
|
+
expose: ({ params }) => ({ walls: wallTable(params) }),
|
|
360
|
+
draw: ({ params, hosted }) => {
|
|
361
|
+
const cuts = hosted.map((h) => h.exposed?.cut).filter(Boolean);
|
|
362
|
+
return wallSolids(params, cuts);
|
|
363
|
+
},
|
|
364
|
+
|
|
365
|
+
// A door: picked by clicking a plan's wall; `attach` turns the click
|
|
366
|
+
// (plan-local) into its params.
|
|
367
|
+
inputs: [{ name: "plan", type: "host", types: ["@my-blocks/floor-plan"] }],
|
|
368
|
+
expose: ({ params }) => ({ cut: { wall: params.wall, at: params.at, width: params.width } }),
|
|
369
|
+
attach: ({ host, point }) => nearestWall(host.walls, point), // → { wall, at }
|
|
370
|
+
draw: ({ params, host }) => doorLeaf(host.walls[params.wall], params),
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
`expose` never sees the host or what's on it, so the two can't loop
|
|
374
|
+
(ADR 0008). What a host publishes and what its openings read is a
|
|
375
|
+
contract between the modules: document it.
|
|
376
|
+
|
|
377
|
+
A hosted block has no host in Library / marketplace previews. Give it a
|
|
378
|
+
stand-in with `previewHost`: the JSON a host's `expose` would return.
|
|
379
|
+
The preview runs `attach` as if the host were clicked at its origin, and
|
|
380
|
+
`draw` gets the stand-in as `host` (the save-time dry run uses it too):
|
|
381
|
+
|
|
382
|
+
```ts
|
|
383
|
+
previewHost: { preview: true, walls: { A: { a: [-1500, 0], b: [1500, 0], t: 200 } } },
|
|
384
|
+
// …and in draw, `host.preview` can add context: a stretch of wall.
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
#### Handles and actions
|
|
388
|
+
|
|
389
|
+
`handles({ params, inputs })` returns the handles a selected instance
|
|
390
|
+
shows, in block-local coordinates. It re-runs as values change, so a
|
|
391
|
+
handle can sit at the current width:
|
|
392
|
+
|
|
393
|
+
```ts
|
|
394
|
+
handles: ({ params }) => [
|
|
395
|
+
// Drag along local X: the distance becomes `width` (clamped to its min/max).
|
|
396
|
+
{ id: "width", at: [params.width, 0], shape: "triangle",
|
|
397
|
+
along: { origin: [0, 0], direction: [1, 0] }, param: "width" },
|
|
398
|
+
// A button: one click, one undo step.
|
|
399
|
+
{ id: "flip", at: [params.width / 2, 150], fixed: true, icon: "flip-horizontal",
|
|
400
|
+
click: ({ params }) => ({ params: { swing: params.swing === "left" ? "right" : "left" } }) },
|
|
401
|
+
// A line handle (shown while hovered) with a hover menu.
|
|
402
|
+
{ id: "wall", kind: "line", from: [0, 0], to: [params.width, 0], fixed: true,
|
|
403
|
+
menu: ["thickness",
|
|
404
|
+
{ field: { type: "boolean", label: "Enabled" }, value: !params.off,
|
|
405
|
+
set: (on) => ({ params: { off: !on } }) }],
|
|
406
|
+
actions: [{ label: "Reset", icon: "x", run: () => ({ params: { off: false } }) }] },
|
|
407
|
+
],
|
|
408
|
+
// The instance's context menu (right-click): pick a point, then run.
|
|
409
|
+
actions: [
|
|
410
|
+
{ label: "Add mark", pick: "point",
|
|
411
|
+
run: ({ params, point }) => ({ params: { marks: [...params.marks, [point.x, point.y]] } }) },
|
|
412
|
+
],
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
A handle has ONE drag behaviour: `param` (the constrained value → a number
|
|
416
|
+
param), `input` (moves a point input, replacing its default handle), or
|
|
417
|
+
`drag` (a function returning a patch). Otherwise it is `fixed`. The
|
|
418
|
+
constraint is free, `along` an axis (value = distance) or `around` a
|
|
419
|
+
centre (value = angle in radians). A line handle moves along its normal by
|
|
420
|
+
default. `click` turns it into a button. Shapes are `square`, `circle`,
|
|
421
|
+
`diamond`, `triangle`, `arrow`, `double-arrow`, `plus` and `minus`, and `icon` names a
|
|
422
|
+
lucide glyph from a small set. Handle functions and actions return a PATCH
|
|
423
|
+
— `{ params?, inputs? }`, with inputs by name and block-local — and never
|
|
424
|
+
mutate anything. Each applies as one undo step. The save-time dry run
|
|
425
|
+
checks every handle record.
|
|
426
|
+
|
|
305
427
|
### Writing a command
|
|
306
428
|
|
|
307
429
|
A command is a macro with a single `defineCommand` default export. Its
|
|
308
|
-
whole run is one undo step; Esc during a pick reverts cleanly.
|
|
430
|
+
whole run is one undo step; Esc during a pick reverts cleanly. Its
|
|
431
|
+
`inputs` table is the same one blocks declare; `object` / `objects` inputs
|
|
432
|
+
take the current selection when it fits (types and count) and arrive as
|
|
433
|
+
ids. To ask more DURING the run (the next question depends on the last
|
|
434
|
+
answer), use `editor.pickPoint` / `pickObject` / `prompt`, or
|
|
435
|
+
`editor.ask(paramsTable, { title })` for several fields in one dialog —
|
|
436
|
+
and declare `requiresEditor: true`, so CLI / agent runs refuse the command
|
|
437
|
+
up front instead of failing halfway. A
|
|
309
438
|
`params` table (the same rows a block's `params` uses) is asked for in a
|
|
310
439
|
dialog before the run and arrives typed as `ctx.params`; headless callers
|
|
311
440
|
pass it by name.
|
|
@@ -317,11 +446,12 @@ import { defineCommand } from "lineadraw";
|
|
|
317
446
|
export default defineCommand({
|
|
318
447
|
id: "@my-blocks/circle-here",
|
|
319
448
|
name: "Circle here",
|
|
320
|
-
inputs: ["Center point"],
|
|
449
|
+
inputs: [{ name: "center", type: "point", label: "Center point" }],
|
|
321
450
|
params: [{ name: "radius", type: "number", default: 10, min: 0.1 }],
|
|
322
|
-
// `inputs` are picked in the editor (or passed by a headless
|
|
323
|
-
// `params` asked for in a dialog; `editor`
|
|
324
|
-
|
|
451
|
+
// `inputs` are picked in the editor (or passed by name by a headless
|
|
452
|
+
// caller: { center: [0, 0] }), `params` asked for in a dialog; `editor`
|
|
453
|
+
// is absent when headless.
|
|
454
|
+
run: async ({ document, editor, inputs: { center }, params }) => {
|
|
325
455
|
document.add([{ type: "circle", center, radius: params.radius }]);
|
|
326
456
|
editor?.toast("Done", "success");
|
|
327
457
|
},
|
|
@@ -371,11 +501,11 @@ Collection name and owner come from your package.json:
|
|
|
371
501
|
|
|
372
502
|
### Using a marketplace in the editor
|
|
373
503
|
|
|
374
|
-
In [
|
|
375
|
-
gear
|
|
376
|
-
`owner/repo` (or `owner/repo@branch`). For a private repository,
|
|
504
|
+
In [Linea](https://lineadraw.com): **App settings → Marketplaces → Add a
|
|
505
|
+
marketplace** (the gear in Library → Marketplace opens the same tab) and
|
|
506
|
+
enter `owner/repo` (or `owner/repo@branch`). For a private repository,
|
|
377
507
|
create a fine-grained personal access token with read-only Contents access
|
|
378
|
-
to just that repository and paste it
|
|
508
|
+
to just that repository and paste it under "Add an access token" — it is stored only
|
|
379
509
|
on that device. Installing embeds the module (and its declared dependency
|
|
380
510
|
closure) in the document, so drawings keep working offline and travel with
|
|
381
511
|
the file.
|
|
@@ -386,8 +516,9 @@ the file.
|
|
|
386
516
|
lineadraw status App version, port, the open drawings: id, name, path, kind, dirty
|
|
387
517
|
lineadraw open <file.linea> Open a file in a new window
|
|
388
518
|
lineadraw close [--editor <x>] [--discard]
|
|
389
|
-
lineadraw call <operation> ['<json>'] [--editor <x>] Run one linea_* operation
|
|
390
|
-
lineadraw tools
|
|
519
|
+
lineadraw call <operation> ['<json>' | @file.json | -] [--editor <x>] Run one linea_* operation
|
|
520
|
+
lineadraw tools [<operation>] The operations the bridge offers, or one's argument schema
|
|
521
|
+
lineadraw --version
|
|
391
522
|
```
|
|
392
523
|
|
|
393
524
|
These commands talk to the running Linea desktop app on `127.0.0.1:7431`
|
|
@@ -401,6 +532,9 @@ SDK's [`connectEditors()`](#running-editors-the-desktop-bridge).
|
|
|
401
532
|
npx lineadraw call linea_add_objects '{"objects":[{"type":"circle","center":[0,0],"radius":500}]}'
|
|
402
533
|
```
|
|
403
534
|
|
|
535
|
+
The arguments can also come from a file (`@args.json`) or stdin (`-`),
|
|
536
|
+
which spares quoting JSON in PowerShell or cmd.
|
|
537
|
+
|
|
404
538
|
## Ecosystem
|
|
405
539
|
|
|
406
540
|
- [Linea](https://lineadraw.com) — the CAD editor, on the desktop and on
|
package/bin/lineadraw.mjs
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
13
13
|
import { isDeepStrictEqual } from "node:util";
|
|
14
14
|
import { dirname, join, resolve } from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
15
16
|
import {
|
|
16
17
|
buildManifest,
|
|
17
18
|
manifestJson,
|
|
@@ -35,12 +36,42 @@ Running editors (the Linea desktop app on 127.0.0.1:7431):
|
|
|
35
36
|
status app version, port, the open drawings (id, name, path, kind, dirty)
|
|
36
37
|
open <file.linea> open a file in a window of its own (returns its editor)
|
|
37
38
|
close [--editor <x>] [--discard] close an editor like its window's x
|
|
38
|
-
call <operation> ['<json>'] [--editor <x>]
|
|
39
|
-
run one linea_* operation (see tools)
|
|
40
|
-
|
|
39
|
+
call <operation> ['<json>' | @file.json | -] [--editor <x>]
|
|
40
|
+
run one linea_* operation (see tools);
|
|
41
|
+
its arguments as JSON text, a file, or stdin
|
|
42
|
+
tools [<operation>] the operations the bridge offers, or
|
|
43
|
+
one operation's argument schema
|
|
41
44
|
|
|
42
45
|
The desktop's bridge.json (port, agent token) is read automatically;
|
|
43
|
-
LINEA_BRIDGE_TOKEN or --token override the token, --port the port
|
|
46
|
+
LINEA_BRIDGE_TOKEN or --token override the token, --port the port.
|
|
47
|
+
|
|
48
|
+
--version the lineadraw version --help this text`;
|
|
49
|
+
|
|
50
|
+
const VERSION = JSON.parse(
|
|
51
|
+
readFileSync(
|
|
52
|
+
join(dirname(fileURLToPath(import.meta.url)), "..", "package.json"),
|
|
53
|
+
"utf8",
|
|
54
|
+
),
|
|
55
|
+
).version;
|
|
56
|
+
|
|
57
|
+
/** `call`'s arguments: JSON text, `@file.json`, or `-` for stdin (quoting
|
|
58
|
+
* JSON on a Windows command line is a fight best not picked). */
|
|
59
|
+
const readCallArgs = (spec) => {
|
|
60
|
+
if (spec === undefined) return {};
|
|
61
|
+
const text =
|
|
62
|
+
spec === "-"
|
|
63
|
+
? readFileSync(0, "utf8")
|
|
64
|
+
: spec.startsWith("@")
|
|
65
|
+
? readFileSync(resolve(spec.slice(1)), "utf8")
|
|
66
|
+
: spec;
|
|
67
|
+
try {
|
|
68
|
+
return JSON.parse(text);
|
|
69
|
+
} catch (e) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`call: the arguments are not valid JSON (${e instanceof Error ? e.message : e})`,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
44
75
|
|
|
45
76
|
const args = process.argv.slice(2);
|
|
46
77
|
const command = args[0];
|
|
@@ -90,12 +121,20 @@ const bridgeCommand = async (cmd, positional, flags) => {
|
|
|
90
121
|
const [operation, json] = positional;
|
|
91
122
|
if (!operation)
|
|
92
123
|
throw new Error("call needs an operation name (see `lineadraw tools`)");
|
|
93
|
-
return b.call(operation, json
|
|
94
|
-
|
|
95
|
-
|
|
124
|
+
return b.call(operation, readCallArgs(json), { editor });
|
|
125
|
+
}
|
|
126
|
+
case "tools": {
|
|
127
|
+
const tools = await b.tools();
|
|
128
|
+
const wanted = positional[0];
|
|
129
|
+
if (wanted === undefined)
|
|
130
|
+
return tools.map(({ name, description }) => ({ name, description }));
|
|
131
|
+
const tool = tools.find((t) => t.name === wanted);
|
|
132
|
+
if (!tool)
|
|
133
|
+
throw new Error(
|
|
134
|
+
`Unknown operation "${wanted}". \`lineadraw tools\` lists them.`,
|
|
135
|
+
);
|
|
136
|
+
return tool;
|
|
96
137
|
}
|
|
97
|
-
case "tools":
|
|
98
|
-
return b.tools();
|
|
99
138
|
default:
|
|
100
139
|
throw new Error(`Unknown command: ${cmd}\n\n${USAGE}`);
|
|
101
140
|
}
|
|
@@ -184,8 +223,19 @@ switch (command) {
|
|
|
184
223
|
}
|
|
185
224
|
break;
|
|
186
225
|
}
|
|
226
|
+
case "--version":
|
|
227
|
+
case "-v":
|
|
228
|
+
console.log(VERSION);
|
|
229
|
+
break;
|
|
230
|
+
case "--help":
|
|
231
|
+
case "-h":
|
|
232
|
+
case "help":
|
|
233
|
+
console.log(USAGE);
|
|
234
|
+
break;
|
|
187
235
|
default: {
|
|
188
|
-
if (
|
|
236
|
+
if (command === undefined) fail(USAGE);
|
|
237
|
+
if (!BRIDGE_COMMANDS.includes(command))
|
|
238
|
+
fail(`Unknown command "${command}".\n\n${USAGE}`);
|
|
189
239
|
const { positional, flags } = parseArgs(args.slice(1));
|
|
190
240
|
try {
|
|
191
241
|
const result = await bridgeCommand(command, positional, flags);
|
package/dist/bridge.d.ts
CHANGED
|
@@ -78,6 +78,7 @@ interface LineaBridge {
|
|
|
78
78
|
tools(): Promise<{
|
|
79
79
|
name: string;
|
|
80
80
|
description?: string;
|
|
81
|
+
inputSchema?: unknown;
|
|
81
82
|
}[]>;
|
|
82
83
|
/** Open a `.linea` file in a window of its own (an absolute path, or one
|
|
83
84
|
* relative to the current directory); resolves once it has loaded. */
|