@hraness/slopcamera 3.2.7 → 3.2.8

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 (67) hide show
  1. package/NOTICE.md +1 -7
  2. package/PRIVACY.md +16 -7
  3. package/README.md +37 -12
  4. package/apps/desktop/README.md +14 -130
  5. package/apps/desktop/application/context.ts +0 -9
  6. package/apps/desktop/application/default-registry.ts +0 -10
  7. package/apps/desktop/application/operation.ts +1 -5
  8. package/apps/desktop/application/operations/index.ts +0 -1
  9. package/apps/desktop/cli/args.ts +14 -86
  10. package/apps/desktop/cli/command-host-resources.ts +2 -1
  11. package/apps/desktop/cli/commands.ts +28 -67
  12. package/apps/desktop/cli/help.ts +12 -18
  13. package/apps/desktop/cli/html-scene.ts +139 -28
  14. package/apps/desktop/cli/io.ts +2 -1
  15. package/apps/desktop/cli/main.ts +23 -47
  16. package/apps/desktop/cli/menubar.ts +244 -0
  17. package/apps/desktop/cli/music-analysis-service.ts +61 -0
  18. package/apps/desktop/cli/portable-surface.ts +12 -4
  19. package/apps/desktop/code/application-node-planner.ts +0 -47
  20. package/apps/desktop/code/host-source-layout.ts +46 -0
  21. package/apps/desktop/code/public.ts +0 -1
  22. package/apps/desktop/code/runtime-identity.ts +50 -8
  23. package/apps/desktop/code/semantic-builder.ts +0 -43
  24. package/apps/desktop/code/source-bundle.ts +23 -6
  25. package/apps/desktop/code/source-typecheck.ts +131 -43
  26. package/apps/desktop/code/worker-client.ts +14 -2
  27. package/apps/desktop/core/music-analysis.ts +124 -1
  28. package/apps/desktop/dist/cli/main.js +244 -250
  29. package/apps/desktop/html-overlay/audio-reactivity.ts +127 -0
  30. package/apps/desktop/html-overlay/index.ts +9 -0
  31. package/apps/desktop/html-overlay/runtime.ts +2 -0
  32. package/apps/desktop/html-overlay/scene.ts +29 -0
  33. package/dist/cli.js +83 -81
  34. package/dist/{index-rvghzt7b.js → index-7131pg1c.js} +43 -236
  35. package/dist/{index-mcy8z0br.js → index-fava6pge.js} +1 -1
  36. package/dist/{index-z7239b4h.js → index-h1k0fnjq.js} +1 -1
  37. package/dist/{index-p63wavx0.js → index-zfnddgay.js} +1 -1
  38. package/dist/index.js +4 -18
  39. package/dist/operations.js +2 -2
  40. package/dist/vectorize/worker.js +1 -1
  41. package/dist/workflow.js +3 -3
  42. package/docs/README.md +1 -1
  43. package/docs/studio.md +1 -1
  44. package/package.json +6 -21
  45. package/skills/slopcamera/SKILL.md +8 -0
  46. package/skills/slopcamera/references/diagrams.md +5 -14
  47. package/skills/slopcamera/references/install.md +1 -1
  48. package/skills/slopcamera/references/music-video.md +23 -3
  49. package/skills/slopcamera/references/reference-led-3d.md +1 -1
  50. package/skills/slopcamera/references/support.md +25 -0
  51. package/skills/slopcamera/references/web-media-excerpts.md +120 -0
  52. package/src/cli.ts +28 -98
  53. package/src/index.ts +0 -23
  54. package/src/support-completion.ts +16 -0
  55. package/src/support.ts +42 -0
  56. package/src/version.ts +1 -1
  57. package/apps/desktop/application/operations/recording/index.ts +0 -5
  58. package/apps/desktop/application/operations/recording/pause.ts +0 -34
  59. package/apps/desktop/application/operations/recording/resume.ts +0 -34
  60. package/apps/desktop/application/operations/recording/shared.ts +0 -199
  61. package/apps/desktop/application/operations/recording/start.ts +0 -169
  62. package/apps/desktop/application/operations/recording/stop.ts +0 -34
  63. package/apps/desktop/capture/protocol.ts +0 -689
  64. package/apps/desktop/cli/capture-bundle.ts +0 -1117
  65. package/apps/desktop/cli/recording-controller.ts +0 -1567
  66. package/apps/desktop/cli/recording-daemon.ts +0 -931
  67. package/src/desktop.ts +0 -253
