fluidcad 0.0.32 → 0.0.34
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 +3 -2
- package/bin/commands/init.js +55 -0
- package/bin/commands/mcp.js +33 -0
- package/bin/commands/serve.js +77 -0
- package/bin/fluidcad.js +15 -107
- package/lib/dist/common/scene-object.d.ts +4 -1
- package/lib/dist/common/scene-object.js +9 -2
- package/lib/dist/common/solid.d.ts +4 -1
- package/lib/dist/common/solid.js +13 -0
- package/lib/dist/core/2d/tarc.d.ts +20 -2
- package/lib/dist/core/2d/tarc.js +24 -0
- package/lib/dist/core/index.d.ts +2 -1
- package/lib/dist/core/index.js +1 -0
- package/lib/dist/core/interfaces.d.ts +107 -2
- package/lib/dist/core/load.d.ts +2 -2
- package/lib/dist/core/repeat.js +62 -46
- package/lib/dist/core/rib.d.ts +18 -0
- package/lib/dist/core/rib.js +37 -0
- package/lib/dist/features/2d/arc.d.ts +8 -2
- package/lib/dist/features/2d/arc.js +94 -17
- package/lib/dist/features/2d/back.js +3 -2
- package/lib/dist/features/2d/sketch.d.ts +4 -0
- package/lib/dist/features/2d/sketch.js +21 -0
- package/lib/dist/features/2d/tarc-constrained.d.ts +2 -0
- package/lib/dist/features/2d/tarc-constrained.js +8 -0
- package/lib/dist/features/2d/tarc-radius-to-object.d.ts +16 -0
- package/lib/dist/features/2d/tarc-radius-to-object.js +58 -0
- package/lib/dist/features/2d/tarc-to-object.d.ts +18 -0
- package/lib/dist/features/2d/tarc-to-object.js +66 -0
- package/lib/dist/features/2d/tarc-to-point-tangent.d.ts +2 -0
- package/lib/dist/features/2d/tarc-to-point-tangent.js +3 -0
- package/lib/dist/features/2d/tarc-to-point.d.ts +2 -0
- package/lib/dist/features/2d/tarc-to-point.js +3 -0
- package/lib/dist/features/2d/tarc-with-tangent.d.ts +2 -0
- package/lib/dist/features/2d/tarc-with-tangent.js +3 -0
- package/lib/dist/features/2d/tarc.d.ts +2 -0
- package/lib/dist/features/2d/tarc.js +3 -0
- package/lib/dist/features/extrude-base.d.ts +9 -0
- package/lib/dist/features/extrude-base.js +22 -0
- package/lib/dist/features/extrude-to-face.js +1 -5
- package/lib/dist/features/extrude-two-distances.js +1 -2
- package/lib/dist/features/extrude.js +1 -2
- package/lib/dist/features/load.d.ts +6 -0
- package/lib/dist/features/load.js +53 -1
- package/lib/dist/features/mirror-feature.d.ts +3 -2
- package/lib/dist/features/mirror-feature.js +1 -1
- package/lib/dist/features/repeat-circular.d.ts +3 -3
- package/lib/dist/features/repeat-circular.js +8 -1
- package/lib/dist/features/repeat-linear.d.ts +4 -2
- package/lib/dist/features/repeat-linear.js +10 -1
- package/lib/dist/features/repeat-matrix.d.ts +3 -1
- package/lib/dist/features/repeat-matrix.js +7 -2
- package/lib/dist/features/rib.d.ts +31 -0
- package/lib/dist/features/rib.js +321 -0
- package/lib/dist/features/select.d.ts +1 -0
- package/lib/dist/features/select.js +81 -10
- package/lib/dist/features/shell.d.ts +4 -1
- package/lib/dist/features/shell.js +14 -3
- package/lib/dist/filters/edge/belongs-to-face.d.ts +12 -9
- package/lib/dist/filters/edge/belongs-to-face.js +64 -15
- package/lib/dist/filters/filter-builder-base.d.ts +25 -0
- package/lib/dist/filters/filter-builder-base.js +47 -0
- package/lib/dist/filters/filter.js +39 -14
- package/lib/dist/filters/from-object.d.ts +4 -0
- package/lib/dist/filters/from-object.js +10 -0
- package/lib/dist/helpers/clone-transform.d.ts +2 -1
- package/lib/dist/helpers/scene-helpers.d.ts +1 -1
- package/lib/dist/helpers/scene-helpers.js +146 -12
- package/lib/dist/index.d.ts +7 -1
- package/lib/dist/index.js +3 -3
- package/lib/dist/io/file-import.d.ts +5 -1
- package/lib/dist/io/file-import.js +29 -18
- package/lib/dist/math/lazy-matrix.d.ts +31 -0
- package/lib/dist/math/lazy-matrix.js +66 -0
- package/lib/dist/oc/color-transfer.d.ts +19 -8
- package/lib/dist/oc/color-transfer.js +70 -12
- package/lib/dist/oc/constraints/constraint-solver-adaptor.d.ts +5 -0
- package/lib/dist/oc/constraints/constraint-solver-adaptor.js +16 -0
- package/lib/dist/oc/constraints/constraint-solver.d.ts +4 -0
- package/lib/dist/oc/constraints/curve/curve-constraint-solver.d.ts +4 -0
- package/lib/dist/oc/constraints/curve/curve-constraint-solver.js +3 -0
- package/lib/dist/oc/constraints/geometric/geometric-constraint-solver.d.ts +6 -1
- package/lib/dist/oc/constraints/geometric/geometric-constraint-solver.js +4 -0
- package/lib/dist/oc/constraints/geometric/tangent-arc-from-point-tangent.d.ts +8 -0
- package/lib/dist/oc/constraints/geometric/tangent-arc-from-point-tangent.js +111 -0
- package/lib/dist/oc/constraints/geometric/tangent-arc-radius-to-object.d.ts +8 -0
- package/lib/dist/oc/constraints/geometric/tangent-arc-radius-to-object.js +161 -0
- package/lib/dist/oc/extrude-ops.d.ts +2 -1
- package/lib/dist/oc/extrude-ops.js +51 -2
- package/lib/dist/oc/mesh.d.ts +9 -4
- package/lib/dist/oc/mesh.js +14 -13
- package/lib/dist/oc/rib-ops.d.ts +35 -0
- package/lib/dist/oc/rib-ops.js +619 -0
- package/lib/dist/oc/shell-ops.d.ts +2 -1
- package/lib/dist/oc/shell-ops.js +5 -2
- package/lib/dist/oc/topology-index.d.ts +6 -0
- package/lib/dist/oc/topology-index.js +36 -0
- package/lib/dist/rendering/mesh-builder.d.ts +3 -0
- package/lib/dist/rendering/mesh-builder.js +8 -4
- package/lib/dist/rendering/render-edge.d.ts +2 -1
- package/lib/dist/rendering/render-edge.js +2 -2
- package/lib/dist/rendering/render-face.d.ts +2 -1
- package/lib/dist/rendering/render-face.js +2 -2
- package/lib/dist/rendering/render-solid.d.ts +2 -1
- package/lib/dist/rendering/render-solid.js +3 -5
- package/lib/dist/rendering/render-wire.d.ts +2 -1
- package/lib/dist/rendering/render-wire.js +2 -2
- package/lib/dist/rendering/render.d.ts +4 -0
- package/lib/dist/rendering/render.js +50 -2
- package/lib/dist/rendering/scene-compare.js +3 -0
- package/lib/dist/rendering/scene.d.ts +1 -0
- package/lib/dist/rendering/scene.js +4 -0
- package/lib/dist/scene-manager.d.ts +4 -2
- package/lib/dist/scene-manager.js +12 -4
- package/lib/dist/tests/features/2d/arc.test.js +64 -0
- package/lib/dist/tests/features/2d/back.test.js +17 -1
- package/lib/dist/tests/features/2d/tarc.test.js +157 -0
- package/lib/dist/tests/features/color-lineage.test.js +18 -0
- package/lib/dist/tests/features/filter-positional.test.d.ts +1 -0
- package/lib/dist/tests/features/filter-positional.test.js +129 -0
- package/lib/dist/tests/features/repeat-user-repro.test.d.ts +1 -0
- package/lib/dist/tests/features/repeat-user-repro.test.js +60 -0
- package/lib/dist/tests/features/rib.test.d.ts +1 -0
- package/lib/dist/tests/features/rib.test.js +598 -0
- package/lib/dist/tests/features/shell.test.js +36 -0
- package/lib/dist/tests/global-setup.js +2 -1
- package/lib/dist/tests/helpers/extract-blocks.d.ts +9 -0
- package/lib/dist/tests/helpers/extract-blocks.js +56 -0
- package/lib/dist/tests/llm-docs-examples.test.d.ts +1 -0
- package/lib/dist/tests/llm-docs-examples.test.js +62 -0
- package/lib/dist/tests/scene-compare.test.d.ts +1 -0
- package/lib/dist/tests/scene-compare.test.js +77 -0
- package/lib/dist/tests/setup.js +2 -1
- package/lib/dist/tsconfig.tsbuildinfo +1 -1
- package/llm-docs/.coverage-allowlist.txt +9 -0
- package/llm-docs/api/arc.md +48 -0
- package/llm-docs/api/axis.md +42 -0
- package/llm-docs/api/bezier.md +42 -0
- package/llm-docs/api/booleans.md +44 -0
- package/llm-docs/api/chamfer.md +40 -0
- package/llm-docs/api/circle.md +36 -0
- package/llm-docs/api/color.md +34 -0
- package/llm-docs/api/connect.md +41 -0
- package/llm-docs/api/constraint-qualifiers.md +48 -0
- package/llm-docs/api/copy.md +63 -0
- package/llm-docs/api/cursor-lines.md +50 -0
- package/llm-docs/api/cursor-move.md +61 -0
- package/llm-docs/api/cut.md +55 -0
- package/llm-docs/api/draft.md +36 -0
- package/llm-docs/api/edge-filter.md +57 -0
- package/llm-docs/api/ellipse.md +34 -0
- package/llm-docs/api/extrude.md +74 -0
- package/llm-docs/api/face-filter.md +61 -0
- package/llm-docs/api/fillet.md +51 -0
- package/llm-docs/api/index.json +139 -0
- package/llm-docs/api/line.md +42 -0
- package/llm-docs/api/load.md +37 -0
- package/llm-docs/api/local.md +38 -0
- package/llm-docs/api/loft.md +37 -0
- package/llm-docs/api/mirror.md +44 -0
- package/llm-docs/api/offset.md +36 -0
- package/llm-docs/api/part.md +40 -0
- package/llm-docs/api/plane.md +44 -0
- package/llm-docs/api/polygon.md +37 -0
- package/llm-docs/api/primitive-solids.md +39 -0
- package/llm-docs/api/project-intersect.md +48 -0
- package/llm-docs/api/rect.md +48 -0
- package/llm-docs/api/remove.md +32 -0
- package/llm-docs/api/repeat.md +79 -0
- package/llm-docs/api/revolve.md +38 -0
- package/llm-docs/api/rib.md +40 -0
- package/llm-docs/api/rotate.md +37 -0
- package/llm-docs/api/select.md +41 -0
- package/llm-docs/api/shell.md +41 -0
- package/llm-docs/api/sketch.md +76 -0
- package/llm-docs/api/slot.md +36 -0
- package/llm-docs/api/split-trim.md +42 -0
- package/llm-docs/api/sweep.md +43 -0
- package/llm-docs/api/tarc.md +45 -0
- package/llm-docs/api/tcircle.md +38 -0
- package/llm-docs/api/tline.md +42 -0
- package/llm-docs/api/translate.md +40 -0
- package/llm-docs/api/types/aline.md +35 -0
- package/llm-docs/api/types/arc-angles.md +29 -0
- package/llm-docs/api/types/arc-points.md +48 -0
- package/llm-docs/api/types/axis-like.md +38 -0
- package/llm-docs/api/types/axis.md +21 -0
- package/llm-docs/api/types/boolean-operation.md +50 -0
- package/llm-docs/api/types/circular-repeat-options.md +31 -0
- package/llm-docs/api/types/common.md +32 -0
- package/llm-docs/api/types/cut.md +125 -0
- package/llm-docs/api/types/draft.md +21 -0
- package/llm-docs/api/types/extrudable-geometry.md +23 -0
- package/llm-docs/api/types/extrude.md +194 -0
- package/llm-docs/api/types/geometry.md +51 -0
- package/llm-docs/api/types/hline.md +35 -0
- package/llm-docs/api/types/linear-repeat-options.md +31 -0
- package/llm-docs/api/types/loft.md +154 -0
- package/llm-docs/api/types/mirror.md +35 -0
- package/llm-docs/api/types/offset.md +31 -0
- package/llm-docs/api/types/plane-like.md +35 -0
- package/llm-docs/api/types/plane-transform-options.md +29 -0
- package/llm-docs/api/types/plane.md +21 -0
- package/llm-docs/api/types/point-like.md +22 -0
- package/llm-docs/api/types/point2dlike.md +26 -0
- package/llm-docs/api/types/polygon.md +46 -0
- package/llm-docs/api/types/rect.md +128 -0
- package/llm-docs/api/types/revolve.md +102 -0
- package/llm-docs/api/types/rib.md +133 -0
- package/llm-docs/api/types/scene-object.md +33 -0
- package/llm-docs/api/types/select.md +21 -0
- package/llm-docs/api/types/shell.md +54 -0
- package/llm-docs/api/types/slot.md +43 -0
- package/llm-docs/api/types/sweep.md +189 -0
- package/llm-docs/api/types/tangent-arc-two-objects.md +46 -0
- package/llm-docs/api/types/transformable.md +93 -0
- package/llm-docs/api/types/trim.md +27 -0
- package/llm-docs/api/types/two-objects-tangent-line.md +46 -0
- package/llm-docs/api/types/vertex.md +17 -0
- package/llm-docs/api/types/vline.md +35 -0
- package/llm-docs/concepts/coordinate-system.md +45 -0
- package/llm-docs/concepts/history-and-rollback.md +40 -0
- package/llm-docs/concepts/last-selection.md +49 -0
- package/llm-docs/concepts/scene-graph.md +37 -0
- package/llm-docs/index.json +1750 -0
- package/mcp/dist/client.d.ts +64 -0
- package/mcp/dist/client.js +248 -0
- package/mcp/dist/discovery.d.ts +11 -0
- package/mcp/dist/discovery.js +78 -0
- package/mcp/dist/docs-index.d.ts +81 -0
- package/mcp/dist/docs-index.js +261 -0
- package/mcp/dist/resources.d.ts +4 -0
- package/mcp/dist/resources.js +115 -0
- package/mcp/dist/server.d.ts +12 -0
- package/mcp/dist/server.js +489 -0
- package/mcp/dist/tools/coordination.d.ts +9 -0
- package/mcp/dist/tools/coordination.js +46 -0
- package/mcp/dist/tools/docs.d.ts +66 -0
- package/mcp/dist/tools/docs.js +122 -0
- package/mcp/dist/tools/engine.d.ts +56 -0
- package/mcp/dist/tools/engine.js +145 -0
- package/mcp/dist/tools/inspection.d.ts +75 -0
- package/mcp/dist/tools/inspection.js +121 -0
- package/mcp/dist/tools/screenshot.d.ts +63 -0
- package/mcp/dist/tools/screenshot.js +263 -0
- package/mcp/dist/tools/source.d.ts +84 -0
- package/mcp/dist/tools/source.js +434 -0
- package/mcp/dist/tools/workspaces.d.ts +13 -0
- package/mcp/dist/tools/workspaces.js +33 -0
- package/mcp/dist/types.d.ts +18 -0
- package/mcp/dist/types.js +11 -0
- package/package.json +19 -5
- package/server/dist/code-editor.d.ts +36 -0
- package/server/dist/code-editor.js +8 -0
- package/server/dist/fluidcad-server.d.ts +50 -0
- package/server/dist/fluidcad-server.js +153 -1
- package/server/dist/global-registry.d.ts +30 -0
- package/server/dist/global-registry.js +126 -0
- package/server/dist/index.js +171 -26
- package/server/dist/instance-file.d.ts +31 -0
- package/server/dist/instance-file.js +73 -0
- package/server/dist/lint-fluid-js.d.ts +15 -0
- package/server/dist/lint-fluid-js.js +271 -0
- package/server/dist/routes/editor.d.ts +24 -0
- package/server/dist/routes/editor.js +44 -0
- package/server/dist/routes/export.d.ts +1 -1
- package/server/dist/routes/export.js +45 -8
- package/server/dist/routes/health.d.ts +7 -0
- package/server/dist/routes/health.js +14 -0
- package/server/dist/routes/lint.d.ts +10 -0
- package/server/dist/routes/lint.js +28 -0
- package/server/dist/routes/render.d.ts +33 -0
- package/server/dist/routes/render.js +34 -0
- package/server/dist/routes/scene.d.ts +5 -0
- package/server/dist/routes/scene.js +48 -0
- package/server/dist/routes/screenshot.js +68 -1
- package/server/dist/ws-protocol.d.ts +56 -2
- package/ui/dist/assets/{index-DMw0OYCF.js → index-BdqrMDRu.js} +30 -30
- package/ui/dist/index.html +1 -1
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Documentation tools — the agent-facing surface over `llm-docs/`.
|
|
2
|
+
//
|
|
3
|
+
// Each tool is a pure function over an injected `DocsIndex` so the server
|
|
4
|
+
// wires it up via closure (no module-level singleton). Errors never throw
|
|
5
|
+
// across the MCP boundary; everything is funneled into `ToolResult<T>`.
|
|
6
|
+
import { err, ok } from "../types.js";
|
|
7
|
+
export function listDocs(index, input = {}) {
|
|
8
|
+
try {
|
|
9
|
+
const docs = index.list(input.tag).map((d) => ({
|
|
10
|
+
id: d.id,
|
|
11
|
+
title: d.title,
|
|
12
|
+
summary: d.summary,
|
|
13
|
+
tags: d.tags,
|
|
14
|
+
}));
|
|
15
|
+
return ok({ docs });
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
return err('internal', toMessage(error));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function readDoc(index, input) {
|
|
22
|
+
if (!input || typeof input.id !== 'string' || input.id.length === 0) {
|
|
23
|
+
return err('invalid-input', '`id` is required and must be a non-empty string.');
|
|
24
|
+
}
|
|
25
|
+
const doc = index.get(input.id);
|
|
26
|
+
if (!doc) {
|
|
27
|
+
return err('invalid-input', `No doc with id "${input.id}".`);
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const body = index.body(doc.id) ?? '';
|
|
31
|
+
return ok({
|
|
32
|
+
id: doc.id,
|
|
33
|
+
title: doc.title,
|
|
34
|
+
body,
|
|
35
|
+
seeAlso: doc.seeAlso,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
return err('internal', toMessage(error));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function searchDocs(index, input) {
|
|
43
|
+
if (!input || typeof input.query !== 'string' || input.query.length === 0) {
|
|
44
|
+
return err('invalid-input', '`query` is required and must be a non-empty string.');
|
|
45
|
+
}
|
|
46
|
+
if (input.limit !== undefined &&
|
|
47
|
+
(typeof input.limit !== 'number' || input.limit <= 0 || !Number.isFinite(input.limit))) {
|
|
48
|
+
return err('invalid-input', '`limit` must be a positive number when provided.');
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const limit = input.limit ?? 10;
|
|
52
|
+
const results = index.search(input.query, limit);
|
|
53
|
+
return ok({ results });
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
return err('internal', toMessage(error));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export function getApiSignature(index, input) {
|
|
60
|
+
if (!input || typeof input.name !== 'string' || input.name.length === 0) {
|
|
61
|
+
return err('invalid-input', '`name` is required and must be a non-empty string.');
|
|
62
|
+
}
|
|
63
|
+
const docId = index.symbols[input.name];
|
|
64
|
+
if (!docId) {
|
|
65
|
+
return err('invalid-input', `No API symbol "${input.name}".`);
|
|
66
|
+
}
|
|
67
|
+
const doc = index.get(docId);
|
|
68
|
+
if (!doc) {
|
|
69
|
+
// The api index points at a docId that the main index does not know about
|
|
70
|
+
// — only possible if the manifests were generated separately, which should
|
|
71
|
+
// never happen because `build-llm-docs.ts` writes both atomically.
|
|
72
|
+
return err('internal', `API symbol "${input.name}" maps to missing doc "${docId}".`);
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
const signature = index.firstCodeBlock(docId) ?? '';
|
|
76
|
+
return ok({
|
|
77
|
+
symbol: input.name,
|
|
78
|
+
docId: doc.id,
|
|
79
|
+
title: doc.title,
|
|
80
|
+
signature,
|
|
81
|
+
summary: doc.summary,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
return err('internal', toMessage(error));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export function getTypeDefinition(index, input) {
|
|
89
|
+
if (!input || typeof input.name !== 'string' || input.name.length === 0) {
|
|
90
|
+
return err('invalid-input', '`name` is required and must be a non-empty string.');
|
|
91
|
+
}
|
|
92
|
+
const docId = index.types[input.name];
|
|
93
|
+
if (!docId) {
|
|
94
|
+
return err('invalid-input', `No type "${input.name}". Call list_docs({tag:"type"}) to see every documented type.`);
|
|
95
|
+
}
|
|
96
|
+
const doc = index.get(docId);
|
|
97
|
+
if (!doc) {
|
|
98
|
+
return err('internal', `Type "${input.name}" maps to missing doc "${docId}".`);
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
const definition = index.firstCodeBlock(docId) ?? '';
|
|
102
|
+
const body = index.body(docId) ?? '';
|
|
103
|
+
return ok({
|
|
104
|
+
name: doc.title,
|
|
105
|
+
docId: doc.id,
|
|
106
|
+
title: doc.title,
|
|
107
|
+
definition,
|
|
108
|
+
body,
|
|
109
|
+
summary: doc.summary,
|
|
110
|
+
seeAlso: doc.seeAlso,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
return err('internal', toMessage(error));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function toMessage(error) {
|
|
118
|
+
if (error instanceof Error) {
|
|
119
|
+
return error.message;
|
|
120
|
+
}
|
|
121
|
+
return String(error);
|
|
122
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type WorkspaceArg } from './inspection.ts';
|
|
2
|
+
import { type ToolResult } from '../types.ts';
|
|
3
|
+
export type RecomputeInput = WorkspaceArg;
|
|
4
|
+
export type RecomputeOutput = {
|
|
5
|
+
success: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function recompute(input: RecomputeInput): Promise<ToolResult<RecomputeOutput>>;
|
|
8
|
+
export type RollbackToInput = WorkspaceArg & {
|
|
9
|
+
index: number;
|
|
10
|
+
};
|
|
11
|
+
export type RollbackToOutput = {
|
|
12
|
+
success: boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare function rollbackTo(input: RollbackToInput): Promise<ToolResult<RollbackToOutput>>;
|
|
15
|
+
export type AddBreakpointInput = WorkspaceArg & {
|
|
16
|
+
file: string;
|
|
17
|
+
line: number;
|
|
18
|
+
};
|
|
19
|
+
export type AddBreakpointOutput = {
|
|
20
|
+
success: boolean;
|
|
21
|
+
};
|
|
22
|
+
export declare function addBreakpoint(input: AddBreakpointInput): Promise<ToolResult<AddBreakpointOutput>>;
|
|
23
|
+
export type ClearBreakpointsInput = WorkspaceArg;
|
|
24
|
+
export type ClearBreakpointsOutput = {
|
|
25
|
+
success: boolean;
|
|
26
|
+
};
|
|
27
|
+
export declare function clearBreakpoints(input: ClearBreakpointsInput): Promise<ToolResult<ClearBreakpointsOutput>>;
|
|
28
|
+
export type ImportStepInput = WorkspaceArg & {
|
|
29
|
+
path: string;
|
|
30
|
+
};
|
|
31
|
+
export type ImportStepOutput = {
|
|
32
|
+
success: boolean;
|
|
33
|
+
fileName: string;
|
|
34
|
+
};
|
|
35
|
+
export declare function importStep(input: ImportStepInput): Promise<ToolResult<ImportStepOutput>>;
|
|
36
|
+
export type ExportFormat = 'step' | 'stl';
|
|
37
|
+
export type ExportResolution = 'coarse' | 'medium' | 'fine';
|
|
38
|
+
export type ExportInput = WorkspaceArg & {
|
|
39
|
+
format: ExportFormat;
|
|
40
|
+
shapeIds: string[];
|
|
41
|
+
saveAsPath?: string;
|
|
42
|
+
resolution?: ExportResolution;
|
|
43
|
+
includeColors?: boolean;
|
|
44
|
+
};
|
|
45
|
+
export type ExportSavedOutput = {
|
|
46
|
+
savedTo: string;
|
|
47
|
+
bytesWritten: number;
|
|
48
|
+
};
|
|
49
|
+
export type ExportBase64Output = {
|
|
50
|
+
format: ExportFormat;
|
|
51
|
+
mimeType: string;
|
|
52
|
+
base64: string;
|
|
53
|
+
bytes: number;
|
|
54
|
+
};
|
|
55
|
+
export type ExportOutput = ExportSavedOutput | ExportBase64Output;
|
|
56
|
+
export declare function exportShapes(input: ExportInput): Promise<ToolResult<ExportOutput>>;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// Engine-control tools — wrappers around existing FluidCAD REST routes that
|
|
2
|
+
// let the agent recompute, rollback, set breakpoints, and import/export
|
|
3
|
+
// geometry. All workspace resolution and HTTP-error mapping is shared with
|
|
4
|
+
// the inspection tools.
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import fsp from 'node:fs/promises';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { resolveClient } from "./inspection.js";
|
|
9
|
+
import { HttpError } from "../client.js";
|
|
10
|
+
import { err, ok } from "../types.js";
|
|
11
|
+
async function callWithClient(input, fn) {
|
|
12
|
+
const resolved = resolveClient(input);
|
|
13
|
+
if (resolved.ok === false) {
|
|
14
|
+
return resolved;
|
|
15
|
+
}
|
|
16
|
+
const { client } = resolved.data;
|
|
17
|
+
try {
|
|
18
|
+
const data = await fn(client);
|
|
19
|
+
return ok(data);
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
if (e instanceof HttpError) {
|
|
23
|
+
return err('http-error', `HTTP ${e.statusCode}: ${e.body.slice(0, 200)}`, {
|
|
24
|
+
statusCode: e.statusCode,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return err('internal', e?.message ?? String(e));
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
await client.close().catch(() => { });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export async function recompute(input) {
|
|
34
|
+
return callWithClient(input, (client) => client.postJson('/api/recompute', {}));
|
|
35
|
+
}
|
|
36
|
+
export async function rollbackTo(input) {
|
|
37
|
+
if (typeof input?.index !== 'number' || !Number.isInteger(input.index) || input.index < 0) {
|
|
38
|
+
return err('invalid-input', '`index` is required and must be a non-negative integer.');
|
|
39
|
+
}
|
|
40
|
+
const { index } = input;
|
|
41
|
+
return callWithClient(input, (client) => client.postJson('/api/rollback', { index }));
|
|
42
|
+
}
|
|
43
|
+
export async function addBreakpoint(input) {
|
|
44
|
+
if (!input?.file || typeof input.file !== 'string') {
|
|
45
|
+
return err('invalid-input', '`file` is required and must be a non-empty string.');
|
|
46
|
+
}
|
|
47
|
+
if (typeof input?.line !== 'number' || !Number.isInteger(input.line) || input.line < 0) {
|
|
48
|
+
return err('invalid-input', '`line` is required and must be a non-negative integer.');
|
|
49
|
+
}
|
|
50
|
+
const sourceLocation = { filePath: input.file, line: input.line };
|
|
51
|
+
return callWithClient(input, (client) => client.postJson('/api/add-breakpoint', { sourceLocation }));
|
|
52
|
+
}
|
|
53
|
+
export async function clearBreakpoints(input) {
|
|
54
|
+
return callWithClient(input, (client) => client.postJson('/api/clear-breakpoints', {}));
|
|
55
|
+
}
|
|
56
|
+
export async function importStep(input) {
|
|
57
|
+
if (!input?.path || typeof input.path !== 'string') {
|
|
58
|
+
return err('invalid-input', '`path` is required and must be a non-empty string.');
|
|
59
|
+
}
|
|
60
|
+
const absPath = path.resolve(input.path);
|
|
61
|
+
let bytes;
|
|
62
|
+
try {
|
|
63
|
+
bytes = await fsp.readFile(absPath);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
if (e?.code === 'ENOENT') {
|
|
67
|
+
return err('invalid-input', `File not found: ${input.path}`);
|
|
68
|
+
}
|
|
69
|
+
return err('internal', e?.message ?? String(e));
|
|
70
|
+
}
|
|
71
|
+
const fileName = path.basename(absPath);
|
|
72
|
+
const data = bytes.toString('base64');
|
|
73
|
+
return callWithClient(input, (client) => client.postJson('/api/import-file', { fileName, data }));
|
|
74
|
+
}
|
|
75
|
+
export async function exportShapes(input) {
|
|
76
|
+
if (input?.format !== 'step' && input?.format !== 'stl') {
|
|
77
|
+
return err('invalid-input', '`format` is required and must be "step" or "stl".');
|
|
78
|
+
}
|
|
79
|
+
if (!Array.isArray(input?.shapeIds) || input.shapeIds.length === 0) {
|
|
80
|
+
return err('invalid-input', '`shapeIds` is required and must be a non-empty array.');
|
|
81
|
+
}
|
|
82
|
+
if (input.shapeIds.some((id) => typeof id !== 'string' || id.length === 0)) {
|
|
83
|
+
return err('invalid-input', '`shapeIds` entries must be non-empty strings.');
|
|
84
|
+
}
|
|
85
|
+
if (input.resolution !== undefined &&
|
|
86
|
+
input.resolution !== 'coarse' &&
|
|
87
|
+
input.resolution !== 'medium' &&
|
|
88
|
+
input.resolution !== 'fine') {
|
|
89
|
+
return err('invalid-input', '`resolution` must be "coarse", "medium", or "fine".');
|
|
90
|
+
}
|
|
91
|
+
if (input.saveAsPath !== undefined && typeof input.saveAsPath !== 'string') {
|
|
92
|
+
return err('invalid-input', '`saveAsPath` must be a string when provided.');
|
|
93
|
+
}
|
|
94
|
+
const body = {
|
|
95
|
+
format: input.format,
|
|
96
|
+
shapeIds: input.shapeIds,
|
|
97
|
+
resolution: input.resolution ?? 'medium',
|
|
98
|
+
};
|
|
99
|
+
if (input.includeColors !== undefined) {
|
|
100
|
+
body.includeColors = input.includeColors;
|
|
101
|
+
}
|
|
102
|
+
if (input.saveAsPath !== undefined) {
|
|
103
|
+
body.saveAsPath = input.saveAsPath;
|
|
104
|
+
}
|
|
105
|
+
const resolved = resolveClient(input);
|
|
106
|
+
if (resolved.ok === false) {
|
|
107
|
+
return resolved;
|
|
108
|
+
}
|
|
109
|
+
const { client } = resolved.data;
|
|
110
|
+
try {
|
|
111
|
+
const raw = await client.postRaw('/api/export', body);
|
|
112
|
+
if (raw.statusCode >= 400) {
|
|
113
|
+
const text = raw.data.toString('utf8');
|
|
114
|
+
return err('http-error', `HTTP ${raw.statusCode}: ${text.slice(0, 200)}`, {
|
|
115
|
+
statusCode: raw.statusCode,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
if (raw.contentType.includes('application/json')) {
|
|
119
|
+
const parsed = JSON.parse(raw.data.toString('utf8'));
|
|
120
|
+
// Mirror the server's `savedTo` so the agent always returns absolute
|
|
121
|
+
// paths to the user; double-check the file exists for friendlier errors.
|
|
122
|
+
if (parsed?.savedTo && !fs.existsSync(parsed.savedTo)) {
|
|
123
|
+
return err('internal', `Server reported savedTo=${parsed.savedTo} but the file is missing.`);
|
|
124
|
+
}
|
|
125
|
+
return ok(parsed);
|
|
126
|
+
}
|
|
127
|
+
return ok({
|
|
128
|
+
format: input.format,
|
|
129
|
+
mimeType: raw.contentType,
|
|
130
|
+
base64: raw.data.toString('base64'),
|
|
131
|
+
bytes: raw.data.length,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
if (e instanceof HttpError) {
|
|
136
|
+
return err('http-error', `HTTP ${e.statusCode}: ${e.body.slice(0, 200)}`, {
|
|
137
|
+
statusCode: e.statusCode,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return err('internal', e?.message ?? String(e));
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
await client.close().catch(() => { });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { FluidCadClient } from '../client.ts';
|
|
2
|
+
import { type ToolResult } from '../types.ts';
|
|
3
|
+
import type { RegistryEntry } from '../types.ts';
|
|
4
|
+
export type WorkspaceArg = {
|
|
5
|
+
workspace?: string;
|
|
6
|
+
};
|
|
7
|
+
export type ResolvedClient = {
|
|
8
|
+
client: FluidCadClient;
|
|
9
|
+
entry: RegistryEntry;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Resolve a workspace argument to a `FluidCadClient`. Returns an error
|
|
13
|
+
* variant when the argument is ambiguous or cannot be matched. Callers own
|
|
14
|
+
* `client.close()` (typically inside a finally).
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveClient(input: WorkspaceArg): ToolResult<ResolvedClient>;
|
|
17
|
+
export type GetSceneSummaryInput = WorkspaceArg;
|
|
18
|
+
export declare function getSceneSummary(input: GetSceneSummaryInput): Promise<ToolResult<unknown>>;
|
|
19
|
+
export type ListShapesInput = WorkspaceArg;
|
|
20
|
+
export declare function listShapes(input: ListShapesInput): Promise<ToolResult<unknown>>;
|
|
21
|
+
export type GetCompileErrorInput = WorkspaceArg;
|
|
22
|
+
export declare function getCompileError(input: GetCompileErrorInput): Promise<ToolResult<unknown>>;
|
|
23
|
+
export type GetShapePropertiesInput = WorkspaceArg & {
|
|
24
|
+
shapeId: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function getShapeProperties(input: GetShapePropertiesInput): Promise<{
|
|
27
|
+
ok: false;
|
|
28
|
+
code: import("../types.ts").ToolErrorCode;
|
|
29
|
+
message: string;
|
|
30
|
+
details?: unknown;
|
|
31
|
+
} | {
|
|
32
|
+
ok: true;
|
|
33
|
+
data: unknown;
|
|
34
|
+
}>;
|
|
35
|
+
export type GetFacePropertiesInput = WorkspaceArg & {
|
|
36
|
+
shapeId: string;
|
|
37
|
+
faceIndex: number;
|
|
38
|
+
};
|
|
39
|
+
export declare function getFaceProperties(input: GetFacePropertiesInput): Promise<{
|
|
40
|
+
ok: false;
|
|
41
|
+
code: import("../types.ts").ToolErrorCode;
|
|
42
|
+
message: string;
|
|
43
|
+
details?: unknown;
|
|
44
|
+
} | {
|
|
45
|
+
ok: true;
|
|
46
|
+
data: unknown;
|
|
47
|
+
}>;
|
|
48
|
+
export type GetEdgePropertiesInput = WorkspaceArg & {
|
|
49
|
+
shapeId: string;
|
|
50
|
+
edgeIndex: number;
|
|
51
|
+
};
|
|
52
|
+
export declare function getEdgeProperties(input: GetEdgePropertiesInput): Promise<{
|
|
53
|
+
ok: false;
|
|
54
|
+
code: import("../types.ts").ToolErrorCode;
|
|
55
|
+
message: string;
|
|
56
|
+
details?: unknown;
|
|
57
|
+
} | {
|
|
58
|
+
ok: true;
|
|
59
|
+
data: unknown;
|
|
60
|
+
}>;
|
|
61
|
+
export type HitTestInput = WorkspaceArg & {
|
|
62
|
+
shapeId: string;
|
|
63
|
+
rayOrigin: [number, number, number];
|
|
64
|
+
rayDir: [number, number, number];
|
|
65
|
+
edgeThreshold?: number;
|
|
66
|
+
};
|
|
67
|
+
export declare function hitTest(input: HitTestInput): Promise<{
|
|
68
|
+
ok: false;
|
|
69
|
+
code: import("../types.ts").ToolErrorCode;
|
|
70
|
+
message: string;
|
|
71
|
+
details?: unknown;
|
|
72
|
+
} | {
|
|
73
|
+
ok: true;
|
|
74
|
+
data: unknown;
|
|
75
|
+
}>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// Inspection tools — read-only views of a running FluidCAD workspace.
|
|
2
|
+
//
|
|
3
|
+
// Each tool maps to a single HTTP call against the FluidCAD server. The
|
|
4
|
+
// workspace resolution rule is consistent across all of them: an explicit
|
|
5
|
+
// `workspace` wins; with one running instance the singleton is used; with
|
|
6
|
+
// multiple, the agent must disambiguate.
|
|
7
|
+
import { findByWorkspace, listLiveInstances } from "../discovery.js";
|
|
8
|
+
import { FluidCadClient, HttpError } from "../client.js";
|
|
9
|
+
import { err, ok } from "../types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a workspace argument to a `FluidCadClient`. Returns an error
|
|
12
|
+
* variant when the argument is ambiguous or cannot be matched. Callers own
|
|
13
|
+
* `client.close()` (typically inside a finally).
|
|
14
|
+
*/
|
|
15
|
+
export function resolveClient(input) {
|
|
16
|
+
if (input?.workspace) {
|
|
17
|
+
const entry = findByWorkspace(input.workspace);
|
|
18
|
+
if (!entry) {
|
|
19
|
+
return err('workspace-not-found', `No running FluidCAD workspace at "${input.workspace}". Call list_workspaces to see what's available.`);
|
|
20
|
+
}
|
|
21
|
+
return ok({ client: new FluidCadClient(entry), entry });
|
|
22
|
+
}
|
|
23
|
+
const instances = listLiveInstances();
|
|
24
|
+
if (instances.length === 0) {
|
|
25
|
+
return err('no-server', 'No running FluidCAD workspaces. Start one with `fluidcad serve`.');
|
|
26
|
+
}
|
|
27
|
+
if (instances.length > 1) {
|
|
28
|
+
return err('no-workspace', `Multiple FluidCAD workspaces are running (${instances.length}). Pass \`workspace\` to disambiguate.`, { workspaces: instances.map((e) => e.workspacePath) });
|
|
29
|
+
}
|
|
30
|
+
return ok({ client: new FluidCadClient(instances[0]), entry: instances[0] });
|
|
31
|
+
}
|
|
32
|
+
async function callWithClient(input, fn) {
|
|
33
|
+
const resolved = resolveClient(input);
|
|
34
|
+
if (resolved.ok === false) {
|
|
35
|
+
return resolved;
|
|
36
|
+
}
|
|
37
|
+
const { client } = resolved.data;
|
|
38
|
+
try {
|
|
39
|
+
const data = await fn(client);
|
|
40
|
+
return ok(data);
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
if (e instanceof HttpError) {
|
|
44
|
+
return err('http-error', `HTTP ${e.statusCode}: ${e.body.slice(0, 200)}`, {
|
|
45
|
+
statusCode: e.statusCode,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return err('internal', e?.message ?? String(e));
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
await client.close().catch(() => { });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export async function getSceneSummary(input) {
|
|
55
|
+
return callWithClient(input, (client) => client.getJson('/api/scene/summary'));
|
|
56
|
+
}
|
|
57
|
+
export async function listShapes(input) {
|
|
58
|
+
return callWithClient(input, (client) => client.getJson('/api/scene/shapes'));
|
|
59
|
+
}
|
|
60
|
+
export async function getCompileError(input) {
|
|
61
|
+
return callWithClient(input, (client) => client.getJson('/api/scene/compile-error'));
|
|
62
|
+
}
|
|
63
|
+
export async function getShapeProperties(input) {
|
|
64
|
+
if (!input?.shapeId || typeof input.shapeId !== 'string') {
|
|
65
|
+
return err('invalid-input', '`shapeId` is required and must be a non-empty string.');
|
|
66
|
+
}
|
|
67
|
+
const shapeId = input.shapeId;
|
|
68
|
+
return callWithClient(input, (client) => client.getJson(`/api/shape-properties?shapeId=${encodeURIComponent(shapeId)}`));
|
|
69
|
+
}
|
|
70
|
+
export async function getFaceProperties(input) {
|
|
71
|
+
if (!input?.shapeId || typeof input.shapeId !== 'string') {
|
|
72
|
+
return err('invalid-input', '`shapeId` is required and must be a non-empty string.');
|
|
73
|
+
}
|
|
74
|
+
if (typeof input.faceIndex !== 'number' ||
|
|
75
|
+
!Number.isInteger(input.faceIndex) ||
|
|
76
|
+
input.faceIndex < 0) {
|
|
77
|
+
return err('invalid-input', '`faceIndex` is required and must be a non-negative integer.');
|
|
78
|
+
}
|
|
79
|
+
const { shapeId, faceIndex } = input;
|
|
80
|
+
return callWithClient(input, (client) => client.getJson(`/api/face-properties?shapeId=${encodeURIComponent(shapeId)}&faceIndex=${faceIndex}`));
|
|
81
|
+
}
|
|
82
|
+
export async function getEdgeProperties(input) {
|
|
83
|
+
if (!input?.shapeId || typeof input.shapeId !== 'string') {
|
|
84
|
+
return err('invalid-input', '`shapeId` is required and must be a non-empty string.');
|
|
85
|
+
}
|
|
86
|
+
if (typeof input.edgeIndex !== 'number' ||
|
|
87
|
+
!Number.isInteger(input.edgeIndex) ||
|
|
88
|
+
input.edgeIndex < 0) {
|
|
89
|
+
return err('invalid-input', '`edgeIndex` is required and must be a non-negative integer.');
|
|
90
|
+
}
|
|
91
|
+
const { shapeId, edgeIndex } = input;
|
|
92
|
+
return callWithClient(input, (client) => client.getJson(`/api/edge-properties?shapeId=${encodeURIComponent(shapeId)}&edgeIndex=${edgeIndex}`));
|
|
93
|
+
}
|
|
94
|
+
export async function hitTest(input) {
|
|
95
|
+
if (!input?.shapeId || typeof input.shapeId !== 'string') {
|
|
96
|
+
return err('invalid-input', '`shapeId` is required and must be a non-empty string.');
|
|
97
|
+
}
|
|
98
|
+
if (!isVec3(input?.rayOrigin)) {
|
|
99
|
+
return err('invalid-input', '`rayOrigin` must be a 3-element array of finite numbers.');
|
|
100
|
+
}
|
|
101
|
+
if (!isVec3(input?.rayDir)) {
|
|
102
|
+
return err('invalid-input', '`rayDir` must be a 3-element array of finite numbers.');
|
|
103
|
+
}
|
|
104
|
+
const edgeThreshold = input.edgeThreshold;
|
|
105
|
+
if (edgeThreshold !== undefined &&
|
|
106
|
+
(typeof edgeThreshold !== 'number' || !Number.isFinite(edgeThreshold) || edgeThreshold < 0)) {
|
|
107
|
+
return err('invalid-input', '`edgeThreshold` must be a non-negative finite number when provided.');
|
|
108
|
+
}
|
|
109
|
+
const body = {
|
|
110
|
+
shapeId: input.shapeId,
|
|
111
|
+
rayOrigin: input.rayOrigin,
|
|
112
|
+
rayDir: input.rayDir,
|
|
113
|
+
edgeThreshold: edgeThreshold ?? 0,
|
|
114
|
+
};
|
|
115
|
+
return callWithClient(input, (client) => client.postJson('/api/hit-test', body));
|
|
116
|
+
}
|
|
117
|
+
function isVec3(value) {
|
|
118
|
+
return (Array.isArray(value) &&
|
|
119
|
+
value.length === 3 &&
|
|
120
|
+
value.every((n) => typeof n === 'number' && Number.isFinite(n)));
|
|
121
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type WorkspaceArg } from './inspection.ts';
|
|
2
|
+
import { type ToolResult } from '../types.ts';
|
|
3
|
+
declare const NAMED_VIEWS: readonly ["front", "back", "left", "right", "top", "bottom", "iso-ftr", "iso-fbr", "iso-ftl", "iso-fbl", "iso-btr", "iso-bbr", "iso-btl", "iso-bbl"];
|
|
4
|
+
export type NamedView = (typeof NAMED_VIEWS)[number];
|
|
5
|
+
export type ScreenshotView = {
|
|
6
|
+
kind: 'current';
|
|
7
|
+
} | {
|
|
8
|
+
kind: 'named';
|
|
9
|
+
name: NamedView;
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'orbit-from-current';
|
|
12
|
+
azimuthDeg: number;
|
|
13
|
+
elevationDeg: number;
|
|
14
|
+
} | {
|
|
15
|
+
kind: 'look-from';
|
|
16
|
+
eye: [number, number, number];
|
|
17
|
+
target?: [number, number, number];
|
|
18
|
+
};
|
|
19
|
+
export type ImageResult = {
|
|
20
|
+
image: {
|
|
21
|
+
mimeType: string;
|
|
22
|
+
base64: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export type ScreenshotInput = WorkspaceArg & {
|
|
26
|
+
view?: ScreenshotView;
|
|
27
|
+
width?: number;
|
|
28
|
+
height?: number;
|
|
29
|
+
showGrid?: boolean;
|
|
30
|
+
showAxes?: boolean;
|
|
31
|
+
transparent?: boolean;
|
|
32
|
+
autoCrop?: boolean;
|
|
33
|
+
fitToModel?: boolean;
|
|
34
|
+
margin?: number;
|
|
35
|
+
};
|
|
36
|
+
export declare function screenshot(input: ScreenshotInput): Promise<ToolResult<ImageResult>>;
|
|
37
|
+
export type ScreenshotMultiInput = WorkspaceArg & {
|
|
38
|
+
width?: number;
|
|
39
|
+
height?: number;
|
|
40
|
+
showGrid?: boolean;
|
|
41
|
+
showAxes?: boolean;
|
|
42
|
+
transparent?: boolean;
|
|
43
|
+
margin?: number;
|
|
44
|
+
};
|
|
45
|
+
export declare function screenshotMulti(input: ScreenshotMultiInput): Promise<ToolResult<ImageResult>>;
|
|
46
|
+
export type ScreenshotShapeInput = WorkspaceArg & {
|
|
47
|
+
shapeId: string;
|
|
48
|
+
margin?: number;
|
|
49
|
+
width?: number;
|
|
50
|
+
height?: number;
|
|
51
|
+
showGrid?: boolean;
|
|
52
|
+
showAxes?: boolean;
|
|
53
|
+
transparent?: boolean;
|
|
54
|
+
};
|
|
55
|
+
export declare function screenshotShape(input: ScreenshotShapeInput): Promise<ToolResult<ImageResult>>;
|
|
56
|
+
export type CameraState = {
|
|
57
|
+
position: [number, number, number];
|
|
58
|
+
target: [number, number, number];
|
|
59
|
+
up: [number, number, number];
|
|
60
|
+
projection: 'orthographic' | 'perspective';
|
|
61
|
+
};
|
|
62
|
+
export declare function getCameraState(input: WorkspaceArg): Promise<ToolResult<CameraState>>;
|
|
63
|
+
export {};
|