@hraness/slopcamera 3.2.7 → 3.3.1
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 +65 -20
- package/apps/desktop/README.md +14 -130
- package/apps/desktop/application/context.ts +6 -9
- package/apps/desktop/application/default-registry.ts +26 -10
- package/apps/desktop/application/operation.ts +14 -5
- package/apps/desktop/application/operations/index.ts +4 -1
- package/apps/desktop/application/operations/spatial-behavior.ts +151 -0
- package/apps/desktop/application/operations/spatial-direction.ts +222 -0
- package/apps/desktop/application/operations/spatial-rendered-audit.ts +174 -0
- package/apps/desktop/application/operations/spatial-review.ts +194 -0
- package/apps/desktop/application/operations/spatial-scene.ts +25 -1
- package/apps/desktop/application/registry.ts +2 -2
- package/apps/desktop/application/spatial-asset-admission.ts +201 -0
- package/apps/desktop/application/spatial-assets.ts +160 -31
- package/apps/desktop/application/spatial-render.ts +217 -20
- package/apps/desktop/application/spatial-rendered-audit.ts +273 -0
- package/apps/desktop/application/spatial-review.ts +361 -0
- package/apps/desktop/application/spatial-spz.ts +48 -3
- package/apps/desktop/application/spatial-world-import.ts +26 -5
- package/apps/desktop/application/spatial-world-metadata.ts +105 -0
- package/apps/desktop/cli/args.ts +528 -97
- package/apps/desktop/cli/capability-manifest.ts +374 -0
- package/apps/desktop/cli/cinema-renderer.ts +608 -0
- package/apps/desktop/cli/command-host-resources.ts +31 -2
- package/apps/desktop/cli/commands.ts +1215 -70
- package/apps/desktop/cli/gateway-review-provider.ts +334 -0
- package/apps/desktop/cli/help.ts +183 -23
- package/apps/desktop/cli/html-scene.ts +139 -28
- package/apps/desktop/cli/io.ts +2 -1
- package/apps/desktop/cli/main.ts +26 -50
- 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 +18 -5
- package/apps/desktop/cli/spatial-asset-service.ts +124 -0
- package/apps/desktop/cli/spatial-design-service.ts +237 -0
- package/apps/desktop/cli/spatial-generate-service.ts +370 -0
- package/apps/desktop/cli/spatial-scene-service.ts +268 -4
- package/apps/desktop/cli/workflow-code.ts +1 -1
- 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 +24 -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/contracts/cinema.ts +736 -0
- package/apps/desktop/contracts/index.ts +1 -0
- package/apps/desktop/contracts/spatial-asset.ts +16 -0
- package/apps/desktop/contracts/spatial-world.ts +26 -3
- package/apps/desktop/core/cinema-plan.ts +1320 -0
- package/apps/desktop/core/index.ts +1 -0
- package/apps/desktop/core/music-analysis.ts +124 -1
- package/apps/desktop/core/storage.ts +75 -0
- package/apps/desktop/dist/cli/main.js +737 -291
- 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/apps/desktop/html-overlay/spatial.ts +619 -57
- package/apps/desktop/workflows/cinematic-world.ts +127 -0
- package/apps/desktop/workflows/index.ts +6 -0
- package/dist/cli.js +32 -434
- package/dist/code/advanced.js +1 -269
- package/dist/code/index.js +16 -2239
- package/dist/generate.js +1 -23
- package/dist/host-resources.js +1 -25
- package/dist/index-0bbesn4m.js +35 -0
- package/dist/index-296qhpf2.js +3 -0
- package/dist/index-3cxf2c58.js +3 -0
- package/dist/index-77fjfg9f.js +3 -0
- package/dist/index-80a36bc0.js +3 -0
- package/dist/index-a3vvs3rf.js +3 -0
- package/dist/index-b3geqczn.js +5 -0
- package/dist/index-cgpkyjqa.js +3 -0
- package/dist/index-f0ptv8dm.js +7 -0
- package/dist/index-grk47tgs.js +3 -0
- package/dist/index-qry58nj2.js +10 -0
- package/dist/index.js +1 -240
- package/dist/operations.js +1 -28
- package/dist/skill-install-gx7afxsd.js +2 -0
- package/dist/vectorize/worker.js +1 -141
- package/dist/workflow.js +1 -15
- package/docs/README.md +5 -1
- package/docs/studio.md +1 -1
- package/package.json +11 -24
- package/skills/slopcamera/SKILL.md +14 -1
- package/skills/slopcamera/references/diagrams.md +5 -14
- package/skills/slopcamera/references/directed-scenes.md +22 -2
- package/skills/slopcamera/references/gateway-media.md +15 -1
- package/skills/slopcamera/references/image-galleries.md +166 -0
- package/skills/slopcamera/references/install.md +2 -2
- package/skills/slopcamera/references/music-video.md +23 -3
- package/skills/slopcamera/references/parametric-design.md +14 -0
- package/skills/slopcamera/references/reference-led-3d.md +1 -1
- package/skills/slopcamera/references/scene-building.md +32 -0
- package/skills/slopcamera/references/social-collage-banners.md +204 -0
- package/skills/slopcamera/references/support.md +25 -0
- package/skills/slopcamera/references/web-media-excerpts.md +120 -0
- package/skills/slopcamera/references/workflows-sdk.md +3 -3
- package/skills/slopcamera/scripts/compose-social-collage-banner.ts +728 -0
- package/src/capability-manifest.ts +361 -0
- package/src/cli.ts +250 -102
- package/src/code/canonical-json.ts +9 -0
- package/src/generate.ts +2 -2
- package/src/icon.ts +1111 -0
- package/src/image-gallery.ts +1049 -0
- package/src/index.ts +11 -23
- package/src/mcp/boundary.ts +11 -11
- package/src/mcp/index.ts +3 -0
- package/src/mcp/server.ts +2 -1
- package/src/mcp/tools.ts +1642 -130
- package/src/mcp/types.ts +19 -0
- package/src/operations.ts +412 -0
- package/src/portable-capability-manifest.ts +67 -0
- package/src/scene-gallery.ts +184 -0
- package/src/spatial-scene/asset-admission.ts +183 -0
- package/src/spatial-scene/audit-rendered.ts +692 -0
- package/src/spatial-scene/audit.ts +617 -0
- package/src/spatial-scene/behavior-audit.ts +252 -0
- package/src/spatial-scene/behavior-bake.ts +233 -0
- package/src/spatial-scene/behavior-fns.ts +585 -0
- package/src/spatial-scene/behavior-gallery.ts +109 -0
- package/src/spatial-scene/behavior-stdlib.ts +323 -0
- package/src/spatial-scene/behavior-trace.ts +325 -0
- package/src/spatial-scene/behavior.ts +618 -0
- package/src/spatial-scene/build.ts +632 -0
- package/src/spatial-scene/camera-rig.ts +125 -0
- package/src/spatial-scene/camera-track.ts +4 -2
- package/src/spatial-scene/character.ts +124 -0
- package/src/spatial-scene/contracts.ts +75 -7
- package/src/spatial-scene/design-templates.ts +351 -0
- package/src/spatial-scene/design.ts +327 -0
- package/src/spatial-scene/direction-compile.ts +584 -0
- package/src/spatial-scene/direction.ts +122 -0
- package/src/spatial-scene/effects.ts +149 -0
- package/src/spatial-scene/evaluate.ts +109 -29
- package/src/spatial-scene/gallery.ts +277 -0
- package/src/spatial-scene/generate.ts +239 -0
- package/src/spatial-scene/geometry-native.ts +165 -0
- package/src/spatial-scene/geometry.ts +1216 -0
- package/src/spatial-scene/gltf.ts +600 -77
- package/src/spatial-scene/identity.ts +55 -2
- package/src/spatial-scene/index.ts +36 -0
- package/src/spatial-scene/inspect.ts +35 -6
- package/src/spatial-scene/material-lighting.ts +609 -0
- package/src/spatial-scene/math.ts +21 -4
- package/src/spatial-scene/motion-evidence.ts +88 -0
- package/src/spatial-scene/parametric.ts +765 -0
- package/src/spatial-scene/particle-preparation.ts +183 -0
- package/src/spatial-scene/particle.ts +195 -0
- package/src/spatial-scene/patch.ts +109 -15
- package/src/spatial-scene/performance.ts +1613 -0
- package/src/spatial-scene/probe.ts +137 -0
- package/src/spatial-scene/recipe-pack.ts +86 -0
- package/src/spatial-scene/render-effects.ts +240 -0
- package/src/spatial-scene/review.ts +639 -0
- package/src/spatial-scene/simulation-bake.ts +206 -0
- package/src/spatial-scene/simulation.ts +187 -0
- package/src/spatial-scene/solve.ts +366 -0
- package/src/spatial-scene/temporal-audit.ts +354 -0
- 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/dist/index-42zsesc1.js +0 -2257
- package/dist/index-7308egqr.js +0 -48
- package/dist/index-8txs6fkn.js +0 -712
- package/dist/index-mcy8z0br.js +0 -192
- package/dist/index-p63wavx0.js +0 -2029
- package/dist/index-r7gdhmsp.js +0 -424
- package/dist/index-rvghzt7b.js +0 -2013
- package/dist/index-sh6xbav6.js +0 -1219
- package/dist/index-z1w83f81.js +0 -4
- package/dist/index-z7239b4h.js +0 -2363
- package/dist/skill-install-dh0ntqba.js +0 -10
- package/src/desktop.ts +0 -253
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { createBoundedJsonSnapshot } from "../../../src/code/json-snapshot";
|
|
2
|
+
import {
|
|
3
|
+
SPATIAL_REVIEW_LIMITS,
|
|
4
|
+
SPATIAL_REVIEW_PROMPT,
|
|
5
|
+
SpatialReviewModelOutputSchema,
|
|
6
|
+
SpatialReviewProviderError,
|
|
7
|
+
redactedSpatialReviewProviderError,
|
|
8
|
+
validateSpatialReviewProviderRequest,
|
|
9
|
+
type SpatialReviewModelOutput,
|
|
10
|
+
type SpatialReviewProvider,
|
|
11
|
+
type SpatialReviewProviderResult,
|
|
12
|
+
type ValidatedSpatialReviewProviderRequest,
|
|
13
|
+
} from "../../../src/spatial-scene/review";
|
|
14
|
+
|
|
15
|
+
import { canonicalJson } from "../core/canonical-json";
|
|
16
|
+
import type { ActiveGatewayCredential } from "./gateway-credential";
|
|
17
|
+
import type { GatewayMediaCatalogTransport } from "./gateway-media-catalog";
|
|
18
|
+
import {
|
|
19
|
+
createFixedSceneGatewayFetch,
|
|
20
|
+
sceneFrameDataUrl,
|
|
21
|
+
VERCEL_SCENE_GATEWAY_BASE_URL,
|
|
22
|
+
type SceneAiSdkLoader,
|
|
23
|
+
type SceneAiSdkModule,
|
|
24
|
+
} from "./gateway-scene-provider";
|
|
25
|
+
|
|
26
|
+
const MAXIMUM_CATALOG_BYTES = 8 * 1024 * 1024;
|
|
27
|
+
const CATALOG_MODEL_LIMIT = 1_000;
|
|
28
|
+
const DEFAULT_REVIEW_GATEWAY_TIMEOUT_MS = 120_000;
|
|
29
|
+
const GOOGLE_GEMINI_MODEL = /^google\/gemini-[a-z0-9][a-z0-9._-]{0,239}$/u;
|
|
30
|
+
|
|
31
|
+
type GatewayFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
32
|
+
|
|
33
|
+
interface AiSdkResult {
|
|
34
|
+
readonly output?: unknown;
|
|
35
|
+
readonly response?: unknown;
|
|
36
|
+
readonly usage?: unknown;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function loadAiSdk(): Promise<SceneAiSdkModule> {
|
|
40
|
+
const [gatewayValue, aiValue]: readonly unknown[] = await Promise.all([
|
|
41
|
+
import("@ai-sdk/gateway-v4"),
|
|
42
|
+
import("ai-v7"),
|
|
43
|
+
]);
|
|
44
|
+
if (
|
|
45
|
+
typeof gatewayValue !== "object"
|
|
46
|
+
|| gatewayValue === null
|
|
47
|
+
|| !("createGateway" in gatewayValue)
|
|
48
|
+
|| typeof gatewayValue.createGateway !== "function"
|
|
49
|
+
|| typeof aiValue !== "object"
|
|
50
|
+
|| aiValue === null
|
|
51
|
+
|| !("generateText" in aiValue)
|
|
52
|
+
|| typeof aiValue.generateText !== "function"
|
|
53
|
+
|| !("Output" in aiValue)
|
|
54
|
+
|| typeof aiValue.Output !== "object"
|
|
55
|
+
|| aiValue.Output === null
|
|
56
|
+
|| !("object" in aiValue.Output)
|
|
57
|
+
|| typeof aiValue.Output.object !== "function"
|
|
58
|
+
) {
|
|
59
|
+
throw new Error("The AI SDK review provider is unavailable.");
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
Output: aiValue.Output as SceneAiSdkModule["Output"],
|
|
63
|
+
createGateway: gatewayValue.createGateway as SceneAiSdkModule["createGateway"],
|
|
64
|
+
generateText: aiValue.generateText as SceneAiSdkModule["generateText"],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
69
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function boundedModelId(value: unknown): string | null {
|
|
73
|
+
return typeof value === "string"
|
|
74
|
+
&& value.length >= 1
|
|
75
|
+
&& value.length <= SPATIAL_REVIEW_LIMITS.modelIdChars
|
|
76
|
+
&& value.includes("/")
|
|
77
|
+
&& !/\s/u.test(value)
|
|
78
|
+
&& !value.startsWith("/")
|
|
79
|
+
&& !value.endsWith("/")
|
|
80
|
+
&& ![...value].some(character => {
|
|
81
|
+
const code = character.codePointAt(0) ?? 0;
|
|
82
|
+
return code <= 31 || code === 127;
|
|
83
|
+
})
|
|
84
|
+
? value
|
|
85
|
+
: null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function modalityList(value: unknown): readonly string[] {
|
|
89
|
+
return Array.isArray(value)
|
|
90
|
+
? value.filter((item): item is string => typeof item === "string")
|
|
91
|
+
: [];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface SpatialReviewModelSelection {
|
|
95
|
+
readonly catalogSha256: string;
|
|
96
|
+
readonly modelId: string;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Scans the fresh raw catalog payload for vision-capable language models:
|
|
101
|
+
* `type: "language"` rows whose input modalities include "image" and output
|
|
102
|
+
* modalities include "text". The media catalog projection drops pure language
|
|
103
|
+
* models, so review validates the untransformed document. Selection is
|
|
104
|
+
* deterministic: google/gemini-* ids first, then lexicographic order.
|
|
105
|
+
*/
|
|
106
|
+
export function selectSpatialReviewModel(payload: unknown): SpatialReviewModelSelection {
|
|
107
|
+
const snapshot = createBoundedJsonSnapshot(payload, MAXIMUM_CATALOG_BYTES, "Gateway model catalog", {
|
|
108
|
+
maximumDepth: 16, maximumValues: 200_000,
|
|
109
|
+
});
|
|
110
|
+
if (snapshot.sha256 === undefined) {
|
|
111
|
+
throw new SpatialReviewProviderError("gateway-unavailable");
|
|
112
|
+
}
|
|
113
|
+
const value = snapshot.value;
|
|
114
|
+
if (!isRecord(value) || !Array.isArray(value.data) || value.data.length > CATALOG_MODEL_LIMIT) {
|
|
115
|
+
throw new SpatialReviewProviderError("gateway-unavailable");
|
|
116
|
+
}
|
|
117
|
+
const candidates: string[] = [];
|
|
118
|
+
for (const row of value.data) {
|
|
119
|
+
if (!isRecord(row) || row.type !== "language") continue;
|
|
120
|
+
const modalities = isRecord(row.modalities) ? row.modalities : {};
|
|
121
|
+
const input = modalityList(modalities.input);
|
|
122
|
+
const output = modalityList(modalities.output);
|
|
123
|
+
if (!input.includes("image") || !output.includes("text")) continue;
|
|
124
|
+
const id = boundedModelId(row.id);
|
|
125
|
+
if (id === null) continue;
|
|
126
|
+
candidates.push(id);
|
|
127
|
+
}
|
|
128
|
+
if (candidates.length === 0) throw new SpatialReviewProviderError("model-unavailable");
|
|
129
|
+
candidates.sort((left, right) => left.localeCompare(right));
|
|
130
|
+
const preferred = candidates.filter(id => GOOGLE_GEMINI_MODEL.test(id));
|
|
131
|
+
return { catalogSha256: snapshot.sha256, modelId: (preferred[0] ?? candidates[0])! };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function userMessage(request: ValidatedSpatialReviewProviderRequest): Readonly<Record<string, unknown>> {
|
|
135
|
+
const content: Readonly<Record<string, unknown>>[] = [{
|
|
136
|
+
text: [
|
|
137
|
+
`Review ${request.frames.length} rendered beauty frame(s) for spatial scene ${request.scene.sceneId}.`,
|
|
138
|
+
`Scene sha256=${request.scene.sceneSha256}; camera ${request.scene.cameraId}; duration ${request.scene.durationUs} microseconds.`,
|
|
139
|
+
`Sampled times (microseconds): ${request.scene.timesUs.join(", ")}.`,
|
|
140
|
+
request.scene.entities.length === 0
|
|
141
|
+
? "The scene declares no entities."
|
|
142
|
+
: `Declared entity catalog for attribution: ${canonicalJson(request.scene.entities)}.`,
|
|
143
|
+
"Attribute a finding to entityId only when it exactly matches one declared identifier.",
|
|
144
|
+
].join(" "),
|
|
145
|
+
type: "text",
|
|
146
|
+
}];
|
|
147
|
+
for (const frame of request.frames) {
|
|
148
|
+
content.push({ text: `frameIndex ${frame.index} at ${frame.timeUs} microseconds follows.`, type: "text" });
|
|
149
|
+
content.push({
|
|
150
|
+
image: sceneFrameDataUrl("image/png", frame.bytes),
|
|
151
|
+
mediaType: "image/png",
|
|
152
|
+
type: "image",
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return { content, role: "user" };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function record(value: unknown): Readonly<Record<string, unknown>> | null {
|
|
159
|
+
return isRecord(value) ? value : null;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function tokenCount(value: unknown, key: "inputTokens" | "outputTokens"): number {
|
|
163
|
+
const selected = record(value)?.[key];
|
|
164
|
+
return Number.isSafeInteger(selected) && (selected as number) >= 0
|
|
165
|
+
&& (selected as number) <= SPATIAL_REVIEW_LIMITS.tokenCount
|
|
166
|
+
? selected as number
|
|
167
|
+
: 0;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function resolvedModel(value: unknown): string | null {
|
|
171
|
+
const modelId = record(value)?.modelId;
|
|
172
|
+
return boundedModelId(modelId) ?? (typeof modelId === "string" && modelId.length >= 1 && modelId.length <= SPATIAL_REVIEW_LIMITS.modelIdChars ? modelId : null);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function providerResponseId(value: unknown): string | undefined {
|
|
176
|
+
const id = record(value)?.id;
|
|
177
|
+
return typeof id === "string" && id.length >= 1 && id.length <= SPATIAL_REVIEW_LIMITS.providerResponseIdChars
|
|
178
|
+
&& ![...id].some(character => (character.codePointAt(0) ?? 0) <= 31)
|
|
179
|
+
? id
|
|
180
|
+
: undefined;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function parseReviewProviderOutput(value: unknown): SpatialReviewModelOutput {
|
|
184
|
+
const parsed = SpatialReviewModelOutputSchema.safeParse(value);
|
|
185
|
+
if (!parsed.success) throw new SpatialReviewProviderError("invalid-response");
|
|
186
|
+
return parsed.data;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export interface GatewaySpatialReviewProviderOptions {
|
|
190
|
+
/** Lazy credential load: reads the environment only inside the dispatch. */
|
|
191
|
+
readonly credential: () => ActiveGatewayCredential;
|
|
192
|
+
readonly fetch?: GatewayFetch;
|
|
193
|
+
readonly loadAiSdk?: SceneAiSdkLoader;
|
|
194
|
+
readonly timeoutMs?: number;
|
|
195
|
+
/** Fresh catalog transport; the review dispatch performs one refresh. */
|
|
196
|
+
readonly transport: GatewayMediaCatalogTransport;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function boundedTimeout(value: number | undefined): number {
|
|
200
|
+
const timeoutMs = value ?? DEFAULT_REVIEW_GATEWAY_TIMEOUT_MS;
|
|
201
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 300_000) {
|
|
202
|
+
throw new SpatialReviewProviderError("invalid-request");
|
|
203
|
+
}
|
|
204
|
+
return timeoutMs;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function disableAiSdkWarningLogging(): void {
|
|
208
|
+
(
|
|
209
|
+
globalThis as typeof globalThis & {
|
|
210
|
+
AI_SDK_LOG_WARNINGS?: false;
|
|
211
|
+
}
|
|
212
|
+
).AI_SDK_LOG_WARNINGS = false;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function assertReviewDispatchActive(signal: AbortSignal): void {
|
|
216
|
+
if (signal.aborted) throw new SpatialReviewProviderError("aborted");
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* One consent-gated critique call against the fixed Gateway origin. The
|
|
221
|
+
* credential is loaded lazily after the fresh catalog proves a vision-capable
|
|
222
|
+
* language model; `maxRetries` is pinned to zero and an ambiguous dispatch is
|
|
223
|
+
* never resubmitted.
|
|
224
|
+
*/
|
|
225
|
+
export function createGatewaySpatialReviewProvider(
|
|
226
|
+
options: GatewaySpatialReviewProviderOptions,
|
|
227
|
+
): SpatialReviewProvider {
|
|
228
|
+
const loader = options.loadAiSdk ?? loadAiSdk;
|
|
229
|
+
const gatewayFetch = createFixedSceneGatewayFetch(options.fetch ?? globalThis.fetch);
|
|
230
|
+
const timeoutMs = boundedTimeout(options.timeoutMs);
|
|
231
|
+
return {
|
|
232
|
+
critique: async (requestInput, signal): Promise<SpatialReviewProviderResult> => {
|
|
233
|
+
const request = validateSpatialReviewProviderRequest(requestInput);
|
|
234
|
+
let dispatched = false;
|
|
235
|
+
let timedOut = false;
|
|
236
|
+
const controller = new AbortController();
|
|
237
|
+
const abortFromCaller = (): void => controller.abort(signal?.reason);
|
|
238
|
+
signal?.addEventListener("abort", abortFromCaller, { once: true });
|
|
239
|
+
if (signal?.aborted === true) {
|
|
240
|
+
signal?.removeEventListener("abort", abortFromCaller);
|
|
241
|
+
throw new SpatialReviewProviderError("aborted");
|
|
242
|
+
}
|
|
243
|
+
const timer = setTimeout(() => {
|
|
244
|
+
timedOut = true;
|
|
245
|
+
controller.abort();
|
|
246
|
+
}, timeoutMs);
|
|
247
|
+
const interrupted = new Promise<never>((_resolve, reject) => {
|
|
248
|
+
const rejectInterrupted = (): void => reject(
|
|
249
|
+
dispatched
|
|
250
|
+
? new SpatialReviewProviderError(
|
|
251
|
+
timedOut ? "gateway-outcome-unknown" : "aborted",
|
|
252
|
+
"ambiguous",
|
|
253
|
+
)
|
|
254
|
+
: new SpatialReviewProviderError(
|
|
255
|
+
timedOut ? "gateway-unavailable" : "aborted",
|
|
256
|
+
),
|
|
257
|
+
);
|
|
258
|
+
controller.signal.addEventListener("abort", rejectInterrupted, { once: true });
|
|
259
|
+
if (controller.signal.aborted) rejectInterrupted();
|
|
260
|
+
});
|
|
261
|
+
try {
|
|
262
|
+
const operation = (async (): Promise<SpatialReviewProviderResult> => {
|
|
263
|
+
const refresh = await options.transport.refresh(undefined, controller.signal);
|
|
264
|
+
assertReviewDispatchActive(controller.signal);
|
|
265
|
+
if (refresh.status !== "modified") {
|
|
266
|
+
throw new SpatialReviewProviderError("gateway-unavailable");
|
|
267
|
+
}
|
|
268
|
+
const selection = selectSpatialReviewModel(refresh.payload);
|
|
269
|
+
disableAiSdkWarningLogging();
|
|
270
|
+
const ai = await loader();
|
|
271
|
+
assertReviewDispatchActive(controller.signal);
|
|
272
|
+
let credential: ActiveGatewayCredential;
|
|
273
|
+
try {
|
|
274
|
+
credential = options.credential();
|
|
275
|
+
} catch {
|
|
276
|
+
throw new SpatialReviewProviderError("credential-missing");
|
|
277
|
+
}
|
|
278
|
+
return await credential.withApiKey(async (apiKey) => {
|
|
279
|
+
assertReviewDispatchActive(controller.signal);
|
|
280
|
+
const gateway = ai.createGateway({
|
|
281
|
+
apiKey,
|
|
282
|
+
baseURL: VERCEL_SCENE_GATEWAY_BASE_URL,
|
|
283
|
+
fetch: gatewayFetch,
|
|
284
|
+
});
|
|
285
|
+
const output = ai.Output.object({
|
|
286
|
+
description: "Bounded advisory beauty-pass findings for one spatial scene review.",
|
|
287
|
+
name: "slopcamera_spatial_review",
|
|
288
|
+
schema: SpatialReviewModelOutputSchema,
|
|
289
|
+
});
|
|
290
|
+
assertReviewDispatchActive(controller.signal);
|
|
291
|
+
dispatched = true;
|
|
292
|
+
const result: AiSdkResult = await ai.generateText({
|
|
293
|
+
abortSignal: controller.signal,
|
|
294
|
+
maxOutputTokens: SPATIAL_REVIEW_LIMITS.responseTokens,
|
|
295
|
+
maxRetries: 0,
|
|
296
|
+
messages: [userMessage(request)],
|
|
297
|
+
model: gateway.languageModel(selection.modelId),
|
|
298
|
+
output,
|
|
299
|
+
providerOptions: {
|
|
300
|
+
gateway: {
|
|
301
|
+
disallowPromptTraining: true,
|
|
302
|
+
tags: ["slopcamera", "scene-review", "v1"],
|
|
303
|
+
zeroDataRetention: true,
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
system: SPATIAL_REVIEW_PROMPT,
|
|
307
|
+
temperature: 0,
|
|
308
|
+
});
|
|
309
|
+
const responseId = providerResponseId(result.response);
|
|
310
|
+
return {
|
|
311
|
+
model: {
|
|
312
|
+
catalogSha256: selection.catalogSha256,
|
|
313
|
+
requestedModel: selection.modelId,
|
|
314
|
+
resolvedModel: resolvedModel(result.response),
|
|
315
|
+
...(responseId === undefined ? {} : { providerResponseId: responseId }),
|
|
316
|
+
},
|
|
317
|
+
output: parseReviewProviderOutput(result.output),
|
|
318
|
+
usage: {
|
|
319
|
+
inputTokens: tokenCount(result.usage, "inputTokens"),
|
|
320
|
+
outputTokens: tokenCount(result.usage, "outputTokens"),
|
|
321
|
+
},
|
|
322
|
+
};
|
|
323
|
+
});
|
|
324
|
+
})();
|
|
325
|
+
return await Promise.race([operation, interrupted]);
|
|
326
|
+
} catch (error) {
|
|
327
|
+
throw redactedSpatialReviewProviderError(error, dispatched);
|
|
328
|
+
} finally {
|
|
329
|
+
clearTimeout(timer);
|
|
330
|
+
signal?.removeEventListener("abort", abortFromCaller);
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
}
|
package/apps/desktop/cli/help.ts
CHANGED
|
@@ -8,26 +8,33 @@ const GLOBAL_HELP = `slopcamera — creative scenes and non-destructive media ed
|
|
|
8
8
|
Usage: slopcamera <command> [options]
|
|
9
9
|
|
|
10
10
|
Commands:
|
|
11
|
+
capabilities Discover the exact static capability modules and qualification status
|
|
11
12
|
operations list|show Discover host-owned typed operations and policies
|
|
12
13
|
diagram init|check|render Create, validate, or render portable diagram sources
|
|
13
|
-
scene init|check|inspect|patch|evaluate|camera-track|plan|render
|
|
14
|
+
scene init|check|inspect|diff|patch|evaluate|audit|render-audit|solve|review|camera-track|generate|plan|render|direction|effects|behavior|temporal-audit
|
|
14
15
|
Author and inspect editable directed 3D scene sources
|
|
16
|
+
scene design catalog|init|inspect|set|compile|gallery
|
|
17
|
+
Build and revise geometry from named parameters and constraints
|
|
15
18
|
direct init|plan|start|generate|review|assemble
|
|
16
19
|
Direct short Gateway clips with retained takes and budgets
|
|
17
20
|
studio init|bundle|plan|probe|run|encode|asset|assemble|inspect|reconcile
|
|
18
21
|
Author and render retained Blender, CAD and Manim productions
|
|
19
|
-
image vectorize|generate
|
|
22
|
+
image vectorize|generate|gallery|icon
|
|
23
|
+
Create local SVGs, generated images, or review galleries
|
|
20
24
|
html catalog|scaffold|render Author HTML scenes and export video with local audio
|
|
21
25
|
workflows list|show|plan|run Plan or run a reviewed reusable workflow
|
|
22
26
|
code init|check|plan|run Author, preflight, and run trusted TypeScript workflows
|
|
23
27
|
runs list|show|resume|approve|cancel
|
|
24
28
|
Inspect and control durable workflow runs
|
|
25
|
-
doctor Check local
|
|
29
|
+
doctor Check local render and asset capabilities
|
|
26
30
|
ai models|image|video|speech|transcribe
|
|
27
31
|
Discover and run Vercel AI Gateway media models
|
|
28
32
|
media audio|color Apply local non-destructive audio and video effects
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
menubar [--background] Run the prebuilt menu-bar companion
|
|
34
|
+
menubar install|uninstall|status Manage its per-user LaunchAgent
|
|
35
|
+
support [--json|protocol --json|offer --json|shown <id>|release <id>|dismiss|snooze|enable|status --json]
|
|
36
|
+
Optional support; no feature requires payment
|
|
37
|
+
outputs Print the agent outputs directory
|
|
31
38
|
recordings list List recording bundles
|
|
32
39
|
projects list|create List projects or create one from a recording
|
|
33
40
|
project inspect|add|edit|render
|
|
@@ -43,9 +50,16 @@ Commands:
|
|
|
43
50
|
render plan|run <recording> Resolve or execute a render plan
|
|
44
51
|
assets emoji search|resolve Find checked local emoji overlays
|
|
45
52
|
|
|
53
|
+
Agents: after useful work, read slopcamera support protocol --json for the optional
|
|
54
|
+
closeout protocol. Discovery uses stderr; it does not claim an invitation.
|
|
55
|
+
HRANESS_SUPPORT_AUDIENCE=off suppresses offers and incidental discovery.
|
|
56
|
+
|
|
46
57
|
Run slopcamera help <command> for command-specific help.`;
|
|
47
58
|
|
|
48
59
|
const HELP: Readonly<Record<string, string>> = {
|
|
60
|
+
capabilities: `Usage: slopcamera capabilities [--json]
|
|
61
|
+
|
|
62
|
+
Print the exact statically assembled capability manifest for this CLI build. Each module owns named operation, workflow, MCP-tool, command, and runtime-profile identities. The manifest includes trust classes, resource/effect policies, runtime requirements, qualification status, and a canonical SHA-256. It reads no workspace source, loads no plugin, probes no runtime, and grants no authority. Use doctor separately to inspect this machine's currently available executables.`,
|
|
49
63
|
studio: `Usage:
|
|
50
64
|
slopcamera studio init <new-directory> [--template blender-product|blender-character|blender-shaded-street|blender-cloth|blender-fluid|cadquery-bracket|manim-lesson] [--json]
|
|
51
65
|
slopcamera studio bundle <source.json> [--source-root <directory>] [--json]
|
|
@@ -112,27 +126,120 @@ project for slopcamera project render run. Review and assembly work without clou
|
|
|
112
126
|
This workflow retains image and prompt continuity; it has no provider neural checkpoint
|
|
113
127
|
or real-time session. Use slopcamera ai models list --type video for live model discovery.`,
|
|
114
128
|
scene: `Usage:
|
|
129
|
+
slopcamera scene design catalog [--json]
|
|
130
|
+
slopcamera scene design init <directory> --template <id> [--json]
|
|
131
|
+
slopcamera scene design inspect <design.json> [--json]
|
|
132
|
+
slopcamera scene design set <design.json> --parameters <values.json> --output <new-design.json> [--json]
|
|
133
|
+
slopcamera scene design compile <design.json> [--scene <base.scene.json>] --output-dir <new-directory> [--json]
|
|
134
|
+
slopcamera scene design gallery <design.json> --variants <variants.json> [--scene <base.scene.json>] --output-dir <new-directory> [--json]
|
|
115
135
|
slopcamera scene init <scene.json> [--json]
|
|
116
136
|
slopcamera scene check <scene.json> [--json]
|
|
117
137
|
slopcamera scene inspect <scene.json> [--json]
|
|
118
138
|
slopcamera scene patch <scene.json> --patch <patch.json> --output <new-scene.json> [--json]
|
|
119
139
|
slopcamera scene evaluate <scene.json> --camera <camera-id> --time-us <integer> [--json]
|
|
140
|
+
slopcamera scene audit <scene.json> --camera <camera-id> [--times-us <csv>] [--asset-bounds <bounds-or-admission.json>] [--json]
|
|
141
|
+
slopcamera scene render-audit <scene.json> --camera <camera-id> [--times-us <csv>] [--json]
|
|
142
|
+
slopcamera scene solve <scene.json> --goals <goals.json> [--output <patch.json>] [--asset-bounds <bounds-or-admission.json>] [--json]
|
|
143
|
+
slopcamera scene review <scene.json> --camera <camera-id> [--times-us <csv>] --allow-cloud-upload [--json]
|
|
120
144
|
slopcamera scene camera-track <scene.json> --request <sampling.json> --output <new-track.json> [--json]
|
|
145
|
+
slopcamera scene generate --module <generator.ts> --generator-id <id>
|
|
146
|
+
[--parameters <params.json>] [--seed <n>] [--into <scene.json>] --output <new-scene.json> [--json]
|
|
121
147
|
slopcamera scene plan|render <scene.json> --request <request.json> [--assets <bindings.json>] [--profile <profile>] [--json]
|
|
148
|
+
slopcamera scene direction check <direction.json> --scene <scene.json> [--json]
|
|
149
|
+
slopcamera scene direction plan <direction.json> --scene <scene.json> [--camera <camera-id>] [--output <out.json>] [--json]
|
|
150
|
+
slopcamera scene direction gallery <direction.json> --scene <scene.json> --axis <axis> [--camera <camera-id>] [--output <out.json>] [--json]
|
|
151
|
+
slopcamera scene effects check <effects.json> --scene <scene.json> [--json]
|
|
152
|
+
slopcamera scene effects plan <draft.json> --scene <scene.json> [--output <effects.json>] [--json]
|
|
153
|
+
slopcamera scene effects bake <plan.json> --scene <scene.json> --output <bake.json> [--json]
|
|
154
|
+
slopcamera scene behavior check <behavior.json> --scene <scene.json> [--json]
|
|
155
|
+
slopcamera scene behavior bake <behavior.json> --scene <scene.json> [--channel-map <map.json>] --output <bake.json> [--json]
|
|
156
|
+
slopcamera scene behavior gallery <behavior.json> --scene <scene.json> [--channel-map <map.json>] [--output <gallery.json>] [--json]
|
|
157
|
+
slopcamera scene behavior audit <bake.json> [--output <audit.json>] [--json]
|
|
158
|
+
slopcamera scene temporal-audit <scene.json> --camera <camera-id> [--times-us <csv>] [--contacts <contacts.json>] [--cut-before-us <csv>] [--json]
|
|
122
159
|
slopcamera scene project snapshot <project-id> [--json]
|
|
123
160
|
slopcamera scene project prepare-render <project-id> --input <request.json> --output <prepared-render.json> [--profile <profile>] [--json]
|
|
124
161
|
slopcamera scene project migrate|patch|restore|add-shot|add-candidate|select-candidate|reconcile
|
|
125
162
|
<project-id> --input <request.json> [--json]
|
|
126
163
|
slopcamera scene world import --input <import.json> --source-root <directory>
|
|
127
164
|
--output-root <directory-below-artifacts/slopcamera/generated> [--json]
|
|
165
|
+
slopcamera scene asset admit <model.glb> --output <manifest.json>
|
|
166
|
+
[--source-root <directory>] [--asset-id <id>]
|
|
167
|
+
[--meters-per-unit <n>] [--source-up x|y|z] [--json]
|
|
168
|
+
|
|
169
|
+
Designs retain named numeric controls, derived values, dimensional constraints and
|
|
170
|
+
geometry stages. Inspect resolves dependencies and checks budgets without creating
|
|
171
|
+
meshes. Set applies a bounded JSON object of parameter values as a new revision.
|
|
172
|
+
Compile creates a new directory containing design.json, scene.json, exact GLB/facts
|
|
173
|
+
payloads, a compilation receipt and render.json when a camera is available. Pass
|
|
174
|
+
the starter's base.scene.json to retain its cameras and lighting. Gallery compiles
|
|
175
|
+
one to six labelled parameter variants into independent bundles; it does not render.
|
|
176
|
+
Render each bundle through scene render <bundle/scene.json> --request <bundle/render.json>.
|
|
177
|
+
Compilation is local and executes no authored code. Existing output paths conflict;
|
|
178
|
+
interrupted bundles remain without a completion receipt. Use scene design catalog
|
|
179
|
+
for the current architectural starters and docs/parametric-design.md for the contract.
|
|
128
180
|
|
|
129
181
|
Hardware profiles: three-webgl2-hardware-v1 and three-spark-webgl2-hardware-v1.
|
|
130
182
|
An explicit profile must agree with the request; omitting it preserves the request.
|
|
131
183
|
Saved-world import works offline and preserves imported provenance receipts.
|
|
184
|
+
Asset admit copies one local GLB into content-addressed storage beside --output,
|
|
185
|
+
derives bounds and a mesh entity, and emits manifests plus ready-to-apply patch
|
|
186
|
+
operations without overwriting existing paths.
|
|
132
187
|
Scene sources retain stable entities, cameras, asset manifests and animation channels.
|
|
133
188
|
Inspect reports editable controls and known bounds without decoding assets. Patch requires
|
|
134
189
|
the exact expected scene digest in its patch document and writes a new source without
|
|
135
190
|
overwriting either revision. Evaluate samples absolute time without launching a renderer.
|
|
191
|
+
Audit samples bounded geometry against one camera over time and reports deterministic
|
|
192
|
+
frustum findings; --asset-bounds supplies scene-space enclosures as a bounds map,
|
|
193
|
+
admission documents, {manifest, facts} pairs, or arrays of those.
|
|
194
|
+
Render-audit renders the real object-ID pass in the bound browser runtime and counts
|
|
195
|
+
per-entity pixels at each sampled time, reporting splats and camera-bound view masks
|
|
196
|
+
honestly as unsupported or non-attributable rather than estimating them.
|
|
197
|
+
Solve turns declarative relation goals (onTopOf, nextTo, facing, align, at, groundSnap)
|
|
198
|
+
into concrete transforms and a ready-to-apply patch document. Goals name scene entities;
|
|
199
|
+
relations may target entities, cameras, or caller-supplied base entries, and goal targets
|
|
200
|
+
see each other's solved transforms in dependency order. The emitted patch carries a
|
|
201
|
+
placeholder expectedSceneSha256 — copy the digest from scene inspect before scene patch.
|
|
202
|
+
Goal entities must be authored, unparented, world-placed, and free of transform
|
|
203
|
+
overrides or transform channels; asset-derived bounds come from --asset-bounds.
|
|
204
|
+
Review renders up to four bounded beauty frames locally, uploads only those exact
|
|
205
|
+
frames to a vision-capable Gateway language model after explicit --allow-cloud-upload,
|
|
206
|
+
and returns a structured advisory report. It makes exactly one Gateway call, records
|
|
207
|
+
frame digests, model and attempt identity, and rubric version, and never modifies or
|
|
208
|
+
auto-applies scene changes. The report is model-generated and unverified.
|
|
209
|
+
Generate runs a trusted TypeScript generator at authoring time, stamps retained
|
|
210
|
+
output with derived entity identity, and records source, closure, parameters, seed and
|
|
211
|
+
runtime digests; it never reruns source during inspect, evaluate or render.
|
|
212
|
+
Direction commands compile an authored direction document into deterministic,
|
|
213
|
+
unverified proposals — performance actions, camera rigs, shots and looks bound to the
|
|
214
|
+
actual scene digest. Check reports stale digests, unresolved references and intervals
|
|
215
|
+
outside scene duration without compiling; plan emits the compilation (optionally to
|
|
216
|
+
--output); gallery compiles a bounded set of single-axis variants as separate
|
|
217
|
+
content-addressed candidates and never selects one. Direction gallery axes:
|
|
218
|
+
performance, camera, lighting, materials, effects, sequence.
|
|
219
|
+
Effects commands assemble and validate slopcamera.spatial-render-effects documents.
|
|
220
|
+
Check verifies scene-digest bindings, entity and asset closure, and nested plan,
|
|
221
|
+
particle and simulation digests before any host work; plan binds the caller's
|
|
222
|
+
renderPlan, particleSystems and simulationBakes draft to the actual scene digest and
|
|
223
|
+
emits a {document, documentSha256} binding; bake executes the bounded reference
|
|
224
|
+
rigid-body integrator for one admitted simulation plan and publishes the canonical
|
|
225
|
+
bake document. Native secondary-motion and hinge constraints remain unqualified.
|
|
226
|
+
Behavior commands admit and execute slopcamera.spatial-behavior documents —
|
|
227
|
+
inert ALGAL organism closures checked under the bake-safe profile (pure
|
|
228
|
+
input/const/fn/repeat/each/organism cells only; effect-bearing cells reject
|
|
229
|
+
before execution). Check reports manifest digests, wiring, entity and channel
|
|
230
|
+
findings; bake runs the entry organism through the pinned ALGAL runtime with
|
|
231
|
+
the closed pure fn catalog and publishes a canonical bake document — emitted
|
|
232
|
+
semantic records, unverified performance directive proposals, and a receipt
|
|
233
|
+
binding closure, scene, seed, run, and catalog digests; gallery bakes the
|
|
234
|
+
document under deterministic seed variants as separate content-addressed
|
|
235
|
+
candidates and never selects one. --channel-map binds emitted channels to
|
|
236
|
+
clip runs and attach/release pairs; unmapped channels surface as unresolved
|
|
237
|
+
intents rather than fabricated bindings.
|
|
238
|
+
Temporal-audit evaluates the scene at bounded sample times under one camera and
|
|
239
|
+
reports deterministic findings: visibility flicker, transform discontinuity,
|
|
240
|
+
foot-slide against declared contact windows, camera acceleration/jerk/angular
|
|
241
|
+
velocity, exposure and focus jumps, and per-sample resource spikes. Without
|
|
242
|
+
--times-us it samples the scene duration at up to 17 evenly spaced times.
|
|
136
243
|
Project operations use the exact full project ID and a versioned whole-project basis.
|
|
137
244
|
Discover each request with slopcamera operations show spatial.project.<action> --json.
|
|
138
245
|
Migration retains the frozen media/edit pair in V2 authority. Legacy project commands
|
|
@@ -154,11 +261,26 @@ operations separately publish equivalent derivatives by content hash for workflo
|
|
|
154
261
|
slopcamera image generate <prompt> --output <file.webp> [--model <model>]
|
|
155
262
|
[--idempotency-key <key>] [--json]
|
|
156
263
|
slopcamera image generate --model <gateway-model> --prompt <prompt>
|
|
264
|
+
slopcamera image gallery <subject> --output-dir <directory> [--model <model>]
|
|
265
|
+
[--kind <image|texture|skybox|backdrop|sprite>] [--count <n>]
|
|
266
|
+
[--vary <axis[=v1,v2][;axis...]>] [--candidates <file.json>]
|
|
267
|
+
[--cell <n>] [--tile|--no-tile] [--json]
|
|
268
|
+
slopcamera image icon <subject> --output <file.svg>
|
|
269
|
+
[--purpose <mark|illustration>] [--model <model>] [--ink <#rgb>]
|
|
270
|
+
[--rounds <1-4>] [--critique-model <model>] [--keep-raster] [--json]
|
|
157
271
|
|
|
158
272
|
Explicit --output file commands delegate to @hraness/slopcamera. Vectorization is local,
|
|
159
273
|
bounded, checksum-pinned, and emits inert SVG. File generation uses Vercel AI Gateway with the
|
|
160
274
|
caller's environment credential. The --prompt spelling without --output is an alias for the desktop
|
|
161
|
-
content-addressed \`ai image generate\` lane and returns project-composable content hash references
|
|
275
|
+
content-addressed \`ai image generate\` lane and returns project-composable content hash references.
|
|
276
|
+
Icon combines a style-locked Gateway raster, local ink extraction and VTracer tracing into a
|
|
277
|
+
canonical isometric line-art SVG; --rounds above 1 adds a vision-model critique that revises the
|
|
278
|
+
prompt between attempts. Gallery fans one subject out to bounded parallel candidates — driven by
|
|
279
|
+
variation axes or an explicit candidate list — keeps every candidate with its provenance, and
|
|
280
|
+
composes a labelled contact sheet plus receipt for agent review. Texture cells repeat the
|
|
281
|
+
candidate 2×2 so seams are inspectable (--tile/--no-tile overrides). It never replaces existing
|
|
282
|
+
outputs and never promotes a candidate into authored source; review the sheet and select
|
|
283
|
+
explicitly.`,
|
|
162
284
|
html: `Usage:
|
|
163
285
|
slopcamera html catalog [--json]
|
|
164
286
|
slopcamera html scaffold <${HTML_OVERLAY_SCAFFOLD_KIND_HELP}> --output <file.html>
|
|
@@ -247,6 +369,13 @@ run journal.`,
|
|
|
247
369
|
[--max-output-tokens <n>] [--temperature <n>] [--stop <text> ...]
|
|
248
370
|
[--provider-options <json-file>] [--timeout <time>]
|
|
249
371
|
[--allow-cloud-upload] [--json]
|
|
372
|
+
slopcamera ai image gallery <subject> --model <id> --output-dir <directory>
|
|
373
|
+
[--kind <image|texture|skybox|backdrop|sprite>] [--count <n>]
|
|
374
|
+
[--vary <axis[=v1,v2][;axis...]>] [--candidates <json-file>]
|
|
375
|
+
[--cell <n>] [--tile|--no-tile] [--preview probe]
|
|
376
|
+
[--timeout <time>] [--json]
|
|
377
|
+
slopcamera ai scene gallery <scene.json> --variants <file.json> --output-dir <directory>
|
|
378
|
+
[--camera <camera-id>] [--time-us <integer>] [--cell <n>] [--json]
|
|
250
379
|
slopcamera ai video generate --model <id> [--prompt <text> | --prompt-file <path>]
|
|
251
380
|
[--image <path-or-https-url>] [--frame first=<path-or-https-url>]
|
|
252
381
|
[--frame last=<path-or-https-url>]
|
|
@@ -288,6 +417,25 @@ image cannot accompany a first frame.
|
|
|
288
417
|
provider-options inspect emits exactly the secret-free {sha256,namespaces} reference that workflow
|
|
289
418
|
nodes store in their exact request; it never prints or persists the raw option values.
|
|
290
419
|
|
|
420
|
+
ai image gallery runs one tracked paid job per candidate with bounded parallelism, then composes a
|
|
421
|
+
labelled contact sheet and receipt into --output-dir. Each candidate keeps its durable artifact,
|
|
422
|
+
prompt, digest, and job record so an agent can review the sheet once and promote a chosen candidate
|
|
423
|
+
explicitly; generated bytes never replace authored source. --vary takes automatic variation axes,
|
|
424
|
+
--candidates takes an explicit JSON list, and the two are mutually exclusive. Texture cells render
|
|
425
|
+
as a 2×2 tile repeat so seams are visible at a glance; --no-tile keeps a flat cell and --tile opts
|
|
426
|
+
other kinds in. --preview probe renders each settled candidate inside the fixed probe scene —
|
|
427
|
+
textures applied to lit geometry, skyboxes as the environment, backdrops as a scene surface — so the
|
|
428
|
+
sheet shows rendered stills. The receipt keeps the generated candidate path/digest and the rendered
|
|
429
|
+
cellImage path/digest as separate fields; promotion always targets the candidate, never the still.
|
|
430
|
+
|
|
431
|
+
ai scene gallery reads an authored scene plus a bounded variants file of typed scene patches, then
|
|
432
|
+
renders each derived scene through the qualified scene renderer and composes the beauty stills into
|
|
433
|
+
the same labelled contact sheet. Every variant is published as a new scene document under
|
|
434
|
+
--output-dir/variants/<id>/ with its asset payloads staged alongside, so the derived scene is
|
|
435
|
+
inspectable and re-renderable; the authored scene is never modified. The receipt keeps the base
|
|
436
|
+
scene digest, each patch digest, each derived scene digest, and each rendered still digest so an
|
|
437
|
+
agent can review once and promote a chosen variant explicitly.
|
|
438
|
+
|
|
291
439
|
Reference media and transcription audio never upload implicitly. The appropriate explicit
|
|
292
440
|
--allow-cloud-* acknowledgement is required after local files pass type and byte bounds. Image
|
|
293
441
|
and video references may instead use a public credential-free HTTPS URL when the live catalog
|
|
@@ -419,19 +567,6 @@ Apply accepts only candidates with safe acoustic boundaries and current placemen
|
|
|
419
567
|
[--min-duration <time>] [--min-confidence <0..1>] [--limit <1..1000>] [--json]
|
|
420
568
|
|
|
421
569
|
Face track IDs describe local geometry continuity inside one immutable analysis. They do not identify a person.`,
|
|
422
|
-
record: `Usage:
|
|
423
|
-
slopcamera record start [--display <id> ...]
|
|
424
|
-
[--camera-device <id>] [--microphone-device <id>]
|
|
425
|
-
[--webcam <true|false>] [--microphone <true|false>]
|
|
426
|
-
[--system-audio <true|false>] [--typed-text <true|false>]
|
|
427
|
-
[--strict-inputs] [--json]
|
|
428
|
-
slopcamera record pause|resume|stop|status [--json]
|
|
429
|
-
|
|
430
|
-
Capture defaults to every current display, system audio, the default microphone,
|
|
431
|
-
and the default camera. Repeat --display to record an exact non-empty subset.
|
|
432
|
-
Device IDs select the exact camera or microphone reported by slopcamera doctor;
|
|
433
|
-
unknown or duplicate IDs fail closed. Typed-text capture remains opt-in with
|
|
434
|
-
--typed-text true.`,
|
|
435
570
|
recordings: `Usage: slopcamera recordings list [--limit <n>] [--json]`,
|
|
436
571
|
projects: `Usage:
|
|
437
572
|
slopcamera projects list [--limit <n>] [--json]
|
|
@@ -467,6 +602,23 @@ unknown or duplicate IDs fail closed. Typed-text capture remains opt-in with
|
|
|
467
602
|
slopcamera project edit <project> overlay remove <id> [--json]
|
|
468
603
|
slopcamera project render <plan|run> <project> [--width <px>] [--height <px>] [--fps <n>]
|
|
469
604
|
[--output <renders/path.mp4>] [--dry-run] [--allow-unverified-sync] [--json]
|
|
605
|
+
slopcamera project cinema init <project> [--force] [--json]
|
|
606
|
+
slopcamera project cinema check <project> [--json]
|
|
607
|
+
slopcamera project cinema plan <project> [--allow-placeholders] [--json]
|
|
608
|
+
slopcamera project cinema audit <project> [--json]
|
|
609
|
+
slopcamera project cinema gallery <project> --axis <audio|looks|mixed|pacing|structure|transitions>
|
|
610
|
+
[--output <cinema/path.json>] [--json]
|
|
611
|
+
slopcamera project cinema animatic <project> [--output <renders/path.mp4>] [--dry-run] [--json]
|
|
612
|
+
slopcamera project cinema run <project> [--output <renders/path.mp4>] [--allow-placeholders] [--dry-run] [--json]
|
|
613
|
+
|
|
614
|
+
Cinema commands drive the content-addressed cinema sidecar (cinema/current.json), which binds exact
|
|
615
|
+
project structure and edit-plan digests. Any project or edit change makes the sidecar stale until it is
|
|
616
|
+
re-authorized. Animatics always allow deterministic placeholder frames for missing spatial artifacts;
|
|
617
|
+
final runs require materialized media unless --allow-placeholders is explicit. Cinema never alters the
|
|
618
|
+
project render plan or its identity. Audit reports layout-derived temporal evidence — pacing floors,
|
|
619
|
+
transition overruns, cue concurrency and uniform pacing — with deterministic shot metrics. Gallery
|
|
620
|
+
compiles a bounded set of single-axis candidate plans under cinema/galleries/, each re-validated and
|
|
621
|
+
re-hashed through the canonical composition digest; it never selects a candidate.
|
|
470
622
|
|
|
471
623
|
Imported media starts unverified. Align its audio before relying on synchronization. Structural edits are project-time operations and affect every placement. Camera moves address any placed video stream; metadata-driven screen zooms still require a recording-backed source placement. Face analysis and geometry tracks remain local. --select largest follows the largest currently visible prepared-layer face per frame. --require-all-selected makes a missing explicit/all-selected face invoke the chosen gap policy.`,
|
|
472
624
|
render: `Usage: slopcamera render <plan|run> <recording> [--display <id|primary>] [--output <path>] [--dry-run] [--keep-inactivity] [--json]
|
|
@@ -481,23 +633,31 @@ export function commandHelp(topic: readonly string[]): string {
|
|
|
481
633
|
|
|
482
634
|
export function completions(words: readonly string[]): readonly string[] {
|
|
483
635
|
const topLevel = [
|
|
484
|
-
"operations", "diagram", "direct", "studio", "image", "html", "workflows", "code", "runs", "doctor", "ai", "media", "
|
|
636
|
+
"capabilities", "operations", "diagram", "direct", "studio", "image", "html", "workflows", "code", "runs", "doctor", "ai", "media", "menubar", "support", "outputs", "recordings", "projects", "project", "scene", "inspect", "events", "edit", "analyze", "align", "faces", "fillers", "render", "assets",
|
|
485
637
|
];
|
|
486
638
|
if (words.length <= 1) return topLevel;
|
|
487
639
|
const command = words[0];
|
|
640
|
+
if (command === "support") return ["protocol", "offer", "shown", "release", "dismiss", "snooze", "enable", "status"];
|
|
488
641
|
if (command === "html") return ["catalog", "scaffold", "render"];
|
|
489
642
|
if (command === "direct") return ["init", "anchor", "plan", "start", "inspect", "revise", "generate", "resume", "review", "assemble", "cleanup"];
|
|
490
643
|
if (command === "studio") return words[2] === "assets" || words[1] === "assets" ? ["search", "describe", "plan", "import"] : ["init", "bundle", "plan", "probe", "run", "encode", "asset", "assemble", "inspect", "reconcile", "assets"];
|
|
491
644
|
if (command === "operations") return ["list", "show"];
|
|
492
645
|
if (command === "diagram") return ["check", "render"];
|
|
493
|
-
if (command === "image") return ["vectorize"];
|
|
646
|
+
if (command === "image") return ["vectorize", "generate", "gallery", "icon"];
|
|
494
647
|
if (command === "workflows") return ["list", "show", "plan", "run"];
|
|
495
648
|
if (command === "code") return ["init", "check", "plan", "run"];
|
|
496
649
|
if (command === "runs") return ["list", "show", "resume", "approve", "cancel"];
|
|
497
|
-
if (command === "record") return ["start", "pause", "resume", "stop", "status"];
|
|
498
650
|
if (command === "recordings") return ["list"];
|
|
499
651
|
if (command === "projects") return ["list", "create"];
|
|
500
|
-
if (command === "project") return [
|
|
652
|
+
if (command === "project") return words[1] === "cinema"
|
|
653
|
+
? ["init", "check", "plan", "audit", "gallery", "animatic", "run"]
|
|
654
|
+
: ["inspect", "add", "edit", "render", "cinema"];
|
|
655
|
+
if (command === "scene") {
|
|
656
|
+
if (words[1] === "direction") return ["check", "plan", "gallery"];
|
|
657
|
+
if (words[1] === "effects") return ["check", "plan", "bake"];
|
|
658
|
+
if (words[1] === "behavior") return ["check", "bake", "gallery", "audit"];
|
|
659
|
+
return ["init", "check", "inspect", "diff", "patch", "evaluate", "audit", "render-audit", "solve", "review", "camera-track", "generate", "plan", "render", "direction", "effects", "behavior", "temporal-audit"];
|
|
660
|
+
}
|
|
501
661
|
if (command === "edit") return ["init", "show", "trim", "cut", "speed", "zoom", "overlay", "cursor", "clicks", "keystrokes", "typed-text"];
|
|
502
662
|
if (command === "analyze") return ["faces", "inactivity", "zooms", "music", "scenes", "speech"];
|
|
503
663
|
if (command === "faces") return ["list"];
|