@@ -16,7 +16,7 @@ import {
16
16
  SlopcameraWorkflowError,
17
17
  defineSlopcameraWorkflow,
18
18
  runSlopcameraWorkflow
19
- } from "./index-mcy8z0br.js";
19
+ } from "./index-fava6pge.js";
20
20
  import {
21
21
  DiagramValidationError,
22
22
  SlopcameraOperationError,
@@ -39,13 +39,12 @@ import {
39
39
  slopcameraOperationRegistry,
40
40
  stackLayoutDefaults,
41
41
  withSlopcameraOperationHostAdmission
42
- } from "./index-z7239b4h.js";
42
+ } from "./index-h1k0fnjq.js";
43
43
  import {
44
44
  VectorizeError,
45
- nonGatewayChildEnvironment,
46
45
  vectorizeHardLimits,
47
46
  vectorizeImage
48
- } from "./index-p63wavx0.js";
47
+ } from "./index-zfnddgay.js";
49
48
  import {
50
49
  SlopcameraCloudError,
51
50
  generateSlopcameraImage,
@@ -288,204 +287,19 @@ function artifactSummary(artifacts) {
288
287
  `);
289
288
  }
290
289
 
291
- // src/desktop.ts
292
- import { createHash } from "crypto";
293
- import { createReadStream, createWriteStream } from "fs";
294
- import { chmod, mkdir as mkdir2, readFile as readFile3, rename as rename2, rm as rm2 } from "fs/promises";
295
- import { homedir, platform as hostPlatform, arch as hostArch } from "os";
296
- import { dirname as dirname3, join as join2, resolve as resolve3 } from "path";
297
- import { Readable } from "stream";
298
- import { pipeline } from "stream/promises";
299
- var releaseApi = "https://api.github.com/repos/tldraw/tldraw-offline/releases/latest";
300
- var desktopDownloadPage = "https://offline.tldraw.com";
301
- function isRecord2(value) {
302
- return typeof value === "object" && value !== null && !Array.isArray(value);
303
- }
304
- function parseRelease(value) {
305
- if (!isRecord2(value) || typeof value.tag_name !== "string" || typeof value.html_url !== "string" || !Array.isArray(value.assets)) {
306
- throw new Error("GitHub returned an invalid tldraw Offline release");
307
- }
308
- const assets = value.assets.map((asset, index) => {
309
- if (!isRecord2(asset) || typeof asset.name !== "string" || typeof asset.browser_download_url !== "string" || typeof asset.size !== "number" || asset.digest !== null && asset.digest !== undefined && typeof asset.digest !== "string") {
310
- throw new Error(`GitHub returned an invalid release asset at index ${index}`);
311
- }
312
- return {
313
- name: asset.name,
314
- browser_download_url: asset.browser_download_url,
315
- size: asset.size,
316
- digest: asset.digest ?? null
317
- };
318
- });
319
- return { tag_name: value.tag_name, html_url: value.html_url, assets };
320
- }
321
- function selectDesktopAsset(release, platform = hostPlatform(), architecture = hostArch()) {
322
- const expectedName = platform === "darwin" ? "tldraw-offline-mac-universal.dmg" : platform === "win32" ? architecture === "arm64" ? "tldraw-offline-win-arm64.exe" : "tldraw-offline-win-x64.exe" : platform === "linux" ? architecture === "arm64" ? "tldraw-offline-linux-arm64.AppImage" : "tldraw-offline-linux-x86_64.AppImage" : null;
323
- if (expectedName === null) {
324
- throw new Error(`tldraw Offline has no automated installer for ${platform}/${architecture}`);
325
- }
326
- const asset = release.assets.find((candidate) => candidate.name === expectedName);
327
- if (asset === undefined) {
328
- throw new Error(`The latest tldraw Offline release does not contain ${expectedName}`);
329
- }
330
- return asset;
331
- }
332
- async function getLatestDesktopRelease() {
333
- const response = await fetch(releaseApi, {
334
- headers: {
335
- Accept: "application/vnd.github+json",
336
- "User-Agent": "hraness-slopcamera",
337
- "X-GitHub-Api-Version": "2022-11-28"
338
- }
339
- });
340
- if (!response.ok)
341
- throw new Error(`GitHub release lookup failed with HTTP ${response.status}`);
342
- return parseRelease(await response.json());
343
- }
344
- async function sha256(filePath) {
345
- const hash = createHash("sha256");
346
- for await (const chunk of createReadStream(filePath))
347
- hash.update(chunk);
348
- return hash.digest("hex");
349
- }
350
- async function download(asset, filePath) {
351
- const response = await fetch(asset.browser_download_url, {
352
- headers: { "User-Agent": "hraness-slopcamera" },
353
- redirect: "follow"
354
- });
355
- if (!response.ok || response.body === null) {
356
- throw new Error(`Installer download failed with HTTP ${response.status}`);
357
- }
358
- const temporary = `${filePath}.part-${process.pid}`;
359
- await mkdir2(dirname3(filePath), { recursive: true });
360
- try {
361
- await pipeline(Readable.fromWeb(response.body), createWriteStream(temporary, { mode: 384 }));
362
- const expected = asset.digest?.startsWith("sha256:") ? asset.digest.slice(7) : null;
363
- if (expected === null) {
364
- throw new Error("GitHub did not publish a SHA-256 digest for this installer");
365
- }
366
- const actual = await sha256(temporary);
367
- if (actual !== expected) {
368
- throw new Error(`Installer checksum mismatch: expected ${expected}, received ${actual}`);
369
- }
370
- await rename2(temporary, filePath);
371
- } catch (error) {
372
- await rm2(temporary, { force: true });
373
- throw error;
374
- }
375
- }
376
- function spawnDetached(command) {
377
- const child = Bun.spawn([...command], {
378
- env: nonGatewayChildEnvironment(),
379
- stdin: "ignore",
380
- stdout: "ignore",
381
- stderr: "ignore"
382
- });
383
- child.unref();
384
- }
385
- async function installDesktop(options) {
386
- const release = await getLatestDesktopRelease();
387
- const asset = selectDesktopAsset(release);
388
- const cacheDirectory = join2(homedir(), ".cache", "slopcamera", "installers", release.tag_name);
389
- const installerPath = join2(cacheDirectory, asset.name);
390
- let reusable = false;
391
- if (await pathExists(installerPath)) {
392
- const expected = asset.digest?.startsWith("sha256:") ? asset.digest.slice(7) : null;
393
- reusable = expected !== null && await sha256(installerPath) === expected;
394
- }
395
- if (!reusable)
396
- await download(asset, installerPath);
397
- if (hostPlatform() === "linux") {
398
- const installedPath = join2(homedir(), ".local", "bin", "tldraw-offline");
399
- await mkdir2(dirname3(installedPath), { recursive: true });
400
- const temporary = `${installedPath}.tmp-${process.pid}`;
401
- await Bun.write(temporary, Bun.file(installerPath));
402
- await chmod(temporary, 493);
403
- await rename2(temporary, installedPath);
404
- if (!options.downloadOnly)
405
- spawnDetached([installedPath]);
406
- return { filePath: installedPath, release: release.tag_name };
407
- }
408
- if (!options.downloadOnly) {
409
- if (hostPlatform() === "darwin") {
410
- spawnDetached(["open", installerPath]);
411
- } else {
412
- spawnDetached(["cmd.exe", "/d", "/s", "/c", "start", "", installerPath]);
413
- }
414
- }
415
- return { filePath: installerPath, release: release.tag_name };
416
- }
417
- async function findDesktopApplication() {
418
- const candidates = hostPlatform() === "darwin" ? [
419
- "/Applications/tldraw offline.app",
420
- join2(homedir(), "Applications", "tldraw offline.app")
421
- ] : hostPlatform() === "linux" ? [join2(homedir(), ".local", "bin", "tldraw-offline")] : [
422
- join2(process.env.LOCALAPPDATA ?? join2(homedir(), "AppData", "Local"), "Programs", "tldraw offline", "tldraw offline.exe")
423
- ];
424
- for (const candidate of candidates)
425
- if (await pathExists(candidate))
426
- return candidate;
427
- return null;
428
- }
429
- function serverFilePath() {
430
- if (hostPlatform() === "darwin") {
431
- return join2(homedir(), "Library", "Application Support", "tldraw", "server.json");
432
- }
433
- if (hostPlatform() === "win32") {
434
- return join2(process.env.APPDATA ?? join2(homedir(), "AppData", "Roaming"), "tldraw", "server.json");
435
- }
436
- return join2(process.env.XDG_CONFIG_HOME ?? join2(homedir(), ".config"), "tldraw", "server.json");
437
- }
438
- async function desktopStatus() {
439
- const installedPath = await findDesktopApplication();
440
- const filePath = serverFilePath();
441
- if (!await pathExists(filePath))
442
- return { installedPath, server: null };
443
- try {
444
- const parsed = JSON.parse(await readFile3(filePath, "utf8"));
445
- if (!isRecord2(parsed) || typeof parsed.port !== "number") {
446
- return { installedPath, server: null };
447
- }
448
- return {
449
- installedPath,
450
- server: {
451
- port: parsed.port,
452
- pid: typeof parsed.pid === "number" ? parsed.pid : null
453
- }
454
- };
455
- } catch {
456
- return { installedPath, server: null };
457
- }
458
- }
459
- async function openInDesktop(filePath) {
460
- const absolutePath = resolve3(filePath);
461
- if (!await pathExists(absolutePath))
462
- throw new Error(`File does not exist: ${absolutePath}`);
463
- const application = await findDesktopApplication();
464
- if (application === null) {
465
- throw new Error(`tldraw Offline is not installed. Run "slopcamera canvas install" or visit ${desktopDownloadPage}`);
466
- }
467
- if (hostPlatform() === "darwin") {
468
- spawnDetached(["open", "-a", application, absolutePath]);
469
- } else if (hostPlatform() === "win32") {
470
- spawnDetached(["cmd.exe", "/d", "/s", "/c", "start", "", absolutePath]);
471
- } else {
472
- spawnDetached([application, absolutePath]);
473
- }
474
- }
475
-
476
290
  // src/mcp/tools.ts
477
- import { rename as rename3, rm as rm3, writeFile as writeFile2 } from "fs/promises";
478
- import { dirname as dirname5, join as join4 } from "path";
291
+ import { rename as rename2, rm as rm2, writeFile as writeFile2 } from "fs/promises";
292
+ import { dirname as dirname4, join as join3 } from "path";
479
293
 
480
294
  // src/mcp/boundary.ts
481
- import { open, mkdir as mkdir3, realpath, stat } from "fs/promises";
295
+ import { open, mkdir as mkdir2, realpath, stat } from "fs/promises";
482
296
  import {
483
297
  basename as basename2,
484
- dirname as dirname4,
298
+ dirname as dirname3,
485
299
  isAbsolute as isAbsolute2,
486
- join as join3,
300
+ join as join2,
487
301
  relative,
488
- resolve as resolve4,
302
+ resolve as resolve3,
489
303
  win32
490
304
  } from "path";
491
305
  var mcpSourceByteLimit = 1024 * 1024;
@@ -578,7 +392,7 @@ class WorkspaceBoundary {
578
392
  static async create(rootDirectory) {
579
393
  let resolvedRoot;
580
394
  try {
581
- resolvedRoot = await realpath(resolve4(rootDirectory));
395
+ resolvedRoot = await realpath(resolve3(rootDirectory));
582
396
  if (!(await stat(resolvedRoot)).isDirectory()) {
583
397
  throw new WorkspaceBoundaryError("OUTPUT_NOT_DIRECTORY", "MCP root must be a directory.");
584
398
  }
@@ -601,7 +415,7 @@ class WorkspaceBoundary {
601
415
  }
602
416
  async readSource(value) {
603
417
  const normalized = normalizeRelativePath(value, { allowRoot: false });
604
- const lexicalPath = resolve4(this.rootDirectory, normalized.native);
418
+ const lexicalPath = resolve3(this.rootDirectory, normalized.native);
605
419
  this.assertConfined(lexicalPath);
606
420
  let canonicalPath;
607
421
  try {
@@ -621,7 +435,7 @@ class WorkspaceBoundary {
621
435
  }
622
436
  async resolveInputFile(value, maximumBytes) {
623
437
  const normalized = normalizeRelativePath(value, { allowRoot: false });
624
- const lexicalPath = resolve4(this.rootDirectory, normalized.native);
438
+ const lexicalPath = resolve3(this.rootDirectory, normalized.native);
625
439
  this.assertConfined(lexicalPath);
626
440
  let canonicalPath;
627
441
  try {
@@ -653,8 +467,8 @@ class WorkspaceBoundary {
653
467
  if (fileName === "." || fileName === ".." || fileName.length === 0) {
654
468
  throw new WorkspaceBoundaryError("INVALID_PATH", "Output path must identify a file below the root.");
655
469
  }
656
- const directory = await this.prepareOutputDirectory(dirname4(normalized.native));
657
- const absolutePath = join3(directory.absolutePath, fileName);
470
+ const directory = await this.prepareOutputDirectory(dirname3(normalized.native));
471
+ const absolutePath = join2(directory.absolutePath, fileName);
658
472
  this.assertConfined(absolutePath);
659
473
  return {
660
474
  absolutePath,
@@ -663,7 +477,7 @@ class WorkspaceBoundary {
663
477
  }
664
478
  async prepareOutputDirectory(value) {
665
479
  const normalized = normalizeRelativePath(value, { allowRoot: true });
666
- const lexicalPath = resolve4(this.rootDirectory, normalized.native);
480
+ const lexicalPath = resolve3(this.rootDirectory, normalized.native);
667
481
  this.assertConfined(lexicalPath);
668
482
  let ancestor = lexicalPath;
669
483
  for (;; ) {
@@ -677,7 +491,7 @@ class WorkspaceBoundary {
677
491
  if (filesystemCode(error) !== "ENOENT") {
678
492
  throw new WorkspaceBoundaryError("FILESYSTEM_ERROR", "Output directory could not be resolved.");
679
493
  }
680
- const parent = dirname4(ancestor);
494
+ const parent = dirname3(ancestor);
681
495
  if (parent === ancestor) {
682
496
  throw new WorkspaceBoundaryError("PATH_OUTSIDE_ROOT", "Output directory resolves outside the MCP root.");
683
497
  }
@@ -685,7 +499,7 @@ class WorkspaceBoundary {
685
499
  }
686
500
  }
687
501
  try {
688
- await mkdir3(lexicalPath, { recursive: true });
502
+ await mkdir2(lexicalPath, { recursive: true });
689
503
  const canonicalPath = await realpath(lexicalPath);
690
504
  this.assertConfined(canonicalPath);
691
505
  if (!(await stat(canonicalPath)).isDirectory()) {
@@ -959,7 +773,7 @@ class ToolFailure extends Error {
959
773
  this.issues = issues;
960
774
  }
961
775
  }
962
- function isRecord3(value) {
776
+ function isRecord2(value) {
963
777
  return typeof value === "object" && value !== null && !Array.isArray(value);
964
778
  }
965
779
  function safeFragment(value, maximumLength = 160) {
@@ -984,14 +798,14 @@ function parsePath(value) {
984
798
  return value;
985
799
  }
986
800
  function parseCheckArguments(value) {
987
- if (!isRecord3(value)) {
801
+ if (!isRecord2(value)) {
988
802
  throw new ToolFailure("INVALID_ARGUMENTS", "Tool arguments must be an object.");
989
803
  }
990
804
  rejectUnknownKeys(value, new Set(["path"]));
991
805
  return { path: parsePath(value.path) };
992
806
  }
993
807
  function parseRenderArguments(value) {
994
- if (!isRecord3(value)) {
808
+ if (!isRecord2(value)) {
995
809
  throw new ToolFailure("INVALID_ARGUMENTS", "Tool arguments must be an object.");
996
810
  }
997
811
  rejectUnknownKeys(value, new Set(["path", "out_dir", "scale"]));
@@ -1010,7 +824,7 @@ function parseRenderArguments(value) {
1010
824
  };
1011
825
  }
1012
826
  function parseSearchArguments(value) {
1013
- if (!isRecord3(value)) {
827
+ if (!isRecord2(value)) {
1014
828
  throw new ToolFailure("INVALID_ARGUMENTS", "Tool arguments must be an object.");
1015
829
  }
1016
830
  rejectUnknownKeys(value, new Set(["query", "limit"]));
@@ -1022,11 +836,11 @@ function parseSearchArguments(value) {
1022
836
  return { query, limit };
1023
837
  }
1024
838
  function parseExecuteArguments(value) {
1025
- if (!isRecord3(value)) {
839
+ if (!isRecord2(value)) {
1026
840
  throw new ToolFailure("INVALID_ARGUMENTS", "Tool arguments must be an object.");
1027
841
  }
1028
842
  rejectUnknownKeys(value, new Set(["operation", "input"]));
1029
- if (typeof value.operation !== "string" || !slopcameraOperationCodes.includes(value.operation) || !isRecord3(value.input)) {
843
+ if (typeof value.operation !== "string" || !slopcameraOperationCodes.includes(value.operation) || !isRecord2(value.input)) {
1030
844
  throw new ToolFailure("INVALID_ARGUMENTS", "operation must be an exact Slopcamera operation code and input must be an object.");
1031
845
  }
1032
846
  return {
@@ -1048,7 +862,7 @@ function assertComplexityLimits(spec) {
1048
862
  }
1049
863
  }
1050
864
  function assertRawComplexityLimits(value) {
1051
- if (!isRecord3(value))
865
+ if (!isRecord2(value))
1052
866
  return;
1053
867
  const shapeCount = Array.isArray(value.shapes) ? value.shapes.length : 0;
1054
868
  const edgeCount = Array.isArray(value.edges) ? value.edges.length : 0;
@@ -1131,20 +945,20 @@ function portableDirectory(filePath) {
1131
945
  return separator === -1 ? "." : filePath.slice(0, separator);
1132
946
  }
1133
947
  async function atomicOverwrite(filePath, data) {
1134
- const temporaryPath = join4(dirname5(filePath), `.${crypto.randomUUID()}.slopcamera-mcp.tmp`);
948
+ const temporaryPath = join3(dirname4(filePath), `.${crypto.randomUUID()}.slopcamera-mcp.tmp`);
1135
949
  try {
1136
950
  await writeFile2(temporaryPath, data, { flag: "wx" });
1137
951
  try {
1138
- await rename3(temporaryPath, filePath);
952
+ await rename2(temporaryPath, filePath);
1139
953
  } catch (error) {
1140
954
  const code = typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" ? error.code : undefined;
1141
955
  if (code !== "EEXIST" && code !== "EPERM")
1142
956
  throw error;
1143
- await rm3(filePath, { force: true });
1144
- await rename3(temporaryPath, filePath);
957
+ await rm2(filePath, { force: true });
958
+ await rename2(temporaryPath, filePath);
1145
959
  }
1146
960
  } finally {
1147
- await rm3(temporaryPath, { force: true });
961
+ await rm2(temporaryPath, { force: true });
1148
962
  }
1149
963
  }
1150
964
  async function loadDiagram(boundary, path) {
@@ -1307,11 +1121,11 @@ class SlopcameraMcpToolRuntime {
1307
1121
  const darkPng = renderPng(dark, builtInConfig, options.scale);
1308
1122
  const absoluteArtifacts = {
1309
1123
  spec: source.absolutePath,
1310
- tldr: join4(outputDirectory.absolutePath, `${spec.name}.tldr`),
1311
- lightSvg: join4(outputDirectory.absolutePath, `${spec.name}.light.svg`),
1312
- darkSvg: join4(outputDirectory.absolutePath, `${spec.name}.dark.svg`),
1313
- lightPng: join4(outputDirectory.absolutePath, `${spec.name}.light.png`),
1314
- darkPng: join4(outputDirectory.absolutePath, `${spec.name}.dark.png`)
1124
+ tldr: join3(outputDirectory.absolutePath, `${spec.name}.tldr`),
1125
+ lightSvg: join3(outputDirectory.absolutePath, `${spec.name}.light.svg`),
1126
+ darkSvg: join3(outputDirectory.absolutePath, `${spec.name}.dark.svg`),
1127
+ lightPng: join3(outputDirectory.absolutePath, `${spec.name}.light.png`),
1128
+ darkPng: join3(outputDirectory.absolutePath, `${spec.name}.dark.png`)
1315
1129
  };
1316
1130
  await Promise.all([
1317
1131
  atomicOverwrite(absoluteArtifacts.tldr, tldr),
@@ -1347,23 +1161,23 @@ class SlopcameraMcpToolRuntime {
1347
1161
  }
1348
1162
 
1349
1163
  // src/version.ts
1350
- var SLOPCAMERA_VERSION = "3.2.7";
1164
+ var SLOPCAMERA_VERSION = "3.2.8";
1351
1165
 
1352
1166
  // src/mcp/server.ts
1353
1167
  var slopcameraMcpProtocolVersion = "2025-11-25";
1354
1168
  var slopcameraMcpServerName = "hraness-slopcamera";
1355
1169
  var maximumMessageBytes = 1024 * 1024;
1356
- function isRecord4(value) {
1170
+ function isRecord3(value) {
1357
1171
  return typeof value === "object" && value !== null && !Array.isArray(value);
1358
1172
  }
1359
1173
  function isJsonRpcId(value) {
1360
1174
  return typeof value === "string" || typeof value === "number" && Number.isSafeInteger(value);
1361
1175
  }
1362
1176
  function isInitializeParams(value) {
1363
- return isRecord4(value) && typeof value.protocolVersion === "string" && isRecord4(value.capabilities) && isRecord4(value.clientInfo) && typeof value.clientInfo.name === "string" && typeof value.clientInfo.version === "string";
1177
+ return isRecord3(value) && typeof value.protocolVersion === "string" && isRecord3(value.capabilities) && isRecord3(value.clientInfo) && typeof value.clientInfo.name === "string" && typeof value.clientInfo.version === "string";
1364
1178
  }
1365
1179
  function parseRequest(value) {
1366
- if (!isRecord4(value) || value.jsonrpc !== "2.0" || typeof value.method !== "string" || value.method.length === 0 || "id" in value && !isJsonRpcId(value.id)) {
1180
+ if (!isRecord3(value) || value.jsonrpc !== "2.0" || typeof value.method !== "string" || value.method.length === 0 || "id" in value && !isJsonRpcId(value.id)) {
1367
1181
  throw new Error("invalid request");
1368
1182
  }
1369
1183
  return {
@@ -1380,7 +1194,7 @@ function failure(id, code, message) {
1380
1194
  return { jsonrpc: "2.0", id, error: { code, message } };
1381
1195
  }
1382
1196
  function parseToolCall(params) {
1383
- if (!isRecord4(params) || typeof params.name !== "string" || params.arguments !== undefined && !isRecord4(params.arguments)) {
1197
+ if (!isRecord3(params) || typeof params.name !== "string" || params.arguments !== undefined && !isRecord3(params.arguments)) {
1384
1198
  throw new Error("invalid params");
1385
1199
  }
1386
1200
  const unknownKeys = Object.keys(params).filter((key) => key !== "name" && key !== "arguments");
@@ -1442,7 +1256,7 @@ class SlopcameraMcpSession {
1442
1256
  if (request.method === "ping")
1443
1257
  return success(id, {});
1444
1258
  if (request.method === "tools/list") {
1445
- if (request.params !== undefined && (!isRecord4(request.params) || Object.keys(request.params).length > 0)) {
1259
+ if (request.params !== undefined && (!isRecord3(request.params) || Object.keys(request.params).length > 0)) {
1446
1260
  return failure(id, -32602, "Invalid tools/list parameters");
1447
1261
  }
1448
1262
  return success(id, { tools: slopcameraMcpTools });
@@ -1462,11 +1276,11 @@ class SlopcameraMcpSession {
1462
1276
  }
1463
1277
  }
1464
1278
  async function defaultWriteLine(line) {
1465
- await new Promise((resolve5, reject) => {
1279
+ await new Promise((resolve4, reject) => {
1466
1280
  process.stdout.write(`${line}
1467
1281
  `, (error) => {
1468
1282
  if (error === null || error === undefined)
1469
- resolve5();
1283
+ resolve4();
1470
1284
  else
1471
1285
  reject(error);
1472
1286
  });
@@ -1966,27 +1780,21 @@ var slopcameraApi = Object.freeze({
1966
1780
  builtInIcons,
1967
1781
  bundledSkillPath,
1968
1782
  checkDiagramFile,
1969
- desktopDownloadPage,
1970
- desktopStatus,
1971
1783
  defineSlopcameraWorkflow,
1972
1784
  DiagramValidationError,
1973
- findDesktopApplication,
1974
1785
  generateSlopcameraImage,
1975
1786
  generateSlopcameraImageFile,
1976
- getLatestDesktopRelease,
1977
1787
  slopcameraGatewayCredentialStatus,
1978
1788
  slopcameraMcpProtocolVersion,
1979
1789
  slopcameraMcpServerName,
1980
1790
  slopcameraMcpTools,
1981
1791
  slopcameraOperationRegistry,
1982
1792
  SlopcameraMcpToolRuntime,
1983
- installDesktop,
1984
1793
  installSkill,
1985
1794
  lintDiagram,
1986
1795
  mcpMaximumRenderedPixels,
1987
1796
  mcpMaximumScale,
1988
1797
  mcpSourceByteLimit,
1989
- openInDesktop,
1990
1798
  parseDiagramSource,
1991
1799
  parseDiagramSpec,
1992
1800
  readDiagramFile,
@@ -1999,7 +1807,6 @@ var slopcameraApi = Object.freeze({
1999
1807
  runSlopcameraWorkflow,
2000
1808
  runMcpServer,
2001
1809
  searchSlopcameraOperations,
2002
- selectDesktopAsset,
2003
1810
  serializeTldr,
2004
1811
  stackLayoutDefaults,
2005
1812
  StackLayoutError,
@@ -2010,4 +1817,4 @@ var slopcameraApi = Object.freeze({
2010
1817
  executeSlopcameraOperation
2011
1818
  });
2012
1819
  var diagramApi = slopcameraApi;
2013
- export { readDiagramFile, checkDiagramFile, renderDiagramFile, artifactSummary, desktopDownloadPage, selectDesktopAsset, getLatestDesktopRelease, installDesktop, findDesktopApplication, desktopStatus, openInDesktop, mcpSourceByteLimit, WorkspaceBoundaryError, WorkspaceBoundary, mcpMaximumScale, mcpMaximumRenderedPixels, slopcameraMcpTools, SlopcameraMcpToolRuntime, SLOPCAMERA_VERSION, slopcameraMcpProtocolVersion, slopcameraMcpServerName, runMcpServer, STUDIO_LIMITS, StudioDigestSchema, StudioEngineSchema, StudioPathSchema, StudioSourceBundleSchema, parseStudioSourceBundle, StudioSourceSpaceSchema, StudioOutputRoleSchema, StudioOutputFormatSchema, StudioOutputInterpretationSchema, StudioOutputSpecSchema, StudioRenderSchema, StudioEngineOptionsSchema, StudioExecutionProfileSchema, StudioJobSchema, parseStudioJob, StudioCapabilityNameSchema, StudioRuntimeIdentitySchema, parseStudioRuntimeIdentity, StudioOutputArtifactSchema, studioSourceBundleSha256, studioJobSha256, studioRuntimeSha256, studioOutputPath, StudioPlanSchema, parseStudioPlan, planStudioJob, StudioReceiptSchema, parseStudioReceipt, validateStudioReceipt, inspectStudioBundle, inspectStudioPlan, slopcameraApi, diagramApi };
1820
+ export { readDiagramFile, checkDiagramFile, renderDiagramFile, artifactSummary, mcpSourceByteLimit, WorkspaceBoundaryError, WorkspaceBoundary, mcpMaximumScale, mcpMaximumRenderedPixels, slopcameraMcpTools, SlopcameraMcpToolRuntime, SLOPCAMERA_VERSION, slopcameraMcpProtocolVersion, slopcameraMcpServerName, runMcpServer, STUDIO_LIMITS, StudioDigestSchema, StudioEngineSchema, StudioPathSchema, StudioSourceBundleSchema, parseStudioSourceBundle, StudioSourceSpaceSchema, StudioOutputRoleSchema, StudioOutputFormatSchema, StudioOutputInterpretationSchema, StudioOutputSpecSchema, StudioRenderSchema, StudioEngineOptionsSchema, StudioExecutionProfileSchema, StudioJobSchema, parseStudioJob, StudioCapabilityNameSchema, StudioRuntimeIdentitySchema, parseStudioRuntimeIdentity, StudioOutputArtifactSchema, studioSourceBundleSha256, studioJobSha256, studioRuntimeSha256, studioOutputPath, StudioPlanSchema, parseStudioPlan, planStudioJob, StudioReceiptSchema, parseStudioReceipt, validateStudioReceipt, inspectStudioBundle, inspectStudioPlan, slopcameraApi, diagramApi };
@@ -4,7 +4,7 @@ import {
4
4
  isSlopcameraOperationCode,
5
5
  parseSlopcameraOperationInput,
6
6
  slopcameraOperationHostResourceClaims
7
- } from "./index-z7239b4h.js";
7
+ } from "./index-h1k0fnjq.js";
8
8
  import {
9
9
  createDefaultHostResourceCoordinator
10
10
  } from "./index-sh6xbav6.js";
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  vectorizeImage
4
- } from "./index-p63wavx0.js";
4
+ } from "./index-zfnddgay.js";
5
5
  import {
6
6
  generateSlopcameraImageFile,
7
7
  slopcameraMaximumPromptBytes
@@ -2026,4 +2026,4 @@ async function writeSvgAtomically(path, svg) {
2026
2026
  return outputPath;
2027
2027
  }
2028
2028
 
2029
- export { nonGatewayChildEnvironment, vectorizeProfileNames, VectorizeError, vectorizeHardLimits, vectorizeDefaultLimits, withInheritedCommandFileDescriptors, forwardVectorizeWorkerTermination, VTRACER_VERSION, vtracerReleases, configureVectorizeSharpConcurrency, VECTORIZE_WORKER_PROTOCOL, MAX_VECTORIZE_REQUEST_BYTES, MAX_VECTORIZE_RESPONSE_BYTES, vectorizeImage, vectorizeImageInProcess };
2029
+ export { vectorizeProfileNames, VectorizeError, vectorizeHardLimits, vectorizeDefaultLimits, withInheritedCommandFileDescriptors, forwardVectorizeWorkerTermination, VTRACER_VERSION, vtracerReleases, configureVectorizeSharpConcurrency, VECTORIZE_WORKER_PROTOCOL, MAX_VECTORIZE_REQUEST_BYTES, MAX_VECTORIZE_RESPONSE_BYTES, vectorizeImage, vectorizeImageInProcess };
package/dist/index.js CHANGED
@@ -25,18 +25,12 @@ import {
25
25
  WorkspaceBoundaryError,
26
26
  artifactSummary,
27
27
  checkDiagramFile,
28
- desktopDownloadPage,
29
- desktopStatus,
30
28
  diagramApi,
31
- findDesktopApplication,
32
- getLatestDesktopRelease,
33
29
  inspectStudioBundle,
34
30
  inspectStudioPlan,
35
- installDesktop,
36
31
  mcpMaximumRenderedPixels,
37
32
  mcpMaximumScale,
38
33
  mcpSourceByteLimit,
39
- openInDesktop,
40
34
  parseStudioJob,
41
35
  parseStudioPlan,
42
36
  parseStudioReceipt,
@@ -46,7 +40,6 @@ import {
46
40
  readDiagramFile,
47
41
  renderDiagramFile,
48
42
  runMcpServer,
49
- selectDesktopAsset,
50
43
  slopcameraApi,
51
44
  slopcameraMcpProtocolVersion,
52
45
  slopcameraMcpServerName,
@@ -56,7 +49,7 @@ import {
56
49
  studioRuntimeSha256,
57
50
  studioSourceBundleSha256,
58
51
  validateStudioReceipt
59
- } from "./index-rvghzt7b.js";
52
+ } from "./index-7131pg1c.js";
60
53
  import {
61
54
  bundledSkillPath,
62
55
  installSkill
@@ -66,7 +59,7 @@ import {
66
59
  SlopcameraWorkflowError,
67
60
  defineSlopcameraWorkflow,
68
61
  runSlopcameraWorkflow
69
- } from "./index-mcy8z0br.js";
62
+ } from "./index-fava6pge.js";
70
63
  import {
71
64
  DiagramValidationError,
72
65
  SlopcameraOperationError,
@@ -91,7 +84,7 @@ import {
91
84
  slopcameraOperationRegistry,
92
85
  stackLayoutDefaults,
93
86
  withSlopcameraOperationHostAdmission
94
- } from "./index-z7239b4h.js";
87
+ } from "./index-h1k0fnjq.js";
95
88
  import {
96
89
  VTRACER_VERSION,
97
90
  VectorizeError,
@@ -100,7 +93,7 @@ import {
100
93
  vectorizeImage,
101
94
  vectorizeProfileNames,
102
95
  vtracerReleases
103
- } from "./index-p63wavx0.js";
96
+ } from "./index-zfnddgay.js";
104
97
  import {
105
98
  SlopcameraCloudError,
106
99
  createFixedGatewayFetch,
@@ -154,7 +147,6 @@ export {
154
147
  slopcameraGatewayApiBaseUrl,
155
148
  slopcameraApi,
156
149
  serializeTldr,
157
- selectDesktopAsset,
158
150
  searchSlopcameraOperations,
159
151
  runSlopcameraWorkflow,
160
152
  runMcpServer,
@@ -174,7 +166,6 @@ export {
174
166
  parseSlopcameraOperationInput,
175
167
  parseDiagramSpec,
176
168
  parseDiagramSource,
177
- openInDesktop,
178
169
  normalizeHostResourceProfile,
179
170
  normalizeHostResourceClaims,
180
171
  mcpSourceByteLimit,
@@ -183,18 +174,13 @@ export {
183
174
  lintDiagram,
184
175
  isSlopcameraOperationCode,
185
176
  installSkill,
186
- installDesktop,
187
177
  inspectStudioPlan,
188
178
  inspectStudioBundle,
189
- getLatestDesktopRelease,
190
179
  generateSlopcameraImageFile,
191
180
  generateSlopcameraImage,
192
- findDesktopApplication,
193
181
  executeSlopcameraOperationWithLease,
194
182
  executeSlopcameraOperation,
195
183
  diagramApi,
196
- desktopStatus,
197
- desktopDownloadPage,
198
184
  defineSlopcameraWorkflow,
199
185
  defaultSlopcameraHostResourceStateRoot,
200
186
  defaultSlopcameraHostResourceProfile,
@@ -10,8 +10,8 @@ import {
10
10
  slopcameraOperationHostResourceClaims,
11
11
  slopcameraOperationRegistry,
12
12
  withSlopcameraOperationHostAdmission
13
- } from "./index-z7239b4h.js";
14
- import"./index-p63wavx0.js";
13
+ } from "./index-h1k0fnjq.js";
14
+ import"./index-zfnddgay.js";
15
15
  import"./index-r7gdhmsp.js";
16
16
  import"./index-sh6xbav6.js";
17
17
  import"./index-z1w83f81.js";
@@ -8,7 +8,7 @@ import {
8
8
  forwardVectorizeWorkerTermination,
9
9
  vectorizeImageInProcess,
10
10
  withInheritedCommandFileDescriptors
11
- } from "../index-p63wavx0.js";
11
+ } from "../index-zfnddgay.js";
12
12
  import"../index-z1w83f81.js";
13
13
 
14
14
  // src/vectorize/worker.ts
package/dist/workflow.js CHANGED
@@ -3,9 +3,9 @@ import {
3
3
  SlopcameraWorkflowError,
4
4
  defineSlopcameraWorkflow,
5
5
  runSlopcameraWorkflow
6
- } from "./index-mcy8z0br.js";
7
- import"./index-z7239b4h.js";
8
- import"./index-p63wavx0.js";
6
+ } from "./index-fava6pge.js";
7
+ import"./index-h1k0fnjq.js";
8
+ import"./index-zfnddgay.js";
9
9
  import"./index-r7gdhmsp.js";
10
10
  import"./index-sh6xbav6.js";
11
11
  import"./index-z1w83f81.js";
package/docs/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Slopcamera retains editable source, renders local or generated media, and assembles it into inspectable video projects. Choose a guide for the work you want to do.
4
4
 
5
- These pages describe Slopcamera from current source. [Install that source](how-to/use-current-source.md) to use the CLI, SDK and matching Agent Skill; no Slopcamera release archive is available yet. Historical Atet archives retain their original package and commands. The [capability reference](reference/capabilities.md) distinguishes them and lists local runtime requirements.
5
+ These pages describe Slopcamera from current source. [Install that source](how-to/use-current-source.md) to use the CLI, SDK and matching Agent Skill; no Slopcamera release archive is available yet. Historical Atet archives retain their original package and commands. The CLI also has an optional unbundled macOS menu-bar companion; the [menu-bar release contract](menubar-release.md) covers its prebuilt binary and LaunchAgent. The [capability reference](reference/capabilities.md) distinguishes them and lists local runtime requirements.
6
6
 
7
7
  ## Learn by making something
8
8