@womp/kakapo-sdk 0.2.0 → 0.2.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 +5 -0
- package/dist/api.js +13 -3
- package/dist/types.d.ts +13 -2
- package/dist/validation.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -51,6 +51,11 @@ kakapo.disconnect();
|
|
|
51
51
|
The transport uses the browser's native `WebSocket` when bundled for the web and loads `ws`
|
|
52
52
|
dynamically in Node.js.
|
|
53
53
|
|
|
54
|
+
Applications that already own a renderer connection can pass a `KakapoAPITransport` as
|
|
55
|
+
`new KakapoAPI({ transport })`. The adapter defines connection lifecycle, RPC, and token responses.
|
|
56
|
+
`captureScreenshot({ view: "current" })` requests the renderer's JPEG without changing the camera
|
|
57
|
+
or requiring a cached scene. Current-view captures cannot include `targetId` or `targetIds`.
|
|
58
|
+
|
|
54
59
|
All public inputs are checked at runtime as well as by TypeScript. Invalid calls throw structured
|
|
55
60
|
`KakapoValidationError` objects with a stable `code`, offending `path`, expected rule, and a
|
|
56
61
|
correction `hint` intended for automated agents.
|
package/dist/api.js
CHANGED
|
@@ -25,7 +25,7 @@ export class KakapoAPI {
|
|
|
25
25
|
draftDirty = false;
|
|
26
26
|
rendererSyncRequired = false;
|
|
27
27
|
constructor(options = {}) {
|
|
28
|
-
this.transport = new KakapoTransport({
|
|
28
|
+
this.transport = options.transport ?? new KakapoTransport({
|
|
29
29
|
url: options.url ?? "ws://127.0.0.1:5502",
|
|
30
30
|
requestTimeoutMs: options.requestTimeoutMs ?? 10_000,
|
|
31
31
|
connectTimeoutMs: options.connectTimeoutMs ?? 30_000,
|
|
@@ -211,6 +211,17 @@ export class KakapoAPI {
|
|
|
211
211
|
async captureScreenshot(options) {
|
|
212
212
|
this.assertEngineReadAllowed("captureScreenshot");
|
|
213
213
|
const { targetId, timeoutMs } = options;
|
|
214
|
+
if (options.view === "current") {
|
|
215
|
+
if (targetId !== undefined || options.targetIds !== undefined) {
|
|
216
|
+
throw new KakapoValidationError("A current-view screenshot cannot specify framing targets.", {
|
|
217
|
+
code: "AMBIGUOUS_SCREENSHOT_TARGET",
|
|
218
|
+
operation: "captureScreenshot",
|
|
219
|
+
expected: "current view without target selectors",
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
const frame = await this.captureRendererFrame(timeoutMs);
|
|
223
|
+
return { data: frame.payload, mediaType: "image/jpeg", width: frame.width, height: frame.height, view: "current", targetId: 0 };
|
|
224
|
+
}
|
|
214
225
|
if (targetId !== undefined && options.targetIds !== undefined) {
|
|
215
226
|
throw new KakapoValidationError("captureScreenshot accepts targetId or targetIds, not both.", {
|
|
216
227
|
code: "AMBIGUOUS_SCREENSHOT_TARGET",
|
|
@@ -282,8 +293,7 @@ export class KakapoAPI {
|
|
|
282
293
|
async captureRendererFrame(timeoutMs) {
|
|
283
294
|
const token = this.newToken();
|
|
284
295
|
const waiting = this.waitForToken(token, timeoutMs);
|
|
285
|
-
await this.call("get_color_buffer", [[token]]);
|
|
286
|
-
const message = await waiting;
|
|
296
|
+
const [, message] = await Promise.all([this.call("get_color_buffer", [[token]]), waiting]);
|
|
287
297
|
if (!isBinaryFrame(message)) {
|
|
288
298
|
const error = "error" in message ? String(message.error) : "Kakapo returned a non-binary renderer frame";
|
|
289
299
|
throw new KakapoRpcError("get_color_buffer", error);
|
package/dist/types.d.ts
CHANGED
|
@@ -322,7 +322,8 @@ export interface CaptureScreenshotOptions {
|
|
|
322
322
|
/** Omit both selectors to frame all visible top-level scene nodes. */
|
|
323
323
|
targetId?: number;
|
|
324
324
|
targetIds?: number[];
|
|
325
|
-
|
|
325
|
+
/** "current" captures the renderer's existing camera without framing or reading scene state. */
|
|
326
|
+
view?: ScreenshotView | "current";
|
|
326
327
|
timeoutMs?: number;
|
|
327
328
|
}
|
|
328
329
|
export interface ScreenshotImage {
|
|
@@ -330,7 +331,7 @@ export interface ScreenshotImage {
|
|
|
330
331
|
mediaType: "image/jpeg";
|
|
331
332
|
width: number;
|
|
332
333
|
height: number;
|
|
333
|
-
view: ScreenshotView;
|
|
334
|
+
view: ScreenshotView | "current";
|
|
334
335
|
targetId: number;
|
|
335
336
|
}
|
|
336
337
|
export type JsonPatchOperation = {
|
|
@@ -357,7 +358,17 @@ export interface ListNodeOptions {
|
|
|
357
358
|
export interface DeleteNodeOptions {
|
|
358
359
|
recursive?: boolean;
|
|
359
360
|
}
|
|
361
|
+
/** An application can supply its existing connection; its adapter owns connection lifecycle. */
|
|
362
|
+
export interface KakapoAPITransport {
|
|
363
|
+
readonly connected: boolean;
|
|
364
|
+
connect(): Promise<void>;
|
|
365
|
+
disconnect(): void;
|
|
366
|
+
rpc<T>(method: string, params?: JsonValue[]): Promise<T>;
|
|
367
|
+
newToken(): string;
|
|
368
|
+
waitForToken(token: string, timeoutMs?: number): Promise<TokenMessage>;
|
|
369
|
+
}
|
|
360
370
|
export interface KakapoAPIOptions {
|
|
371
|
+
transport?: KakapoAPITransport;
|
|
361
372
|
url?: string;
|
|
362
373
|
requestTimeoutMs?: number;
|
|
363
374
|
connectTimeoutMs?: number;
|
package/dist/validation.js
CHANGED
|
@@ -143,7 +143,7 @@ export function assertScene(scene, operation) {
|
|
|
143
143
|
if (!parentRaw)
|
|
144
144
|
fail(`Tree parent ${parentId} does not exist.`, operation, `tree.${parentId}`, parentId, "existing parent node", undefined, "MISSING_TREE_NODE");
|
|
145
145
|
const parentKind = kindFromWire(parentRaw.type);
|
|
146
|
-
if (!CONTAINERS.has(parentKind))
|
|
146
|
+
if (Object.keys(children).length > 0 && !CONTAINERS.has(parentKind))
|
|
147
147
|
fail(`Node ${parentId} (${parentKind}) cannot contain children.`, operation, `tree.${parentId}`, parentKind, "Union or Group parent", "Reparent the children under a Union or Group.", "LEAF_NODE_HAS_CHILDREN");
|
|
148
148
|
for (const childId of Object.values(children)) {
|
|
149
149
|
if (!scene.nodes[String(childId)])
|