@womp/spark-agent 3.0.1 → 3.0.3

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/dist/prompt.js CHANGED
@@ -1,19 +1,19 @@
1
- export const SPARK_AGENT_PROMPT = `You are Spark, Womp's unified assistant.
2
- Use read_skill to discover the APIs needed for the user's request. Skills provide TypeScript
3
- declarations for documentation; execute_javascript runs JavaScript, with top-level await.
4
- Only the listed capabilities are available. Reading a skill does not grant additional permissions.
5
- Use only the supplied womp APIs and output helpers to access application services and state.
6
- If a capability is unavailable, explain what is missing and ask the user to enable it when applicable.
7
- Do not work around missing capabilities by inspecting page globals, DOM or framework internals,
8
- or making direct network requests. Native execution is not a security sandbox; it does not expand
9
- the supported API or the user's granted capabilities.
10
- Each execution has fresh local variables. Keep stable object, job, and artifact references.
11
- Use print for concise, filtered observations; await emitImage or emitFile with a host-issued artifact
12
- reference to show actual output. Inspect the scene before editing and verify the committed result.
13
- Preserve existing content unless the user asks to replace or delete it. Use the latest target revision
14
- when a write requires one. Capabilities own transactions: an entire script is not atomic.
15
- If an operation fails after earlier effects, use its receipts to inspect and retry only unresolved work.
16
- Never claim an uncertain commit rolled back. Never resubmit a job just because waiting timed out.
17
- Complete related work in this conversation without delegating to another agent. Report limits,
18
- unsupported actions, cancellation, and incomplete work truthfully. Finish with a concise explanation
1
+ export const SPARK_AGENT_PROMPT = `You are Spark, Womp's unified assistant.
2
+ Use read_skill to discover the APIs needed for the user's request. Skills provide TypeScript
3
+ declarations for documentation; execute_javascript runs JavaScript, with top-level await.
4
+ Only the listed capabilities are available. Reading a skill does not grant additional permissions.
5
+ Use only the supplied womp APIs and output helpers to access application services and state.
6
+ If a capability is unavailable, explain what is missing and ask the user to enable it when applicable.
7
+ Do not work around missing capabilities by inspecting page globals, DOM or framework internals,
8
+ or making direct network requests. Native execution is not a security sandbox; it does not expand
9
+ the supported API or the user's granted capabilities.
10
+ Each execution has fresh local variables. Keep stable object, job, and artifact references.
11
+ Use print for concise, filtered observations; await emitImage or emitFile with a host-issued artifact
12
+ reference to show actual output. Inspect the scene before editing and verify the committed result.
13
+ Preserve existing content unless the user asks to replace or delete it. Use the latest target revision
14
+ when a write requires one. Capabilities own transactions: an entire script is not atomic.
15
+ If an operation fails after earlier effects, use its receipts to inspect and retry only unresolved work.
16
+ Never claim an uncertain commit rolled back. Never resubmit a job just because waiting timed out.
17
+ Complete related work in this conversation without delegating to another agent. Report limits,
18
+ unsupported actions, cancellation, and incomplete work truthfully. Finish with a concise explanation
19
19
  of the result in the user's language; keep implementation details out of that explanation.`;
@@ -113,11 +113,16 @@ export async function executeSceneOperation(options) {
113
113
  catch (error) {
114
114
  const status = error instanceof KakapoSceneCommitError ? error.outcome
115
115
  : "rolled_back";
116
- await store.saveSceneOperation({
117
- ...(status === "rolled_back" ? complete(operation, status) : { ...operation, status }),
118
- error: error instanceof Error ? error.message : String(error),
119
- ...(operation.save && status === "rolled_back" ? { save: { status: "not_needed" } } : {}),
120
- });
116
+ try {
117
+ await store.saveSceneOperation({
118
+ ...(status === "rolled_back" ? complete(operation, status) : { ...operation, status }),
119
+ error: error instanceof Error ? error.message : String(error),
120
+ ...(operation.save && status === "rolled_back" ? { save: { status: "not_needed" } } : {}),
121
+ });
122
+ }
123
+ catch {
124
+ // Keep the original error; recovery can inspect the prepared record.
125
+ }
121
126
  throw error;
122
127
  }
123
128
  // Recovery requires both the operation marker and the exact prepared scene revision.
@@ -24,8 +24,8 @@ export type SdkSceneEditorOptions = {
24
24
  /** Supply this when the host adds a stricter connection lifetime. */
25
25
  context?: SparkInvocationContext) => Promise<T>): Promise<T>;
26
26
  assertEditable(context: SparkInvocationContext): void | Promise<void>;
