bambu-printer-mcp 1.1.27 → 1.1.29
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/CONTRIBUTORS.md +7 -1
- package/README.md +29 -10
- package/dist/ams-mapping.d.ts +18 -2
- package/dist/ams-mapping.js +36 -5
- package/dist/bambu-native.d.ts +55 -0
- package/dist/bambu-native.js +212 -13
- package/dist/index.js +154 -71
- package/dist/printers/bambu.d.ts +29 -2
- package/dist/printers/bambu.js +59 -28
- package/dist/safety/hidden-hms.d.ts +32 -0
- package/dist/safety/hidden-hms.js +405 -0
- package/dist/safety/limits.d.ts +6 -0
- package/dist/safety/limits.js +9 -0
- package/dist/safety/print-file.d.ts +2 -0
- package/dist/safety/print-file.js +83 -7
- package/dist/safety/printer-state.d.ts +11 -0
- package/dist/safety/printer-state.js +115 -22
- package/dist/slicer/profile-flatten.js +25 -0
- package/dist/slicer/remote-slicer.d.ts +12 -0
- package/dist/slicer/remote-slicer.js +240 -0
- package/dist/stl/stl-manipulator.d.ts +2 -1
- package/dist/stl/stl-manipulator.js +71 -42
- package/native/bambu-native-print.cpp +100 -26
- package/package.json +7 -5
- package/scripts/build-bambu-native.sh +53 -0
- package/scripts/setup-bambu-native.mjs +372 -0
- package/src/ams-mapping.ts +38 -5
- package/src/bambu-native.ts +229 -14
- package/src/index.ts +156 -67
- package/src/printers/bambu.ts +65 -25
- package/src/safety/hidden-hms.ts +406 -0
- package/src/safety/limits.ts +9 -0
- package/src/safety/print-file.ts +71 -7
- package/src/safety/printer-state.ts +117 -22
- package/src/slicer/profile-flatten.ts +32 -0
- package/src/slicer/remote-slicer.ts +216 -0
- package/src/stl/stl-manipulator.ts +70 -43
- package/scripts/build-bambu-native.zsh +0 -33
|
@@ -11,6 +11,7 @@ import * as crypto from 'crypto';
|
|
|
11
11
|
import { execFile } from 'child_process';
|
|
12
12
|
import { flattenForCli, detectProfilesRoot, resolveBblMachineProfile } from '../slicer/profile-flatten.js';
|
|
13
13
|
import { profileJsonFiles } from '../slicer/profile-files.js';
|
|
14
|
+
import { sliceWithOrcaApi, validateRemoteSliceOptions } from '../slicer/remote-slicer.js';
|
|
14
15
|
|
|
15
16
|
const readFileAsync = promisify(fs.readFile);
|
|
16
17
|
const writeFileAsync = promisify(fs.writeFile);
|
|
@@ -57,6 +58,7 @@ export const SLICER_TYPES = [
|
|
|
57
58
|
'bambustudio',
|
|
58
59
|
'orcaslicer',
|
|
59
60
|
'orcaslicer-bambulab',
|
|
61
|
+
'orca-slicer-api',
|
|
60
62
|
'prusaslicer',
|
|
61
63
|
'cura',
|
|
62
64
|
'slic3r',
|
|
@@ -81,6 +83,8 @@ const SLICER_TYPE_ALIASES: Record<string, SlicerType> = {
|
|
|
81
83
|
orcastudio: 'orcaslicer-bambulab',
|
|
82
84
|
'orcaslicer-bmcu': 'orcaslicer-bambulab',
|
|
83
85
|
'orca-bmcu': 'orcaslicer-bambulab',
|
|
86
|
+
'orca-slicer-api': 'orca-slicer-api',
|
|
87
|
+
'orcaslicer-api': 'orca-slicer-api',
|
|
84
88
|
prusaslicer: 'prusaslicer',
|
|
85
89
|
'prusa-slicer': 'prusaslicer',
|
|
86
90
|
cura: 'cura',
|
|
@@ -105,7 +109,8 @@ export function isBambuCompatibleSlicer(slicerType: SlicerType): boolean {
|
|
|
105
109
|
return (
|
|
106
110
|
slicerType === 'bambustudio' ||
|
|
107
111
|
slicerType === 'orcaslicer' ||
|
|
108
|
-
slicerType === 'orcaslicer-bambulab'
|
|
112
|
+
slicerType === 'orcaslicer-bambulab' ||
|
|
113
|
+
slicerType === 'orca-slicer-api'
|
|
109
114
|
);
|
|
110
115
|
}
|
|
111
116
|
|
|
@@ -166,6 +171,7 @@ export interface BambuSliceOptions {
|
|
|
166
171
|
filamentColours?: string[]; // positional #RRGGBB per loaded filament slot
|
|
167
172
|
bedType?: string; // Bambu bed type, e.g. textured_plate or cool_plate
|
|
168
173
|
nozzleType?: string; // installed hotend material written into the machine preset
|
|
174
|
+
nozzleVolumeType?: 'Standard' | 'High Flow'; // installed nozzle flow, the machine preset's nozzle_volume_type
|
|
169
175
|
enableTimelapse?: boolean; // --enable-timelapse: timelapse-aware slicing
|
|
170
176
|
allowMixTemp?: boolean; // --allow-mix-temp: allow mixed-temp filaments
|
|
171
177
|
scale?: number; // --scale factor: uniform scale
|
|
@@ -563,6 +569,7 @@ export class STLManipulator extends EventEmitter {
|
|
|
563
569
|
userProfileRoots: configuredBambuProfileDirs(),
|
|
564
570
|
tempDir: this.tempDir,
|
|
565
571
|
bedType: this.resolveBambuStudioBedType(bambuOptions?.bedType),
|
|
572
|
+
nozzleVolumeType: bambuOptions?.nozzleVolumeType,
|
|
566
573
|
filamentColours: bambuOptions?.filamentColours ?? bundle.filamentColours,
|
|
567
574
|
projectTowerPosition: bundle.projectTowerPosition,
|
|
568
575
|
sourceProfiles: {
|
|
@@ -1589,7 +1596,7 @@ export class STLManipulator extends EventEmitter {
|
|
|
1589
1596
|
const operationId = this.generateOperationId();
|
|
1590
1597
|
this.activeOperations.set(operationId, true);
|
|
1591
1598
|
|
|
1592
|
-
if (isPathLikeExecutable(slicerPath) && !fs.existsSync(slicerPath)) {
|
|
1599
|
+
if (slicerType !== 'orca-slicer-api' && isPathLikeExecutable(slicerPath) && !fs.existsSync(slicerPath)) {
|
|
1593
1600
|
throw new Error(`Slicer executable not found at: ${slicerPath}`);
|
|
1594
1601
|
}
|
|
1595
1602
|
if (slicerProfile && !fs.existsSync(slicerProfile)) {
|
|
@@ -1636,6 +1643,7 @@ export class STLManipulator extends EventEmitter {
|
|
|
1636
1643
|
case 'bambustudio':
|
|
1637
1644
|
case 'orcaslicer':
|
|
1638
1645
|
case 'orcaslicer-bambulab':
|
|
1646
|
+
case 'orca-slicer-api':
|
|
1639
1647
|
// Bambu-compatible CLI: slice and export as 3MF with embedded gcode.
|
|
1640
1648
|
// FULU's OrcaSlicer-bambulab fork keeps this Bambu-style path.
|
|
1641
1649
|
// For 3MF input: slice in place and export sliced 3MF
|
|
@@ -1643,12 +1651,19 @@ export class STLManipulator extends EventEmitter {
|
|
|
1643
1651
|
{
|
|
1644
1652
|
const is3mf = stlFilePath.toLowerCase().endsWith('.3mf');
|
|
1645
1653
|
const outputBase = path.basename(stlFilePath, is3mf ? '.3mf' : '.stl');
|
|
1646
|
-
const
|
|
1654
|
+
const remote = slicerType === 'orca-slicer-api';
|
|
1655
|
+
if (remote) {
|
|
1656
|
+
validateRemoteSliceOptions(bambuOptions);
|
|
1657
|
+
if (!process.env.BAMBU_PROFILES_ROOT) throw new Error('Remote slicing requires BAMBU_PROFILES_ROOT pointing to the matching Orca profile tree (a read-only mount is sufficient).');
|
|
1658
|
+
if (slicerProfile && !fs.existsSync(slicerProfile)) throw new Error('Remote slicing process profile does not exist.');
|
|
1659
|
+
}
|
|
1660
|
+
const profileSlicerType = remote ? 'orcaslicer' : slicerType;
|
|
1661
|
+
const bambuOutputPath = path.join(this.tempDir, outputBase + (remote ? `_${operationId}` : '') + '_sliced.3mf');
|
|
1647
1662
|
const outputDir = path.dirname(bambuOutputPath);
|
|
1648
|
-
const profilesRoot = detectProfilesRoot(slicerPath,
|
|
1663
|
+
const profilesRoot = detectProfilesRoot(remote ? undefined : slicerPath, profileSlicerType);
|
|
1649
1664
|
const rawBundle = await this.resolveBambuLikeSettingsBundle(
|
|
1650
1665
|
outputBase,
|
|
1651
|
-
|
|
1666
|
+
profileSlicerType,
|
|
1652
1667
|
slicerProfile,
|
|
1653
1668
|
printerPreset,
|
|
1654
1669
|
bambuOptions,
|
|
@@ -1674,7 +1689,7 @@ export class STLManipulator extends EventEmitter {
|
|
|
1674
1689
|
// absolute-extrusion normalization after resolving those ancestors.
|
|
1675
1690
|
// The machine owns the extrusion mode and layer G-code once process
|
|
1676
1691
|
// files lose machine keys, so normalize it there as well.
|
|
1677
|
-
if (
|
|
1692
|
+
if (profileSlicerType === 'orcaslicer' && settingsBundle.settingsArg) {
|
|
1678
1693
|
const [machinePath, processPath] = settingsBundle.settingsArg.split(';');
|
|
1679
1694
|
settingsBundle.settingsArg = [
|
|
1680
1695
|
this.writeTempJson(outputBase, 'machine_orca_resolved',
|
|
@@ -1684,6 +1699,16 @@ export class STLManipulator extends EventEmitter {
|
|
|
1684
1699
|
].join(';');
|
|
1685
1700
|
}
|
|
1686
1701
|
const cliBundle = this.isolateMachineSettings(settingsBundle);
|
|
1702
|
+
if (remote) {
|
|
1703
|
+
const [machinePath, processPath] = cliBundle.settingsArg?.split(';') ?? [];
|
|
1704
|
+
if (!machinePath || !processPath) throw new Error('Remote slicing requires complete prepared machine and process profiles.');
|
|
1705
|
+
outputFilePath = await sliceWithOrcaApi({
|
|
1706
|
+
inputPath: stlFilePath, machinePath, processPath,
|
|
1707
|
+
filamentPaths: cliBundle.filamentPaths, outputPath: bambuOutputPath,
|
|
1708
|
+
options: bambuOptions, isCancelled: () => !this.activeOperations.get(operationId),
|
|
1709
|
+
});
|
|
1710
|
+
break;
|
|
1711
|
+
}
|
|
1687
1712
|
args = [
|
|
1688
1713
|
'--slice', String(bambuOptions?.slicePlate ?? 0),
|
|
1689
1714
|
'--outputdir', outputDir,
|
|
@@ -1727,47 +1752,49 @@ export class STLManipulator extends EventEmitter {
|
|
|
1727
1752
|
throw new Error(`Unsupported slicer type: ${slicerType}`);
|
|
1728
1753
|
}
|
|
1729
1754
|
|
|
1730
|
-
if (
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1755
|
+
if (slicerType !== 'orca-slicer-api') {
|
|
1756
|
+
if (progressCallback) progressCallback(20, `Executing slicer: ${slicerPath} ${args.join(' ')}`);
|
|
1757
|
+
console.error(`Executing: ${slicerPath} ${args.join(' ')}`);
|
|
1758
|
+
|
|
1759
|
+
// Execute the slicer
|
|
1760
|
+
await new Promise<void>((resolve, reject) => {
|
|
1761
|
+
const process = execFile(slicerPath, args, (error, stdout, stderr) => {
|
|
1762
|
+
if (error) {
|
|
1763
|
+
console.error(`Slicer Error: ${error.message}`);
|
|
1764
|
+
console.error(`Slicer Stderr: ${stderr}`);
|
|
1765
|
+
reject(new Error(`Slicer failed: ${error.message}. Stderr: ${stderr}`));
|
|
1766
|
+
} else {
|
|
1767
|
+
console.error(`Slicer Stdout: ${stdout}`);
|
|
1768
|
+
if (stderr) {
|
|
1769
|
+
console.warn(`Slicer Stderr: ${stderr}`); // Log stderr even on success
|
|
1770
|
+
}
|
|
1771
|
+
resolve();
|
|
1772
|
+
}
|
|
1773
|
+
});
|
|
1748
1774
|
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1775
|
+
// Optional: Add listeners for stdout/stderr for real-time progress if slicer provides it
|
|
1776
|
+
// process.stdout?.on('data', (data) => { console.error(`Slicer stdout: ${data}`); });
|
|
1777
|
+
// process.stderr?.on('data', (data) => { console.error(`Slicer stderr: ${data}`); });
|
|
1752
1778
|
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1779
|
+
// Check for cancellation periodically
|
|
1780
|
+
const checkCancel = setInterval(() => {
|
|
1781
|
+
if (!this.activeOperations.get(operationId)) {
|
|
1782
|
+
clearInterval(checkCancel);
|
|
1783
|
+
try {
|
|
1784
|
+
process.kill(); // Attempt to kill the slicer process
|
|
1785
|
+
reject(new Error("Slicing operation cancelled"));
|
|
1786
|
+
} catch (killError) {
|
|
1787
|
+
console.error("Error attempting to kill slicer process:", killError);
|
|
1788
|
+
reject(new Error("Slicing operation cancelled, but failed to kill process."));
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
}, 500);
|
|
1766
1792
|
|
|
1767
|
-
|
|
1768
|
-
|
|
1793
|
+
process.on('exit', () => clearInterval(checkCancel));
|
|
1794
|
+
process.on('error', () => clearInterval(checkCancel)); // Ensure interval cleared on process error too
|
|
1769
1795
|
|
|
1770
|
-
|
|
1796
|
+
});
|
|
1797
|
+
}
|
|
1771
1798
|
|
|
1772
1799
|
if (!this.activeOperations.get(operationId)) {
|
|
1773
1800
|
// This check might be redundant if the promise rejected on kill, but good safety
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
#!/bin/zsh
|
|
2
|
-
|
|
3
|
-
# Build the optional macOS adapter that calls Bambu Studio's installed
|
|
4
|
-
# networking plug-in at runtime. The plug-in itself is not bundled here.
|
|
5
|
-
set -euo pipefail
|
|
6
|
-
|
|
7
|
-
if [[ "$(uname -s)" != "Darwin" ]]; then
|
|
8
|
-
print -u2 "The Bambu native helper currently supports macOS only."
|
|
9
|
-
exit 1
|
|
10
|
-
fi
|
|
11
|
-
|
|
12
|
-
SCRIPT_DIR="${0:A:h}"
|
|
13
|
-
PROJECT_ROOT="${SCRIPT_DIR:h}"
|
|
14
|
-
CXX_BIN="${CXX:-clang++}"
|
|
15
|
-
OUTPUT="${PROJECT_ROOT}/native/bambu-native-print"
|
|
16
|
-
SOURCE="${PROJECT_ROOT}/native/bambu-native-print.cpp"
|
|
17
|
-
|
|
18
|
-
if ! command -v "$CXX_BIN" >/dev/null 2>&1; then
|
|
19
|
-
print -u2 "C++ compiler not found: $CXX_BIN"
|
|
20
|
-
exit 1
|
|
21
|
-
fi
|
|
22
|
-
|
|
23
|
-
"$CXX_BIN" \
|
|
24
|
-
-std=c++17 \
|
|
25
|
-
-O2 \
|
|
26
|
-
-Wall \
|
|
27
|
-
-Wextra \
|
|
28
|
-
-o "$OUTPUT" \
|
|
29
|
-
"$SOURCE" \
|
|
30
|
-
-ldl
|
|
31
|
-
|
|
32
|
-
chmod 755 "$OUTPUT"
|
|
33
|
-
print "Built $OUTPUT"
|