@cutoptim/engine 1.5.0 → 1.8.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.
@@ -190,6 +190,10 @@ export interface NestStock {
190
190
  exclusions?: Array<NestZone>;
191
191
  /** Echoed on every sheet cut from this stock row. */
192
192
  meta?: Record<string, unknown>;
193
+ /** Marker mode: this row is a ROLL of width `w` and free length (fabric, leather, film, any roll good). Give `w` only — no `h`, `polygon` or `exclusions` — and make it the only stock row. The answer is ONE sheet `w` wide whose `h` is the shortest length found (also `metrics.length`), edge gap included at both ends. Both engines: `lbf` answers synchronously; `max` (async) starts from that marker and spends `options.timeBudgetMs` on a strip search that may shorten it, never lengthen it. */
194
+ roll?: boolean;
195
+ /** With `roll` only: the longest the marker may be (at most 200000). Parts that do not fit within it are returned in `unplaced` — a roll never becomes a second sheet. Omit it and the length is unbounded up to 200000. */
196
+ maxLength?: number;
193
197
  }
194
198
  /** Solve options. All optional. */
195
199
  export interface NestOptions {
@@ -288,6 +292,8 @@ export interface NestMetrics {
288
292
  cutLength: number;
289
293
  /** Σ `sheets[].pierces`. */
290
294
  pierces: number;
295
+ /** Present only for a `roll` (marker mode): the marker length — the `h` of the one sheet, from the roll start to the far edge gap, rounded up to 0.001, in your unit. 0 when no part fits the roll width. */
296
+ length?: number;
291
297
  }
292
298
  /** Sheets used per request stock ROW ("quantity per sheet size"). The unit is the row, not the size: two rows with the same w × h but a different price or meta are two entries. */
293
299
  export interface NestStockUsage {
@@ -313,6 +319,17 @@ export interface UnplacedNest {
313
319
  name: string;
314
320
  /** How many copies could not be placed. */
315
321
  qty: number;
322
+ /** Only in `unplaced`, and only when the engine can tell. `too_large`: the part alone fits no rectangular sheet of its material — its bounding box plus the edge gap (`edgeClearance`, else `minSeparation`) on both sides is bigger than the sheet at every allowed rotation; `minSheet` says what would fit. `no_room`: it fits a sheet on its own, but no sheet had room left (limited stock with `respectStock`, spacing, the other parts). Absent when the job has a polygon sheet the part does not obviously fit. */
323
+ reason?: "too_large" | "no_room";
324
+ /** With `reason: "too_large"` only: the smallest rectangular sheet that holds this part alone, edge gap included on both sides, at the allowed rotation with the smallest bounding box. Rounded up to 0.001. */
325
+ minSheet?: {
326
+ /** Minimum sheet width. */
327
+ w: number;
328
+ /** Minimum sheet height (length). */
329
+ h: number;
330
+ /** The rotation, in degrees, these dimensions are for. */
331
+ rotation: number;
332
+ };
316
333
  }
317
334
  /** One material's totals across the sheets cut from it. */
318
335
  export interface NestMaterialSummary {
@@ -502,10 +519,15 @@ export interface LabelOptions {
502
519
  stages?: Array<string>;
503
520
  /** Your own word for a built-in stage key, at most 6 characters; empty or absent = the English abbreviation (RC, C2S, EB, S, D). */
504
521
  stageWords?: {
522
+ /** Your word for `rc` (rough cut); default RC. */
505
523
  rc?: string;
524
+ /** Your word for `c2s` (cut to size); default C2S. */
506
525
  c2s?: string;
526
+ /** Your word for `eb` (edge banded); default EB. */
507
527
  eb?: string;
528
+ /** Your word for `s` (sanded); default S. */
508
529
  s?: string;
530
+ /** Your word for `d` (drilled); default D. */
509
531
  d?: string;
510
532
  };
511
533
  /** Mark FE on the edges of a piece that lie on a sheet edge with no `trim` on that side (the board's factory edge). */
@@ -517,12 +539,17 @@ export interface LabelOptions {
517
539
  }
518
540
  /** Printer offset in mm: moves everything printed on the label right (`x`) and down (`y`); negative values move it back. Applied rounded to 0.1 mm. */
519
541
  export interface LabelOffset {
542
+ /** Shift right in mm (negative = left). */
520
543
  x?: number;
544
+ /** Shift down in mm (negative = up). */
521
545
  y?: number;
522
546
  }
523
547
  export interface Optimize2DRequest {
548
+ /** The rectangular parts to cut, one row per part type (`w`, `h`, optional `qty`, `name`, grain, edge banding). */
524
549
  parts: Array<Part2D>;
550
+ /** The sheet sizes to cut from, one row per size (`w`, `h`, optional `qty`, `price`). */
525
551
  stock: Array<Stock2D>;
552
+ /** Kerf, trim, first-cut direction, cost and stock rules, effort and label output; every field is optional. */
526
553
  options?: Options2D;
527
554
  /** Which optimizer to run. `heuristic` is the guillotine multi-strategy packer: highest yield, every layout edge-to-edge saw-cuttable, always a full `cutPlan`. `balanced` is a MaxRects free-nesting packer: much faster on large jobs for a small yield cost, but its layouts are often not guillotine (`guillotineValid: false`, `cutPlan: null`), and it does not model `tolerance`, `minimizeCost`, `grainGroup`, `maxCutStages` or `minimizeRotations` — set one of those and a string in `warnings` tells you it was ignored. `max` is the ASYNCHRONOUS tree-search tier (2D only): it reaches the proven optimum on far more jobs at the cost of seconds-to-a-minute per solve, so instead of a plan it returns **202** with a `jobId` — poll `GET /v1/jobs/{id}` for the result. Still deterministic and guillotine-valid. Where the tier is not enabled on a deployment, `engine: "max"` fails closed with **503**. **What `max` models.** It packs ONE stock format at full sheet size with unlimited supply and a fixed 3-stage guillotine pattern. Anything that would make the returned plan physically WRONG is therefore REFUSED with **400** at submission — before a call is reserved and before you wait for the solve: a second `stock` row, `options.trim`, `options.respectStock`, any `material`, any `grainGroup`, a non-empty `matchedSets` (an empty one is fine). Options that only make the plan less tuned are accepted and listed in `warnings`: `tolerance`, `minimizeCost`, `maxCutStages` (fixed at 3), `minimizeRotations`, `firstCut`, `effort`. A `max` result reports no `offcuts`. Send those jobs to `heuristic`. The default never changes silently. */
528
555
  engine?: "heuristic" | "balanced" | "max";
@@ -614,7 +641,9 @@ export interface Options1D {
614
641
  mitrePairing?: boolean;
615
642
  }
616
643
  export interface Optimize1DRequest {
644
+ /** The lengths to cut, one row per part type (`length`, optional `qty`, `name`, mitred `ends`). */
617
645
  parts: Array<Part1D>;
646
+ /** The bar lengths to cut from, one row per length (`length`, optional `qty`, `price`). */
618
647
  stock: Array<Stock1D>;
619
648
  options?: Options1D;
620
649
  /** `max` is not offered here: it is a 2D (and, separately, nesting) tier, and `engine: "max"` on this path is a **400** before a call is charged. In 1D `balanced` resolves to the same packer as `heuristic` — the linear packer is already a best-of-multiple-strategies search, so there is no separate balanced mode. The value is accepted and echoed back so a single client can send one engine id for both endpoints. */
@@ -682,6 +711,7 @@ export interface OptionsWood {
682
711
  mitrePairing?: boolean;
683
712
  }
684
713
  export interface OptimizeWoodRequest {
714
+ /** The timber parts to cut, one row per part type: cross-section `sw` × `sh`, `length`, optional `qty`. */
685
715
  parts: Array<PartWood>;
686
716
  /** At most 50 rows. Since every cross-section needs at least one stock row, this is also the practical ceiling on cross-sections in a single job; a wider catalogue should be split into several requests. */
687
717
  stock: Array<StockWood>;
@@ -1171,6 +1201,24 @@ export interface UsageResponse {
1171
1201
  env?: "test";
1172
1202
  /** Present (`"tenant"`) only for a key CutOptim issues to its own first-party service. Absent for every key you create in the dashboard. */
1173
1203
  keyClass?: "tenant";
1204
+ trial?: UsageTrial;
1205
+ }
1206
+ /** Present only for a TEST key of an account without an Engine API subscription: such a key runs inside a free trial. While it is present, `used`, `limit` and `remaining` count the whole trial (not a calendar month) and `periodEnd` is the trial's last day. After `endsAt` every call answers 403 `key_revoked` with a message that names the trial. Absent for live keys and for test keys of a subscribed account. */
1207
+ export interface UsageTrial {
1208
+ /** When the trial ends (UTC timestamp). */
1209
+ endsAt: string;
1210
+ /** Calls allowed in the whole trial, across all the account's test keys. */
1211
+ callsLimit: number;
1212
+ /** Calls counted since the trial started. Refused and refunded calls are not counted. */
1213
+ callsUsed: number;
1214
+ /** `callsLimit` − `callsUsed`, never negative. */
1215
+ callsRemaining: number;
1216
+ /** Asynchronous engine `max` jobs allowed in the trial. Failed jobs are not counted. */
1217
+ maxJobsLimit: number;
1218
+ /** Engine `max` jobs submitted since the trial started (queued, running or succeeded). */
1219
+ maxJobsUsed: number;
1220
+ /** `maxJobsLimit` − `maxJobsUsed`, never negative. At 0 a new `max` job answers 402 `quota_exceeded`; engine `lbf` keeps working. */
1221
+ maxJobsRemaining: number;
1174
1222
  }
1175
1223
  export interface HealthResponse {
1176
1224
  /** Always `"healthy"` when the process answers. */
package/dist/types.gen.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // GENERATED by scripts/gen-sdks.ts from the CutOptim Engine API OpenAPI document — DO NOT EDIT.
2
- // contract 1 · spec sha256 57abd7b68ca9e86fe7040dd2e979516274a2bdea5394258959f21bbefc28f624 · @cutoptim/engine 1.5.0
2
+ // contract 1 · spec sha256 3ee9cdfbd131610871eac13aacdd1739434688a0e4743ab71c9373d089ea232c · @cutoptim/engine 1.8.0
3
3
  export {};
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "1.5.0";
1
+ export declare const VERSION = "1.8.0";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // The package version — rewritten by scripts/gen-sdks.ts together with package.json (sent as the User-Agent).
2
- export const VERSION = '1.5.0';
2
+ export const VERSION = '1.8.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cutoptim/engine",
3
- "version": "1.5.0",
3
+ "version": "1.8.0",
4
4
  "description": "Official client for the CutOptim Engine API — cutting optimization (2D panels, 1D linear, timber, true-shape nesting) over HTTPS.",
5
5
  "license": "MIT",
6
6
  "author": "CutOptim <support@cutoptim.com>",