27
- /** Acquire host coordination only after the draft is durably prepared. */
28
- prepareCommit?(operation: SceneOperation, context: SparkInvocationContext): Promise<() => void | Promise<void>>;
27
+ /** Acquire after preparation. Cleanup receives false until rollback or host synchronization is confirmed. */
28
+ prepareCommit?(operation: SceneOperation, context: SparkInvocationContext): Promise<(synchronized: boolean) => void | Promise<void>>;
29
29
  /** Must adopt each operation ID at most once, including during recovery. */
30
30
  onCommitted?(operation: SceneOperation, api: KakapoAPI, context: SparkInvocationContext, identity: SdkSceneEditIdentity): Promise<Record<string, unknown> | void>;
31
31
  };
@@ -89,6 +89,26 @@ export function createSdkSceneEditor(options) {
89
89
  },
90
90
  });
91
91
  let releaseCommit;
92
+ let synchronized = false;
93
+ let hostDetails = {};
94
+ const record = async (operation, details) => {
95
+ hostDetails = { ...hostDetails, ...details };
96
+ await activeContext.recordReceipt({
97
+ ...receipt(),
98
+ status: operation.status === "committed"
99
+ ? "committed"
100
+ : operation.status === "rolled_back"
101
+ ? "rolled_back"
102
+ : "unknown",
103
+ details: {
104
+ ...hostDetails,
105
+ result: operation.result,
106
+ save: operation.save,
107
+ error: operation.error,
108
+ synchronized,
109
+ },
110
+ });
111
+ };
92
112
  try {
93
113
  let result;
94
114
  try {
@@ -117,39 +137,54 @@ export function createSdkSceneEditor(options) {
117
137
  });
118
138
  }
119
139
  catch (error) {
120
- const operation = await options.operations.getSceneOperation(options.targetKey, id);
121
- if (operation)
122
- await activeContext.recordReceipt({
123
- ...receipt(),
124
- status: operation.status === "committed"
125
- ? "committed"
126
- : operation.status === "rolled_back"
127
- ? "rolled_back"
128
- : "unknown",
129
- });
140
+ // Receipt persistence must not replace the original SDK/tool error.
141
+ try {
142
+ const operation = await options.operations.getSceneOperation(options.targetKey, id);
143
+ if (operation) {
144
+ synchronized = operation.status === "rolled_back";
145
+ await record(operation);
146
+ }
147
+ }
148
+ catch {
149
+ /* The prepared receipt remains recoverable. */
150
+ }
130
151
  throw error;
131
152
  }
132
- let details;
133
- if (result.operation.changed) {
134
- const adopted = await options.onCommitted?.(result.operation, api, activeContext, identity);
135
- const finalized = await afterCommitted?.(result.operation, api);
136
- details = { ...adopted, ...finalized };
153
+ synchronized = !result.operation.changed || !options.onCommitted;
154
+ await record(result.operation);
155
+ if (!synchronized) {
156
+ let details;
157
+ try {
158
+ details = await options.onCommitted(result.operation, api, activeContext, identity);
159
+ synchronized = true;
160
+ }
161
+ catch (error) {
162
+ try {
163
+ await record(result.operation, {
164
+ synchronizationError: error instanceof Error ? error.message : String(error),
165
+ });
166
+ }
167
+ catch {
168
+ /* Preserve the synchronization error. */
169
+ }
170
+ throw error;
171
+ }
172
+ await record(result.operation, details || undefined);
137
173
  }
138
- await activeContext.recordReceipt({
139
- ...receipt(),
140
- status: "committed",
141
- ...(details && Object.keys(details).length ? { details } : {}),
142
- });
143
174
  if (result.operation.changed) {
144
175
  if (result.operation.save?.status === "failed")
145
176
  throw new Error(`The scene edit was applied, but the save failed: ${result.operation.save.error} Do not repeat the edit.`);
146
- if (result.operation.save?.status === "unknown")
177
+ if (result.operation.save?.status === "unknown" ||
178
+ result.operation.save?.status === "requested")
147
179
  throw new Error("The scene edit was applied, but its save outcome is unknown. Inspect persistence before continuing; do not repeat the edit.");
180
+ const details = await afterCommitted?.(result.operation, api);
181
+ if (details)
182
+ await record(result.operation, details);
148
183
  }
149
184
  return result;
150
185
  }
151
186
  finally {
152
- await releaseCommit?.();
187
+ await releaseCommit?.(synchronized);
153
188
  }
154
189
  });
155
190
  },
