@womp/spark-agent 4.0.1 → 4.1.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.
- package/.env.example +6 -0
- package/README.md +67 -59
- package/dist/agent-tools.js +49 -7
- package/dist/capabilities/geometry.js +18 -14
- package/dist/capabilities/operations.js +13 -9
- package/dist/capabilities/scene.js +8 -8
- package/dist/generated/account-declarations.d.ts +1 -1
- package/dist/generated/account-declarations.js +1 -1
- package/dist/generated/asset-import-declarations.d.ts +1 -1
- package/dist/generated/asset-import-declarations.js +1 -1
- package/dist/generated/assets-declarations.d.ts +1 -1
- package/dist/generated/assets-declarations.js +1 -1
- package/dist/generated/flow-declarations.d.ts +1 -1
- package/dist/generated/flow-declarations.js +1 -1
- package/dist/generated/geometry-declarations.d.ts +1 -1
- package/dist/generated/geometry-declarations.js +1 -1
- package/dist/generated/knowledge-declarations.d.ts +1 -1
- package/dist/generated/knowledge-declarations.js +1 -1
- package/dist/generated/openscad-declarations.d.ts +1 -1
- package/dist/generated/openscad-declarations.js +1 -1
- package/dist/generated/operations-declarations.d.ts +1 -1
- package/dist/generated/operations-declarations.js +1 -1
- package/dist/generated/scene-declarations.d.ts +1 -1
- package/dist/generated/scene-declarations.js +1 -1
- package/dist/geometry/lower.js +3 -1
- package/dist/geometry/schemas/flowir-dialect.json +53 -9
- package/dist/geometry.js +2 -1
- package/dist/model-history.js +1 -1
- package/dist/prompt.d.ts +1 -1
- package/dist/prompt.js +57 -53
- package/dist/server/service.js +14 -16
- package/dist/tool-input-label.d.ts +2 -0
- package/dist/tool-input-label.js +39 -0
- package/dist/ui.d.ts +14 -0
- package/dist/ui.js +1 -0
- package/package.json +1 -1
package/dist/prompt.js
CHANGED
|
@@ -7,65 +7,69 @@ If a capability is unavailable, explain what is missing and ask the user to enab
|
|
|
7
7
|
Do not work around missing capabilities by inspecting page globals, DOM or framework internals,
|
|
8
8
|
or making direct network requests. Native execution is not a security sandbox; it does not expand
|
|
9
9
|
the supported API or the user's granted capabilities.
|
|
10
|
+
Give each execute_javascript call a concise present-progressive purpose, such as "Generating a car image", "Inspecting the scene", or "Importing the model". Write purpose before code.
|
|
10
11
|
Each execution has fresh local variables. Keep stable object, job, and artifact references.
|
|
11
12
|
Use print for concise, filtered observations; await emitImage or emitFile with a host-issued artifact
|
|
12
|
-
reference to show actual output.
|
|
13
|
+
reference to show actual output. emitImage inspects by default; use { inspect: false } to display without adding image bytes to model context.
|
|
14
|
+
Completed generations are shown automatically to the user; image bytes are intentionally omitted from your context. Acknowledge completion without listing, re-emitting, or inspecting outputs unless the task requires it. Use returned artifact references for follow-up work.
|
|
15
|
+
Do not claim visual verification without inspecting the image. Missing artifact references must be recovered or reported; omitted image bytes alone are not a missing result.
|
|
16
|
+
Inspect the scene before editing and verify the committed result.
|
|
13
17
|
Preserve existing content unless the user asks to replace or delete it. Use the latest target revision
|
|
14
18
|
when a write requires one. Capabilities own transactions: an entire script is not atomic.
|
|
15
19
|
If an operation fails after earlier effects, use its receipts to inspect and retry only unresolved work.
|
|
16
20
|
Never claim an uncertain commit rolled back. Never resubmit a job just because waiting timed out.
|
|
17
21
|
Complete related work in this conversation without delegating to another agent. Report limits,
|
|
18
22
|
unsupported actions, cancellation, and incomplete work truthfully. Finish with a concise explanation
|
|
19
|
-
of the result in the user's language; keep implementation details out of that explanation.
|
|
20
|
-
|
|
21
|
-
Creation intent
|
|
22
|
-
|
|
23
|
-
Choose the workflow from the user's intended result and the conversation.
|
|
24
|
-
Describe choices by their outcome, not internal tools.
|
|
25
|
-
|
|
26
|
-
- Use editable CAD for printable, measured, mechanical, or real-world-fit
|
|
27
|
-
objects. Ask about missing dimensions only when a sensible default would
|
|
28
|
-
likely make the result wrong. CAD is the preferred printing workflow;
|
|
29
|
-
do not claim print readiness without supporting validation.
|
|
30
|
-
|
|
31
|
-
- Build directly in the scene for ordinary 3D requests, including “3D X”
|
|
32
|
-
and “make X in 3D,” and when the user wants individually editable shapes
|
|
33
|
-
or geometry that blends with existing objects. Printable, measured,
|
|
34
|
-
or mechanical intent takes precedence and routes to CAD.
|
|
35
|
-
|
|
36
|
-
- Use mesh generation when the user explicitly requests a mesh, asks to
|
|
37
|
-
turn an existing image into 3D, or chooses a sculpted result rather than
|
|
38
|
-
individually editable shapes.
|
|
39
|
-
|
|
40
|
-
- Use image generation for pictures, logos, concept art, wallpapers,
|
|
41
|
-
and other clearly visual output.
|
|
42
|
-
|
|
43
|
-
- For an ambiguous creative request without explicit 3D or printing intent,
|
|
44
|
-
generate one image preview first. Then offer one short, outcome-based
|
|
45
|
-
choice: refine the image, turn it into a sculpted 3D piece, or build it
|
|
46
|
-
from individually editable shapes. Offer adjustable CAD instead of
|
|
47
|
-
editable shapes when the subject is measured or must fit something real.
|
|
48
|
-
|
|
49
|
-
- When a requested 3D subject needs fine sculpted detail or realism that
|
|
50
|
-
editable shapes cannot reasonably capture, ask before building:
|
|
51
|
-
a sculpted result from an image preview, or a simpler editable-shape build.
|
|
52
|
-
Respect an explicit choice already made by the user.
|
|
53
|
-
|
|
54
|
-
- When the user chooses editable shapes or CAD after a preview, preserve
|
|
55
|
-
its palette, proportions, and defining features. When they choose a
|
|
56
|
-
sculpted result, use that preview as the image-to-mesh input rather
|
|
57
|
-
than starting again from a text prompt.
|
|
58
|
-
|
|
59
|
-
- If the user wants repeated generation variations and Flow is available,
|
|
60
|
-
offer a reusable Flow workflow.
|
|
61
|
-
|
|
62
|
-
- Ask at most one focused question at a time, only when a sensible default
|
|
63
|
-
would likely produce the wrong outcome. Do not repeat resolved questions.
|
|
64
|
-
Interpret replies using the preceding offer; if several options were
|
|
65
|
-
offered and “yes” does not identify one, clarify briefly.
|
|
66
|
-
|
|
67
|
-
- Treat a clear answer to your question as an instruction to proceed.
|
|
68
|
-
Continue from existing results rather than restarting the workflow.
|
|
69
|
-
|
|
70
|
-
Offer only workflows available in this host. Follow their authorization
|
|
23
|
+
of the result in the user's language; keep implementation details out of that explanation.
|
|
24
|
+
|
|
25
|
+
Creation intent
|
|
26
|
+
|
|
27
|
+
Choose the workflow from the user's intended result and the conversation.
|
|
28
|
+
Describe choices by their outcome, not internal tools.
|
|
29
|
+
|
|
30
|
+
- Use editable CAD for printable, measured, mechanical, or real-world-fit
|
|
31
|
+
objects. Ask about missing dimensions only when a sensible default would
|
|
32
|
+
likely make the result wrong. CAD is the preferred printing workflow;
|
|
33
|
+
do not claim print readiness without supporting validation.
|
|
34
|
+
|
|
35
|
+
- Build directly in the scene for ordinary 3D requests, including “3D X”
|
|
36
|
+
and “make X in 3D,” and when the user wants individually editable shapes
|
|
37
|
+
or geometry that blends with existing objects. Printable, measured,
|
|
38
|
+
or mechanical intent takes precedence and routes to CAD.
|
|
39
|
+
|
|
40
|
+
- Use mesh generation when the user explicitly requests a mesh, asks to
|
|
41
|
+
turn an existing image into 3D, or chooses a sculpted result rather than
|
|
42
|
+
individually editable shapes.
|
|
43
|
+
|
|
44
|
+
- Use image generation for pictures, logos, concept art, wallpapers,
|
|
45
|
+
and other clearly visual output.
|
|
46
|
+
|
|
47
|
+
- For an ambiguous creative request without explicit 3D or printing intent,
|
|
48
|
+
generate one image preview first. Then offer one short, outcome-based
|
|
49
|
+
choice: refine the image, turn it into a sculpted 3D piece, or build it
|
|
50
|
+
from individually editable shapes. Offer adjustable CAD instead of
|
|
51
|
+
editable shapes when the subject is measured or must fit something real.
|
|
52
|
+
|
|
53
|
+
- When a requested 3D subject needs fine sculpted detail or realism that
|
|
54
|
+
editable shapes cannot reasonably capture, ask before building:
|
|
55
|
+
a sculpted result from an image preview, or a simpler editable-shape build.
|
|
56
|
+
Respect an explicit choice already made by the user.
|
|
57
|
+
|
|
58
|
+
- When the user chooses editable shapes or CAD after a preview, preserve
|
|
59
|
+
its palette, proportions, and defining features. When they choose a
|
|
60
|
+
sculpted result, use that preview as the image-to-mesh input rather
|
|
61
|
+
than starting again from a text prompt.
|
|
62
|
+
|
|
63
|
+
- If the user wants repeated generation variations and Flow is available,
|
|
64
|
+
offer a reusable Flow workflow.
|
|
65
|
+
|
|
66
|
+
- Ask at most one focused question at a time, only when a sensible default
|
|
67
|
+
would likely produce the wrong outcome. Do not repeat resolved questions.
|
|
68
|
+
Interpret replies using the preceding offer; if several options were
|
|
69
|
+
offered and “yes” does not identify one, clarify briefly.
|
|
70
|
+
|
|
71
|
+
- Treat a clear answer to your question as an instruction to proceed.
|
|
72
|
+
Continue from existing results rather than restarting the workflow.
|
|
73
|
+
|
|
74
|
+
Offer only workflows available in this host. Follow their authorization
|
|
71
75
|
and confirmation requirements before generation or scene changes.`;
|
package/dist/server/service.js
CHANGED
|
@@ -68,7 +68,7 @@ export class SparkAgentService {
|
|
|
68
68
|
executeRun;
|
|
69
69
|
controllers = new Map();
|
|
70
70
|
listeners = new Map();
|
|
71
|
-
executions = new
|
|
71
|
+
executions = new Map();
|
|
72
72
|
constructor(options) {
|
|
73
73
|
this.store = options.store;
|
|
74
74
|
this.executeRun = options.executeRun;
|
|
@@ -138,7 +138,7 @@ export class SparkAgentService {
|
|
|
138
138
|
async close() {
|
|
139
139
|
for (const controller of this.controllers.values())
|
|
140
140
|
controller.abort(new Error("Standalone host is shutting down"));
|
|
141
|
-
await Promise.all([...this.executions]);
|
|
141
|
+
await Promise.all([...this.executions.values()]);
|
|
142
142
|
}
|
|
143
143
|
async submitMessage(input) {
|
|
144
144
|
const conversation = await this.getConversation(input.ownerId, input.conversationId);
|
|
@@ -208,8 +208,8 @@ export class SparkAgentService {
|
|
|
208
208
|
const controller = new AbortController();
|
|
209
209
|
this.controllers.set(run.id, controller);
|
|
210
210
|
const execution = this.runInBackground(run, conversation, controller);
|
|
211
|
-
this.executions.
|
|
212
|
-
void execution.finally(() => this.executions.delete(
|
|
211
|
+
this.executions.set(run.id, execution);
|
|
212
|
+
void execution.finally(() => this.executions.delete(run.id)).catch((error) => {
|
|
213
213
|
console.error("Spark run persistence failed", error);
|
|
214
214
|
});
|
|
215
215
|
return run;
|
|
@@ -218,18 +218,14 @@ export class SparkAgentService {
|
|
|
218
218
|
const run = await this.getRun(ownerId, runId);
|
|
219
219
|
if (TERMINAL_STATUSES.has(run.status))
|
|
220
220
|
return run;
|
|
221
|
-
|
|
222
|
-
this.
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
};
|
|
230
|
-
await this.store.saveRun(cancelled);
|
|
231
|
-
this.wakeRun(run.id);
|
|
232
|
-
return cancelled;
|
|
221
|
+
const controller = this.controllers.get(run.id);
|
|
222
|
+
const execution = this.executions.get(run.id);
|
|
223
|
+
if (!controller || !execution)
|
|
224
|
+
throw new Error("The run's executor is unavailable; cancellation could not be confirmed.");
|
|
225
|
+
controller.abort(new Error("Run cancelled by the user."));
|
|
226
|
+
// Drain receipts and pending host work before publishing a terminal state.
|
|
227
|
+
await execution;
|
|
228
|
+
return this.getRun(ownerId, runId);
|
|
233
229
|
}
|
|
234
230
|
async *streamRun(ownerId, runId, afterSequence, signal) {
|
|
235
231
|
await this.getRun(ownerId, runId);
|
|
@@ -331,6 +327,7 @@ export class SparkAgentService {
|
|
|
331
327
|
if (executionError !== undefined)
|
|
332
328
|
throw executionError;
|
|
333
329
|
if (controller.signal.aborted) {
|
|
330
|
+
await this.appendStatus(run, "cancelled");
|
|
334
331
|
await this.finishRun(run, conversation, "cancelled");
|
|
335
332
|
return;
|
|
336
333
|
}
|
|
@@ -340,6 +337,7 @@ export class SparkAgentService {
|
|
|
340
337
|
}
|
|
341
338
|
catch (error) {
|
|
342
339
|
if (controller.signal.aborted) {
|
|
340
|
+
await this.appendStatus(run, "cancelled");
|
|
343
341
|
await this.finishRun(run, conversation, "cancelled");
|
|
344
342
|
return;
|
|
345
343
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Read a fully closed top-level JSON string without repairing partial JSON. */
|
|
2
|
+
export function completedInputString(text, field) {
|
|
3
|
+
const tokens = /\s+|"(?:[^"\\\x00-\x1f]|\\(?:["\\/bfnrt]|u[0-9a-fA-F]{4}))*"|[{}\[\]:,]|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null/gy;
|
|
4
|
+
let depth = 0;
|
|
5
|
+
let key;
|
|
6
|
+
let expecting = "key";
|
|
7
|
+
let token;
|
|
8
|
+
while ((token = tokens.exec(text))) {
|
|
9
|
+
const value = token[0];
|
|
10
|
+
if (!value.trim())
|
|
11
|
+
continue;
|
|
12
|
+
if (depth === 1) {
|
|
13
|
+
if (expecting === "key" && value.startsWith('"')) {
|
|
14
|
+
key = JSON.parse(value);
|
|
15
|
+
expecting = "colon";
|
|
16
|
+
}
|
|
17
|
+
else if (expecting === "colon" && value === ":") {
|
|
18
|
+
expecting = "value";
|
|
19
|
+
}
|
|
20
|
+
else if (expecting === "value") {
|
|
21
|
+
if (key === field && value.startsWith('"'))
|
|
22
|
+
return JSON.parse(value);
|
|
23
|
+
expecting = "comma";
|
|
24
|
+
}
|
|
25
|
+
else if (expecting === "comma" && value === ",") {
|
|
26
|
+
expecting = "key";
|
|
27
|
+
}
|
|
28
|
+
else if (value !== "}")
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
if (value === "{" || value === "[")
|
|
32
|
+
depth++;
|
|
33
|
+
if (value === "}" || value === "]")
|
|
34
|
+
depth--;
|
|
35
|
+
if (depth <= 0)
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
package/dist/ui.d.ts
CHANGED
|
@@ -70,6 +70,11 @@ export declare const sparkExecutionReceiptSchema: z.ZodObject<{
|
|
|
70
70
|
details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
71
71
|
}, z.core.$strip>;
|
|
72
72
|
export type SparkDataParts = {
|
|
73
|
+
"tool-input-label": {
|
|
74
|
+
toolCallId: string;
|
|
75
|
+
field: "name" | "purpose";
|
|
76
|
+
value: string;
|
|
77
|
+
};
|
|
73
78
|
console: SparkConsoleData;
|
|
74
79
|
artifact: SparkArtifact;
|
|
75
80
|
"run-status": SparkRunStatusData;
|
|
@@ -93,6 +98,7 @@ export type ExecuteJavaScriptOutput = {
|
|
|
93
98
|
artifacts: {
|
|
94
99
|
kind: "image" | "file";
|
|
95
100
|
artifact: SparkArtifact;
|
|
101
|
+
inspect?: boolean;
|
|
96
102
|
}[];
|
|
97
103
|
error?: string;
|
|
98
104
|
};
|
|
@@ -153,6 +159,14 @@ export declare const sparkMessageMetadataSchema: z.ZodObject<{
|
|
|
153
159
|
error: z.ZodOptional<z.ZodString>;
|
|
154
160
|
}, z.core.$strip>;
|
|
155
161
|
export declare const sparkDataPartSchemas: {
|
|
162
|
+
readonly "tool-input-label": z.ZodObject<{
|
|
163
|
+
toolCallId: z.ZodString;
|
|
164
|
+
field: z.ZodEnum<{
|
|
165
|
+
name: "name";
|
|
166
|
+
purpose: "purpose";
|
|
167
|
+
}>;
|
|
168
|
+
value: z.ZodString;
|
|
169
|
+
}, z.core.$strip>;
|
|
156
170
|
readonly "execution-receipt": z.ZodObject<{
|
|
157
171
|
toolCallId: z.ZodString;
|
|
158
172
|
receipt: z.ZodObject<{
|
package/dist/ui.js
CHANGED
|
@@ -50,6 +50,7 @@ export const sparkMessageMetadataSchema = z.object({
|
|
|
50
50
|
error: z.string().optional(),
|
|
51
51
|
});
|
|
52
52
|
export const sparkDataPartSchemas = {
|
|
53
|
+
"tool-input-label": z.object({ toolCallId: z.string(), field: z.enum(["name", "purpose"]), value: z.string() }),
|
|
53
54
|
"execution-receipt": z.object({ toolCallId: z.string(), receipt: sparkExecutionReceiptSchema }),
|
|
54
55
|
console: z.object({
|
|
55
56
|
stream: z.enum(["stdout", "stderr"]),
|