@womp/spark-agent 4.4.1 → 5.0.0

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.
Files changed (46) hide show
  1. package/.env.example +6 -0
  2. package/README.md +21 -2
  3. package/dist/capabilities/geometry.d.ts +0 -3
  4. package/dist/capabilities/geometry.js +7 -8
  5. package/dist/capabilities/openscad-instructions.d.ts +1 -1
  6. package/dist/capabilities/openscad-instructions.js +80 -81
  7. package/dist/capabilities/openscad.d.ts +0 -3
  8. package/dist/capabilities/openscad.js +1 -2
  9. package/dist/capabilities/scene.d.ts +4 -11
  10. package/dist/capabilities/scene.js +38 -55
  11. package/dist/generated/geometry-declarations.d.ts +1 -1
  12. package/dist/generated/geometry-declarations.js +1 -1
  13. package/dist/generated/openscad-declarations.d.ts +1 -1
  14. package/dist/generated/openscad-declarations.js +1 -1
  15. package/dist/generated/scene-declarations.d.ts +1 -1
  16. package/dist/generated/scene-declarations.js +1 -1
  17. package/dist/native-executor.js +2 -2
  18. package/dist/openscad.d.ts +1 -2
  19. package/dist/openscad.js +1 -19
  20. package/dist/quickjs-executor.js +1 -1
  21. package/dist/repair-state.d.ts +2 -0
  22. package/dist/repair-state.js +15 -0
  23. package/dist/runtime.d.ts +1 -5
  24. package/dist/runtime.js +8 -14
  25. package/dist/scene-environment.js +1 -1
  26. package/dist/scene-health.d.ts +1 -2
  27. package/dist/scene-health.js +0 -17
  28. package/dist/scene-operations.d.ts +5 -5
  29. package/dist/scene-operations.js +24 -43
  30. package/dist/sdk-geometry-host.d.ts +2 -2
  31. package/dist/sdk-geometry-host.js +44 -61
  32. package/dist/sdk-openscad-host.js +63 -102
  33. package/dist/sdk-scene-health-host.d.ts +2 -1
  34. package/dist/sdk-scene-health-host.js +54 -4
  35. package/dist/sdk-scene-host.d.ts +20 -5
  36. package/dist/sdk-scene-host.js +34 -31
  37. package/dist/sdk-scene-screenshot.d.ts +2 -2
  38. package/dist/sdk-scene-screenshot.js +3 -16
  39. package/dist/server/scene-access.d.ts +4 -0
  40. package/dist/server/scene-access.js +40 -0
  41. package/dist/server/standalone.js +24 -19
  42. package/dist/womp-scene-api.d.ts +15 -0
  43. package/dist/womp-scene-api.js +18 -1
  44. package/package.json +139 -139
  45. package/dist/server/scene-initialization.d.ts +0 -3
  46. package/dist/server/scene-initialization.js +0 -44
@@ -3,7 +3,7 @@ import { createOpenAI } from "@ai-sdk/openai";
3
3
  import { createGoogleGenerativeAI } from "@ai-sdk/google";
4
4
  import express from "express";
5
5
  import { getSparkModel, SPARK_MODELS } from "../models.js";
6
- import { KakapoAPI, KakapoRpcError } from "@womp/kakapo-sdk";
6
+ import { KakapoAPI, KakapoRpcError, KakapoSceneCommitError } from "@womp/kakapo-sdk";
7
7
  import { captureSdkSceneScreenshot } from "../sdk-scene-screenshot.js";
8
8
  import { composeCapabilities, createAccountCapability, createGeometryCapability, createOpenScadCapability, createSceneCapability, } from "../capabilities.js";
9
9
  import { loadDemoSceneMaterials } from "./demo-scene-materials.js";
@@ -13,7 +13,7 @@ import { createSdkGeometryHost } from "../sdk-geometry-host.js";
13
13
  import { createSdkOpenScadHost } from "../sdk-openscad-host.js";
