@instruktlabs/kiln 1.1.0 → 1.2.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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +12 -0
- package/dist/agent-run.mjs +220 -150
- package/dist/build.json +22 -22
- package/dist/cli.mjs +225 -150
- package/dist/mcp-engine.mjs +398 -144
- package/dist/mcp-server.mjs +1 -1
- package/docs/sdk.md +23 -0
- package/docs/tools-operations.md +1529 -0
- package/lib/discovery/index.d.ts +1 -1
- package/lib/discovery/index.js +2 -2
- package/lib/discovery/service.d.ts +3 -1
- package/lib/discovery/service.js +4 -2
- package/lib/engine-identity.d.ts +1 -1
- package/lib/engine-identity.js +1 -1
- package/lib/mcp-core.d.ts +2 -1
- package/lib/mcp-core.js +1 -0
- package/lib/mcp-engine.d.ts +2 -0
- package/lib/mcp-engine.js +8 -3
- package/lib/tools/discovery.d.ts +1 -1
- package/lib/tools/discovery.js +11 -9
- package/lib/tools/materials.d.ts +1 -1
- package/lib/tools/materials.js +44 -14
- package/lib/tools/operation-contract.d.ts +8 -0
- package/lib/tools/operation-contract.js +37 -0
- package/lib/tools/operations.d.ts +3 -0
- package/lib/tools/operations.js +154 -0
- package/lib/tools/registry.d.ts +6 -2
- package/lib/tools/registry.js +71 -23
- package/package.json +2 -1
- package/plugin.json +1 -1
- package/plugins/kiln-engine/.claude-plugin/plugin.json +1 -1
- package/plugins/kiln-engine/README.md +3 -3
- package/plugins/kiln-engine/package-provenance.json +6 -6
- package/plugins/kiln-engine/plugin.json +1 -1
- package/plugins/kiln-engine/runtime.json +1 -1
- package/src/discovery/index.ts +2 -0
- package/src/discovery/service.ts +3 -1
- package/src/engine-identity.ts +1 -1
- package/src/mcp-core.ts +3 -0
- package/src/mcp-engine.ts +11 -1
- package/src/tools/discovery.ts +20 -10
- package/src/tools/materials.ts +59 -15
- package/src/tools/operation-contract.ts +51 -0
- package/src/tools/operations.ts +177 -0
- package/src/tools/registry.ts +100 -20
package/dist/mcp-engine.mjs
CHANGED
|
@@ -36106,7 +36106,7 @@ import { readFile as readFile8 } from "node:fs/promises";
|
|
|
36106
36106
|
var KILN_ASSET_WIDGET_URI = "ui://kiln/asset-v5.html";
|
|
36107
36107
|
|
|
36108
36108
|
// src/engine-identity.ts
|
|
36109
|
-
var ENGINE_VERSION = "1.
|
|
36109
|
+
var ENGINE_VERSION = "1.2.0";
|
|
36110
36110
|
var ENGINE_INSTALL_URL = new URL("../", import.meta.url).href;
|
|
36111
36111
|
function engineIdentity() {
|
|
36112
36112
|
return { version: ENGINE_VERSION, installUrl: ENGINE_INSTALL_URL };
|
|
@@ -36117,6 +36117,7 @@ init_requirements_json();
|
|
|
36117
36117
|
var MCP_SERVER_NAME = "kiln";
|
|
36118
36118
|
var MCP_SERVER_VERSION = ENGINE_VERSION;
|
|
36119
36119
|
var MCP_SERVER_INSTRUCTIONS = "Kiln turns JavaScript you write into GLB assets and returns rendered views. Work by reference: send a program once to kiln_validate or kiln_render, keep the returned programRef exactly, and use it for every later render, inspect, kiln_source and kiln_edit call; never resend a program to change part of it. Call kiln_discover first for helper contracts, with capabilities:true for the host's runtime, project and camera facts. Read viewFidelity before judging materials: a CPU view shows shape, not material; GPU views need the render service in render-service/. Agent Skills for authoring, refining, QA and scenes ship in skills/ beside this server's dist/; read the matching SKILL.md first.";
|
|
36120
|
+
var MCP_OPERATION_INSTRUCTIONS = "Kiln turns authored JavaScript into editable GLB assets and rendered views. Send source once to kiln_validate or kiln_render, then preserve the exact programRef for later reads, edits and renders. Use kiln_discover for helper contracts and full input shapes; use kiln_capabilities for host configuration and limits. Read viewFidelity before judging materials: CPU geometry views are not material evidence. Search saved assets with kiln_assets_search; reopen exact source with kiln_assets_restore. Browse materials with kiln_material_search and create with kiln_material_create. Save only when requested. Pin collection, asset and revision IDs for reuse and export.";
|
|
36120
36121
|
var KILN_WIDGET_META = {
|
|
36121
36122
|
ui: { prefersBorder: true, csp: { connectDomains: [], resourceDomains: [] } },
|
|
36122
36123
|
"openai/widgetDescription": "Inspect the saved 3D asset and download its GLB or editable bundle.",
|
|
@@ -36243,7 +36244,7 @@ var PRE_HANDSHAKE_METHODS = new Set(["initialize", "ping"]);
|
|
|
36243
36244
|
// src/tools/registry.ts
|
|
36244
36245
|
init_capture_cache();
|
|
36245
36246
|
init_assets();
|
|
36246
|
-
import { z as
|
|
36247
|
+
import { z as z23 } from "zod";
|
|
36247
36248
|
|
|
36248
36249
|
// src/requirements-assets.ts
|
|
36249
36250
|
init_requirements_context();
|
|
@@ -40400,7 +40401,7 @@ var MAX_RESPONSE_BYTES = 64 * 1024;
|
|
|
40400
40401
|
var MAX_TEXT_CHARS = 16 * 1024;
|
|
40401
40402
|
var DETAIL_RESULT_BUDGET = 15000;
|
|
40402
40403
|
var compare2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
40403
|
-
function createDiscoveryService(source, index, capabilities, retirements = {}, notes = async () => []) {
|
|
40404
|
+
function createDiscoveryService(source, index, capabilities, retirements = {}, notes = async () => [], capabilitiesCall = "capabilities:true") {
|
|
40404
40405
|
const entries = parseCatalog(source);
|
|
40405
40406
|
const byId = new Map(entries.map((entry) => [entry.id, entry]));
|
|
40406
40407
|
const byName = new Map(entries.filter((entry) => entry.kind !== "recipe").map((entry) => [entry.name, entry]));
|
|
@@ -40423,7 +40424,7 @@ function createDiscoveryService(source, index, capabilities, retirements = {}, n
|
|
|
40423
40424
|
"Parts auto-add to opts.parent; do not wrap createPart in parent.add. Part rotation uses degrees.",
|
|
40424
40425
|
"Custom THREE.BufferGeometry and ordinary JavaScript functions remain available. Recipes offer guidance and never restrict modeling.",
|
|
40425
40426
|
"Send source once and reuse programRef for reads, edits, inspection and rendering. Review geometry, materials and destination constraints separately.",
|
|
40426
|
-
|
|
40427
|
+
`Search for the operation you need in ordinary language, then fetch exact contracts with ids. Use ${capabilitiesCall} for the current host.`
|
|
40427
40428
|
]
|
|
40428
40429
|
};
|
|
40429
40430
|
const error = (mode, code, message) => ({
|
|
@@ -40604,12 +40605,12 @@ var snapshot2;
|
|
|
40604
40605
|
function createDiscovery(capabilities = async () => ({
|
|
40605
40606
|
host: "No host capability provider was supplied.",
|
|
40606
40607
|
discovery: { mode: "lexical", offline: true, requiresModel: false }
|
|
40607
|
-
}), notes = async () => []) {
|
|
40608
|
+
}), notes = async () => [], capabilitiesCall = "capabilities:true") {
|
|
40608
40609
|
snapshot2 ??= (() => {
|
|
40609
40610
|
const entries = listDiscoveryEntries();
|
|
40610
40611
|
return { entries, index: createLexicalDiscoveryIndex(entries) };
|
|
40611
40612
|
})();
|
|
40612
|
-
return createDiscoveryService(snapshot2.entries, snapshot2.index, capabilities, REMOVED_AUTHORING_HELPERS, notes);
|
|
40613
|
+
return createDiscoveryService(snapshot2.entries, snapshot2.index, capabilities, REMOVED_AUTHORING_HELPERS, notes, capabilitiesCall);
|
|
40613
40614
|
}
|
|
40614
40615
|
|
|
40615
40616
|
// src/tools/discovery.ts
|
|
@@ -40618,8 +40619,8 @@ init_capture_limits();
|
|
|
40618
40619
|
init_geometry_export();
|
|
40619
40620
|
init_community_exporter();
|
|
40620
40621
|
init_material_resources();
|
|
40621
|
-
function createKilnDiscoveryDef(context) {
|
|
40622
|
-
const run = createDiscovery(() => currentCapabilities(context), async () => projectNotes(context));
|
|
40622
|
+
function createKilnDiscoveryDef(context, presentation = "grouped") {
|
|
40623
|
+
const run = createDiscovery(() => currentCapabilities(context, presentation), async () => projectNotes(context), presentation === "operations" ? "kiln_capabilities({})" : "capabilities:true");
|
|
40623
40624
|
return {
|
|
40624
40625
|
name: "kiln_discover",
|
|
40625
40626
|
description: "Discover Kiln operations, assemblies, recipes, tool-input shapes and current host capabilities. Omit arguments for a compact overview. Search with ordinary modeling language using query; refine with family, kind or tags. Fetch complete contracts/examples with ids (up to six exact IDs, executable names or shape: ids). Overview/search pages default to six summaries. Recipes guide construction without restricting the asset. Search runs locally without models or network calls.",
|
|
@@ -40643,7 +40644,7 @@ function projectNotes(context) {
|
|
|
40643
40644
|
`Project ${projectId} is configured for this workspace and applies when projectId is omitted: read its brief, design, inventory and material pins first with kiln_project { action: "get", projectId: "${projectId}" }; projectId: null selects standalone work.`
|
|
40644
40645
|
] : [];
|
|
40645
40646
|
}
|
|
40646
|
-
async function currentCapabilities(context) {
|
|
40647
|
+
async function currentCapabilities(context, presentation) {
|
|
40647
40648
|
const externalEvaluator = Boolean(context.evaluatorPort) || context.evaluatorProfile === "evaluator-required";
|
|
40648
40649
|
const approvedTextures = context.approvedTextureResources ? context.approvedTextureResources() : externalEvaluator ? null : approvedTextureCatalogV1();
|
|
40649
40650
|
const textureSlots = approvedTextures === null ? null : {};
|
|
@@ -40672,7 +40673,7 @@ async function currentCapabilities(context) {
|
|
|
40672
40673
|
requiresModel: false
|
|
40673
40674
|
},
|
|
40674
40675
|
engine: engineIdentity(),
|
|
40675
|
-
project: {
|
|
40676
|
+
project: presentation === "operations" && !context.projectStore ? { available: false } : {
|
|
40676
40677
|
configured: configuredProject(context),
|
|
40677
40678
|
select: "projectId per call; omitted uses the configured project, null selects standalone work",
|
|
40678
40679
|
read: 'kiln_project { action: "get", projectId } returns the brief, design, inventory and material pins'
|
|
@@ -40691,7 +40692,7 @@ async function currentCapabilities(context) {
|
|
|
40691
40692
|
available: Boolean(context.assetLibrary),
|
|
40692
40693
|
collections: context.assetLibrary?.collections() ?? [],
|
|
40693
40694
|
save: "kiln_save persists exact GLB, source and provenance; draft renders do not populate collections",
|
|
40694
|
-
resume: "kiln_assets action=restore imports a saved revision into the current program store
|
|
40695
|
+
resume: `${presentation === "operations" ? "kiln_assets_restore" : "kiln_assets action=restore"} imports a saved revision into the current program store`,
|
|
40695
40696
|
downloads: "kiln_export returns GLB/source/ZIP resource links; client presentation varies",
|
|
40696
40697
|
viewer: "kiln_present opens a saved revision in supporting chat clients with 3D viewing and downloads; kiln view opens a local collection or standalone GLB/ZIP"
|
|
40697
40698
|
},
|
|
@@ -41080,13 +41081,39 @@ var MATERIAL_ACTIONS = [
|
|
|
41080
41081
|
"create-procedural",
|
|
41081
41082
|
"import"
|
|
41082
41083
|
];
|
|
41083
|
-
var
|
|
41084
|
-
presets: {
|
|
41085
|
-
|
|
41086
|
-
|
|
41087
|
-
|
|
41088
|
-
|
|
41089
|
-
|
|
41084
|
+
var MATERIAL_CONTRACT = {
|
|
41085
|
+
presets: {
|
|
41086
|
+
fields: ["tag"],
|
|
41087
|
+
required: [],
|
|
41088
|
+
description: "List shipped material recipes, optionally filtered by tag."
|
|
41089
|
+
},
|
|
41090
|
+
"create-preset": {
|
|
41091
|
+
fields: ["presetId", "seed", "creator", "license", "size", "materialId"],
|
|
41092
|
+
required: ["presetId", "seed", "creator", "license"],
|
|
41093
|
+
description: "Create an immutable material from a shipped preset with explicit seed, creator and license."
|
|
41094
|
+
},
|
|
41095
|
+
list: {
|
|
41096
|
+
fields: ["tag"],
|
|
41097
|
+
required: [],
|
|
41098
|
+
description: "List saved immutable material revisions, optionally filtered by tag."
|
|
41099
|
+
},
|
|
41100
|
+
get: {
|
|
41101
|
+
fields: ["materialId", "revisionId"],
|
|
41102
|
+
required: ["materialId"],
|
|
41103
|
+
description: "Read a material revision, provenance and portable specification. Omit revisionId only when exactly one revision exists."
|
|
41104
|
+
},
|
|
41105
|
+
"create-procedural": {
|
|
41106
|
+
fields: ["draft"],
|
|
41107
|
+
required: ["draft"],
|
|
41108
|
+
shapes: { draft: "shape:material-draft" },
|
|
41109
|
+
description: "Create an immutable material from a bounded procedural draft. Does not fetch URLs or execute source."
|
|
41110
|
+
},
|
|
41111
|
+
import: {
|
|
41112
|
+
fields: ["payload"],
|
|
41113
|
+
required: ["payload"],
|
|
41114
|
+
shapes: { payload: "shape:material-import" },
|
|
41115
|
+
description: "Import complete normalized material records and embedded PNGs. Does not fetch URLs or execute source."
|
|
41116
|
+
}
|
|
41090
41117
|
};
|
|
41091
41118
|
var record7 = (description) => z18.record(z18.string(), z18.unknown()).optional().describe(description);
|
|
41092
41119
|
var tag = z18.string().min(1).max(80).optional().describe("presets, list: keep one tag.");
|
|
@@ -41108,13 +41135,13 @@ var materialResult = (material) => ({
|
|
|
41108
41135
|
material,
|
|
41109
41136
|
portableSpec: materialLibraryPortableSpec(material)
|
|
41110
41137
|
});
|
|
41111
|
-
var unknownMaterial = (materialId, revisionId) => new Error(`Unknown material ${materialId}${revisionId ? ` at ${revisionId}` : ""}.
|
|
41112
|
-
async function onlyRevision(library, materialId) {
|
|
41138
|
+
var unknownMaterial = (materialId, revisionId, listCall) => new Error(`Unknown material ${materialId}${revisionId ? ` at ${revisionId}` : ""}. ${listCall} lists the materials in this workspace with their revision IDs.`);
|
|
41139
|
+
async function onlyRevision(library, materialId, listCall) {
|
|
41113
41140
|
const revisions = (await library.list()).filter((material) => material.materialId === materialId).map((material) => material.revisionId).sort();
|
|
41114
41141
|
if (revisions.length === 1)
|
|
41115
41142
|
return revisions[0];
|
|
41116
41143
|
if (revisions.length === 0)
|
|
41117
|
-
throw unknownMaterial(materialId);
|
|
41144
|
+
throw unknownMaterial(materialId, undefined, listCall);
|
|
41118
41145
|
throw new Error(`Material ${materialId} has ${revisions.length} revisions: ${revisions.join(", ")}. Pass revisionId to get one.`);
|
|
41119
41146
|
}
|
|
41120
41147
|
function aliasMaterialId(raw) {
|
|
@@ -41127,11 +41154,13 @@ function aliasMaterialId(raw) {
|
|
|
41127
41154
|
throw new Error(`kiln_material: resourceId (${String(resourceId)}) and materialId (${String(rest.materialId)}) name different materials; pass materialId alone.`);
|
|
41128
41155
|
return { ...rest, materialId: resourceId };
|
|
41129
41156
|
}
|
|
41130
|
-
function createKilnMaterialDef(library) {
|
|
41157
|
+
function createKilnMaterialDef(library, presentation = "grouped") {
|
|
41158
|
+
const listCall = presentation === "operations" ? 'kiln_material_search({ scope: "saved" })' : "kiln_material { action: 'list' }";
|
|
41131
41159
|
return {
|
|
41132
41160
|
name: "kiln_material",
|
|
41133
41161
|
description: "Manage optional immutable material resources in this workspace. presets discovers shipped architecture, wood, metal, fabric and ground recipes; create-preset bakes one with an explicit seed, creator and license; list returns compact material/revision summaries; get returns full provenance, hashes, map conventions, physical repeat scale and a code-ready portable material spec; create-procedural bakes bounded editable layer recipes including optional height-derived normals; import accepts complete normalized records with embedded PNG bytes. No action downloads URLs or executes source. Pin the returned materialId/revisionId through per-invocation materialDependencies or project dependencies before authored evaluation resolves the resources; no project is required.",
|
|
41134
41162
|
inputSchema: materialToolInput,
|
|
41163
|
+
actionContract: MATERIAL_CONTRACT,
|
|
41135
41164
|
annotations: {
|
|
41136
41165
|
readOnlyHint: false,
|
|
41137
41166
|
destructiveHint: false,
|
|
@@ -41141,7 +41170,7 @@ function createKilnMaterialDef(library) {
|
|
|
41141
41170
|
async run(raw) {
|
|
41142
41171
|
assertMaterialJson(raw);
|
|
41143
41172
|
const input = materialToolInput.parse(aliasMaterialId(raw));
|
|
41144
|
-
requireActionFields("kiln_material", input.action, input,
|
|
41173
|
+
requireActionFields("kiln_material", input.action, input, MATERIAL_CONTRACT[input.action]);
|
|
41145
41174
|
switch (input.action) {
|
|
41146
41175
|
case "presets":
|
|
41147
41176
|
return {
|
|
@@ -41177,12 +41206,12 @@ function createKilnMaterialDef(library) {
|
|
|
41177
41206
|
};
|
|
41178
41207
|
}
|
|
41179
41208
|
case "get": {
|
|
41180
|
-
const revisionId = input.revisionId ?? await onlyRevision(library, input.materialId);
|
|
41209
|
+
const revisionId = input.revisionId ?? await onlyRevision(library, input.materialId, listCall);
|
|
41181
41210
|
try {
|
|
41182
41211
|
return materialResult((await library.read(input.materialId, revisionId)).manifest);
|
|
41183
41212
|
} catch (error) {
|
|
41184
41213
|
if (error.code === "ENOENT")
|
|
41185
|
-
throw unknownMaterial(input.materialId, revisionId);
|
|
41214
|
+
throw unknownMaterial(input.materialId, revisionId, listCall);
|
|
41186
41215
|
throw error;
|
|
41187
41216
|
}
|
|
41188
41217
|
}
|
|
@@ -41233,7 +41262,7 @@ async function persistedPreviewFidelity(fidelity, glb) {
|
|
|
41233
41262
|
var operationId = z19.string().regex(/^op_[a-f0-9-]{36}$/);
|
|
41234
41263
|
var assetId = z19.string().regex(/^[a-z][a-z0-9_-]{0,79}$/);
|
|
41235
41264
|
var REVIEW_ACTIONS = ["list", "get", "pin", "save"];
|
|
41236
|
-
var
|
|
41265
|
+
var REQUIREMENTS2 = {
|
|
41237
41266
|
list: { required: [] },
|
|
41238
41267
|
get: { required: ["operationId"] },
|
|
41239
41268
|
pin: { required: ["operationId", "pinned"] },
|
|
@@ -41315,7 +41344,7 @@ function createKilnReviewDef(context) {
|
|
|
41315
41344
|
},
|
|
41316
41345
|
async run(raw) {
|
|
41317
41346
|
const input = reviewToolInput.parse(raw);
|
|
41318
|
-
requireActionFields("kiln_review", input.action, input,
|
|
41347
|
+
requireActionFields("kiln_review", input.action, input, REQUIREMENTS2[input.action]);
|
|
41319
41348
|
if (input.action === "list") {
|
|
41320
41349
|
const snapshot = await store.snapshot({ projectId: input.projectId });
|
|
41321
41350
|
const offset = input.offset ?? 0;
|
|
@@ -41487,6 +41516,191 @@ function withWorkspaceContext(def, context) {
|
|
|
41487
41516
|
};
|
|
41488
41517
|
}
|
|
41489
41518
|
|
|
41519
|
+
// src/tools/operations.ts
|
|
41520
|
+
import { z as z22 } from "zod";
|
|
41521
|
+
|
|
41522
|
+
// src/tools/operation-contract.ts
|
|
41523
|
+
import { z as z21 } from "zod";
|
|
41524
|
+
function projectActionSchemas(name, input, actions) {
|
|
41525
|
+
if (input.def.checks?.length)
|
|
41526
|
+
throw new Error(`${name}: cross-field constraints require an explicit operation schema`);
|
|
41527
|
+
const json = z21.toJSONSchema(input, { io: "input" });
|
|
41528
|
+
const selector = json.properties?.action;
|
|
41529
|
+
const expected = Object.keys(actions).sort();
|
|
41530
|
+
if (!Array.isArray(selector?.enum) || JSON.stringify([...selector.enum].sort()) !== JSON.stringify(expected))
|
|
41531
|
+
throw new Error(`${name}: unclassified actions`);
|
|
41532
|
+
const classified = new Set([
|
|
41533
|
+
"action",
|
|
41534
|
+
...Object.values(actions).flatMap((contract) => [...contract.fields])
|
|
41535
|
+
]);
|
|
41536
|
+
const unclassified = Object.keys(input.shape).filter((field) => !classified.has(field));
|
|
41537
|
+
if (unclassified.length)
|
|
41538
|
+
throw new Error(`${name}: Unclassified fields: ${unclassified.join(", ")}`);
|
|
41539
|
+
const schemas = [];
|
|
41540
|
+
for (const [action, contract] of Object.entries(actions)) {
|
|
41541
|
+
for (const field of contract.required)
|
|
41542
|
+
if (!contract.fields.includes(field))
|
|
41543
|
+
throw new Error(`${name}.${action}: unmapped required ${field}`);
|
|
41544
|
+
for (const field of json.required ?? [])
|
|
41545
|
+
if (field !== "action" && !contract.fields.includes(field))
|
|
41546
|
+
throw new Error(`${name}.${action}: would omit required ${field}`);
|
|
41547
|
+
const shape = {};
|
|
41548
|
+
for (const field of contract.fields) {
|
|
41549
|
+
if (field === "action" || !Object.hasOwn(input.shape, field))
|
|
41550
|
+
throw new Error(`${name}.${action}: missing or reserved field ${field}`);
|
|
41551
|
+
classified.add(field);
|
|
41552
|
+
const source = input.shape[field];
|
|
41553
|
+
shape[field] = contract.required.includes(field) ? source.nonoptional() : source;
|
|
41554
|
+
}
|
|
41555
|
+
schemas.push([action, z21.strictObject(shape)]);
|
|
41556
|
+
}
|
|
41557
|
+
return Object.fromEntries(schemas);
|
|
41558
|
+
}
|
|
41559
|
+
|
|
41560
|
+
// src/tools/operations.ts
|
|
41561
|
+
function projectOperationDefs(defs, context) {
|
|
41562
|
+
return defs.flatMap((def) => {
|
|
41563
|
+
if (!context.assetLibrary && ["kiln_save", "kiln_assets", "kiln_present", "kiln_export", "kiln_import"].includes(def.name))
|
|
41564
|
+
return [];
|
|
41565
|
+
if (def.name === "kiln_renderer")
|
|
41566
|
+
return rendererOperations(def, context);
|
|
41567
|
+
if (def.name === "kiln_discover")
|
|
41568
|
+
return discoveryOperations(def);
|
|
41569
|
+
if (def.name === "kiln_material")
|
|
41570
|
+
return materialOperations(def);
|
|
41571
|
+
if (def.name === "kiln_assets")
|
|
41572
|
+
return assetOperations(def, context);
|
|
41573
|
+
return [def];
|
|
41574
|
+
});
|
|
41575
|
+
}
|
|
41576
|
+
function actionTools(def) {
|
|
41577
|
+
if (!(def.inputSchema instanceof z22.ZodObject) || !def.actionContract)
|
|
41578
|
+
throw new Error(`${def.name}: missing shared action contract`);
|
|
41579
|
+
const schemas = projectActionSchemas(def.name, def.inputSchema, def.actionContract);
|
|
41580
|
+
return Object.fromEntries(Object.entries(def.actionContract).map(([action, contract]) => [
|
|
41581
|
+
action,
|
|
41582
|
+
{
|
|
41583
|
+
...def,
|
|
41584
|
+
actionContract: undefined,
|
|
41585
|
+
name: `${def.name}_${action.replaceAll("-", "_")}`,
|
|
41586
|
+
description: contract.description,
|
|
41587
|
+
inputSchema: schemas[action],
|
|
41588
|
+
run: async (raw) => def.run({ ...schemas[action].parse(raw), action })
|
|
41589
|
+
}
|
|
41590
|
+
]));
|
|
41591
|
+
}
|
|
41592
|
+
function assetOperations(def, context) {
|
|
41593
|
+
const tools = actionTools(def);
|
|
41594
|
+
const list = tools.list;
|
|
41595
|
+
const listSchema = list.inputSchema;
|
|
41596
|
+
const collection = listSchema.shape.collection.unwrap().optional().describe("Collection ID from kiln_assets_collections; omitted searches all configured collections.");
|
|
41597
|
+
const inputSchema = listSchema.extend({ collection });
|
|
41598
|
+
const search = {
|
|
41599
|
+
...list,
|
|
41600
|
+
name: "kiln_assets_search",
|
|
41601
|
+
description: "Search saved assets with pagination. Omit collection for all configured collections, or select one explicitly. Results identify exact collection, asset and revision; partial read failures are reported.",
|
|
41602
|
+
inputSchema,
|
|
41603
|
+
run: async (raw) => {
|
|
41604
|
+
const input = inputSchema.parse(raw);
|
|
41605
|
+
const { collection: _collection, ...filters } = input;
|
|
41606
|
+
if (input.collection === undefined)
|
|
41607
|
+
return tools.catalog.run(filters);
|
|
41608
|
+
if (!context.assetLibrary?.collections().some((item) => item.id === input.collection))
|
|
41609
|
+
throw new Error("Unknown collection. Use kiln_assets_collections to list available destinations.");
|
|
41610
|
+
const result = await list.run(input);
|
|
41611
|
+
return {
|
|
41612
|
+
errors: [],
|
|
41613
|
+
total: result.total,
|
|
41614
|
+
nextOffset: result.nextOffset,
|
|
41615
|
+
assets: result.assets.map((asset) => ({ ...asset, collection: input.collection }))
|
|
41616
|
+
};
|
|
41617
|
+
}
|
|
41618
|
+
};
|
|
41619
|
+
return [tools.collections, search, tools.get, tools.restore];
|
|
41620
|
+
}
|
|
41621
|
+
function materialOperations(def) {
|
|
41622
|
+
const tools = actionTools(def);
|
|
41623
|
+
const presets = tools.presets;
|
|
41624
|
+
const inputSchema = presets.inputSchema.extend({
|
|
41625
|
+
scope: z22.enum(["all", "presets", "saved"]).default("all")
|
|
41626
|
+
});
|
|
41627
|
+
const search = {
|
|
41628
|
+
...presets,
|
|
41629
|
+
name: "kiln_material_search",
|
|
41630
|
+
description: "Browse shipped material recipes and saved material revisions, optionally filtered by exact tag. Recipe IDs and saved material IDs are distinct. Use scope to select presets, saved or both.",
|
|
41631
|
+
inputSchema,
|
|
41632
|
+
run: async (raw) => {
|
|
41633
|
+
const { scope, ...input } = inputSchema.parse(raw);
|
|
41634
|
+
const recipes = scope === "saved" ? { presets: [] } : await presets.run(input);
|
|
41635
|
+
const saved = scope === "presets" ? { materials: [] } : await tools.list.run(input);
|
|
41636
|
+
return {
|
|
41637
|
+
ok: true,
|
|
41638
|
+
presets: recipes.presets.map((item) => ({ ...item, kind: "preset" })),
|
|
41639
|
+
materials: saved.materials.map((item) => ({ ...item, kind: "saved" }))
|
|
41640
|
+
};
|
|
41641
|
+
}
|
|
41642
|
+
};
|
|
41643
|
+
const preset = tools["create-preset"];
|
|
41644
|
+
const procedural = tools["create-procedural"];
|
|
41645
|
+
const createInput = z22.strictObject({
|
|
41646
|
+
definition: z22.discriminatedUnion("kind", [
|
|
41647
|
+
preset.inputSchema.extend({ kind: z22.literal("preset") }),
|
|
41648
|
+
procedural.inputSchema.extend({ kind: z22.literal("procedural") })
|
|
41649
|
+
])
|
|
41650
|
+
});
|
|
41651
|
+
const create = {
|
|
41652
|
+
...preset,
|
|
41653
|
+
name: "kiln_material_create",
|
|
41654
|
+
description: "Create and retain one immutable material from a preset or procedural definition. Presets require explicit seed, creator and license. Pin the returned materialId/revisionId for rendering. Does not fetch URLs or execute source.",
|
|
41655
|
+
inputSchema: createInput,
|
|
41656
|
+
run: async (raw) => {
|
|
41657
|
+
const { kind, ...input } = createInput.parse(raw).definition;
|
|
41658
|
+
return (kind === "preset" ? preset : procedural).run(input);
|
|
41659
|
+
}
|
|
41660
|
+
};
|
|
41661
|
+
return [search, tools.get, create, tools.import];
|
|
41662
|
+
}
|
|
41663
|
+
function rendererOperations(def, context) {
|
|
41664
|
+
if (!context.renderCapabilities)
|
|
41665
|
+
return [];
|
|
41666
|
+
return ["status", ...context.reprobeRenderer ? ["reprobe"] : []].map((action) => {
|
|
41667
|
+
const inputSchema = z22.strictObject({});
|
|
41668
|
+
return {
|
|
41669
|
+
...def,
|
|
41670
|
+
name: `kiln_renderer_${action}`,
|
|
41671
|
+
inputSchema,
|
|
41672
|
+
run: async (raw) => {
|
|
41673
|
+
inputSchema.parse(raw);
|
|
41674
|
+
return def.run({ action });
|
|
41675
|
+
}
|
|
41676
|
+
};
|
|
41677
|
+
});
|
|
41678
|
+
}
|
|
41679
|
+
function discoveryOperations(def) {
|
|
41680
|
+
const original = def.inputSchema;
|
|
41681
|
+
const { capabilities: _capabilities, ...fields } = original.shape;
|
|
41682
|
+
const inputSchema = z22.strictObject(fields);
|
|
41683
|
+
const empty = z22.strictObject({});
|
|
41684
|
+
return [
|
|
41685
|
+
{
|
|
41686
|
+
...def,
|
|
41687
|
+
description: "Discover geometry helpers, assemblies, recipes and complete input shapes. Search with modeling language or fetch up to six exact IDs. Use kiln_capabilities for current host facts.",
|
|
41688
|
+
inputSchema,
|
|
41689
|
+
run: async (raw) => def.run(inputSchema.parse(raw))
|
|
41690
|
+
},
|
|
41691
|
+
{
|
|
41692
|
+
...def,
|
|
41693
|
+
name: "kiln_capabilities",
|
|
41694
|
+
description: "Inspect declared host capabilities, execution limits and available storage. Observed rendering fidelity is returned by each render.",
|
|
41695
|
+
inputSchema: empty,
|
|
41696
|
+
run: async (raw) => {
|
|
41697
|
+
empty.parse(raw);
|
|
41698
|
+
return def.run({ capabilities: true });
|
|
41699
|
+
}
|
|
41700
|
+
}
|
|
41701
|
+
];
|
|
41702
|
+
}
|
|
41703
|
+
|
|
41490
41704
|
// src/tools/registry.ts
|
|
41491
41705
|
init_validation();
|
|
41492
41706
|
init_source_check();
|
|
@@ -41952,11 +42166,11 @@ function derivativeReviewFidelity(receipts) {
|
|
|
41952
42166
|
...reasonCodes.length ? { reasonCodes } : {}
|
|
41953
42167
|
};
|
|
41954
42168
|
}
|
|
41955
|
-
var validateInput =
|
|
41956
|
-
code:
|
|
42169
|
+
var validateInput = z23.object({
|
|
42170
|
+
code: z23.string().describe("Kiln source code (defines `meta` + `build()`, optional `animate()`).")
|
|
41957
42171
|
});
|
|
41958
|
-
var renderInput =
|
|
41959
|
-
code:
|
|
42172
|
+
var renderInput = z23.object({
|
|
42173
|
+
code: z23.string().describe("Kiln source code to execute and render to an in-memory GLB.")
|
|
41960
42174
|
});
|
|
41961
42175
|
var renderViewsInput = renderInput.extend({ capture: captureInput, detail: reviewDetailInput });
|
|
41962
42176
|
var reviewDetailOptions = (context) => ({
|
|
@@ -41969,26 +42183,26 @@ var reviewDetailOptions = (context) => ({
|
|
|
41969
42183
|
}
|
|
41970
42184
|
});
|
|
41971
42185
|
var renderViewsBufferInput = renderViewsInput.omit({ code: true });
|
|
41972
|
-
var screenshotAnimationInput =
|
|
42186
|
+
var screenshotAnimationInput = z23.object({
|
|
41973
42187
|
shot: cameraShotInput.optional(),
|
|
41974
|
-
measureParts:
|
|
41975
|
-
frames:
|
|
41976
|
-
frameTimes:
|
|
41977
|
-
framing:
|
|
41978
|
-
size:
|
|
42188
|
+
measureParts: z23.array(cameraShotInput.shape.subject.unwrap()).min(1).max(16).optional().describe("Exact names or paths of subtrees measured together at each phase, independent of camera selection."),
|
|
42189
|
+
frames: z23.number().int().min(2).max(6).optional(),
|
|
42190
|
+
frameTimes: z23.array(z23.number().min(0).max(1)).min(1).max(9).optional().describe("Ordered phase fractions 0..1; mutually exclusive with frames."),
|
|
42191
|
+
framing: z23.enum(["locked", "follow"]).optional(),
|
|
42192
|
+
size: z23.number().int().min(128).max(1024).optional().describe("Frame size in px; default 256."),
|
|
41979
42193
|
detail: reviewDetailInput,
|
|
41980
|
-
code:
|
|
41981
|
-
clip:
|
|
41982
|
-
camera:
|
|
41983
|
-
perFrame:
|
|
42194
|
+
code: z23.string().describe("Kiln source code to execute; must define animate() returning the named clip."),
|
|
42195
|
+
clip: z23.string().describe('The animation clip to view, by name (e.g. "walk", "attack"). Must be one your animate() returns.'),
|
|
42196
|
+
camera: z23.string().optional().describe("Camera angle: right (default — side profile, best for leg swing + knee bend direction), front " + "(reveals sideways/lateral motion), back, left, top, or three-quarter."),
|
|
42197
|
+
perFrame: z23.boolean().optional().describe("Return the frames as separate high-res images instead of one composite grid. Default false.")
|
|
41984
42198
|
});
|
|
41985
42199
|
var screenshotAnimationAdvertisedInput = screenshotAnimationInput.extend({
|
|
41986
42200
|
shot: cameraShotRecordInput
|
|
41987
42201
|
});
|
|
41988
|
-
var viewInteriorInput =
|
|
42202
|
+
var viewInteriorInput = z23.object({
|
|
41989
42203
|
capture: advancedCaptureInput.optional(),
|
|
41990
|
-
code:
|
|
41991
|
-
nodeName:
|
|
42204
|
+
code: z23.string().describe("Kiln source code to execute and render with the roof hidden."),
|
|
42205
|
+
nodeName: z23.string().optional().describe("Override: lift the roof by exact node name instead of by role. Matches that node and its " + "children. Normally OMIT it — Kiln finds the roof from its semantic role (anything built " + 'with createRoofPlanes/createGableRoof), falling back to historical "Roof" naming.')
|
|
41992
42206
|
});
|
|
41993
42207
|
var viewInteriorAdvertisedInput = viewInteriorInput.extend({ capture: captureRecordInput });
|
|
41994
42208
|
function runValidate(input, context) {
|
|
@@ -42003,11 +42217,11 @@ function runValidate(input, context) {
|
|
|
42003
42217
|
warnings: result.warnings.map((w) => w.fixHint ? `${w.message} (${w.fixHint})` : w.message)
|
|
42004
42218
|
};
|
|
42005
42219
|
}
|
|
42006
|
-
var partListInput =
|
|
42007
|
-
query:
|
|
42008
|
-
offset:
|
|
42009
|
-
limit:
|
|
42010
|
-
placement:
|
|
42220
|
+
var partListInput = z23.object({
|
|
42221
|
+
query: z23.string().max(4096).optional().describe("Case-insensitive substring of name or exact encoded path; not a regex."),
|
|
42222
|
+
offset: z23.number().int().min(0).optional(),
|
|
42223
|
+
limit: z23.number().int().min(1).max(100).optional(),
|
|
42224
|
+
placement: z23.boolean().optional().describe("Add world position, rotation, scale, mirroring and bounds per part; pages of 50.")
|
|
42011
42225
|
}).strict();
|
|
42012
42226
|
var PLACEMENT_PAGE_LIMIT = 50;
|
|
42013
42227
|
async function listPartNames2(root, options = {}) {
|
|
@@ -42474,35 +42688,35 @@ function createKilnViewInteriorDef(context = {}) {
|
|
|
42474
42688
|
};
|
|
42475
42689
|
}
|
|
42476
42690
|
var kilnViewInteriorDef = createKilnViewInteriorDef();
|
|
42477
|
-
var attachmentEndpointInput =
|
|
42478
|
-
subject:
|
|
42691
|
+
var attachmentEndpointInput = z23.object({
|
|
42692
|
+
subject: z23.object({ path: z23.string().optional(), name: z23.string().optional() }).strict(),
|
|
42479
42693
|
point: cameraVec3Input.optional()
|
|
42480
42694
|
}).strict();
|
|
42481
|
-
var surfacePairInput =
|
|
42482
|
-
var inspectInput =
|
|
42483
|
-
image:
|
|
42695
|
+
var surfacePairInput = z23.array(z23.string().max(4096)).length(2);
|
|
42696
|
+
var inspectInput = z23.object({
|
|
42697
|
+
image: z23.boolean().optional().describe("False: requires listParts/measure/surfacePairs/compare; no image or camera controls. Default true."),
|
|
42484
42698
|
detail: reviewDetailInput,
|
|
42485
42699
|
listParts: partListInput.optional().describe("List exported-scene paths, including nested parts. Default 80, max 100 per page. Follow partListing.nextOffset with the same programRef/query. image:false avoids rendering."),
|
|
42486
|
-
surfacePairs:
|
|
42487
|
-
compare:
|
|
42488
|
-
programRef:
|
|
42489
|
-
offset:
|
|
42490
|
-
limit:
|
|
42491
|
-
paths:
|
|
42700
|
+
surfacePairs: z23.array(surfacePairInput).min(1).max(12).optional().describe("[from,to] pairs of exact listParts paths or unambiguous node names; check surfaceMeasurements.status and each result."),
|
|
42701
|
+
compare: z23.object({
|
|
42702
|
+
programRef: z23.string().regex(programRefPattern),
|
|
42703
|
+
offset: z23.number().int().min(0).optional(),
|
|
42704
|
+
limit: z23.number().int().min(1).max(100).optional(),
|
|
42705
|
+
paths: z23.array(z23.string().max(4096)).min(1).max(12).optional().describe("Exact baseline node paths, scene-prefixed without primitive children. Complete subtree summaries.")
|
|
42492
42706
|
}).strict().optional().describe("Static geometry/material/transform/bounds under current host settings. Follow nextOffset; paths adds complete subtrees."),
|
|
42493
|
-
measure:
|
|
42494
|
-
mode:
|
|
42707
|
+
measure: z23.object({
|
|
42708
|
+
mode: z23.enum(["anchors", "surface"]).optional(),
|
|
42495
42709
|
from: attachmentEndpointInput,
|
|
42496
42710
|
to: attachmentEndpointInput
|
|
42497
42711
|
}).strict().optional().describe("Default anchors: origin/local-point distance. Surface: disjoint mesh triangles, omit points. Rest pose, asset units. Check status/bounds; no solid clearance/attachment proof."),
|
|
42498
42712
|
shot: cameraShotInput.optional().describe("Exact shot; omit part/view/orbit controls."),
|
|
42499
|
-
code:
|
|
42500
|
-
part:
|
|
42501
|
-
view:
|
|
42502
|
-
azimuthDeg:
|
|
42503
|
-
elevationDeg:
|
|
42504
|
-
zoom:
|
|
42505
|
-
isolate:
|
|
42713
|
+
code: z23.string().describe("Kiln source code to execute and inspect."),
|
|
42714
|
+
part: z23.string().optional().describe("Frame named part and descendants (case-insensitive, substring fallback). Omit for whole asset."),
|
|
42715
|
+
view: z23.string().optional().describe("front/right/back/left/top/three-quarter (default). Orbit angles override."),
|
|
42716
|
+
azimuthDeg: z23.number().optional().describe("Orbit degrees: 0 front, 90 right, 180 back, 270 left. Wraps."),
|
|
42717
|
+
elevationDeg: z23.number().optional().describe("Elevation degrees: 0 eye level, positive above. Clamped -89..89."),
|
|
42718
|
+
zoom: z23.number().optional().describe("Bounds padding 1..4; default 1.2. Larger = more context."),
|
|
42719
|
+
isolate: z23.boolean().optional().describe("Hide surrounding geometry. Requires part; default false.")
|
|
42506
42720
|
});
|
|
42507
42721
|
var inspectBufferInput = inspectInput.omit({ code: true });
|
|
42508
42722
|
var inspectAdvertisedInput = inspectInput.extend({ shot: cameraShotRecordInput });
|
|
@@ -42662,15 +42876,15 @@ function createKilnInspectDef(context = {}) {
|
|
|
42662
42876
|
};
|
|
42663
42877
|
}
|
|
42664
42878
|
var kilnInspectDef = createKilnInspectDef();
|
|
42665
|
-
var editOperationInput =
|
|
42666
|
-
oldString:
|
|
42667
|
-
newString:
|
|
42668
|
-
replaceAll:
|
|
42879
|
+
var editOperationInput = z23.object({
|
|
42880
|
+
oldString: z23.string().describe("The exact text to replace, copied verbatim from the program (including whitespace and indentation, and with no line-number prefixes). Must be unique unless replaceAll is true."),
|
|
42881
|
+
newString: z23.string().describe("The replacement text. Use an empty string to delete."),
|
|
42882
|
+
replaceAll: z23.boolean().optional().describe("Replace every occurrence instead of failing when oldString matches more than once.")
|
|
42669
42883
|
});
|
|
42670
|
-
var editInput =
|
|
42671
|
-
code:
|
|
42672
|
-
edits:
|
|
42673
|
-
render:
|
|
42884
|
+
var editInput = z23.object({
|
|
42885
|
+
code: z23.string().describe("The Kiln program to patch. The full current source."),
|
|
42886
|
+
edits: z23.array(editOperationInput).min(1).max(20).describe("Edits applied in order against the program. If any one fails to match, none are applied and the reply says which. Batch related changes into a single call."),
|
|
42887
|
+
render: z23.boolean().optional().describe("Render the patched program and return the views (default true). false = patch only."),
|
|
42674
42888
|
capture: captureInput,
|
|
42675
42889
|
detail: reviewDetailInput
|
|
42676
42890
|
});
|
|
@@ -42896,24 +43110,27 @@ function withCaptureCache(context) {
|
|
|
42896
43110
|
} : {}
|
|
42897
43111
|
};
|
|
42898
43112
|
}
|
|
42899
|
-
var rendererInput =
|
|
42900
|
-
action:
|
|
43113
|
+
var rendererInput = z23.strictObject({
|
|
43114
|
+
action: z23.enum(["status", "reprobe"]).default("status")
|
|
42901
43115
|
});
|
|
42902
|
-
async function readSavedRevision(target, collection, assetId, revisionId) {
|
|
43116
|
+
async function readSavedRevision(target, collection, assetId, revisionId, listCall = `kiln_assets { action: 'list', collection: '${collection}' }`) {
|
|
42903
43117
|
try {
|
|
42904
43118
|
return await target.read(collection, assetId, revisionId);
|
|
42905
43119
|
} catch (error) {
|
|
42906
43120
|
if (error.code === "ENOENT")
|
|
42907
|
-
throw new Error(`Unknown asset ${assetId} revision ${revisionId} in collection ${collection}.
|
|
43121
|
+
throw new Error(`Unknown asset ${assetId} revision ${revisionId} in collection ${collection}. ${listCall} lists the saved revisions.`);
|
|
42908
43122
|
throw error;
|
|
42909
43123
|
}
|
|
42910
43124
|
}
|
|
42911
43125
|
function createKilnProgramToolRegistry(suppliedContext = {}) {
|
|
43126
|
+
return createProgramDefs(suppliedContext, "grouped");
|
|
43127
|
+
}
|
|
43128
|
+
function createProgramDefs(suppliedContext, presentation) {
|
|
42912
43129
|
toolRequirements(suppliedContext);
|
|
42913
43130
|
const store = suppliedContext.programStore ?? new MemoryProgramStore;
|
|
42914
43131
|
const context = withCaptureCache(withBuildCache({ ...suppliedContext, programStore: store }));
|
|
42915
43132
|
return [
|
|
42916
|
-
createKilnDiscoveryDef({ ...suppliedContext, programStore: store }),
|
|
43133
|
+
createKilnDiscoveryDef({ ...suppliedContext, programStore: store }, presentation),
|
|
42917
43134
|
{
|
|
42918
43135
|
name: "kiln_renderer",
|
|
42919
43136
|
description: "Inspect status, or reprobe after renderer setup/repair to refresh this session and reset failed starts. Never installs, starts, stops or renders. Preserves CPU/local/remote selection; environment/credential changes require a host restart. Read viewFidelity after rendering.",
|
|
@@ -42953,7 +43170,7 @@ function createKilnProgramToolRegistry(suppliedContext = {}) {
|
|
|
42953
43170
|
].map((def) => withProgramReferences(def, store, context.readSourceFile)),
|
|
42954
43171
|
createKilnSourceDef(store),
|
|
42955
43172
|
...context.projectStore ? [createKilnProjectDef(context.projectStore, context.projectBundleReader)] : [],
|
|
42956
|
-
...context.materialLibrary ? [createKilnMaterialDef(context.materialLibrary)] : [],
|
|
43173
|
+
...context.materialLibrary ? [createKilnMaterialDef(context.materialLibrary, presentation)] : [],
|
|
42957
43174
|
...context.reviewStore && context.assetLibrary ? [
|
|
42958
43175
|
createKilnReviewDef({
|
|
42959
43176
|
reviewStore: context.reviewStore,
|
|
@@ -42961,7 +43178,7 @@ function createKilnProgramToolRegistry(suppliedContext = {}) {
|
|
|
42961
43178
|
requirements: context.requirements
|
|
42962
43179
|
})
|
|
42963
43180
|
] : [],
|
|
42964
|
-
...createKilnAssetDefs({ ...context, programStore: store })
|
|
43181
|
+
...createKilnAssetDefs({ ...context, programStore: store }, presentation)
|
|
42965
43182
|
].map((def) => withWorkspaceContext(def, context)).map((def) => ({
|
|
42966
43183
|
...def,
|
|
42967
43184
|
annotations: {
|
|
@@ -42973,15 +43190,45 @@ function createKilnProgramToolRegistry(suppliedContext = {}) {
|
|
|
42973
43190
|
}
|
|
42974
43191
|
}));
|
|
42975
43192
|
}
|
|
43193
|
+
function createKilnOperationToolRegistry(context = {}) {
|
|
43194
|
+
return projectOperationDefs(createProgramDefs(context, "operations"), context);
|
|
43195
|
+
}
|
|
42976
43196
|
var assetSelector = {
|
|
42977
|
-
collection:
|
|
42978
|
-
assetId:
|
|
42979
|
-
revisionId:
|
|
43197
|
+
collection: z23.string().regex(/^[a-z][a-z0-9_-]{0,79}$/).describe("Collection ID (list with kiln_assets action=collections): the user destination, else project.").default("project"),
|
|
43198
|
+
assetId: z23.string().regex(/^[a-z][a-z0-9_-]{0,79}$/),
|
|
43199
|
+
revisionId: z23.string().regex(/^[a-z][a-z0-9_-]{0,79}$/)
|
|
42980
43200
|
};
|
|
42981
|
-
|
|
43201
|
+
var ASSET_CONTRACT = {
|
|
43202
|
+
collections: {
|
|
43203
|
+
fields: [],
|
|
43204
|
+
required: [],
|
|
43205
|
+
description: "List configured asset storage collections. Collection is not project membership."
|
|
43206
|
+
},
|
|
43207
|
+
catalog: {
|
|
43208
|
+
fields: ["assetId", "query", "offset", "limit"],
|
|
43209
|
+
required: [],
|
|
43210
|
+
description: "Search saved assets across configured collections with pagination."
|
|
43211
|
+
},
|
|
43212
|
+
list: {
|
|
43213
|
+
fields: ["collection", "assetId", "query", "offset", "limit"],
|
|
43214
|
+
required: [],
|
|
43215
|
+
description: "Search saved assets in one collection with pagination."
|
|
43216
|
+
},
|
|
43217
|
+
get: {
|
|
43218
|
+
fields: ["collection", "assetId", "revisionId"],
|
|
43219
|
+
required: ["assetId"],
|
|
43220
|
+
description: "Read a saved revision and its download descriptors. Omit revisionId for the newest revision."
|
|
43221
|
+
},
|
|
43222
|
+
restore: {
|
|
43223
|
+
fields: ["collection", "assetId", "revisionId"],
|
|
43224
|
+
required: ["assetId"],
|
|
43225
|
+
description: "Restore exact saved source as programRef for editing or rendering. Omit revisionId for the newest revision. Does not overwrite the saved revision. Binary-only assets have no source."
|
|
43226
|
+
}
|
|
43227
|
+
};
|
|
43228
|
+
async function newestRevision(target, collection, assetId, listCall = `kiln_assets { action: 'list', collection: '${collection}' }`) {
|
|
42982
43229
|
const revisions = (await target.list(collection)).filter((a) => a.assetId === assetId);
|
|
42983
43230
|
if (!revisions.length)
|
|
42984
|
-
throw new Error(`Unknown asset ${assetId} in ${collection};
|
|
43231
|
+
throw new Error(`Unknown asset ${assetId} in ${collection}; ${listCall} lists them.`);
|
|
42985
43232
|
const parents = new Set(revisions.map((a) => a.parentRevision).filter(Boolean));
|
|
42986
43233
|
const heads = revisions.filter((a) => !parents.has(a.revisionId));
|
|
42987
43234
|
const newest = (heads.length ? heads : revisions).sort((a, b) => a.createdAt < b.createdAt ? 1 : a.createdAt > b.createdAt ? -1 : 0);
|
|
@@ -43046,7 +43293,12 @@ async function buildProgramAssetDraft(code, context, backdrop) {
|
|
|
43046
43293
|
}
|
|
43047
43294
|
};
|
|
43048
43295
|
}
|
|
43049
|
-
function createKilnAssetDefs(context) {
|
|
43296
|
+
function createKilnAssetDefs(context, presentation = "grouped") {
|
|
43297
|
+
const listCall = (collection) => presentation === "operations" ? `kiln_assets_search({ collection: '${collection}' })` : `kiln_assets { action: 'list', collection: '${collection}' }`;
|
|
43298
|
+
const selector = presentation === "operations" ? {
|
|
43299
|
+
...assetSelector,
|
|
43300
|
+
collection: assetSelector.collection.describe("Collection ID from kiln_assets_collections; default project.")
|
|
43301
|
+
} : assetSelector;
|
|
43050
43302
|
const library = () => {
|
|
43051
43303
|
if (!context.assetLibrary)
|
|
43052
43304
|
throw new Error("No asset library configured. The local CLI/MCP host supplies workspace collections; embedded hosts must inject assetLibrary.");
|
|
@@ -43074,38 +43326,38 @@ function createKilnAssetDefs(context) {
|
|
|
43074
43326
|
resources: (await Promise.resolve().then(() => (init_assets_resources(), exports_assets_resources))).assetLinks(collection, asset),
|
|
43075
43327
|
downloadUrls: await context.assetDownloadUrls?.(collection, asset.assetId, asset.revisionId)
|
|
43076
43328
|
});
|
|
43077
|
-
const saveInput =
|
|
43078
|
-
collection:
|
|
43079
|
-
programRef:
|
|
43080
|
-
name:
|
|
43081
|
-
assetId:
|
|
43082
|
-
parentRevision:
|
|
43083
|
-
tags:
|
|
43084
|
-
brief:
|
|
43085
|
-
description:
|
|
43086
|
-
attribution:
|
|
43087
|
-
model:
|
|
43088
|
-
harness:
|
|
43089
|
-
author:
|
|
43329
|
+
const saveInput = z23.object({
|
|
43330
|
+
collection: selector.collection,
|
|
43331
|
+
programRef: z23.string(),
|
|
43332
|
+
name: z23.string().min(1).max(200),
|
|
43333
|
+
assetId: selector.assetId.optional(),
|
|
43334
|
+
parentRevision: selector.revisionId.optional(),
|
|
43335
|
+
tags: z23.array(z23.string().max(80)).max(30).optional(),
|
|
43336
|
+
brief: z23.string().max(8000).optional(),
|
|
43337
|
+
description: z23.string().max(4000).optional(),
|
|
43338
|
+
attribution: z23.object({
|
|
43339
|
+
model: z23.string().max(200).optional(),
|
|
43340
|
+
harness: z23.string().max(200).optional(),
|
|
43341
|
+
author: z23.string().max(200).optional()
|
|
43090
43342
|
}).optional(),
|
|
43091
|
-
backdrop:
|
|
43092
|
-
});
|
|
43093
|
-
const assetsInput =
|
|
43094
|
-
action:
|
|
43095
|
-
collection:
|
|
43096
|
-
assetId:
|
|
43097
|
-
revisionId:
|
|
43098
|
-
query:
|
|
43099
|
-
offset:
|
|
43100
|
-
limit:
|
|
43101
|
-
});
|
|
43102
|
-
const exportInput =
|
|
43343
|
+
backdrop: z23.enum(BACKDROP_IDS).optional().describe("Preview backdrop: the one the reviewed sheet used.")
|
|
43344
|
+
});
|
|
43345
|
+
const assetsInput = z23.object({
|
|
43346
|
+
action: z23.enum(["collections", "catalog", "list", "get", "restore"]).default("list"),
|
|
43347
|
+
collection: selector.collection,
|
|
43348
|
+
assetId: selector.assetId.optional(),
|
|
43349
|
+
revisionId: selector.revisionId.optional().describe("get, restore: the saved revision; omitted, the newest."),
|
|
43350
|
+
query: z23.string().max(200).optional(),
|
|
43351
|
+
offset: z23.number().int().min(0).default(0),
|
|
43352
|
+
limit: z23.number().int().min(1).max(50).default(20)
|
|
43353
|
+
});
|
|
43354
|
+
const exportInput = z23.object(selector);
|
|
43103
43355
|
const profileExportInput = exportInput.extend({
|
|
43104
|
-
profile:
|
|
43356
|
+
profile: z23.enum(["editable", "runtime"]).default("editable").describe("editable preserves canonical source/GLB/build resources. runtime returns a standalone GLB and versioned review-metadata sidecar; no source bundle or geometry optimization.")
|
|
43105
43357
|
});
|
|
43106
|
-
const importInput =
|
|
43107
|
-
...
|
|
43108
|
-
sourceCollection:
|
|
43358
|
+
const importInput = z23.object({
|
|
43359
|
+
...selector,
|
|
43360
|
+
sourceCollection: selector.collection
|
|
43109
43361
|
});
|
|
43110
43362
|
return [
|
|
43111
43363
|
{
|
|
@@ -43121,7 +43373,7 @@ function createKilnAssetDefs(context) {
|
|
|
43121
43373
|
requirements: activeRequirements.binding
|
|
43122
43374
|
};
|
|
43123
43375
|
if (input.assetId && input.parentRevision) {
|
|
43124
|
-
const previous = await readSavedRevision(target, input.collection, input.assetId, input.parentRevision);
|
|
43376
|
+
const previous = await readSavedRevision(target, input.collection, input.assetId, input.parentRevision, listCall(input.collection));
|
|
43125
43377
|
assertSavedRequirementsAuthorized(previous.manifest, activeRequirements);
|
|
43126
43378
|
}
|
|
43127
43379
|
const code = await context.programStore.get(input.programRef);
|
|
@@ -43136,6 +43388,7 @@ function createKilnAssetDefs(context) {
|
|
|
43136
43388
|
name: "kiln_assets",
|
|
43137
43389
|
description: "Browse saved assets: collections discovers storage; catalog searches all configured collections; list searches one. Both searches paginate. get returns a build record/downloads; restore loads exact source for kiln_source/kiln_edit. Collection is not project membership. Binary-only assets cannot restore source.",
|
|
43138
43390
|
inputSchema: assetsInput,
|
|
43391
|
+
actionContract: ASSET_CONTRACT,
|
|
43139
43392
|
run: async (raw) => {
|
|
43140
43393
|
const input = assetsInput.parse(raw);
|
|
43141
43394
|
const activeRequirements = toolRequirements(context);
|
|
@@ -43180,10 +43433,10 @@ function createKilnAssetDefs(context) {
|
|
|
43180
43433
|
}))
|
|
43181
43434
|
};
|
|
43182
43435
|
}
|
|
43183
|
-
if (
|
|
43436
|
+
if (ASSET_CONTRACT[input.action].required.some((field) => !input[field]))
|
|
43184
43437
|
throw new Error(`kiln_assets ${input.action} requires assetId; kiln_assets { action: 'list', collection: '${input.collection}' } lists them.`);
|
|
43185
|
-
const revisionId = input.revisionId ?? await newestRevision(target, input.collection, input.assetId);
|
|
43186
|
-
const record = await readSavedRevision(target, input.collection, input.assetId, revisionId);
|
|
43438
|
+
const revisionId = input.revisionId ?? await newestRevision(target, input.collection, input.assetId, listCall(input.collection));
|
|
43439
|
+
const record = await readSavedRevision(target, input.collection, input.assetId, revisionId, listCall(input.collection));
|
|
43187
43440
|
if (input.action === "get")
|
|
43188
43441
|
return links(input.collection, record.manifest);
|
|
43189
43442
|
const saved = assertSavedRequirementsAuthorized(record.manifest, activeRequirements);
|
|
@@ -43203,9 +43456,9 @@ function createKilnAssetDefs(context) {
|
|
|
43203
43456
|
name: "kiln_present",
|
|
43204
43457
|
description: "Present one exact saved revision. Supporting MCP App clients show an interactive 3D card with GLB, editable ZIP, and source downloads. Every host receives exact artifact descriptors with resource URIs in the JSON result; verified hosts may also receive core MCP resource-link blocks. This tool does not launch a local browser in coding harnesses. Call after saving or when the user wants to see or download an asset.",
|
|
43205
43458
|
inputSchema: exportInput,
|
|
43206
|
-
outputSchema:
|
|
43207
|
-
ok:
|
|
43208
|
-
collection:
|
|
43459
|
+
outputSchema: z23.object({
|
|
43460
|
+
ok: z23.literal(true),
|
|
43461
|
+
collection: z23.string(),
|
|
43209
43462
|
asset: assetManifestSchema.pick({
|
|
43210
43463
|
assetId: true,
|
|
43211
43464
|
revisionId: true,
|
|
@@ -43216,25 +43469,25 @@ function createKilnAssetDefs(context) {
|
|
|
43216
43469
|
editable: true,
|
|
43217
43470
|
files: true
|
|
43218
43471
|
}).extend({
|
|
43219
|
-
build:
|
|
43220
|
-
engine:
|
|
43221
|
-
rebuild:
|
|
43222
|
-
warningCount:
|
|
43223
|
-
warnings:
|
|
43472
|
+
build: z23.object({
|
|
43473
|
+
engine: z23.string(),
|
|
43474
|
+
rebuild: z23.enum(["engine-required", "external-dependencies-required"]),
|
|
43475
|
+
warningCount: z23.number().int(),
|
|
43476
|
+
warnings: z23.array(z23.string())
|
|
43224
43477
|
}).optional()
|
|
43225
43478
|
}),
|
|
43226
|
-
resources:
|
|
43227
|
-
type:
|
|
43228
|
-
name:
|
|
43229
|
-
uri:
|
|
43230
|
-
mimeType:
|
|
43231
|
-
size:
|
|
43232
|
-
annotations:
|
|
43233
|
-
audience:
|
|
43234
|
-
priority:
|
|
43479
|
+
resources: z23.array(z23.object({
|
|
43480
|
+
type: z23.literal("resource_link"),
|
|
43481
|
+
name: z23.string(),
|
|
43482
|
+
uri: z23.string(),
|
|
43483
|
+
mimeType: z23.string(),
|
|
43484
|
+
size: z23.number().int().nonnegative(),
|
|
43485
|
+
annotations: z23.object({
|
|
43486
|
+
audience: z23.array(z23.enum(["user", "assistant"])),
|
|
43487
|
+
priority: z23.number()
|
|
43235
43488
|
})
|
|
43236
43489
|
})),
|
|
43237
|
-
downloadUrls:
|
|
43490
|
+
downloadUrls: z23.record(z23.string(), z23.string()).optional()
|
|
43238
43491
|
}),
|
|
43239
43492
|
ui: {
|
|
43240
43493
|
resourceUri: KILN_ASSET_WIDGET_URI2,
|
|
@@ -43251,7 +43504,7 @@ function createKilnAssetDefs(context) {
|
|
|
43251
43504
|
inputSchema: profileExportInput,
|
|
43252
43505
|
run: async (raw) => {
|
|
43253
43506
|
const input = profileExportInput.parse(raw);
|
|
43254
|
-
const record = await readSavedRevision(library(), input.collection, input.assetId, input.revisionId);
|
|
43507
|
+
const record = await readSavedRevision(library(), input.collection, input.assetId, input.revisionId, listCall(input.collection));
|
|
43255
43508
|
await Promise.resolve().then(() => init_draw_diagnostics());
|
|
43256
43509
|
if (input.profile === "runtime") {
|
|
43257
43510
|
const output = await (await Promise.resolve().then(() => (init_asset_export(), exports_asset_export))).exportAssetGlb(record, {
|
|
@@ -43285,7 +43538,7 @@ function createKilnAssetDefs(context) {
|
|
|
43285
43538
|
run: async (raw) => {
|
|
43286
43539
|
const input = importInput.parse(raw);
|
|
43287
43540
|
const target = library();
|
|
43288
|
-
const record = await readSavedRevision(target, input.sourceCollection, input.assetId, input.revisionId);
|
|
43541
|
+
const record = await readSavedRevision(target, input.sourceCollection, input.assetId, input.revisionId, listCall(input.sourceCollection));
|
|
43289
43542
|
await target.import(input.collection, [record]);
|
|
43290
43543
|
return links(input.collection, record.manifest);
|
|
43291
43544
|
}
|
|
@@ -43409,7 +43662,7 @@ function createKilnToolHost(context = {}, options = {}) {
|
|
|
43409
43662
|
};
|
|
43410
43663
|
}
|
|
43411
43664
|
};
|
|
43412
|
-
const defs = kilnMcpToolDefs(requestContext);
|
|
43665
|
+
const defs = options.toolPresentation === "operations" ? createKilnOperationToolRegistry(requestContext) : kilnMcpToolDefs(requestContext);
|
|
43413
43666
|
const byName = new Map(defs.map((def) => [def.name, def]));
|
|
43414
43667
|
return {
|
|
43415
43668
|
defs,
|
|
@@ -43476,6 +43729,7 @@ function resourceText(name, bytes) {
|
|
|
43476
43729
|
function createKilnMcpServer(context = {}, options = {}) {
|
|
43477
43730
|
const host = createKilnToolHost(context, options);
|
|
43478
43731
|
return createKilnServer({
|
|
43732
|
+
...options.toolPresentation === "operations" ? { instructions: MCP_OPERATION_INSTRUCTIONS } : {},
|
|
43479
43733
|
manifest: buildMcpManifest(host.defs, context),
|
|
43480
43734
|
host: async () => host
|
|
43481
43735
|
});
|