@@ -1,14 +1,14 @@
1
- {
2
- "name": "Development: Matte Blue",
3
- "resource": {
4
- "data": {
5
- "color.x": 0.08,
6
- "color.y": 0.3,
7
- "color.z": 0.8,
8
- "roughness": 0.85,
9
- "metalness": 0,
10
- "index_of_refraction": 1.5
11
- },
12
- "shaders": []
13
- }
1
+ {
2
+ "name": "Development: Matte Blue",
3
+ "resource": {
4
+ "data": {
5
+ "color.x": 0.08,
6
+ "color.y": 0.3,
7
+ "color.z": 0.8,
8
+ "roughness": 0.85,
9
+ "metalness": 0,
10
+ "index_of_refraction": 1.5
11
+ },
12
+ "shaders": []
13
+ }
14
14
  }
@@ -1,14 +1,14 @@
1
- {
2
- "name": "Development: Polished Copper",
3
- "resource": {
4
- "data": {
5
- "color.x": 0.955,
6
- "color.y": 0.638,
7
- "color.z": 0.538,
8
- "roughness": 0.18,
9
- "metalness": 1,
10
- "index_of_refraction": 1.5
11
- },
12
- "shaders": []
13
- }
1
+ {
2
+ "name": "Development: Polished Copper",
3
+ "resource": {
4
+ "data": {
5
+ "color.x": 0.955,
6
+ "color.y": 0.638,
7
+ "color.z": 0.538,
8
+ "roughness": 0.18,
9
+ "metalness": 1,
10
+ "index_of_refraction": 1.5
11
+ },
12
+ "shaders": []
13
+ }
14
14
  }
@@ -39,14 +39,14 @@ export class SqliteSparkStore {
39
39
  CREATE TABLE IF NOT EXISTS execution_owner (
40
40
  singleton INTEGER PRIMARY KEY CHECK (singleton = 1), pid INTEGER NOT NULL, token TEXT NOT NULL
41
41
  );
42
- CREATE TABLE IF NOT EXISTS scene_operations (
43
- target_key TEXT NOT NULL, id TEXT NOT NULL, revision INTEGER NOT NULL, data TEXT NOT NULL,
44
- PRIMARY KEY (target_key, id)
45
- );
46
- CREATE TABLE IF NOT EXISTS repair_states (
47
- target_key TEXT PRIMARY KEY, revision INTEGER NOT NULL, data TEXT NOT NULL
48
- );
49
- PRAGMA user_version = 4;
42
+ CREATE TABLE IF NOT EXISTS scene_operations (
43
+ target_key TEXT NOT NULL, id TEXT NOT NULL, revision INTEGER NOT NULL, data TEXT NOT NULL,
44
+ PRIMARY KEY (target_key, id)
45
+ );
46
+ CREATE TABLE IF NOT EXISTS repair_states (
47
+ target_key TEXT PRIMARY KEY, revision INTEGER NOT NULL, data TEXT NOT NULL
48
+ );
49
+ PRAGMA user_version = 4;
50
50
  `);
51
51
  }
52
52
  repairStateStore(targetKey) {
package/package.json CHANGED
@@ -1,135 +1,135 @@
1
- {
2
- "name": "@womp/spark-agent",
3
- "version": "3.0.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
- },
11
- "exports": {
12
- "./browser": {
13
- "types": "./dist/browser.d.ts",
14
- "import": "./dist/browser.js",
15
- "default": "./dist/browser.js"
16
- },
17
- "./capabilities": {
18
- "types": "./dist/capabilities.d.ts",
19
- "import": "./dist/capabilities.js",
20
- "default": "./dist/capabilities.js"
21
- },
22
- "./kakapo": {
23
- "types": "./dist/kakapo.d.ts",
24
- "import": "./dist/kakapo.js",
25
- "default": "./dist/kakapo.js"
26
- },
27
- "./geometry": {
28
- "types": "./dist/geometry.d.ts",
29
- "import": "./dist/geometry.js",
30
- "default": "./dist/geometry.js"
31
- },
32
- "./openscad": {
33
- "types": "./dist/openscad.d.ts",
34
- "import": "./dist/openscad.js",
35
- "default": "./dist/openscad.js"
36
- },
37
- "./quickjs": {
38
- "types": "./dist/quickjs-executor.d.ts",
39
- "import": "./dist/quickjs-executor.js",
40
- "default": "./dist/quickjs-executor.js"
41
- },
42
- ".": {
43
- "types": "./dist/index.d.ts",
44
- "import": "./dist/index.js",
45
- "default": "./dist/index.js"
46
- },
47
- "./ui": {
48
- "types": "./dist/ui.d.ts",
49
- "import": "./dist/ui.js",
50
- "default": "./dist/ui.js"
51
- },
52
- "./client": {
53
- "types": "./dist/client.d.ts",
54
- "import": "./dist/client.js",
55
- "default": "./dist/client.js"
56
- },
57
- "./server": {
58
- "types": "./dist/server/index.d.ts",
59
- "import": "./dist/server/index.js",
60
- "default": "./dist/server/index.js"
61
- },
62
- "./express": {
63
- "types": "./dist/server/express.d.ts",
64
- "import": "./dist/server/express.js",
65
- "default": "./dist/server/express.js"
66
- },
67
- "./package.json": "./package.json"
68
- },
69
- "files": [
70
- "dist/**/*.js",
71
- "dist/**/*.d.ts",
72
- "dist/server/fixtures/**/*.json",
73
- "dist/geometry/schemas/**/*.json",
74
- "README.md"
75
- ],
76
- "sideEffects": false,
77
- "engines": {
78
- "node": ">=22.13"
79
- },
80
- "repository": {
81
- "type": "git",
82
- "url": "git+https://github.com/wompxyz/spark-agent.git"
83
- },
84
- "publishConfig": {
85
- "access": "public"
86
- },
87
- "license": "MIT",
88
- "scripts": {
89
- "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
90
- "build": "yarn clean && node scripts/generate-skill-declarations.mjs && tsc -p tsconfig.json && node scripts/copy-fixtures.mjs",
91
- "typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p web/tsconfig.json",
92
- "lint": "yarn typecheck",
93
- "dev": "yarn build && concurrently --kill-others \"yarn dev:server\" \"yarn dev:web\"",
94
- "dev:server": "tsx src/cli.ts",
95
- "dev:demo-account": "yarn build && concurrently --kill-others \"yarn dev:server --profile demo-account\" \"yarn dev:web\"",
96
- "dev:web": "vite --config web/vite.config.ts",
97
- "start": "node dist/cli.js",
98
- "web:build": "yarn build && tsc --noEmit -p web/tsconfig.json && vite build --config web/vite.config.ts",
99
- "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')])\"",
100
- "test:live": "tsx --tsconfig tsconfig.json test/womp-scene-api.live.ts",
101
- "prepack": "yarn build"
102
- },
103
- "dependencies": {
104
- "@ai-sdk/anthropic": "4.0.50",
105
- "@ai-sdk/google": "4.0.69",
106
- "@ai-sdk/openai": "4.0.63",
107
- "@jitl/quickjs-wasmfile-release-sync": "0.32.0",
108
- "@womp/flowir": "0.3.0",
109
- "@womp/kakapo-sdk": "0.3.0",
110
- "ai": "7.0.95",
111
- "eventsource-parser": "^3.0.6",
112
- "express": "^5.2.1",
113
- "lodash": "4.18.1",
114
- "quickjs-emscripten-core": "0.32.0",
115
- "zod": "4.5.4"
116
- },
117
- "devDependencies": {
118
- "@ai-sdk/react": "^4.0.77",
119
- "@types/express": "^5.0.5",
120
- "@types/lodash": "4.17.24",
121
- "@types/node": "^24.0.0",
122
- "@types/react": "^19.2.17",
123
- "@types/react-dom": "^19.2.3",
124
- "@vitejs/plugin-react": "^6.0.4",
125
- "concurrently": "^9.2.1",
126
- "lucide-react": "^1.26.0",
127
- "react": "^19.2.8",
128
- "react-dom": "^19.2.8",
129
- "react-markdown": "^10.1.0",
130
- "remark-gfm": "^4.0.1",
131
- "tsx": "^4.23.1",
132
- "typescript": "^5.9.3",
133
- "vite": "^8.1.5"
134
- }
135
- }
1
+ {
2
+ "name": "@womp/spark-agent",
3
+ "version": "3.0.3",
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
+ },
11
+ "exports": {
12
+ "./browser": {
13
+ "types": "./dist/browser.d.ts",
14
+ "import": "./dist/browser.js",
15
+ "default": "./dist/browser.js"
16
+ },
17
+ "./capabilities": {
18
+ "types": "./dist/capabilities.d.ts",
19
+ "import": "./dist/capabilities.js",
20
+ "default": "./dist/capabilities.js"
21
+ },
22
+ "./kakapo": {
23
+ "types": "./dist/kakapo.d.ts",
24
+ "import": "./dist/kakapo.js",
25
+ "default": "./dist/kakapo.js"
26
+ },
27
+ "./geometry": {
28
+ "types": "./dist/geometry.d.ts",
29
+ "import": "./dist/geometry.js",
30
+ "default": "./dist/geometry.js"
31
+ },
32
+ "./openscad": {
33
+ "types": "./dist/openscad.d.ts",
34
+ "import": "./dist/openscad.js",
35
+ "default": "./dist/openscad.js"
36
+ },
37
+ "./quickjs": {
38
+ "types": "./dist/quickjs-executor.d.ts",
39
+ "import": "./dist/quickjs-executor.js",
40
+ "default": "./dist/quickjs-executor.js"
41
+ },
42
+ ".": {
43
+ "types": "./dist/index.d.ts",
44
+ "import": "./dist/index.js",
45
+ "default": "./dist/index.js"
46
+ },
47
+ "./ui": {
48
+ "types": "./dist/ui.d.ts",
49
+ "import": "./dist/ui.js",
50
+ "default": "./dist/ui.js"
51
+ },
52
+ "./client": {
53
+ "types": "./dist/client.d.ts",
54
+ "import": "./dist/client.js",
55
+ "default": "./dist/client.js"
56
+ },
57
+ "./server": {
58
+ "types": "./dist/server/index.d.ts",
59
+ "import": "./dist/server/index.js",
60
+ "default": "./dist/server/index.js"
61
+ },
62
+ "./express": {
63
+ "types": "./dist/server/express.d.ts",
64
+ "import": "./dist/server/express.js",
65
+ "default": "./dist/server/express.js"
66
+ },
67
+ "./package.json": "./package.json"
68
+ },
69
+ "files": [
70
+ "dist/**/*.js",
71
+ "dist/**/*.d.ts",
72
+ "dist/server/fixtures/**/*.json",
73
+ "dist/geometry/schemas/**/*.json",
74
+ "README.md"
75
+ ],
76
+ "sideEffects": false,
77
+ "engines": {
78
+ "node": ">=22.13"
79
+ },
80
+ "repository": {
81
+ "type": "git",
82
+ "url": "git+https://github.com/wompxyz/spark-agent.git"
83
+ },
84
+ "publishConfig": {
85
+ "access": "public"
86
+ },
87
+ "license": "MIT",
88
+ "scripts": {
89
+ "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
90
+ "build": "yarn clean && node scripts/generate-skill-declarations.mjs && tsc -p tsconfig.json && node scripts/copy-fixtures.mjs",
91
+ "typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p web/tsconfig.json",
92
+ "lint": "yarn typecheck",
93
+ "dev": "yarn build && concurrently --kill-others \"yarn dev:server\" \"yarn dev:web\"",
94
+ "dev:server": "tsx src/cli.ts",
95
+ "dev:demo-account": "yarn build && concurrently --kill-others \"yarn dev:server --profile demo-account\" \"yarn dev:web\"",
96
+ "dev:web": "vite --config web/vite.config.ts",
97
+ "start": "node dist/cli.js",
98
+ "web:build": "yarn build && tsc --noEmit -p web/tsconfig.json && vite build --config web/vite.config.ts",
99
+ "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')])\"",
100
+ "test:live": "tsx --tsconfig tsconfig.json test/womp-scene-api.live.ts",
101
+ "prepack": "yarn build"
102
+ },
103
+ "dependencies": {
104
+ "@ai-sdk/anthropic": "4.0.50",
105
+ "@ai-sdk/google": "4.0.69",
106
+ "@ai-sdk/openai": "4.0.63",
107
+ "@jitl/quickjs-wasmfile-release-sync": "0.32.0",
108
+ "@womp/flowir": "0.3.0",
109
+ "@womp/kakapo-sdk": "0.3.1",
110
+ "ai": "7.0.95",
111
+ "eventsource-parser": "^3.0.6",
112
+ "express": "^5.2.1",
113
+ "lodash": "4.18.1",
114
+ "quickjs-emscripten-core": "0.32.0",
115
+ "zod": "4.5.4"
116
+ },
117
+ "devDependencies": {
118
+ "@ai-sdk/react": "^4.0.77",
119
+ "@types/express": "^5.0.5",
120
+ "@types/lodash": "4.17.24",
121
+ "@types/node": "^24.0.0",
122
+ "@types/react": "^19.2.17",
123
+ "@types/react-dom": "^19.2.3",
124
+ "@vitejs/plugin-react": "^6.0.4",
125
+ "concurrently": "^9.2.1",
126
+ "lucide-react": "^1.26.0",
127
+ "react": "^19.2.8",
128
+ "react-dom": "^19.2.8",
129
+ "react-markdown": "^10.1.0",
130
+ "remark-gfm": "^4.0.1",
131
+ "tsx": "^4.23.1",
132
+ "typescript": "^5.9.3",
133
+ "vite": "^8.1.5"
134
+ }
135
+ }