@pinepaper.studio/mcp-server 1.6.33 → 1.6.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.
Files changed (45) hide show
  1. package/README.md +62 -1
  2. package/dist/build-info.json +2 -2
  3. package/dist/index.js +3 -3
  4. package/dist/index.js.map +1 -1
  5. package/dist/ontology/upstream-vocabulary.d.ts +1 -1
  6. package/dist/ontology/upstream-vocabulary.js +1 -1
  7. package/dist/tools/batch-macros.d.ts +20 -1
  8. package/dist/tools/batch-macros.d.ts.map +1 -1
  9. package/dist/tools/batch-macros.js +146 -7
  10. package/dist/tools/batch-macros.js.map +1 -1
  11. package/dist/tools/compact-descriptions.js +1 -1
  12. package/dist/tools/compact-descriptions.js.map +1 -1
  13. package/dist/tools/definitions.d.ts.map +1 -1
  14. package/dist/tools/definitions.js +53 -39
  15. package/dist/tools/definitions.js.map +1 -1
  16. package/dist/tools/engine-lists.d.ts +3 -3
  17. package/dist/tools/engine-lists.js +3 -3
  18. package/dist/tools/engine-surface.js +3 -3
  19. package/dist/tools/engine-surface.js.map +1 -1
  20. package/dist/tools/handlers.d.ts.map +1 -1
  21. package/dist/tools/handlers.js +15 -8
  22. package/dist/tools/handlers.js.map +1 -1
  23. package/dist/tools/lane.d.ts +8 -1
  24. package/dist/tools/lane.d.ts.map +1 -1
  25. package/dist/tools/lane.js +54 -13
  26. package/dist/tools/lane.js.map +1 -1
  27. package/dist/tools/minimal-descriptions.js +1 -1
  28. package/dist/tools/minimal-descriptions.js.map +1 -1
  29. package/dist/tools/shape-params.d.ts +2 -2
  30. package/dist/tools/shape-params.js +2 -2
  31. package/dist/tools/stick-vocabulary.d.ts +1 -1
  32. package/dist/tools/stick-vocabulary.js +1 -1
  33. package/dist/tools/toolkits.d.ts +1 -1
  34. package/dist/tools/toolkits.d.ts.map +1 -1
  35. package/dist/tools/toolkits.js +7 -2
  36. package/dist/tools/toolkits.js.map +1 -1
  37. package/dist/types/code-generator.d.ts.map +1 -1
  38. package/dist/types/code-generator.js +30 -17
  39. package/dist/types/code-generator.js.map +1 -1
  40. package/dist/types/schemas.d.ts +9 -0
  41. package/dist/types/schemas.d.ts.map +1 -1
  42. package/dist/types/schemas.js +10 -5
  43. package/dist/types/schemas.js.map +1 -1
  44. package/manifest.json +1 -1
  45. package/package.json +1 -1
@@ -124,18 +124,29 @@ ${itemVarName}.${propertyName} = (function() {
124
124
  };
125
125
  })();`;
126
126
  }
127
- // Linear: a diagonal across a 100 px box at the requested position.
128
- const defaultOrigin = origin || [position.x - 50, position.y - 50];
129
- const defaultDestination = destination || [position.x + 50, position.y + 50];
127
+ // A LINEAR RAMP FITS THE ITEM, top to bottom, as the engine's own app.create does (FIREFLY31). This was a fixed
128
+ // 100 px diagonal at the requested position. Leaving the ends out is not enough here: this assigns straight to
129
+ // Paper, where a gradient with no ends is zero-length. An end the caller gave is kept as given.
130
+ const fx = position.x, fy = position.y;
131
+ const o = origin ? `[${origin[0]}, ${origin[1]}]`
132
+ : destination ? `[${destination[0]}, __gb ? __gb.y : ${fy - 50}]`
133
+ : `(__gb ? [__gb.x + __gb.width / 2, __gb.y] : [${fx}, ${fy - 50}])`;
134
+ const d = destination ? `[${destination[0]}, ${destination[1]}]`
135
+ : origin ? `[${origin[0]}, __gb ? __gb.y + __gb.height : ${fy + 50}]`
136
+ : `(__gb ? [__gb.x + __gb.width / 2, __gb.y + __gb.height] : [${fx}, ${fy + 50}])`;
130
137
  return `
131
- ${itemVarName}.${propertyName} = {
132
- gradient: {
133
- stops: [${stopsCode}],
134
- radial: false
135
- },
136
- origin: [${defaultOrigin[0]}, ${defaultOrigin[1]}],
137
- destination: [${defaultDestination[0]}, ${defaultDestination[1]}]
138
- };`;
138
+ ${itemVarName}.${propertyName} = (function() {
139
+ const __b = ${itemVarName} && ${itemVarName}.bounds;
140
+ const __gb = __b && isFinite(__b.x) && isFinite(__b.y) && __b.width > 0 && __b.height > 0 ? __b : null;
141
+ return {
142
+ gradient: {
143
+ stops: [${stopsCode}],
144
+ radial: false
145
+ },
146
+ origin: ${o},
147
+ destination: ${d}
148
+ };
149
+ })();`;
139
150
  }
