@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
package/src/desktop.ts
DELETED
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
import { createHash } from "node:crypto"
|
|
2
|
-
import { createReadStream, createWriteStream } from "node:fs"
|
|
3
|
-
import { chmod, mkdir, readFile, rename, rm } from "node:fs/promises"
|
|
4
|
-
import { homedir, platform as hostPlatform, arch as hostArch } from "node:os"
|
|
5
|
-
import { dirname, join, resolve } from "node:path"
|
|
6
|
-
import { Readable } from "node:stream"
|
|
7
|
-
import { pipeline } from "node:stream/promises"
|
|
8
|
-
import { pathExists } from "./fs.js"
|
|
9
|
-
import { nonGatewayChildEnvironment } from "./process-environment.js"
|
|
10
|
-
|
|
11
|
-
const releaseApi = "https://api.github.com/repos/tldraw/tldraw-offline/releases/latest"
|
|
12
|
-
export const desktopDownloadPage = "https://offline.tldraw.com"
|
|
13
|
-
|
|
14
|
-
export interface ReleaseAsset {
|
|
15
|
-
readonly name: string
|
|
16
|
-
readonly browser_download_url: string
|
|
17
|
-
readonly size: number
|
|
18
|
-
readonly digest: string | null
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface Release {
|
|
22
|
-
readonly tag_name: string
|
|
23
|
-
readonly html_url: string
|
|
24
|
-
readonly assets: readonly ReleaseAsset[]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
28
|
-
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function parseRelease(value: unknown): Release {
|
|
32
|
-
if (
|
|
33
|
-
!isRecord(value) ||
|
|
34
|
-
typeof value.tag_name !== "string" ||
|
|
35
|
-
typeof value.html_url !== "string" ||
|
|
36
|
-
!Array.isArray(value.assets)
|
|
37
|
-
) {
|
|
38
|
-
throw new Error("GitHub returned an invalid tldraw Offline release")
|
|
39
|
-
}
|
|
40
|
-
const assets = value.assets.map((asset, index) => {
|
|
41
|
-
if (
|
|
42
|
-
!isRecord(asset) ||
|
|
43
|
-
typeof asset.name !== "string" ||
|
|
44
|
-
typeof asset.browser_download_url !== "string" ||
|
|
45
|
-
typeof asset.size !== "number" ||
|
|
46
|
-
(asset.digest !== null && asset.digest !== undefined && typeof asset.digest !== "string")
|
|
47
|
-
) {
|
|
48
|
-
throw new Error(`GitHub returned an invalid release asset at index ${index}`)
|
|
49
|
-
}
|
|
50
|
-
return {
|
|
51
|
-
name: asset.name,
|
|
52
|
-
browser_download_url: asset.browser_download_url,
|
|
53
|
-
size: asset.size,
|
|
54
|
-
digest: asset.digest ?? null,
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
return { tag_name: value.tag_name, html_url: value.html_url, assets }
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function selectDesktopAsset(
|
|
61
|
-
release: Release,
|
|
62
|
-
platform: NodeJS.Platform = hostPlatform(),
|
|
63
|
-
architecture: string = hostArch(),
|
|
64
|
-
): ReleaseAsset {
|
|
65
|
-
const expectedName =
|
|
66
|
-
platform === "darwin"
|
|
67
|
-
? "tldraw-offline-mac-universal.dmg"
|
|
68
|
-
: platform === "win32"
|
|
69
|
-
? architecture === "arm64"
|
|
70
|
-
? "tldraw-offline-win-arm64.exe"
|
|
71
|
-
: "tldraw-offline-win-x64.exe"
|
|
72
|
-
: platform === "linux"
|
|
73
|
-
? architecture === "arm64"
|
|
74
|
-
? "tldraw-offline-linux-arm64.AppImage"
|
|
75
|
-
: "tldraw-offline-linux-x86_64.AppImage"
|
|
76
|
-
: null
|
|
77
|
-
if (expectedName === null) {
|
|
78
|
-
throw new Error(`tldraw Offline has no automated installer for ${platform}/${architecture}`)
|
|
79
|
-
}
|
|
80
|
-
const asset = release.assets.find((candidate) => candidate.name === expectedName)
|
|
81
|
-
if (asset === undefined) {
|
|
82
|
-
throw new Error(`The latest tldraw Offline release does not contain ${expectedName}`)
|
|
83
|
-
}
|
|
84
|
-
return asset
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export async function getLatestDesktopRelease(): Promise<Release> {
|
|
88
|
-
const response = await fetch(releaseApi, {
|
|
89
|
-
headers: {
|
|
90
|
-
Accept: "application/vnd.github+json",
|
|
91
|
-
"User-Agent": "hraness-slopcamera",
|
|
92
|
-
"X-GitHub-Api-Version": "2022-11-28",
|
|
93
|
-
},
|
|
94
|
-
})
|
|
95
|
-
if (!response.ok) throw new Error(`GitHub release lookup failed with HTTP ${response.status}`)
|
|
96
|
-
return parseRelease((await response.json()) as unknown)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
async function sha256(filePath: string): Promise<string> {
|
|
100
|
-
const hash = createHash("sha256")
|
|
101
|
-
for await (const chunk of createReadStream(filePath)) hash.update(chunk)
|
|
102
|
-
return hash.digest("hex")
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async function download(asset: ReleaseAsset, filePath: string): Promise<void> {
|
|
106
|
-
const response = await fetch(asset.browser_download_url, {
|
|
107
|
-
headers: { "User-Agent": "hraness-slopcamera" },
|
|
108
|
-
redirect: "follow",
|
|
109
|
-
})
|
|
110
|
-
if (!response.ok || response.body === null) {
|
|
111
|
-
throw new Error(`Installer download failed with HTTP ${response.status}`)
|
|
112
|
-
}
|
|
113
|
-
const temporary = `${filePath}.part-${process.pid}`
|
|
114
|
-
await mkdir(dirname(filePath), { recursive: true })
|
|
115
|
-
try {
|
|
116
|
-
await pipeline(
|
|
117
|
-
Readable.fromWeb(
|
|
118
|
-
response.body as unknown as import("node:stream/web").ReadableStream,
|
|
119
|
-
),
|
|
120
|
-
createWriteStream(temporary, { mode: 0o600 }),
|
|
121
|
-
)
|
|
122
|
-
const expected = asset.digest?.startsWith("sha256:") ? asset.digest.slice(7) : null
|
|
123
|
-
if (expected === null) {
|
|
124
|
-
throw new Error("GitHub did not publish a SHA-256 digest for this installer")
|
|
125
|
-
}
|
|
126
|
-
const actual = await sha256(temporary)
|
|
127
|
-
if (actual !== expected) {
|
|
128
|
-
throw new Error(`Installer checksum mismatch: expected ${expected}, received ${actual}`)
|
|
129
|
-
}
|
|
130
|
-
await rename(temporary, filePath)
|
|
131
|
-
} catch (error) {
|
|
132
|
-
await rm(temporary, { force: true })
|
|
133
|
-
throw error
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function spawnDetached(command: readonly string[]): void {
|
|
138
|
-
const child = Bun.spawn([...command], {
|
|
139
|
-
env: nonGatewayChildEnvironment(),
|
|
140
|
-
stdin: "ignore",
|
|
141
|
-
stdout: "ignore",
|
|
142
|
-
stderr: "ignore",
|
|
143
|
-
})
|
|
144
|
-
child.unref()
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
export async function installDesktop(options: {
|
|
148
|
-
readonly downloadOnly?: boolean
|
|
149
|
-
}): Promise<{ readonly filePath: string; readonly release: string }> {
|
|
150
|
-
const release = await getLatestDesktopRelease()
|
|
151
|
-
const asset = selectDesktopAsset(release)
|
|
152
|
-
const cacheDirectory = join(homedir(), ".cache", "slopcamera", "installers", release.tag_name)
|
|
153
|
-
const installerPath = join(cacheDirectory, asset.name)
|
|
154
|
-
let reusable = false
|
|
155
|
-
if (await pathExists(installerPath)) {
|
|
156
|
-
const expected = asset.digest?.startsWith("sha256:") ? asset.digest.slice(7) : null
|
|
157
|
-
reusable = expected !== null && (await sha256(installerPath)) === expected
|
|
158
|
-
}
|
|
159
|
-
if (!reusable) await download(asset, installerPath)
|
|
160
|
-
|
|
161
|
-
if (hostPlatform() === "linux") {
|
|
162
|
-
const installedPath = join(homedir(), ".local", "bin", "tldraw-offline")
|
|
163
|
-
await mkdir(dirname(installedPath), { recursive: true })
|
|
164
|
-
const temporary = `${installedPath}.tmp-${process.pid}`
|
|
165
|
-
await Bun.write(temporary, Bun.file(installerPath))
|
|
166
|
-
await chmod(temporary, 0o755)
|
|
167
|
-
await rename(temporary, installedPath)
|
|
168
|
-
if (!options.downloadOnly) spawnDetached([installedPath])
|
|
169
|
-
return { filePath: installedPath, release: release.tag_name }
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (!options.downloadOnly) {
|
|
173
|
-
if (hostPlatform() === "darwin") {
|
|
174
|
-
spawnDetached(["open", installerPath])
|
|
175
|
-
} else {
|
|
176
|
-
spawnDetached(["cmd.exe", "/d", "/s", "/c", "start", "", installerPath])
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
return { filePath: installerPath, release: release.tag_name }
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export async function findDesktopApplication(): Promise<string | null> {
|
|
183
|
-
const candidates =
|
|
184
|
-
hostPlatform() === "darwin"
|
|
185
|
-
? [
|
|
186
|
-
"/Applications/tldraw offline.app",
|
|
187
|
-
join(homedir(), "Applications", "tldraw offline.app"),
|
|
188
|
-
]
|
|
189
|
-
: hostPlatform() === "linux"
|
|
190
|
-
? [join(homedir(), ".local", "bin", "tldraw-offline")]
|
|
191
|
-
: [
|
|
192
|
-
join(
|
|
193
|
-
process.env.LOCALAPPDATA ?? join(homedir(), "AppData", "Local"),
|
|
194
|
-
"Programs",
|
|
195
|
-
"tldraw offline",
|
|
196
|
-
"tldraw offline.exe",
|
|
197
|
-
),
|
|
198
|
-
]
|
|
199
|
-
for (const candidate of candidates) if (await pathExists(candidate)) return candidate
|
|
200
|
-
return null
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
function serverFilePath(): string {
|
|
204
|
-
if (hostPlatform() === "darwin") {
|
|
205
|
-
return join(homedir(), "Library", "Application Support", "tldraw", "server.json")
|
|
206
|
-
}
|
|
207
|
-
if (hostPlatform() === "win32") {
|
|
208
|
-
return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), "tldraw", "server.json")
|
|
209
|
-
}
|
|
210
|
-
return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"), "tldraw", "server.json")
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export async function desktopStatus(): Promise<{
|
|
214
|
-
readonly installedPath: string | null
|
|
215
|
-
readonly server: { readonly port: number; readonly pid: number | null } | null
|
|
216
|
-
}> {
|
|
217
|
-
const installedPath = await findDesktopApplication()
|
|
218
|
-
const filePath = serverFilePath()
|
|
219
|
-
if (!(await pathExists(filePath))) return { installedPath, server: null }
|
|
220
|
-
try {
|
|
221
|
-
const parsed = JSON.parse(await readFile(filePath, "utf8")) as unknown
|
|
222
|
-
if (!isRecord(parsed) || typeof parsed.port !== "number") {
|
|
223
|
-
return { installedPath, server: null }
|
|
224
|
-
}
|
|
225
|
-
return {
|
|
226
|
-
installedPath,
|
|
227
|
-
server: {
|
|
228
|
-
port: parsed.port,
|
|
229
|
-
pid: typeof parsed.pid === "number" ? parsed.pid : null,
|
|
230
|
-
},
|
|
231
|
-
}
|
|
232
|
-
} catch {
|
|
233
|
-
return { installedPath, server: null }
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
export async function openInDesktop(filePath: string): Promise<void> {
|
|
238
|
-
const absolutePath = resolve(filePath)
|
|
239
|
-
if (!(await pathExists(absolutePath))) throw new Error(`File does not exist: ${absolutePath}`)
|
|
240
|
-
const application = await findDesktopApplication()
|
|
241
|
-
if (application === null) {
|
|
242
|
-
throw new Error(
|
|
243
|
-
`tldraw Offline is not installed. Run "slopcamera canvas install" or visit ${desktopDownloadPage}`,
|
|
244
|
-
)
|
|
245
|
-
}
|
|
246
|
-
if (hostPlatform() === "darwin") {
|
|
247
|
-
spawnDetached(["open", "-a", application, absolutePath])
|
|
248
|
-
} else if (hostPlatform() === "win32") {
|
|
249
|
-
spawnDetached(["cmd.exe", "/d", "/s", "/c", "start", "", absolutePath])
|
|
250
|
-
} else {
|
|
251
|
-
spawnDetached([application, absolutePath])
|
|
252
|
-
}
|
|
253
|
-
}
|