14
14
  import { createSdkSceneHealthHost } from "../sdk-scene-health-host.js";
15
15
  import { geometryReference } from "../geometry.js";
16
- import { getSdkSceneAreaIds, hasSceneResourcePressure, readStableSdkSceneHealth, } from "../scene-health.js";
16
+ import { hasSceneResourcePressure, } from "../scene-health.js";
17
17
  import { QuickJSJavaScriptExecutor } from "../quickjs-executor.js";
18
18
  import { sparkModelOptions } from "../model-options.js";
19
19
  import { createSparkRunExecutor } from "./executor.js";
@@ -21,7 +21,7 @@ import { createSparkAgentRouter } from "./express.js";
21
21
  import { SparkAgentService } from "./service.js";
22
22
  import { SqliteSparkStore } from "./sqlite-store.js";
23
23
  import { clearSceneContents } from "./scene-actions.js";
24
- import { initializeStandaloneScene } from "./scene-initialization.js";
24
+ import { standaloneSceneAccess } from "./scene-access.js";
25
25
  export async function checkStandaloneServices(api) {
26
26
  const [fonts, openScad] = await Promise.allSettled([
27
27
  api.listFonts(),
@@ -57,6 +57,7 @@ export async function createStandaloneSparkAgentApp(options) {
57
57
  throw error;
58
58
  }
59
59
  const artifactStore = store;
60
+ const sceneAccess = standaloneSceneAccess(options.kakapoUrl);
60
61
  const executeRun = createSparkRunExecutor({
61
62
  createHost: async (context) => {
62
63
  const api = new KakapoAPI({
@@ -65,9 +66,7 @@ export async function createStandaloneSparkAgentApp(options) {
65
66
  });
66
67
  try {
67
68
  context.signal.throwIfAborted();
68
- await api.connect();
69
- context.signal.throwIfAborted();
70
- await initializeStandaloneScene(api, context.signal);
69
+ await api.connect({ refreshScene: false });
71
70
  context.signal.throwIfAborted();
72
71
  const support = await checkStandaloneServices(api);
73
72
  const services = {
@@ -81,12 +80,12 @@ export async function createStandaloneSparkAgentApp(options) {
81
80
  targetKey,
82
81
  operations: store,
83
82
  saveToRenderer: true,
84
- withConnection: async (invocation, action) => {
85
- invocation.signal.throwIfAborted();
83
+ withConnection: (invocation, action) => sceneAccess.run(invocation.signal, async (signal, beginSettlement) => {
86
84
  if (!api.isConnected)
87
85
  throw new Error("The Kakapo connection was interrupted; reconnect before continuing");
88
- return action(api, () => { }, invocation);
89
- },
86
+ return action(api, beginSettlement, { ...invocation, signal });
87
+ }),
88
+ acquireAccess: async () => sceneAccess.release,
90
89
  assertEditable: () => {
91
90
  if (!api.isConnected)
92
91
  throw new Error("The Kakapo connection is unavailable");
@@ -103,16 +102,11 @@ export async function createStandaloneSparkAgentApp(options) {
103
102
  const sceneHost = createSdkSceneHost({
104
103
  ...editorOptions,
105
104
  editor,
106
- health: createSdkSceneHealthHost(editor, onHealth),
107
- onSceneCommitted: async (_operation, api) => {
108
- const sceneHealth = await readStableSdkSceneHealth(api, getSdkSceneAreaIds(api), context.signal);
109
- onHealth(sceneHealth);
110
- return { sceneHealth };
111
- },
105
+ health: createSdkSceneHealthHost(editor, onHealth, repairs),
112
106
  services: async () => services,
113
107
  screenshot: async (settings, invocation) => {
114
108
  invocation.signal.throwIfAborted();
115
- const image = await captureSdkSceneScreenshot(api, settings);
109
+ const image = await editor.withConnection(invocation, activeApi => captureSdkSceneScreenshot(activeApi, settings));
116
110
  options.onScreenshot?.(context.runId);
117
111
  invocation.signal.throwIfAborted();
118
112
  return artifactStore.write(context.ownerId, image);
@@ -254,8 +248,19 @@ export async function createStandaloneSparkAgentApp(options) {
254
248
  clearingScene = true;
255
249
  const api = new KakapoAPI({ url: options.kakapoUrl, requestTimeoutMs: 30_000 });
256
250
  try {
257
- await api.connect();
258
- const { save } = await api.editSceneAndSave(clearSceneContents);
251
+ await api.connect({ refreshScene: false });
252
+ const { save } = await sceneAccess.run(new AbortController().signal, async () => {
253
+ try {
254
+ const result = await api.accessScene(clearSceneContents, { save: true });
255
+ sceneAccess.release(result.save.status !== "unknown");
256
+ return result;
257
+ }
258
+ catch (error) {
259
+ if (error instanceof KakapoSceneCommitError && error.outcome === "unknown")
260
+ sceneAccess.release(false);
261
+ throw error;
262
+ }
263
+ });
259
264
  const warning = save.status === "failed" || save.status === "unknown"
260
265
  ? `Scene cleared, but saving ${save.status === "failed" ? "failed" : "could not be confirmed"}: ${save.error} Do not repeat the clear operation.`
261
266
  : undefined;
@@ -306,5 +306,20 @@ export declare function createWompSceneApi(context: WompSceneApiContext): {
306
306
  g: number;
307
307
  b: number;
308
308
  }) => void;
309
+ unitMultiplier: number;
310
+ /** Current draft summaries. Filters precede pagination; defaults to 100 results, maximum 1000. */
311
+ nodes(options?: {
312
+ ids?: number[];
313
+ type?: number;
314
+ parentId?: number;
315
+ name?: string;
316
+ offset?: number;
317
+ limit?: number;
318
+ }): {
319
+ id: number;
320
+ name: string;
321
+ type: number;
322
+ parentId: number;
323
+ }[];
309
324
  };
310
325
  export {};
@@ -436,6 +436,23 @@ export function createWompSceneApi(context) {
436
436
  return converted;
437
437
  };
438
438
  const api = {
439
+ get unitMultiplier() {
440
+ return sceneUnitMultiplier(scene.getSceneProperties().unit_multiplier);
441
+ },
442
+ /** Current draft summaries. Filters precede pagination; defaults to 100 results, maximum 1000. */
443
+ nodes(options = {}) {
444
+ const { offset = 0, limit = 100 } = options;
445
+ if (!Number.isInteger(offset) || offset < 0 || !Number.isInteger(limit) || limit < 1 || limit > 1000)
446
+ throw new Error("nodes() requires a nonnegative integer offset and a limit from 1 to 1000");
447
+ const ids = options.ids === undefined ? undefined : new Set(options.ids);
448
+ const query = options.name?.toLowerCase();
449
+ return scene.listNodeSummaries().filter(({ id, name, kind, parentId }) => (ids === undefined || ids.has(id)) &&
450
+ (options.type === undefined || sceneNodeType(kind) === options.type) &&
451
+ (options.parentId === undefined || (parentId ?? 0) === options.parentId) &&
452
+ (query === undefined || name.toLowerCase().includes(query))).slice(offset, offset + limit).map(({ id, name, kind, parentId }) => ({
453
+ id, name, type: sceneNodeType(kind), parentId: parentId ?? 0,
454
+ }));
455
+ },
439
456
  ...createSceneEnvironment(scene, context.hdrs, context.print),
440
457
  listSuperMaterials: () => {
441
458
  if (!context.superMaterialNames)
@@ -611,7 +628,7 @@ export function createWompSceneApi(context) {
611
628
  nodeSetLock: (id, locked) => {
612
629
  requireNode(id);
613
630
  const current = metadataObject(scene.getSceneExt([String(id)])[String(id)]);
614
- scene.patchSceneExt([{ op: "add", path: `/${id}`, value: { ...current, locked: Boolean(locked) } }]);
631
+ scene.patchSceneExt([{ op: "add", path: `/${id}`, value: { ...current, locked: Boolean(locked) } }], { returnScene: false });
615
632
  },
616
633
  nodeSetPos: (id, position) => {
617
634
  requireEditableTransform(id);
package/package.json CHANGED
@@ -1,139 +1,139 @@
1
- {
2
- "name": "@womp/spark-agent",
3
- "version": "4.4.1",
4
- "description": "Portable skills-based AI agent with local and durable chat transports for Womp",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
- "bin": {
9
- "spark-agent": "dist/cli.js",
10
- "simple-bench": "dist/simple-bench-cli.js",
11
- "agent-run": "dist/agent-run-cli.js"
12
- },
13
- "exports": {
14
- "./browser": {
15
- "types": "./dist/browser.d.ts",
16
- "import": "./dist/browser.js",
17
- "default": "./dist/browser.js"
18
- },
19
- "./capabilities": {
20
- "types": "./dist/capabilities.d.ts",
21
- "import": "./dist/capabilities.js",
22
- "default": "./dist/capabilities.js"
23
- },
24
- "./kakapo": {
25
- "types": "./dist/kakapo.d.ts",
26
- "import": "./dist/kakapo.js",
27
- "default": "./dist/kakapo.js"
28
- },
29
- "./geometry": {
30
- "types": "./dist/geometry.d.ts",
31
- "import": "./dist/geometry.js",
32
- "default": "./dist/geometry.js"
33
- },
34
- "./openscad": {
35
- "types": "./dist/openscad.d.ts",
36
- "import": "./dist/openscad.js",
37
- "default": "./dist/openscad.js"
38
- },
39
- "./quickjs": {
40
- "types": "./dist/quickjs-executor.d.ts",
41
- "import": "./dist/quickjs-executor.js",
42
- "default": "./dist/quickjs-executor.js"
43
- },
44
- ".": {
45
- "types": "./dist/index.d.ts",
46
- "import": "./dist/index.js",
47
- "default": "./dist/index.js"
48
- },
49
- "./ui": {
50
- "types": "./dist/ui.d.ts",
51
- "import": "./dist/ui.js",
52
- "default": "./dist/ui.js"
53
- },
54
- "./client": {
55
- "types": "./dist/client.d.ts",
56
- "import": "./dist/client.js",
57
- "default": "./dist/client.js"
58
- },
59
- "./server": {
60
- "types": "./dist/server/index.d.ts",
61
- "import": "./dist/server/index.js",
62
- "default": "./dist/server/index.js"
63
- },
64
- "./express": {
65
- "types": "./dist/server/express.d.ts",
66
- "import": "./dist/server/express.js",
67
- "default": "./dist/server/express.js"
68
- },
69
- "./package.json": "./package.json"
70
- },
71
- "files": [
72
- "dist/**/*.js",
73
- "dist/**/*.d.ts",
74
- "dist/server/fixtures/**/*.json",
75
- "dist/geometry/schemas/**/*.json",
76
- "README.md"
77
- ],
78
- "sideEffects": false,
79
- "engines": {
80
- "node": ">=22.13"
81
- },
82
- "repository": {
83
- "type": "git",
84
- "url": "git+https://github.com/wompxyz/spark-agent.git"
85
- },
86
- "publishConfig": {
87
- "access": "public"
88
- },
89
- "license": "MIT",
90
- "scripts": {
91
- "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
92
- "build": "yarn clean && node scripts/generate-skill-declarations.mjs && tsc -p tsconfig.json && node scripts/copy-fixtures.mjs",
93
- "typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p web/tsconfig.json",
94
- "lint": "yarn typecheck",
95
- "dev": "yarn build && concurrently --kill-others \"yarn dev:server\" \"yarn dev:web\"",
96
- "dev:server": "tsx src/cli.ts",
97
- "simple-bench": "tsx src/simple-bench-cli.ts",
98
- "agent-run": "tsx src/agent-run-cli.ts",
99
- "dev:demo-account": "yarn build && concurrently --kill-others \"yarn dev:server --profile demo-account\" \"yarn dev:web\"",
100
- "dev:web": "vite --config web/vite.config.ts",
101
- "start": "node dist/cli.js",
102
- "web:build": "yarn build && tsc --noEmit -p web/tsconfig.json && vite build --config web/vite.config.ts",
103
- "test": "yarn build && tsx --tsconfig tsconfig.json --test test/**/*.test.ts && node --input-type=module -e \"await Promise.all([import('@womp/spark-agent'), import('@womp/spark-agent/ui'), import('@womp/spark-agent/client'), import('@womp/spark-agent/server'), import('@womp/spark-agent/express'), import('@womp/spark-agent/kakapo'), import('@womp/spark-agent/geometry'), import('@womp/spark-agent/openscad')])\"",
104
- "test:live": "tsx --tsconfig tsconfig.json test/womp-scene-api.live.ts",
105
- "prepack": "yarn build"
106
- },
107
- "dependencies": {
108
- "@ai-sdk/anthropic": "4.0.50",
109
- "@ai-sdk/google": "4.0.69",
110
- "@ai-sdk/openai": "4.0.63",
111
- "@jitl/quickjs-wasmfile-release-sync": "0.32.0",
112
- "@womp/flowir": "0.3.0",
113
- "@womp/kakapo-sdk": "0.6.0",
114
- "ai": "7.0.95",
115
- "eventsource-parser": "^3.0.6",
116
- "express": "^5.2.1",
117
- "lodash": "4.18.1",
118
- "quickjs-emscripten-core": "0.32.0",
119
- "zod": "4.5.4"
120
- },
121
- "devDependencies": {
122
- "@ai-sdk/react": "^4.0.77",
123
- "@types/express": "^5.0.5",
124
- "@types/lodash": "4.17.24",
125
- "@types/node": "^24.0.0",
126
- "@types/react": "^19.2.17",
127
- "@types/react-dom": "^19.2.3",
128
- "@vitejs/plugin-react": "^6.0.4",
129
- "concurrently": "^9.2.1",
130
- "lucide-react": "^1.26.0",
131
- "react": "^19.2.8",
132
- "react-dom": "^19.2.8",
133
- "react-markdown": "^10.1.0",
134
- "remark-gfm": "^4.0.1",
135
- "tsx": "^4.23.1",
136
- "typescript": "^5.9.3",
137
- "vite": "^8.1.5"
138
- }
139
- }
1
+ {
2
+ "name": "@womp/spark-agent",
3
+ "version": "5.0.0",
4
+ "description": "Portable skills-based AI agent with local and durable chat transports for Womp",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "spark-agent": "dist/cli.js",
10
+ "simple-bench": "dist/simple-bench-cli.js",
11
+ "agent-run": "dist/agent-run-cli.js"
12
+ },
13
+ "exports": {
14
+ "./browser": {
15
+ "types": "./dist/browser.d.ts",
16
+ "import": "./dist/browser.js",
17
+ "default": "./dist/browser.js"
18
+ },
19
+ "./capabilities": {
20
+ "types": "./dist/capabilities.d.ts",
21
+ "import": "./dist/capabilities.js",
22
+ "default": "./dist/capabilities.js"
23
+ },
24
+ "./kakapo": {
25
+ "types": "./dist/kakapo.d.ts",
26
+ "import": "./dist/kakapo.js",
27
+ "default": "./dist/kakapo.js"
28
+ },
29
+ "./geometry": {
30
+ "types": "./dist/geometry.d.ts",
31
+ "import": "./dist/geometry.js",
32
+ "default": "./dist/geometry.js"
33
+ },
34
+ "./openscad": {
35
+ "types": "./dist/openscad.d.ts",
36
+ "import": "./dist/openscad.js",
37
+ "default": "./dist/openscad.js"
38
+ },
39
+ "./quickjs": {
40
+ "types": "./dist/quickjs-executor.d.ts",
41
+ "import": "./dist/quickjs-executor.js",
42
+ "default": "./dist/quickjs-executor.js"
43
+ },
44
+ ".": {
45
+ "types": "./dist/index.d.ts",
46
+ "import": "./dist/index.js",
47
+ "default": "./dist/index.js"
48
+ },
49
+ "./ui": {
50
+ "types": "./dist/ui.d.ts",
51
+ "import": "./dist/ui.js",
52
+ "default": "./dist/ui.js"
53
+ },
54
+ "./client": {
55
+ "types": "./dist/client.d.ts",
56
+ "import": "./dist/client.js",
57
+ "default": "./dist/client.js"
58
+ },
59
+ "./server": {
60
+ "types": "./dist/server/index.d.ts",
61
+ "import": "./dist/server/index.js",
62
+ "default": "./dist/server/index.js"
63
+ },
64
+ "./express": {
65
+ "types": "./dist/server/express.d.ts",
66
+ "import": "./dist/server/express.js",
67
+ "default": "./dist/server/express.js"
68
+ },
69
+ "./package.json": "./package.json"
70
+ },
71
+ "files": [
72
+ "dist/**/*.js",
73
+ "dist/**/*.d.ts",
74
+ "dist/server/fixtures/**/*.json",
75
+ "dist/geometry/schemas/**/*.json",
76
+ "README.md"
77
+ ],
78
+ "sideEffects": false,
79
+ "engines": {
80
+ "node": ">=22.13"
81
+ },
82
+ "repository": {
83
+ "type": "git",
84
+ "url": "git+https://github.com/wompxyz/spark-agent.git"
85
+ },
86
+ "publishConfig": {
87
+ "access": "public"
88
+ },
89
+ "license": "MIT",
90
+ "scripts": {
91
+ "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
92
+ "build": "yarn clean && node scripts/generate-skill-declarations.mjs && tsc -p tsconfig.json && node scripts/copy-fixtures.mjs",
93
+ "typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p web/tsconfig.json",
94
+ "lint": "yarn typecheck",
95
+ "dev": "yarn build && concurrently --kill-others \"yarn dev:server\" \"yarn dev:web\"",
96
+ "dev:server": "tsx src/cli.ts",
97
+ "simple-bench": "tsx src/simple-bench-cli.ts",
98
+ "agent-run": "tsx src/agent-run-cli.ts",
99
+ "dev:demo-account": "yarn build && concurrently --kill-others \"yarn dev:server --profile demo-account\" \"yarn dev:web\"",
100
+ "dev:web": "vite --config web/vite.config.ts",
101
+ "start": "node dist/cli.js",
102
+ "web:build": "yarn build && tsc --noEmit -p web/tsconfig.json && vite build --config web/vite.config.ts",
103
+ "test": "yarn build && tsx --tsconfig tsconfig.json --test test/**/*.test.ts && node --input-type=module -e \"await Promise.all([import('@womp/spark-agent'), import('@womp/spark-agent/ui'), import('@womp/spark-agent/client'), import('@womp/spark-agent/server'), import('@womp/spark-agent/express'), import('@womp/spark-agent/kakapo'), import('@womp/spark-agent/geometry'), import('@womp/spark-agent/openscad')])\"",
104
+ "test:live": "tsx --tsconfig tsconfig.json test/womp-scene-api.live.ts",
105
+ "prepack": "yarn build"
106
+ },
107
+ "dependencies": {
108
+ "@ai-sdk/anthropic": "4.0.50",
109
+ "@ai-sdk/google": "4.0.69",
110
+ "@ai-sdk/openai": "4.0.63",
111
+ "@jitl/quickjs-wasmfile-release-sync": "0.32.0",
112
+ "@womp/flowir": "0.3.0",
113
+ "@womp/kakapo-sdk": "0.7.0",
114
+ "ai": "7.0.95",
115
+ "eventsource-parser": "^3.0.6",
116
+ "express": "^5.2.1",
117
+ "lodash": "4.18.1",
118
+ "quickjs-emscripten-core": "0.32.0",
119
+ "zod": "4.5.4"
120
+ },
121
+ "devDependencies": {
122
+ "@ai-sdk/react": "^4.0.77",
123
+ "@types/express": "^5.0.5",
124
+ "@types/lodash": "4.17.24",
125
+ "@types/node": "^24.0.0",
126
+ "@types/react": "^19.2.17",
127
+ "@types/react-dom": "^19.2.3",
128
+ "@vitejs/plugin-react": "^6.0.4",
129
+ "concurrently": "^9.2.1",
130
+ "lucide-react": "^1.26.0",
131
+ "react": "^19.2.8",
132
+ "react-dom": "^19.2.8",
133
+ "react-markdown": "^10.1.0",
134
+ "remark-gfm": "^4.0.1",
135
+ "tsx": "^4.23.1",
136
+ "typescript": "^5.9.3",
137
+ "vite": "^8.1.5"
138
+ }
139
+ }
@@ -1,3 +0,0 @@
1
- import { type KakapoAPI } from "@womp/kakapo-sdk";
2
- /** Only for the standalone host's direct, atomic native Kakapo connection. */
3
- export declare function initializeStandaloneScene(api: Pick<KakapoAPI, "rpc" | "refreshScene">, signal: AbortSignal): Promise<void>;
@@ -1,44 +0,0 @@
1
- import { KakapoSceneCommitError } from "@womp/kakapo-sdk";
2
- /** Only for the standalone host's direct, atomic native Kakapo connection. */
3
- export async function initializeStandaloneScene(api, signal) {
4
- signal.throwIfAborted();
5
- const response = await api.rpc("scene_state_get");
6
- signal.throwIfAborted();
7
- const snapshot = typeof response === "string" ? JSON.parse(response) : response;
8
- if (snapshot === null || typeof snapshot !== "object" || Array.isArray(snapshot)) {
9
- throw new Error("Kakapo returned an invalid scene snapshot during scene initialization.");
10
- }
11
- const additions = [];
12
- if (snapshot.ext === undefined)
13
- additions.push({ op: "add", path: "/ext", value: {} });
14
- for (const key of ["materials", "shaders"]) {
15
- if (snapshot.storage[key] === undefined) {
16
- additions.push({ op: "add", path: `/storage/${key}`, value: {} });
17
- }
18
- }
19
- if (snapshot.storage.openscad === undefined) {
20
- additions.push({ op: "add", path: "/storage/openscad", value: { scripts: {} } });
21
- }
22
- else if (snapshot.storage.openscad.scripts === undefined) {
23
- additions.push({ op: "add", path: "/storage/openscad/scripts", value: {} });
24
- }
25
- if (additions.length === 0)
26
- return;
27
- // The SDK requires /ext; native resource updates require per-ID patch paths.
28
- // Initialize missing collections so later edits address individual resources.
29
- // The whole-scene test rejects concurrent changes before editing begins.
30
- let result;
31
- try {
32
- result = await api.rpc("scene_state_patch", [JSON.stringify([
33
- { op: "test", path: "", value: snapshot },
34
- ...additions,
35
- ])]);
36
- }
37
- catch (error) {
38
- throw new KakapoSceneCommitError("unknown", error);
39
- }
40
- if (result !== undefined && result !== null && result !== "") {
41
- throw new KakapoSceneCommitError("unknown", new Error(`Scene initialization was not acknowledged: ${JSON.stringify(result)}`));
42
- }
43
- await api.refreshScene();
44
- }