140
151
  /**
141
152
  * Generate shadow code for an item
@@ -5586,7 +5597,9 @@ return { success: true, action: 'seek', time: ${op.time || 0} };
5586
5597
  }
5587
5598
  generateAgentExport(input) {
5588
5599
  const validated = AgentExportInputSchema.parse(input);
5589
- const { platform, format, quality, framing, duration, estimateOnly, scale, fps, pdf: pdfOpts, region, time: stillTime, maxBytes, loop: gifLoop, broadcast, broadcastHeadroom, bitrate, minBitrate, bitrateMode, audioCodec, transparent, alphaQuantizer, deterministic, motionBlur, ad: adOpts, frames, startTime } = validated;
5600
+ const { platform, format, quality, framing, duration, estimateOnly, scale, fps, pdf: pdfOpts, region, time: stillTime, maxBytes, loop: gifLoop, broadcast, broadcastHeadroom, bitrate, minBitrate, bitrateMode, audioCodec, transparent, alphaQuantizer, deterministic: askedDeterministic, motionBlur, ad: adOpts, frames, startTime } = validated;
5601
+ // Every video is deterministic unless the caller opts out (owner, 2026-11-07), so every receipt says whether its file repeats.
5602
+ const deterministic = askedDeterministic ?? (format === 'mp4' || format === 'webm');
5590
5603
  // Encoder options (FxTool 16719759); the schema keeps them to mp4 / webm.
5591
5604
  const videoEncodeOpts = {};
5592
5605
  // A RANGE of the timeline (FxTool #250): frames for t in [startTime, startTime + duration), each exactly the frame
@@ -6248,10 +6261,10 @@ String(videoDuration) +
6248
6261
  ".264 needs even dimensions, so\n // 1200x675 came out 1200x676 — and platform specs are exact-pixel. The\n // result's dimensions become what the file IS, and fidelity says why.\n const __vd = __vr && __vr.dimensions;\n if (result && result.success && __vd && Array.isArray(__vd.requested) && Array.isArray(__vd.output)\n && (__vd.requested[0] !== __vd.output[0] || __vd.requested[1] !== __vd.output[1])) {\n result.dimensions = { width: __vd.output[0], height: __vd.output[1] };\n result.fidelity = result.fidelity || { warnings: [] };\n result.fidelity.warnings = (result.fidelity.warnings || []).concat([{ code: 'dimensions_rounded',\n message: 'the file is ' + __vd.outpu" +
6249
6262
  "t[0] + 'x' + __vd.output[1] + ', not the requested ' + __vd.requested[0] + 'x' + __vd.requested[1] + ': H.264 needs even dimensions, so an odd side was rounded up by 1 px (the extra row / column is background). For an exact-pixel spec, use an even canvas size, or crop the extra line when re-encoding (ffmpeg -vf crop=' + __vd.requested[0] + ':' + __vd.requested[1] + ':0:0).' }]);\n if (result.fidelity.note) delete result.fidelity.note;\n }\n" +
6250
6263
  String(deterministic ? (" // DETERMINISTIC: the container timestamps are pinned either way; the PIXELS\n // are only identical run to run on the software encoder, because the\n // browser may pick a different hardware backend each time (FxTool\n // e34ae03d: 92/255 between backends, 2/255 run to run on hardware). The\n // engine requests software and reports what it got.\n // Where the studio says outright whether the file repeats (bitExact, FxTool\n // PR #31: it test-encodes and keeps whichever encoder does — often the\n // HARDWARE one on a Mac, since Chrome's software H.264 is not repeatable at\n // some sizes), that answer decides; the encoder name is only the fallback\n // for studios that do not r" +
6251
- "eport it.\n if (result && result.success) {\n const __hw = __vr && __vr.hardwareAcceleration;\n const __exact = __vr && typeof __vr.bitExact === 'boolean' ? __vr.bitExact : null;\n if (__exact === false) {\n result.fidelity = result.fidelity || { warnings: [] };\n result.fidelity.warnings = (result.fidelity.warnings || []).concat([{ code: 'determinism_not_pinned',\n ...(__vr && __vr.cause ? { cause: __vr.cause } : {}),\n message: 'deterministic was asked for, but no encoder on this machine repeats byte for byte at this size (the studio test-encoded and checked' + (__vr && __vr.cause === 'h264-threaded' ? ': the software H.264 encoder is multi-threaded and " +
6252
- "takes no fixed quantizer' : '') + '). What still holds: the frames fed to the encoder are identical (compare frameDigest, not sha256), and the container is identical apart from the encoded samples. Do not cache this file by hash; export WebM for a byte-identical file.' }]);\n if (result.fidelity.note) delete result.fidelity.note;\n } else if (__exact === null && __hw !== 'prefer-software') {\n result.fidelity = result.fidelity || { warnings: [] };\n result.fidelity.warnings = (result.fidelity.warnings || []).concat([{ code: 'determinism_not_pinned',\n message: __hw\n ? 'deterministic was asked for, but the encoder ran with hardwareAcceleration ' + JSON.str" +
6253
- "ingify(__hw) + ': the container is pinned, the pixels may still differ slightly between runs (hardware encoders vary). Do not cache this file by hash.'\n : 'deterministic pinned the container timestamps, but this studio does not report which encoder backend ran, so the pixels may differ slightly between runs if the browser switches between hardware and software encoding. Do not rely on byte-identical files from this studio.' }]);\n if (result.fidelity.note) delete result.fidelity.note;\n }\n }\n"
6254
-
6264
+ "eport it.\n if (result && result.success) {\n const __hw = __vr && __vr.hardwareAcceleration;\n const __exact = __vr && typeof __vr.bitExact === 'boolean' ? __vr.bitExact : null;\n if (__exact === false) {\n result.fidelity = result.fidelity || { warnings: [] };\n result.fidelity.warnings = (result.fidelity.warnings || []).concat([{ code: 'determinism_not_pinned',\n ...(__vr && __vr.determinism && __vr.determinism.cause ? { cause: __vr.determinism.cause } : {}),\n message: 'this file will not repeat byte for byte: no encoder on this machine repeats at this size (the studio test-encoded and checked' + (__vr && __vr.determinism && __vr.determinism.cause === " +
6265
+ "'h264-threaded' ? ': the software H.264 encoder varies run to run at this size on this many CPUs' : '') + '). What still holds: the frames fed to the encoder are identical (compare frameDigest, not sha256), and the container is identical apart from the encoded samples. Do not cache this file by hash. For a byte-identical file, export WebM, or export_png_sequence (pinepaper_interchange) and encode the frames with your own FFmpeg, which the server does not provide.' }]);\n if (result.fidelity.note) delete result.fidelity.note;\n } else if (__exact === null && __hw !== 'prefer-software') {\n result.fidelity = result.fidelity || { warnings: [] };\n result.fidelity.warnings = " +
6266
+ "(result.fidelity.warnings || []).concat([{ code: 'determinism_not_pinned',\n message: __hw\n ? 'this file may not repeat byte for byte: the encoder ran with hardwareAcceleration ' + JSON.stringify(__hw) + ': the container is pinned, the pixels may still differ slightly between runs (hardware encoders vary). Do not cache this file by hash.'\n : 'deterministic pinned the container timestamps, but this studio does not report which encoder backend ran, so the pixels may differ slightly between runs if the browser switches between hardware and software encoding. Do not rely on byte-identical files from this studio.' }]);\n if (result.fidelity.note) delete result.fi" +
6267
+ "delity.note;\n }\n }\n"
6255
6268
 
6256
6269
 
6257
6270
 
@@ -9495,7 +9508,7 @@ String(name ? `\n name: ${JSON.stringify(name)},` : '') +
9495
9508
  "\n bounds: { x: b.x, y: b.y, width: b.width, height: b.height }" +
9496
9509
  String(mask ? `,\n mask: ${jsLiteral(mask)}` : '') +
9497
9510
  String(hasShadow ? ',\n shadow: __shadow' : '') +
9498
- String(loop !== undefined ? ",\n playback: (raster && raster.data && raster.data.animatedImage && raster.data.animatedImage.loop !== undefined) ? { applied: true, plays: raster.data.animatedImage.loop } : { applied: false, warning: 'loop was not applied: this image does not animate in this studio. Animated GIF and WebP do.' }" : '') +
9511
+ String(loop !== undefined ? ",\n playback: (raster && raster.data && raster.data.animatedImage && raster.data.animatedImage.loop !== undefined) ? { applied: true, plays: raster.data.animatedImage.loop } : { applied: false, warning: 'loop was not applied: this image does not animate in this studio. Animated GIF, WebP and APNG do.' }" : '') +
9499
9512
  String(hasLook ? ',\n look: __look' : '') +
9500
9513
  ",\n // Stored smaller than its source (the studio's cap): said, with the\n // way to keep every pixel. The studio reports native size where it can.\n ...((entry && entry.nativeWidth && entry.width && entry.nativeWidth > entry.width)\n ? { stored: { width: entry.width, height: entry.height }, native: { width: entry.nativeWidth, height: entry.nativeHeight },\n note: 'the studio stored this image at ' + entry.width + 'x' + entry.height + ' (its source is ' + entry.nativeWidth + 'x' + entry.nativeHeight + '). Pass maxEdge: \"native\" to keep every pixel.' }\n : {})\n };\n } catch (e) {\n return { error: 'Failed to import image: ' + e.message };\n " +
9501
9514
  " }\n})();\n"