@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.
- package/NOTICE.md +1 -7
- package/PRIVACY.md +16 -7
- package/README.md +37 -12
- package/apps/desktop/README.md +14 -130
- package/apps/desktop/application/context.ts +0 -9
- package/apps/desktop/application/default-registry.ts +0 -10
- package/apps/desktop/application/operation.ts +1 -5
- package/apps/desktop/application/operations/index.ts +0 -1
- package/apps/desktop/cli/args.ts +14 -86
- package/apps/desktop/cli/command-host-resources.ts +2 -1
- package/apps/desktop/cli/commands.ts +28 -67
- package/apps/desktop/cli/help.ts +12 -18
- package/apps/desktop/cli/html-scene.ts +139 -28
- package/apps/desktop/cli/io.ts +2 -1
- package/apps/desktop/cli/main.ts +23 -47
- package/apps/desktop/cli/menubar.ts +244 -0
- package/apps/desktop/cli/music-analysis-service.ts +61 -0
- package/apps/desktop/cli/portable-surface.ts +12 -4
- package/apps/desktop/code/application-node-planner.ts +0 -47
- package/apps/desktop/code/host-source-layout.ts +46 -0
- package/apps/desktop/code/public.ts +0 -1
- package/apps/desktop/code/runtime-identity.ts +50 -8
- package/apps/desktop/code/semantic-builder.ts +0 -43
- package/apps/desktop/code/source-bundle.ts +23 -6
- package/apps/desktop/code/source-typecheck.ts +131 -43
- package/apps/desktop/code/worker-client.ts +14 -2
- package/apps/desktop/core/music-analysis.ts +124 -1
- package/apps/desktop/dist/cli/main.js +244 -250
- package/apps/desktop/html-overlay/audio-reactivity.ts +127 -0
- package/apps/desktop/html-overlay/index.ts +9 -0
- package/apps/desktop/html-overlay/runtime.ts +2 -0
- package/apps/desktop/html-overlay/scene.ts +29 -0
- package/dist/cli.js +83 -81
- package/dist/{index-rvghzt7b.js → index-7131pg1c.js} +43 -236
- package/dist/{index-mcy8z0br.js → index-fava6pge.js} +1 -1
- package/dist/{index-z7239b4h.js → index-h1k0fnjq.js} +1 -1
- package/dist/{index-p63wavx0.js → index-zfnddgay.js} +1 -1
- package/dist/index.js +4 -18
- package/dist/operations.js +2 -2
- package/dist/vectorize/worker.js +1 -1
- package/dist/workflow.js +3 -3
- package/docs/README.md +1 -1
- package/docs/studio.md +1 -1
- package/package.json +6 -21
- package/skills/slopcamera/SKILL.md +8 -0
- package/skills/slopcamera/references/diagrams.md +5 -14
- package/skills/slopcamera/references/install.md +1 -1
- package/skills/slopcamera/references/music-video.md +23 -3
- package/skills/slopcamera/references/reference-led-3d.md +1 -1
- package/skills/slopcamera/references/support.md +25 -0
- package/skills/slopcamera/references/web-media-excerpts.md +120 -0
- package/src/cli.ts +28 -98
- package/src/index.ts +0 -23
- package/src/support-completion.ts +16 -0
- package/src/support.ts +42 -0
- package/src/version.ts +1 -1
- package/apps/desktop/application/operations/recording/index.ts +0 -5
- package/apps/desktop/application/operations/recording/pause.ts +0 -34
- package/apps/desktop/application/operations/recording/resume.ts +0 -34
- package/apps/desktop/application/operations/recording/shared.ts +0 -199
- package/apps/desktop/application/operations/recording/start.ts +0 -169
- package/apps/desktop/application/operations/recording/stop.ts +0 -34
- package/apps/desktop/capture/protocol.ts +0 -689
- package/apps/desktop/cli/capture-bundle.ts +0 -1117
- package/apps/desktop/cli/recording-controller.ts +0 -1567
- package/apps/desktop/cli/recording-daemon.ts +0 -931
- package/src/desktop.ts +0 -253
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
SlopcameraWorkflowError,
|
|
17
17
|
defineSlopcameraWorkflow,
|
|
18
18
|
runSlopcameraWorkflow
|
|
19
|
-
} from "./index-
|
|
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-
|
|
42
|
+
} from "./index-h1k0fnjq.js";
|
|
43
43
|
import {
|
|
44
44
|
VectorizeError,
|
|
45
|
-
nonGatewayChildEnvironment,
|
|
46
45
|
vectorizeHardLimits,
|
|
47
46
|
vectorizeImage
|
|
48
|
-
} from "./index-
|
|
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
|
|
478
|
-
import { dirname as
|
|
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
|
|
295
|
+
import { open, mkdir as mkdir2, realpath, stat } from "fs/promises";
|
|
482
296
|
import {
|
|
483
297
|
basename as basename2,
|
|
484
|
-
dirname as
|
|
298
|
+
dirname as dirname3,
|
|
485
299
|
isAbsolute as isAbsolute2,
|
|
486
|
-
join as
|
|
300
|
+
join as join2,
|
|
487
301
|
relative,
|
|
488
|
-
resolve as
|
|
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(
|
|
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 =
|
|
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 =
|
|
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(
|
|
657
|
-
const absolutePath =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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) || !
|
|
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 (!
|
|
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 =
|
|
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
|
|
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
|
|
1144
|
-
await
|
|
957
|
+
await rm2(filePath, { force: true });
|
|
958
|
+
await rename2(temporaryPath, filePath);
|
|
1145
959
|
}
|
|
1146
960
|
} finally {
|
|
1147
|
-
await
|
|
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:
|
|
1311
|
-
lightSvg:
|
|
1312
|
-
darkSvg:
|
|
1313
|
-
lightPng:
|
|
1314
|
-
darkPng:
|
|
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.
|
|
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
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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 && (!
|
|
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((
|
|
1279
|
+
await new Promise((resolve4, reject) => {
|
|
1466
1280
|
process.stdout.write(`${line}
|
|
1467
1281
|
`, (error) => {
|
|
1468
1282
|
if (error === null || error === undefined)
|
|
1469
|
-
|
|
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,
|
|
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 };
|
|
@@ -2026,4 +2026,4 @@ async function writeSvgAtomically(path, svg) {
|
|
|
2026
2026
|
return outputPath;
|
|
2027
2027
|
}
|
|
2028
2028
|
|
|
2029
|
-
export {
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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,
|
package/dist/operations.js
CHANGED
|
@@ -10,8 +10,8 @@ import {
|
|
|
10
10
|
slopcameraOperationHostResourceClaims,
|
|
11
11
|
slopcameraOperationRegistry,
|
|
12
12
|
withSlopcameraOperationHostAdmission
|
|
13
|
-
} from "./index-
|
|
14
|
-
import"./index-
|
|
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";
|
package/dist/vectorize/worker.js
CHANGED
package/dist/workflow.js
CHANGED
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
SlopcameraWorkflowError,
|
|
4
4
|
defineSlopcameraWorkflow,
|
|
5
5
|
runSlopcameraWorkflow
|
|
6
|
-
} from "./index-
|
|
7
|
-
import"./index-
|
|
8
|
-
import"./index-
|
|
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
|
|