forgecad 0.1.3 → 0.1.5
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 +11 -0
- package/dist/assets/{evalWorker-1m873KWd.js → evalWorker-CbAa_9qg.js} +108 -108
- package/dist/assets/{index-Dvz3nSDc.js → index-DFa4fntx.js} +335 -335
- package/dist/assets/{manifold-C38sUiKu.js → manifold-BGMOVi-H.js} +1 -1
- package/dist/assets/{manifold-rOWQW9fU.js → manifold-BNJTX3qf.js} +1 -1
- package/dist/assets/{manifold-Dk2u-lhj.js → manifold-CL39pgcA.js} +1 -1
- package/dist/assets/{reportWorker-Cj587shw.js → reportWorker-C5Ot2xSE.js} +122 -122
- package/dist/index.html +1 -1
- package/dist-cli/forgecad.js +117 -22
- package/dist-skill/CONTEXT.md +4799 -0
- package/dist-skill/docs/API/model-building/assembly.md +41 -0
- package/dist-skill/docs/API/model-building/reference.md +61 -7
- package/dist-skill/docs/VISION.md +2 -1
- package/examples/api/import-assembly-source.forge.js +22 -0
- package/examples/api/import-assembly.forge.js +26 -0
- package/package.json +1 -1
package/dist/index.html
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
9
9
|
html, body, #root { width: 100%; height: 100%; overflow: hidden; background: var(--fc-bg); color: var(--fc-text); font-family: system-ui, -apple-system, sans-serif; }
|
|
10
10
|
</style>
|
|
11
|
-
<script type="module" crossorigin src="/assets/index-
|
|
11
|
+
<script type="module" crossorigin src="/assets/index-DFa4fntx.js"></script>
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
14
|
<div id="root"></div>
|
package/dist-cli/forgecad.js
CHANGED
|
@@ -14746,6 +14746,42 @@ var Assembly = class {
|
|
|
14746
14746
|
function assembly(name) {
|
|
14747
14747
|
return new Assembly(name);
|
|
14748
14748
|
}
|
|
14749
|
+
var ImportedAssembly = class {
|
|
14750
|
+
constructor(_assembly) {
|
|
14751
|
+
this._assembly = _assembly;
|
|
14752
|
+
}
|
|
14753
|
+
/** The underlying Assembly — use for sweepJoint, addPart into parent, etc. */
|
|
14754
|
+
get assembly() {
|
|
14755
|
+
return this._assembly;
|
|
14756
|
+
}
|
|
14757
|
+
/** Solve the assembly at the given joint state (defaults to each joint's default value). */
|
|
14758
|
+
solve(state) {
|
|
14759
|
+
return this._assembly.solve(state);
|
|
14760
|
+
}
|
|
14761
|
+
/**
|
|
14762
|
+
* Return a specific named part positioned at the given joint state.
|
|
14763
|
+
* Result type mirrors SolvedAssembly.getPart(): Shape, TrackedShape, or ShapeGroup.
|
|
14764
|
+
*/
|
|
14765
|
+
part(name, state) {
|
|
14766
|
+
return this._assembly.solve(state).getPart(name);
|
|
14767
|
+
}
|
|
14768
|
+
/**
|
|
14769
|
+
* Convert all assembly parts to a ShapeGroup with named children.
|
|
14770
|
+
* Child names match the part names used in the assembly.
|
|
14771
|
+
* Useful for embedding a solved sub-assembly in a parent group or assembly.
|
|
14772
|
+
*/
|
|
14773
|
+
toGroup(state) {
|
|
14774
|
+
const solved = this._assembly.solve(state);
|
|
14775
|
+
const def = this._assembly.describe();
|
|
14776
|
+
const children = [];
|
|
14777
|
+
const childNames = [];
|
|
14778
|
+
for (const p of def.parts) {
|
|
14779
|
+
children.push(solved.getPart(p.name));
|
|
14780
|
+
childNames.push(p.name);
|
|
14781
|
+
}
|
|
14782
|
+
return new ShapeGroup(children, childNames);
|
|
14783
|
+
}
|
|
14784
|
+
};
|
|
14749
14785
|
|
|
14750
14786
|
// src/forge/robotExport.ts
|
|
14751
14787
|
var _collectedRobotExport = null;
|
|
@@ -17869,6 +17905,8 @@ function describeScriptResultType(value) {
|
|
|
17869
17905
|
if (value instanceof Sketch) return "Sketch";
|
|
17870
17906
|
if (value instanceof TrackedShape) return "TrackedShape";
|
|
17871
17907
|
if (value instanceof ShapeGroup) return "ShapeGroup";
|
|
17908
|
+
if (value instanceof Assembly) return "Assembly";
|
|
17909
|
+
if (value instanceof ImportedAssembly) return "ImportedAssembly";
|
|
17872
17910
|
if (Array.isArray(value)) return "Array";
|
|
17873
17911
|
if (typeof value === "object" && typeof value.toShape === "function") {
|
|
17874
17912
|
try {
|
|
@@ -18288,6 +18326,26 @@ function executeFile(code, fileName, allFiles, visited, scope = {}, options, exe
|
|
|
18288
18326
|
logImportTrace(fileName, scope, options, "importGroup", resolvedPath, "error", { requested: name, got });
|
|
18289
18327
|
throw new Error(`"${resolvedPath}" did not return a ShapeGroup (got ${got}). Use group(...) as the return value, or use importPart() for single-shape files.`);
|
|
18290
18328
|
};
|
|
18329
|
+
const importAssembly = (name, paramOverrides) => {
|
|
18330
|
+
const { source: src, lookupKey, resolvedPath } = resolveImportSource(fileName, name, allFiles, options);
|
|
18331
|
+
const localOverrides = parseImportParamArgs("importAssembly", name, paramOverrides);
|
|
18332
|
+
const childScope = { namePrefix: makeChildScopePrefix(resolvedPath), localOverrides };
|
|
18333
|
+
logImportTrace(fileName, scope, options, "importAssembly", resolvedPath, "start", { requested: name, overrides: localOverrides });
|
|
18334
|
+
let result;
|
|
18335
|
+
try {
|
|
18336
|
+
result = executeFile(src, lookupKey, allFiles, visited, childScope, options);
|
|
18337
|
+
} catch (error) {
|
|
18338
|
+
logImportTrace(fileName, scope, options, "importAssembly", resolvedPath, "error", { requested: name, error: formatLogError(error) });
|
|
18339
|
+
throw error;
|
|
18340
|
+
}
|
|
18341
|
+
if (result instanceof Assembly) {
|
|
18342
|
+
logImportTrace(fileName, scope, options, "importAssembly", resolvedPath, "success", { requested: name, got: "Assembly" });
|
|
18343
|
+
return new ImportedAssembly(result);
|
|
18344
|
+
}
|
|
18345
|
+
const got = describeScriptResultType(result);
|
|
18346
|
+
logImportTrace(fileName, scope, options, "importAssembly", resolvedPath, "error", { requested: name, got });
|
|
18347
|
+
throw new Error(`"${resolvedPath}" did not return an Assembly (got ${got}). Return the assembly() instance directly (before calling .solve()).`);
|
|
18348
|
+
};
|
|
18291
18349
|
const unwrap2 = (s) => s instanceof TrackedShape ? s.toShape() : s;
|
|
18292
18350
|
const wrappedUnion = (...shapes) => union(...shapes.map(unwrap2));
|
|
18293
18351
|
const wrappedDifference = (...shapes) => difference(...shapes.map(unwrap2));
|
|
@@ -18375,6 +18433,7 @@ function executeFile(code, fileName, allFiles, visited, scope = {}, options, exe
|
|
|
18375
18433
|
importSketch,
|
|
18376
18434
|
importPart,
|
|
18377
18435
|
importGroup,
|
|
18436
|
+
importAssembly,
|
|
18378
18437
|
importSvgSketch,
|
|
18379
18438
|
dim,
|
|
18380
18439
|
dimLine,
|
|
@@ -29242,8 +29301,8 @@ var Loader = class {
|
|
|
29242
29301
|
*/
|
|
29243
29302
|
loadAsync(url, onProgress) {
|
|
29244
29303
|
const scope = this;
|
|
29245
|
-
return new Promise(function(
|
|
29246
|
-
scope.load(url,
|
|
29304
|
+
return new Promise(function(resolve23, reject) {
|
|
29305
|
+
scope.load(url, resolve23, onProgress, reject);
|
|
29247
29306
|
});
|
|
29248
29307
|
}
|
|
29249
29308
|
/**
|
|
@@ -40514,7 +40573,7 @@ async function waitForRenderHtml(port, timeoutMs) {
|
|
|
40514
40573
|
const deadline = Date.now() + timeoutMs;
|
|
40515
40574
|
while (Date.now() < deadline) {
|
|
40516
40575
|
if (await fetchRenderHtml(port)) return true;
|
|
40517
|
-
await new Promise((
|
|
40576
|
+
await new Promise((resolve23) => setTimeout(resolve23, 250));
|
|
40518
40577
|
}
|
|
40519
40578
|
return false;
|
|
40520
40579
|
}
|
|
@@ -40564,7 +40623,7 @@ ${detail}` : `Timed out waiting for Vite on port ${port}.`
|
|
|
40564
40623
|
async function stopDevServer(proc) {
|
|
40565
40624
|
if (!proc || proc.killed) return;
|
|
40566
40625
|
proc.kill("SIGTERM");
|
|
40567
|
-
await new Promise((
|
|
40626
|
+
await new Promise((resolve23) => setTimeout(resolve23, 150));
|
|
40568
40627
|
if (!proc.killed) {
|
|
40569
40628
|
proc.kill("SIGKILL");
|
|
40570
40629
|
}
|
|
@@ -41160,13 +41219,13 @@ function parseCli2(argv) {
|
|
|
41160
41219
|
};
|
|
41161
41220
|
}
|
|
41162
41221
|
function readStdin() {
|
|
41163
|
-
return new Promise((
|
|
41222
|
+
return new Promise((resolve23, reject) => {
|
|
41164
41223
|
let data = "";
|
|
41165
41224
|
input.setEncoding("utf8");
|
|
41166
41225
|
input.on("data", (chunk) => {
|
|
41167
41226
|
data += chunk;
|
|
41168
41227
|
});
|
|
41169
|
-
input.on("end", () =>
|
|
41228
|
+
input.on("end", () => resolve23(data));
|
|
41170
41229
|
input.on("error", reject);
|
|
41171
41230
|
});
|
|
41172
41231
|
}
|
|
@@ -41594,12 +41653,12 @@ function findProjectRoot2(sp) {
|
|
|
41594
41653
|
return root;
|
|
41595
41654
|
}
|
|
41596
41655
|
async function isPortOpen(port) {
|
|
41597
|
-
return new Promise((
|
|
41656
|
+
return new Promise((resolve23) => {
|
|
41598
41657
|
const server = createServer3();
|
|
41599
|
-
server.once("error", () =>
|
|
41658
|
+
server.once("error", () => resolve23(false));
|
|
41600
41659
|
server.once("listening", () => {
|
|
41601
41660
|
server.close();
|
|
41602
|
-
|
|
41661
|
+
resolve23(true);
|
|
41603
41662
|
});
|
|
41604
41663
|
server.listen(port, "127.0.0.1");
|
|
41605
41664
|
});
|
|
@@ -41614,12 +41673,12 @@ async function ensureDevServer2(port) {
|
|
|
41614
41673
|
stdio: "pipe",
|
|
41615
41674
|
detached: false
|
|
41616
41675
|
});
|
|
41617
|
-
await new Promise((
|
|
41676
|
+
await new Promise((resolve23, reject) => {
|
|
41618
41677
|
const timeout = setTimeout(() => reject(new Error("Vite startup timeout")), 15e3);
|
|
41619
41678
|
viteProcess.stdout.on("data", (data) => {
|
|
41620
41679
|
if (data.toString().includes("ready")) {
|
|
41621
41680
|
clearTimeout(timeout);
|
|
41622
|
-
|
|
41681
|
+
resolve23();
|
|
41623
41682
|
}
|
|
41624
41683
|
});
|
|
41625
41684
|
viteProcess.on("error", (e) => {
|
|
@@ -42777,14 +42836,14 @@ function sendJson(res, status, payload) {
|
|
|
42777
42836
|
res.end(JSON.stringify(payload));
|
|
42778
42837
|
}
|
|
42779
42838
|
function readJsonBody(req) {
|
|
42780
|
-
return new Promise((
|
|
42839
|
+
return new Promise((resolve23, reject) => {
|
|
42781
42840
|
let body = "";
|
|
42782
42841
|
req.on("data", (chunk) => {
|
|
42783
42842
|
body += chunk;
|
|
42784
42843
|
});
|
|
42785
42844
|
req.on("end", () => {
|
|
42786
42845
|
try {
|
|
42787
|
-
|
|
42846
|
+
resolve23(body ? JSON.parse(body) : {});
|
|
42788
42847
|
} catch (e) {
|
|
42789
42848
|
reject(e);
|
|
42790
42849
|
}
|
|
@@ -42897,10 +42956,10 @@ function serveStatic(distDir, req, res) {
|
|
|
42897
42956
|
return true;
|
|
42898
42957
|
}
|
|
42899
42958
|
function isPortAvailable(port, host) {
|
|
42900
|
-
return new Promise((
|
|
42959
|
+
return new Promise((resolve23) => {
|
|
42901
42960
|
const s = http.createServer();
|
|
42902
|
-
s.listen(port, host, () => s.close(() =>
|
|
42903
|
-
s.on("error", () =>
|
|
42961
|
+
s.listen(port, host, () => s.close(() => resolve23(true)));
|
|
42962
|
+
s.on("error", () => resolve23(false));
|
|
42904
42963
|
});
|
|
42905
42964
|
}
|
|
42906
42965
|
async function pickPort(preferred, host, strict) {
|
|
@@ -43034,11 +43093,11 @@ data: ${JSON.stringify(entries)}
|
|
|
43034
43093
|
res.end("Not found");
|
|
43035
43094
|
}
|
|
43036
43095
|
});
|
|
43037
|
-
await new Promise((
|
|
43096
|
+
await new Promise((resolve23) => server.listen(port, host, resolve23));
|
|
43038
43097
|
const displayHost = host === "0.0.0.0" ? "localhost" : host;
|
|
43039
43098
|
const url = `http://${displayHost}:${port}`;
|
|
43040
43099
|
if (open) openBrowser(url);
|
|
43041
|
-
const close4 = () => new Promise((
|
|
43100
|
+
const close4 = () => new Promise((resolve23) => {
|
|
43042
43101
|
watcher?.close();
|
|
43043
43102
|
sseClients.forEach((c) => {
|
|
43044
43103
|
try {
|
|
@@ -43047,7 +43106,7 @@ data: ${JSON.stringify(entries)}
|
|
|
43047
43106
|
}
|
|
43048
43107
|
});
|
|
43049
43108
|
sseClients.clear();
|
|
43050
|
-
server.close(() =>
|
|
43109
|
+
server.close(() => resolve23());
|
|
43051
43110
|
});
|
|
43052
43111
|
return { url, close: close4 };
|
|
43053
43112
|
}
|
|
@@ -43130,9 +43189,9 @@ function toViteArgs(options) {
|
|
|
43130
43189
|
return args;
|
|
43131
43190
|
}
|
|
43132
43191
|
function waitForExit(child) {
|
|
43133
|
-
return new Promise((
|
|
43192
|
+
return new Promise((resolve23, reject) => {
|
|
43134
43193
|
child.once("error", reject);
|
|
43135
|
-
child.once("exit", (code) =>
|
|
43194
|
+
child.once("exit", (code) => resolve23(code ?? 0));
|
|
43136
43195
|
});
|
|
43137
43196
|
}
|
|
43138
43197
|
async function runStudioCli(argv = process.argv.slice(2)) {
|
|
@@ -43860,7 +43919,7 @@ Dimension list${showAll ? "" : " (first 20)"}:`);
|
|
|
43860
43919
|
// cli/forge-skill.ts
|
|
43861
43920
|
import { cpSync, existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "fs";
|
|
43862
43921
|
import { homedir as homedir2 } from "os";
|
|
43863
|
-
import { join as join7 } from "path";
|
|
43922
|
+
import { join as join7, resolve as resolve22 } from "path";
|
|
43864
43923
|
async function runSkillInstallCli(_argv = []) {
|
|
43865
43924
|
const srcSkill = resolvePackagePath(import.meta.url, "dist-skill", "SKILL.md");
|
|
43866
43925
|
const srcDocs = resolvePackagePath(import.meta.url, "dist-skill", "docs");
|
|
@@ -43881,6 +43940,26 @@ If you are running from a source checkout, run: npm run build:skill:forgecad`
|
|
|
43881
43940
|
console.log(`ForgeCAD skill installed to ${dest}`);
|
|
43882
43941
|
console.log(`Reload your agent (Claude Code, Codex, OpenCode, \u2026) to activate.`);
|
|
43883
43942
|
}
|
|
43943
|
+
async function runSkillOneFileCli(argv = []) {
|
|
43944
|
+
const outputArg = argv.find((a) => !a.startsWith("-"));
|
|
43945
|
+
if (!outputArg) {
|
|
43946
|
+
throw new Error(
|
|
43947
|
+
`Usage: forgecad skill one-file <output-path>
|
|
43948
|
+
Example: forgecad skill one-file ~/Desktop/forgecad-context.md`
|
|
43949
|
+
);
|
|
43950
|
+
}
|
|
43951
|
+
const src = resolvePackagePath(import.meta.url, "dist-skill", "CONTEXT.md");
|
|
43952
|
+
if (!existsSync6(src)) {
|
|
43953
|
+
throw new Error(
|
|
43954
|
+
`Built context file not found at ${src}.
|
|
43955
|
+
If you are running from a source checkout, run: npm run build:skill:forgecad`
|
|
43956
|
+
);
|
|
43957
|
+
}
|
|
43958
|
+
const dest = resolve22(outputArg);
|
|
43959
|
+
writeFileSync8(dest, readFileSync15(src));
|
|
43960
|
+
console.log(`ForgeCAD context written to ${dest}`);
|
|
43961
|
+
console.log(`Paste the contents into any AI chat UI (Claude.ai, ChatGPT, Gemini, \u2026) to get full ForgeCAD API knowledge.`);
|
|
43962
|
+
}
|
|
43884
43963
|
|
|
43885
43964
|
// cli/forgecad.ts
|
|
43886
43965
|
var SHELL_VALUES = [
|
|
@@ -44040,6 +44119,22 @@ var commands = [
|
|
|
44040
44119
|
examples: ["forgecad skill install"],
|
|
44041
44120
|
run: runSkillInstallCli
|
|
44042
44121
|
},
|
|
44122
|
+
{
|
|
44123
|
+
group: "Shell",
|
|
44124
|
+
path: ["skill", "one-file"],
|
|
44125
|
+
summary: "Write a single self-contained context file with all ForgeCAD docs for pasting into a chat UI (Claude.ai, ChatGPT, \u2026).",
|
|
44126
|
+
usage: ["forgecad skill one-file <output-path>"],
|
|
44127
|
+
examples: [
|
|
44128
|
+
"forgecad skill one-file ~/Desktop/forgecad-context.md",
|
|
44129
|
+
"forgecad skill one-file ./forgecad-context.md"
|
|
44130
|
+
],
|
|
44131
|
+
completion: {
|
|
44132
|
+
positionals: [
|
|
44133
|
+
{ description: "output path for the context file", valueKind: "path" }
|
|
44134
|
+
]
|
|
44135
|
+
},
|
|
44136
|
+
run: runSkillOneFileCli
|
|
44137
|
+
},
|
|
44043
44138
|
{
|
|
44044
44139
|
group: "Shell",
|
|
44045
44140
|
path: ["__complete"],
|