@hraness/slopcamera 3.2.8 → 3.3.2
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/README.md +29 -9
- package/apps/desktop/application/context.ts +6 -0
- package/apps/desktop/application/default-registry.ts +26 -0
- package/apps/desktop/application/operation.ts +14 -1
- package/apps/desktop/application/operations/index.ts +4 -0
- 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 +514 -11
- 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 +29 -1
- package/apps/desktop/cli/commands.ts +1188 -4
- package/apps/desktop/cli/gateway-review-provider.ts +334 -0
- package/apps/desktop/cli/help.ts +172 -6
- package/apps/desktop/cli/main.ts +3 -3
- package/apps/desktop/cli/portable-surface.ts +6 -1
- 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 +271 -4
- package/apps/desktop/cli/workflow-code.ts +1 -1
- package/apps/desktop/code/semantic-builder.ts +24 -0
- 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/storage.ts +75 -0
- package/apps/desktop/dist/cli/main.js +725 -273
- 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 +25 -429
- 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-grk47tgs.js +3 -0
- package/dist/index-gs48afpt.js +7 -0
- package/dist/index-qry58nj2.js +10 -0
- package/dist/index-zhg36tf9.js +3 -0
- package/dist/index.js +1 -226
- 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 +12 -0
- package/package.json +7 -5
- package/skills/slopcamera/SKILL.md +7 -1
- package/skills/slopcamera/references/directed-scenes.md +48 -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 +1 -1
- package/skills/slopcamera/references/music-video.md +4 -0
- package/skills/slopcamera/references/native-studio.md +19 -0
- package/skills/slopcamera/references/parametric-design.md +14 -0
- package/skills/slopcamera/references/scene-building.md +172 -0
- package/skills/slopcamera/references/social-collage-banners.md +204 -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 +222 -4
- 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 -0
- 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 +1649 -132
- 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 +232 -0
- package/src/spatial-scene/behavior-fns.ts +585 -0
- package/src/spatial-scene/behavior-gallery.ts +108 -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 +617 -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/version.ts +1 -1
- package/dist/index-42zsesc1.js +0 -2257
- package/dist/index-7131pg1c.js +0 -1820
- package/dist/index-7308egqr.js +0 -48
- package/dist/index-8txs6fkn.js +0 -712
- package/dist/index-fava6pge.js +0 -192
- package/dist/index-h1k0fnjq.js +0 -2363
- package/dist/index-r7gdhmsp.js +0 -424
- package/dist/index-sh6xbav6.js +0 -1219
- package/dist/index-z1w83f81.js +0 -4
- package/dist/index-zfnddgay.js +0 -2029
- package/dist/skill-install-dh0ntqba.js +0 -10
|
@@ -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,15 +8,19 @@ 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
|
|
@@ -53,6 +57,9 @@ HRANESS_SUPPORT_AUDIENCE=off suppresses offers and incidental discovery.
|
|
|
53
57
|
Run slopcamera help <command> for command-specific help.`;
|
|
54
58
|
|
|
55
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.`,
|
|
56
63
|
studio: `Usage:
|
|
57
64
|
slopcamera studio init <new-directory> [--template blender-product|blender-character|blender-shaded-street|blender-cloth|blender-fluid|cadquery-bracket|manim-lesson] [--json]
|
|
58
65
|
slopcamera studio bundle <source.json> [--source-root <directory>] [--json]
|
|
@@ -119,27 +126,120 @@ project for slopcamera project render run. Review and assembly work without clou
|
|
|
119
126
|
This workflow retains image and prompt continuity; it has no provider neural checkpoint
|
|
120
127
|
or real-time session. Use slopcamera ai models list --type video for live model discovery.`,
|
|
121
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]
|
|
122
135
|
slopcamera scene init <scene.json> [--json]
|
|
123
136
|
slopcamera scene check <scene.json> [--json]
|
|
124
137
|
slopcamera scene inspect <scene.json> [--json]
|
|
125
138
|
slopcamera scene patch <scene.json> --patch <patch.json> --output <new-scene.json> [--json]
|
|
126
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]
|
|
127
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]
|
|
128
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]
|
|
129
159
|
slopcamera scene project snapshot <project-id> [--json]
|
|
130
160
|
slopcamera scene project prepare-render <project-id> --input <request.json> --output <prepared-render.json> [--profile <profile>] [--json]
|
|
131
161
|
slopcamera scene project migrate|patch|restore|add-shot|add-candidate|select-candidate|reconcile
|
|
132
162
|
<project-id> --input <request.json> [--json]
|
|
133
163
|
slopcamera scene world import --input <import.json> --source-root <directory>
|
|
134
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.
|
|
135
180
|
|
|
136
181
|
Hardware profiles: three-webgl2-hardware-v1 and three-spark-webgl2-hardware-v1.
|
|
137
182
|
An explicit profile must agree with the request; omitting it preserves the request.
|
|
138
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.
|
|
139
187
|
Scene sources retain stable entities, cameras, asset manifests and animation channels.
|
|
140
188
|
Inspect reports editable controls and known bounds without decoding assets. Patch requires
|
|
141
189
|
the exact expected scene digest in its patch document and writes a new source without
|
|
142
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.
|
|
143
243
|
Project operations use the exact full project ID and a versioned whole-project basis.
|
|
144
244
|
Discover each request with slopcamera operations show spatial.project.<action> --json.
|
|
145
245
|
Migration retains the frozen media/edit pair in V2 authority. Legacy project commands
|
|
@@ -161,11 +261,26 @@ operations separately publish equivalent derivatives by content hash for workflo
|
|
|
161
261
|
slopcamera image generate <prompt> --output <file.webp> [--model <model>]
|
|
162
262
|
[--idempotency-key <key>] [--json]
|
|
163
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]
|
|
164
271
|
|
|
165
272
|
Explicit --output file commands delegate to @hraness/slopcamera. Vectorization is local,
|
|
166
273
|
bounded, checksum-pinned, and emits inert SVG. File generation uses Vercel AI Gateway with the
|
|
167
274
|
caller's environment credential. The --prompt spelling without --output is an alias for the desktop
|
|
168
|
-
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.`,
|
|
169
284
|
html: `Usage:
|
|
170
285
|
slopcamera html catalog [--json]
|
|
171
286
|
slopcamera html scaffold <${HTML_OVERLAY_SCAFFOLD_KIND_HELP}> --output <file.html>
|
|
@@ -254,6 +369,13 @@ run journal.`,
|
|
|
254
369
|
[--max-output-tokens <n>] [--temperature <n>] [--stop <text> ...]
|
|
255
370
|
[--provider-options <json-file>] [--timeout <time>]
|
|
256
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]
|
|
257
379
|
slopcamera ai video generate --model <id> [--prompt <text> | --prompt-file <path>]
|
|
258
380
|
[--image <path-or-https-url>] [--frame first=<path-or-https-url>]
|
|
259
381
|
[--frame last=<path-or-https-url>]
|
|
@@ -295,6 +417,25 @@ image cannot accompany a first frame.
|
|
|
295
417
|
provider-options inspect emits exactly the secret-free {sha256,namespaces} reference that workflow
|
|
296
418
|
nodes store in their exact request; it never prints or persists the raw option values.
|
|
297
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
|
+
|
|
298
439
|
Reference media and transcription audio never upload implicitly. The appropriate explicit
|
|
299
440
|
--allow-cloud-* acknowledgement is required after local files pass type and byte bounds. Image
|
|
300
441
|
and video references may instead use a public credential-free HTTPS URL when the live catalog
|
|
@@ -461,6 +602,23 @@ Face track IDs describe local geometry continuity inside one immutable analysis.
|
|
|
461
602
|
slopcamera project edit <project> overlay remove <id> [--json]
|
|
462
603
|
slopcamera project render <plan|run> <project> [--width <px>] [--height <px>] [--fps <n>]
|
|
463
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.
|
|
464
622
|
|
|
465
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.`,
|
|
466
624
|
render: `Usage: slopcamera render <plan|run> <recording> [--display <id|primary>] [--output <path>] [--dry-run] [--keep-inactivity] [--json]
|
|
@@ -475,7 +633,7 @@ export function commandHelp(topic: readonly string[]): string {
|
|
|
475
633
|
|
|
476
634
|
export function completions(words: readonly string[]): readonly string[] {
|
|
477
635
|
const topLevel = [
|
|
478
|
-
"operations", "diagram", "direct", "studio", "image", "html", "workflows", "code", "runs", "doctor", "ai", "media", "menubar", "support", "outputs", "recordings", "projects", "project", "inspect", "events", "edit", "analyze", "align", "faces", "fillers", "render", "assets",
|
|
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",
|
|
479
637
|
];
|
|
480
638
|
if (words.length <= 1) return topLevel;
|
|
481
639
|
const command = words[0];
|
|
@@ -485,13 +643,21 @@ export function completions(words: readonly string[]): readonly string[] {
|
|
|
485
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"];
|
|
486
644
|
if (command === "operations") return ["list", "show"];
|
|
487
645
|
if (command === "diagram") return ["check", "render"];
|
|
488
|
-
if (command === "image") return ["vectorize"];
|
|
646
|
+
if (command === "image") return ["vectorize", "generate", "gallery", "icon"];
|
|
489
647
|
if (command === "workflows") return ["list", "show", "plan", "run"];
|
|
490
648
|
if (command === "code") return ["init", "check", "plan", "run"];
|
|
491
649
|
if (command === "runs") return ["list", "show", "resume", "approve", "cancel"];
|
|
492
650
|
if (command === "recordings") return ["list"];
|
|
493
651
|
if (command === "projects") return ["list", "create"];
|
|
494
|
-
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
|
+
}
|
|
495
661
|
if (command === "edit") return ["init", "show", "trim", "cut", "speed", "zoom", "overlay", "cursor", "clicks", "keystrokes", "typed-text"];
|
|
496
662
|
if (command === "analyze") return ["faces", "inactivity", "zooms", "music", "scenes", "speech"];
|
|
497
663
|
if (command === "faces") return ["list"];
|
package/apps/desktop/cli/main.ts
CHANGED
|
@@ -46,7 +46,7 @@ export async function main(
|
|
|
46
46
|
const portableExitCode = await runPortableSurface(unifiedArgv, portableDependencies);
|
|
47
47
|
if (portableExitCode !== undefined) return portableExitCode;
|
|
48
48
|
const earlyCommand = parseCliArgs(unifiedArgv);
|
|
49
|
-
if (earlyCommand.kind === "help" || earlyCommand.kind === "version" || earlyCommand.kind === "complete") {
|
|
49
|
+
if (earlyCommand.kind === "help" || earlyCommand.kind === "version" || earlyCommand.kind === "complete" || earlyCommand.kind === "capabilities") {
|
|
50
50
|
const intro = rootHelpIntro(unifiedArgv, {
|
|
51
51
|
isTTY: process.stdout.isTTY === true, term: process.env.TERM, columns: process.stdout.columns,
|
|
52
52
|
});
|
|
@@ -54,8 +54,8 @@ export async function main(
|
|
|
54
54
|
return await runCli(unifiedArgv, { io: processIo });
|
|
55
55
|
}
|
|
56
56
|
const paths = await resolveRepositoryPaths(processIo.cwd(), processIo.env);
|
|
57
|
-
if (earlyCommand.kind === "html-render" || earlyCommand.kind === "spatial-world" || earlyCommand.kind === "directing" || earlyCommand.kind === "studio"
|
|
58
|
-
|| earlyCommand.kind === "spatial-scene" && earlyCommand.action === "camera-track") {
|
|
57
|
+
if (earlyCommand.kind === "html-render" || earlyCommand.kind === "spatial-world" || earlyCommand.kind === "spatial-asset" || earlyCommand.kind === "spatial-design" || earlyCommand.kind === "directing" || earlyCommand.kind === "studio"
|
|
58
|
+
|| earlyCommand.kind === "spatial-scene" && (earlyCommand.action === "camera-track" || earlyCommand.action === "render-audit" || earlyCommand.action === "review")) {
|
|
59
59
|
const controller = new AbortController();
|
|
60
60
|
const cancel = () => controller.abort(new CliError("cancelled", "Command interrupted."));
|
|
61
61
|
process.on("SIGINT", cancel);
|
|
@@ -235,7 +235,12 @@ export async function runPortableSurface(
|
|
|
235
235
|
)
|
|
236
236
|
|| (
|
|
237
237
|
argv[0] === "image"
|
|
238
|
-
&& (
|
|
238
|
+
&& (
|
|
239
|
+
argv[1] === "vectorize" ||
|
|
240
|
+
argv[1] === "generate" ||
|
|
241
|
+
argv[1] === "icon" ||
|
|
242
|
+
argv[1] === "gallery"
|
|
243
|
+
)
|
|
239
244
|
);
|
|
240
245
|
if (!delegatesToHeadless) return undefined;
|
|
241
246
|
|