@compilr-dev/sdk 0.32.0 → 0.33.1
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.
|
@@ -161,60 +161,94 @@ export const MODEL_REGISTRY = [
|
|
|
161
161
|
// ---------------------------------------------------------------------------
|
|
162
162
|
// Gemini 2.x - Supported
|
|
163
163
|
{
|
|
164
|
-
id: 'gemini-
|
|
165
|
-
displayName: 'Gemini
|
|
166
|
-
description: '
|
|
164
|
+
id: 'gemini-3.8-flash',
|
|
165
|
+
displayName: 'Gemini 3.8 Flash',
|
|
166
|
+
description: 'Most capable',
|
|
167
167
|
provider: 'gemini',
|
|
168
168
|
supportsImages: true,
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
supportsTools: true,
|
|
170
|
+
defaultTier: 'powerful',
|
|
171
|
+
thinkingFormat: 'gemini-v3',
|
|
171
172
|
status: 'supported',
|
|
172
|
-
contextWindow:
|
|
173
|
+
contextWindow: 1048576,
|
|
174
|
+
notes: 'Newest Flash; max output 65,536',
|
|
173
175
|
},
|
|
174
176
|
{
|
|
175
|
-
id: 'gemini-
|
|
176
|
-
displayName: 'Gemini
|
|
177
|
+
id: 'gemini-3.5-flash',
|
|
178
|
+
displayName: 'Gemini 3.5 Flash',
|
|
177
179
|
description: 'Balanced (recommended)',
|
|
178
180
|
provider: 'gemini',
|
|
179
181
|
supportsImages: true,
|
|
182
|
+
supportsTools: true,
|
|
180
183
|
defaultTier: 'balanced',
|
|
181
|
-
thinkingFormat: 'gemini-
|
|
184
|
+
thinkingFormat: 'gemini-v3',
|
|
182
185
|
status: 'supported',
|
|
183
|
-
contextWindow:
|
|
186
|
+
contextWindow: 1048576,
|
|
187
|
+
notes: 'GA; max output 65,536',
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
id: 'gemini-3.5-flash-lite',
|
|
191
|
+
displayName: 'Gemini 3.5 Flash Lite',
|
|
192
|
+
description: 'Fast, low cost',
|
|
193
|
+
provider: 'gemini',
|
|
194
|
+
supportsImages: true,
|
|
195
|
+
supportsTools: true,
|
|
196
|
+
defaultTier: 'fast',
|
|
197
|
+
thinkingFormat: 'gemini-v3',
|
|
198
|
+
status: 'supported',
|
|
199
|
+
contextWindow: 1048576,
|
|
200
|
+
notes: 'Max output 65,536',
|
|
184
201
|
},
|
|
202
|
+
{
|
|
203
|
+
id: 'gemini-3.1-pro-preview',
|
|
204
|
+
displayName: 'Gemini 3.1 Pro (Preview)',
|
|
205
|
+
description: 'Pro tier, preview',
|
|
206
|
+
provider: 'gemini',
|
|
207
|
+
supportsImages: true,
|
|
208
|
+
supportsTools: true,
|
|
209
|
+
thinkingFormat: 'gemini-v3',
|
|
210
|
+
status: 'experimental',
|
|
211
|
+
contextWindow: 1048576,
|
|
212
|
+
notes: 'The only Pro on the Gemini API; PREVIEW — measured 2026-09-30, ~1 turn in 5 returns ' +
|
|
213
|
+
'MALFORMED_RESPONSE (the provider now reports it instead of showing its internal text)',
|
|
214
|
+
},
|
|
215
|
+
// Legacy Gemini models. ⚠️ Google restricts the 2.5 line to accounts that already used it,
|
|
216
|
+
// so these can fail for a new key even though they work for an established one.
|
|
185
217
|
{
|
|
186
218
|
id: 'gemini-2.5-pro',
|
|
187
219
|
displayName: 'Gemini 2.5 Pro',
|
|
188
|
-
description: '
|
|
220
|
+
description: 'Previous generation',
|
|
189
221
|
provider: 'gemini',
|
|
190
222
|
supportsImages: true,
|
|
191
|
-
|
|
223
|
+
supportsTools: true,
|
|
192
224
|
thinkingFormat: 'gemini-v2',
|
|
193
225
|
status: 'supported',
|
|
194
|
-
contextWindow:
|
|
226
|
+
contextWindow: 1048576,
|
|
227
|
+
notes: 'Legacy — restricted to accounts that used it before; consider Gemini 3.8 Flash',
|
|
195
228
|
},
|
|
196
|
-
// Gemini 3.x - Preview, has stability issues with function calling
|
|
197
229
|
{
|
|
198
|
-
id: 'gemini-
|
|
199
|
-
displayName: 'Gemini
|
|
200
|
-
description: '
|
|
230
|
+
id: 'gemini-2.5-flash',
|
|
231
|
+
displayName: 'Gemini 2.5 Flash',
|
|
232
|
+
description: 'Previous generation',
|
|
201
233
|
provider: 'gemini',
|
|
202
234
|
supportsImages: true,
|
|
203
|
-
|
|
235
|
+
supportsTools: true,
|
|
236
|
+
thinkingFormat: 'gemini-v2',
|
|
204
237
|
status: 'supported',
|
|
205
|
-
contextWindow:
|
|
206
|
-
notes: '
|
|
238
|
+
contextWindow: 1048576,
|
|
239
|
+
notes: 'Legacy — restricted to accounts that used it before; consider Gemini 3.5 Flash',
|
|
207
240
|
},
|
|
208
241
|
{
|
|
209
|
-
id: 'gemini-
|
|
210
|
-
displayName: 'Gemini
|
|
211
|
-
description: '
|
|
242
|
+
id: 'gemini-2.5-flash-lite',
|
|
243
|
+
displayName: 'Gemini 2.5 Flash Lite',
|
|
244
|
+
description: 'Previous generation',
|
|
212
245
|
provider: 'gemini',
|
|
213
246
|
supportsImages: true,
|
|
214
|
-
|
|
247
|
+
supportsTools: true,
|
|
248
|
+
thinkingFormat: 'gemini-v2',
|
|
215
249
|
status: 'supported',
|
|
216
|
-
contextWindow:
|
|
217
|
-
notes: '
|
|
250
|
+
contextWindow: 1048576,
|
|
251
|
+
notes: 'Legacy — restricted to accounts that used it before; consider Gemini 3.5 Flash Lite',
|
|
218
252
|
},
|
|
219
253
|
// ---------------------------------------------------------------------------
|
|
220
254
|
// OpenAI Models
|
|
@@ -18,6 +18,37 @@ import { type SceneFile } from '../../canvas/scene.js';
|
|
|
18
18
|
export declare const SCENE_TOOL_NAMES: readonly ["scene_create", "scene_get", "scene_add_object", "scene_update_object", "scene_remove_object", "scene_set_camera", "scene_screenshot"];
|
|
19
19
|
/** "sofa · box · Sofa" rows, indented under their group parent. */
|
|
20
20
|
export declare function sceneOutline(scene: SceneFile): string;
|
|
21
|
+
/**
|
|
22
|
+
* The most JSON one `scene_get` may return.
|
|
23
|
+
*
|
|
24
|
+
* ⚠️ Sized to stay UNDER the context manager's 8,000-token delegation threshold
|
|
25
|
+
* (`delegationThreshold`, agents lib). A read that crosses it gets auto-summarised — and a
|
|
26
|
+
* summary of a scene loses the exact object ids, which is the one thing the agent reads a scene
|
|
27
|
+
* for. So an oversized read must be refused with instructions, never silently shortened.
|
|
28
|
+
*/
|
|
29
|
+
export declare const SCENE_READ_MAX_CHARS = 20000;
|
|
30
|
+
/**
|
|
31
|
+
* What `scene_get` returns: the outline, named objects in full, or the whole scene.
|
|
32
|
+
*
|
|
33
|
+
* ⚠️ THE OUTLINE IS THE DEFAULT ON PURPOSE. This tool used to return
|
|
34
|
+
* `serializeScene(scene)` every time, and its own description told the agent to call it before
|
|
35
|
+
* every edit — about 4,500 tokens for a 51-object house, 11x the outline, on every read of a
|
|
36
|
+
* build loop. It also taught the model to answer in the same register: having just read a page
|
|
37
|
+
* of fully-specified pretty-printed JSON, it would emit one enormous `scene_add_object` and get
|
|
38
|
+
* cut off at the output limit mid-arguments.
|
|
39
|
+
*
|
|
40
|
+
* The outline carries ids, types, names and hierarchy — enough to address anything. Numbers come
|
|
41
|
+
* from `ids`, which is the common case for an edit (the roof, not the house).
|
|
42
|
+
*
|
|
43
|
+
* See 3d-canvas-spec §6.4 for the measurements. Exported for its tests.
|
|
44
|
+
*/
|
|
45
|
+
export declare function sceneReadBody(scene: SceneFile, head: string, ids: unknown, full: unknown): {
|
|
46
|
+
ok: true;
|
|
47
|
+
text: string;
|
|
48
|
+
} | {
|
|
49
|
+
ok: false;
|
|
50
|
+
error: string;
|
|
51
|
+
};
|
|
21
52
|
/**
|
|
22
53
|
* Render a scene through the host's `renderSceneToImage` — shared by scene_screenshot and
|
|
23
54
|
* canvas_screenshot (either tool works on a scene).
|
|
@@ -47,6 +78,10 @@ export declare function createSceneTools(config: PlatformToolsConfig, options?:
|
|
|
47
78
|
title: string;
|
|
48
79
|
scene?: unknown;
|
|
49
80
|
project_id?: number;
|
|
81
|
+
}> | import("@compilr-dev/agents").Tool<{
|
|
82
|
+
canvas_id: number;
|
|
83
|
+
ids?: unknown;
|
|
84
|
+
full?: unknown;
|
|
50
85
|
}> | import("@compilr-dev/agents").Tool<Record<string, unknown> & {
|
|
51
86
|
canvas_id: number;
|
|
52
87
|
}> | import("@compilr-dev/agents").Tool<{
|
|
@@ -72,6 +72,75 @@ export function sceneOutline(scene) {
|
|
|
72
72
|
walk(undefined, 0);
|
|
73
73
|
return rows.join('\n');
|
|
74
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* The most JSON one `scene_get` may return.
|
|
77
|
+
*
|
|
78
|
+
* ⚠️ Sized to stay UNDER the context manager's 8,000-token delegation threshold
|
|
79
|
+
* (`delegationThreshold`, agents lib). A read that crosses it gets auto-summarised — and a
|
|
80
|
+
* summary of a scene loses the exact object ids, which is the one thing the agent reads a scene
|
|
81
|
+
* for. So an oversized read must be refused with instructions, never silently shortened.
|
|
82
|
+
*/
|
|
83
|
+
export const SCENE_READ_MAX_CHARS = 20_000;
|
|
84
|
+
/** "roof, walls" — the first few of a list, for an error that has to name what is available. */
|
|
85
|
+
function someIds(ids, limit = 12) {
|
|
86
|
+
return ids.length <= limit
|
|
87
|
+
? ids.join(', ')
|
|
88
|
+
: `${ids.slice(0, limit).join(', ')}, … (${String(ids.length)} in all)`;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* What `scene_get` returns: the outline, named objects in full, or the whole scene.
|
|
92
|
+
*
|
|
93
|
+
* ⚠️ THE OUTLINE IS THE DEFAULT ON PURPOSE. This tool used to return
|
|
94
|
+
* `serializeScene(scene)` every time, and its own description told the agent to call it before
|
|
95
|
+
* every edit — about 4,500 tokens for a 51-object house, 11x the outline, on every read of a
|
|
96
|
+
* build loop. It also taught the model to answer in the same register: having just read a page
|
|
97
|
+
* of fully-specified pretty-printed JSON, it would emit one enormous `scene_add_object` and get
|
|
98
|
+
* cut off at the output limit mid-arguments.
|
|
99
|
+
*
|
|
100
|
+
* The outline carries ids, types, names and hierarchy — enough to address anything. Numbers come
|
|
101
|
+
* from `ids`, which is the common case for an edit (the roof, not the house).
|
|
102
|
+
*
|
|
103
|
+
* See 3d-canvas-spec §6.4 for the measurements. Exported for its tests.
|
|
104
|
+
*/
|
|
105
|
+
export function sceneReadBody(scene, head, ids, full) {
|
|
106
|
+
const known = scene.objects.map((o) => o.id);
|
|
107
|
+
const guard = (json, over) => json.length > SCENE_READ_MAX_CHARS
|
|
108
|
+
? { ok: false, error: over }
|
|
109
|
+
: { ok: true, text: `${head}\n\n${json}` };
|
|
110
|
+
if (ids !== undefined) {
|
|
111
|
+
if (!Array.isArray(ids) || ids.some((i) => typeof i !== 'string')) {
|
|
112
|
+
return { ok: false, error: 'ids must be an array of object id strings.' };
|
|
113
|
+
}
|
|
114
|
+
const wanted = ids;
|
|
115
|
+
if (wanted.length === 0)
|
|
116
|
+
return {
|
|
117
|
+
ok: false,
|
|
118
|
+
error: 'ids was empty. Omit it for the outline, or name the objects you need.',
|
|
119
|
+
};
|
|
120
|
+
const found = scene.objects.filter((o) => wanted.includes(o.id));
|
|
121
|
+
const missing = wanted.filter((i) => !known.includes(i));
|
|
122
|
+
if (found.length === 0) {
|
|
123
|
+
return {
|
|
124
|
+
ok: false,
|
|
125
|
+
error: `No object in this scene has ${missing.length === 1 ? 'that id' : 'those ids'} (${someIds(missing)}). The scene has: ${someIds(known)}. Call scene_get without ids for the outline.`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const body = guard(JSON.stringify(found, null, 2), `Those ${String(wanted.length)} objects come to more than ${String(SCENE_READ_MAX_CHARS)} characters. Ask for fewer ids at a time.`);
|
|
129
|
+
// A partial hit still answers, but says what was not there — a silently short list reads as
|
|
130
|
+
// "those objects do not exist".
|
|
131
|
+
if (body.ok && missing.length > 0) {
|
|
132
|
+
return { ok: true, text: `${body.text}\n\nNot in this scene: ${someIds(missing)}.` };
|
|
133
|
+
}
|
|
134
|
+
return body;
|
|
135
|
+
}
|
|
136
|
+
if (full === true) {
|
|
137
|
+
return guard(serializeScene(scene), `This scene's JSON is over ${String(SCENE_READ_MAX_CHARS)} characters, which would be summarised before you saw it and you would lose the ids. Call scene_get without full for the outline, then with ids: [...] for the objects you need.`);
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
ok: true,
|
|
141
|
+
text: `${head}\n\n--- objects (id · type · name) ---\n${sceneOutline(scene)}`,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
75
144
|
function clampShot(v, fallback) {
|
|
76
145
|
if (typeof v !== 'number' || !Number.isFinite(v))
|
|
77
146
|
return fallback;
|
|
@@ -231,7 +300,8 @@ export function createSceneTools(config, options) {
|
|
|
231
300
|
name: 'scene_create',
|
|
232
301
|
description: 'Create a 3D SCENE canvas — objects in metres the user can orbit, select, edit and export. ' +
|
|
233
302
|
'Scenes are JSON data, not HTML/code (never use canvas_write for 3D). Pass only a title for an ' +
|
|
234
|
-
'empty scene, then build it with scene_add_object (up to 50
|
|
303
|
+
'empty scene, then build it with scene_add_object (up to 50 per call, but see its note on ' +
|
|
304
|
+
'batch size), or pass a whole ' +
|
|
235
305
|
'scene { objects: [...], camera?, lights? }. Returns the canvas ID used by every scene_* tool.',
|
|
236
306
|
inputSchema: {
|
|
237
307
|
type: 'object',
|
|
@@ -284,12 +354,26 @@ export function createSceneTools(config, options) {
|
|
|
284
354
|
// ---------------------------------------------------------------------------
|
|
285
355
|
const sceneGetTool = defineTool({
|
|
286
356
|
name: 'scene_get',
|
|
287
|
-
description: 'Read a 3D scene
|
|
288
|
-
'
|
|
357
|
+
description: 'Read a 3D scene. By default returns a one-line summary and the OUTLINE — every object as ' +
|
|
358
|
+
'"id · type · name", indented by group — which is what you need to address objects. ' +
|
|
359
|
+
'Always read before editing: the user edits scenes too, and object ids come from here. ' +
|
|
360
|
+
'For an object\'s numbers (position, size, rotation, colour) pass ids: ["roof", "walls"] ' +
|
|
361
|
+
'and you get those objects in full. full: true dumps the entire scene JSON and is rarely ' +
|
|
362
|
+
'worth it — it costs about 11x the outline and is refused on a large scene.',
|
|
289
363
|
inputSchema: {
|
|
290
364
|
type: 'object',
|
|
291
365
|
properties: {
|
|
292
366
|
canvas_id: { type: 'number', description: 'The scene canvas id.' },
|
|
367
|
+
ids: {
|
|
368
|
+
type: 'array',
|
|
369
|
+
items: { type: 'string' },
|
|
370
|
+
description: 'Return these objects IN FULL (all their fields) instead of the outline. The ids come ' +
|
|
371
|
+
'from a previous outline. This is the right way to read detail before an edit.',
|
|
372
|
+
},
|
|
373
|
+
full: {
|
|
374
|
+
type: 'boolean',
|
|
375
|
+
description: 'Return the whole scene as JSON. Only for a wholesale rewrite or an export; prefer ids.',
|
|
376
|
+
},
|
|
293
377
|
},
|
|
294
378
|
required: ['canvas_id'],
|
|
295
379
|
},
|
|
@@ -298,9 +382,11 @@ export function createSceneTools(config, options) {
|
|
|
298
382
|
const r = await writer.read(input.canvas_id);
|
|
299
383
|
if (!r.ok)
|
|
300
384
|
return createErrorResult(r.error);
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
385
|
+
const head = `Scene "${r.title}" (canvas ${String(r.canvasId)}): ${describeScene(r.scene)} · rev ${String(r.rev)}`;
|
|
386
|
+
const body = sceneReadBody(r.scene, head, input.ids, input.full);
|
|
387
|
+
if (!body.ok)
|
|
388
|
+
return createErrorResult(body.error);
|
|
389
|
+
return { success: true, result: withNotice(r.canvasId, body.text) };
|
|
304
390
|
}
|
|
305
391
|
catch (error) {
|
|
306
392
|
return createErrorResult(errorMessage('read scene', error));
|
|
@@ -314,7 +400,11 @@ export function createSceneTools(config, options) {
|
|
|
314
400
|
"Units are metres; position.y is the object's BOTTOM (0 = on the floor); rotation in degrees about Y. " +
|
|
315
401
|
'Build hierarchically: a type "group" with your own id (e.g. "house", then "walls", "roof" inside it), ' +
|
|
316
402
|
'and its parts with group: "<id>" — a batch may name a group it creates itself. ' +
|
|
317
|
-
'Returns the new id(s) — yours, or generated from name when id is omitted.'
|
|
403
|
+
'Returns the new id(s) — yours, or generated from name when id is omitted. ' +
|
|
404
|
+
'BATCH SIZE: about 15-20 per call once objects carry names, colours, groups and rotations. ' +
|
|
405
|
+
'Fifty of those is roughly 3,000 tokens of arguments, your reasoning is drawn from the same ' +
|
|
406
|
+
'output budget, and a call cut off at that limit adds NOTHING and has to be redone — so two ' +
|
|
407
|
+
'moderate calls finish sooner than one oversized one.',
|
|
318
408
|
inputSchema: {
|
|
319
409
|
type: 'object',
|
|
320
410
|
properties: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@compilr-dev/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"description": "Universal agent runtime for building AI-powered applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"node": ">=20.0.0"
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
|
-
"@compilr-dev/agents": "^0.7.
|
|
84
|
+
"@compilr-dev/agents": "^0.7.1",
|
|
85
85
|
"@compilr-dev/logger": "^0.1.0",
|
|
86
86
|
"ajv": "^6.14.0",
|
|
87
87
|
"yaml": "^2.8.4"
|