@instruktlabs/kiln 1.1.0 → 1.2.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.
Files changed (56) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +28 -0
  4. package/dist/agent-run.mjs +224 -151
  5. package/dist/build.json +22 -22
  6. package/dist/cli.mjs +229 -151
  7. package/dist/mcp-engine.mjs +400 -147
  8. package/dist/mcp-server.mjs +6 -6
  9. package/dist/viewer/app.js +180 -180
  10. package/dist/viewer/chat.html +183 -183
  11. package/docs/sdk.md +23 -0
  12. package/docs/tools-operations.md +1529 -0
  13. package/lib/asset-widget-uri.d.ts +1 -1
  14. package/lib/asset-widget-uri.js +1 -1
  15. package/lib/discovery/index.d.ts +1 -1
  16. package/lib/discovery/index.js +2 -2
  17. package/lib/discovery/service.d.ts +3 -1
  18. package/lib/discovery/service.js +4 -2
  19. package/lib/engine-identity.d.ts +1 -1
  20. package/lib/engine-identity.js +1 -1
  21. package/lib/mcp-core.d.ts +2 -1
  22. package/lib/mcp-core.js +1 -0
  23. package/lib/mcp-engine.d.ts +2 -0
  24. package/lib/mcp-engine.js +8 -3
  25. package/lib/tools/discovery.d.ts +1 -1
  26. package/lib/tools/discovery.js +11 -9
  27. package/lib/tools/materials.d.ts +1 -1
  28. package/lib/tools/materials.js +44 -14
  29. package/lib/tools/operation-contract.d.ts +8 -0
  30. package/lib/tools/operation-contract.js +37 -0
  31. package/lib/tools/operations.d.ts +3 -0
  32. package/lib/tools/operations.js +154 -0
  33. package/lib/tools/registry.d.ts +7 -4
  34. package/lib/tools/registry.js +73 -24
  35. package/package.json +2 -1
  36. package/plugin.json +1 -1
  37. package/plugins/kiln-engine/.claude-plugin/plugin.json +1 -1
  38. package/plugins/kiln-engine/README.md +3 -3
  39. package/plugins/kiln-engine/package-provenance.json +6 -6
  40. package/plugins/kiln-engine/plugin.json +1 -1
  41. package/plugins/kiln-engine/runtime.json +1 -1
  42. package/src/asset-widget-uri.ts +1 -1
  43. package/src/discovery/index.ts +2 -0
  44. package/src/discovery/service.ts +3 -1
  45. package/src/engine-identity.ts +1 -1
  46. package/src/generated/mcp-manifest.json +4 -4
  47. package/src/mcp-core.ts +3 -0
  48. package/src/mcp-engine.ts +11 -1
  49. package/src/tools/discovery.ts +20 -10
  50. package/src/tools/materials.ts +59 -15
  51. package/src/tools/operation-contract.ts +51 -0
  52. package/src/tools/operations.ts +177 -0
  53. package/src/tools/registry.ts +102 -21
  54. package/src/viewer/chat-app.ts +6 -2
  55. package/src/viewer/glb-loader.ts +78 -0
  56. package/src/viewer/scene.ts +9 -26
@@ -32234,7 +32234,7 @@ import {
32234
32234
  // src/tools/registry.ts
32235
32235
  init_capture_cache();
32236
32236
  init_assets();
32237
- import { z as z20 } from "zod";
32237
+ import { z as z22 } from "zod";
32238
32238
 
32239
32239
  // src/requirements-assets.ts
32240
32240
  init_requirements_context();
@@ -32939,7 +32939,7 @@ function createKilnSourceDef(store) {
32939
32939
  }
32940
32940
 
32941
32941
  // src/engine-identity.ts
32942
- var ENGINE_VERSION = "1.1.0";
32942
+ var ENGINE_VERSION = "1.2.1";
32943
32943
  var ENGINE_INSTALL_URL = new URL("../", import.meta.url).href;
32944
32944
  function engineIdentity() {
32945
32945
  return { version: ENGINE_VERSION, installUrl: ENGINE_INSTALL_URL };
@@ -36395,7 +36395,7 @@ var MAX_RESPONSE_BYTES = 64 * 1024;
36395
36395
  var MAX_TEXT_CHARS = 16 * 1024;
36396
36396
  var DETAIL_RESULT_BUDGET = 15000;
36397
36397
  var compare = (a, b) => a < b ? -1 : a > b ? 1 : 0;
36398
- function createDiscoveryService(source, index, capabilities, retirements = {}, notes = async () => []) {
36398
+ function createDiscoveryService(source, index, capabilities, retirements = {}, notes = async () => [], capabilitiesCall = "capabilities:true") {
36399
36399
  const entries = parseCatalog(source);
36400
36400
  const byId = new Map(entries.map((entry) => [entry.id, entry]));
36401
36401
  const byName = new Map(entries.filter((entry) => entry.kind !== "recipe").map((entry) => [entry.name, entry]));
@@ -36418,7 +36418,7 @@ function createDiscoveryService(source, index, capabilities, retirements = {}, n
36418
36418
  "Parts auto-add to opts.parent; do not wrap createPart in parent.add. Part rotation uses degrees.",
36419
36419
  "Custom THREE.BufferGeometry and ordinary JavaScript functions remain available. Recipes offer guidance and never restrict modeling.",
36420
36420
  "Send source once and reuse programRef for reads, edits, inspection and rendering. Review geometry, materials and destination constraints separately.",
36421
- "Search for the operation you need in ordinary language, then fetch exact contracts with ids. Use capabilities:true for the current host."
36421
+ `Search for the operation you need in ordinary language, then fetch exact contracts with ids. Use ${capabilitiesCall} for the current host.`
36422
36422
  ]
36423
36423
  };
36424
36424
  const error = (mode, code, message) => ({
@@ -36599,12 +36599,12 @@ var snapshot;
36599
36599
  function createDiscovery(capabilities = async () => ({
36600
36600
  host: "No host capability provider was supplied.",
36601
36601
  discovery: { mode: "lexical", offline: true, requiresModel: false }
36602
- }), notes = async () => []) {
36602
+ }), notes = async () => [], capabilitiesCall = "capabilities:true") {
36603
36603
  snapshot ??= (() => {
36604
36604
  const entries = listDiscoveryEntries();
36605
36605
  return { entries, index: createLexicalDiscoveryIndex(entries) };
36606
36606
  })();
36607
- return createDiscoveryService(snapshot.entries, snapshot.index, capabilities, REMOVED_AUTHORING_HELPERS, notes);
36607
+ return createDiscoveryService(snapshot.entries, snapshot.index, capabilities, REMOVED_AUTHORING_HELPERS, notes, capabilitiesCall);
36608
36608
  }
36609
36609
 
36610
36610
  // src/tools/discovery.ts
@@ -36613,8 +36613,8 @@ init_capture_limits();
36613
36613
  init_geometry_export();
36614
36614
  init_community_exporter();
36615
36615
  init_material_resources();
36616
- function createKilnDiscoveryDef(context) {
36617
- const run = createDiscovery(() => currentCapabilities(context), async () => projectNotes(context));
36616
+ function createKilnDiscoveryDef(context, presentation = "grouped") {
36617
+ const run = createDiscovery(() => currentCapabilities(context, presentation), async () => projectNotes(context), presentation === "operations" ? "kiln_capabilities({})" : "capabilities:true");
36618
36618
  return {
36619
36619
  name: "kiln_discover",
36620
36620
  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.",
@@ -36638,7 +36638,7 @@ function projectNotes(context) {
36638
36638
  `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.`
36639
36639
  ] : [];
36640
36640
  }
36641
- async function currentCapabilities(context) {
36641
+ async function currentCapabilities(context, presentation) {
36642
36642
  const externalEvaluator = Boolean(context.evaluatorPort) || context.evaluatorProfile === "evaluator-required";
36643
36643
  const approvedTextures = context.approvedTextureResources ? context.approvedTextureResources() : externalEvaluator ? null : approvedTextureCatalogV1();
36644
36644
  const textureSlots = approvedTextures === null ? null : {};
@@ -36667,7 +36667,7 @@ async function currentCapabilities(context) {
36667
36667
  requiresModel: false
36668
36668
  },
36669
36669
  engine: engineIdentity(),
36670
- project: {
36670
+ project: presentation === "operations" && !context.projectStore ? { available: false } : {
36671
36671
  configured: configuredProject(context),
36672
36672
  select: "projectId per call; omitted uses the configured project, null selects standalone work",
36673
36673
  read: 'kiln_project { action: "get", projectId } returns the brief, design, inventory and material pins'
@@ -36686,7 +36686,7 @@ async function currentCapabilities(context) {
36686
36686
  available: Boolean(context.assetLibrary),
36687
36687
  collections: context.assetLibrary?.collections() ?? [],
36688
36688
  save: "kiln_save persists exact GLB, source and provenance; draft renders do not populate collections",
36689
- resume: "kiln_assets action=restore imports a saved revision into the current program store",
36689
+ resume: `${presentation === "operations" ? "kiln_assets_restore" : "kiln_assets action=restore"} imports a saved revision into the current program store`,
36690
36690
  downloads: "kiln_export returns GLB/source/ZIP resource links; client presentation varies",
36691
36691
  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"
36692
36692
  },
@@ -37071,13 +37071,39 @@ var MATERIAL_ACTIONS = [
37071
37071
  "create-procedural",
37072
37072
  "import"
37073
37073
  ];
37074
- var REQUIREMENTS2 = {
37075
- presets: { required: [] },
37076
- "create-preset": { required: ["presetId", "seed", "creator", "license"] },
37077
- list: { required: [] },
37078
- get: { required: ["materialId"] },
37079
- "create-procedural": { required: ["draft"], shapes: { draft: "shape:material-draft" } },
37080
- import: { required: ["payload"], shapes: { payload: "shape:material-import" } }
37074
+ var MATERIAL_CONTRACT = {
37075
+ presets: {
37076
+ fields: ["tag"],
37077
+ required: [],
37078
+ description: "List shipped material recipes, optionally filtered by tag."
37079
+ },
37080
+ "create-preset": {
37081
+ fields: ["presetId", "seed", "creator", "license", "size", "materialId"],
37082
+ required: ["presetId", "seed", "creator", "license"],
37083
+ description: "Create an immutable material from a shipped preset with explicit seed, creator and license."
37084
+ },
37085
+ list: {
37086
+ fields: ["tag"],
37087
+ required: [],
37088
+ description: "List saved immutable material revisions, optionally filtered by tag."
37089
+ },
37090
+ get: {
37091
+ fields: ["materialId", "revisionId"],
37092
+ required: ["materialId"],
37093
+ description: "Read a material revision, provenance and portable specification. Omit revisionId only when exactly one revision exists."
37094
+ },
37095
+ "create-procedural": {
37096
+ fields: ["draft"],
37097
+ required: ["draft"],
37098
+ shapes: { draft: "shape:material-draft" },
37099
+ description: "Create an immutable material from a bounded procedural draft. Does not fetch URLs or execute source."
37100
+ },
37101
+ import: {
37102
+ fields: ["payload"],
37103
+ required: ["payload"],
37104
+ shapes: { payload: "shape:material-import" },
37105
+ description: "Import complete normalized material records and embedded PNGs. Does not fetch URLs or execute source."
37106
+ }
37081
37107
  };
37082
37108
  var record7 = (description) => z16.record(z16.string(), z16.unknown()).optional().describe(description);
37083
37109
  var tag = z16.string().min(1).max(80).optional().describe("presets, list: keep one tag.");
@@ -37099,13 +37125,13 @@ var materialResult = (material) => ({
37099
37125
  material,
37100
37126
  portableSpec: materialLibraryPortableSpec(material)
37101
37127
  });
37102
- var unknownMaterial = (materialId, revisionId) => new Error(`Unknown material ${materialId}${revisionId ? ` at ${revisionId}` : ""}. kiln_material { action: 'list' } lists the materials in this workspace with their revision IDs.`);
37103
- async function onlyRevision(library, materialId) {
37128
+ var unknownMaterial = (materialId, revisionId, listCall) => new Error(`Unknown material ${materialId}${revisionId ? ` at ${revisionId}` : ""}. ${listCall} lists the materials in this workspace with their revision IDs.`);
37129
+ async function onlyRevision(library, materialId, listCall) {
37104
37130
  const revisions = (await library.list()).filter((material) => material.materialId === materialId).map((material) => material.revisionId).sort();
37105
37131
  if (revisions.length === 1)
37106
37132
  return revisions[0];
37107
37133
  if (revisions.length === 0)
37108
- throw unknownMaterial(materialId);
37134
+ throw unknownMaterial(materialId, undefined, listCall);
37109
37135
  throw new Error(`Material ${materialId} has ${revisions.length} revisions: ${revisions.join(", ")}. Pass revisionId to get one.`);
37110
37136
  }
37111
37137
  function aliasMaterialId(raw) {
@@ -37118,11 +37144,13 @@ function aliasMaterialId(raw) {
37118
37144
  throw new Error(`kiln_material: resourceId (${String(resourceId)}) and materialId (${String(rest.materialId)}) name different materials; pass materialId alone.`);
37119
37145
  return { ...rest, materialId: resourceId };
37120
37146
  }
37121
- function createKilnMaterialDef(library) {
37147
+ function createKilnMaterialDef(library, presentation = "grouped") {
37148
+ const listCall = presentation === "operations" ? 'kiln_material_search({ scope: "saved" })' : "kiln_material { action: 'list' }";
37122
37149
  return {
37123
37150
  name: "kiln_material",
37124
37151
  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.",
37125
37152
  inputSchema: materialToolInput,
37153
+ actionContract: MATERIAL_CONTRACT,
37126
37154
  annotations: {
37127
37155
  readOnlyHint: false,
37128
37156
  destructiveHint: false,
@@ -37132,7 +37160,7 @@ function createKilnMaterialDef(library) {
37132
37160
  async run(raw) {
37133
37161
  assertMaterialJson(raw);
37134
37162
  const input = materialToolInput.parse(aliasMaterialId(raw));
37135
- requireActionFields("kiln_material", input.action, input, REQUIREMENTS2[input.action]);
37163
+ requireActionFields("kiln_material", input.action, input, MATERIAL_CONTRACT[input.action]);
37136
37164
  switch (input.action) {
37137
37165
  case "presets":
37138
37166
  return {
@@ -37168,12 +37196,12 @@ function createKilnMaterialDef(library) {
37168
37196
  };
37169
37197
  }
37170
37198
  case "get": {
37171
- const revisionId = input.revisionId ?? await onlyRevision(library, input.materialId);
37199
+ const revisionId = input.revisionId ?? await onlyRevision(library, input.materialId, listCall);
37172
37200
  try {
37173
37201
  return materialResult((await library.read(input.materialId, revisionId)).manifest);
37174
37202
  } catch (error) {
37175
37203
  if (error.code === "ENOENT")
37176
- throw unknownMaterial(input.materialId, revisionId);
37204
+ throw unknownMaterial(input.materialId, revisionId, listCall);
37177
37205
  throw error;
37178
37206
  }
37179
37207
  }
@@ -37224,7 +37252,7 @@ async function persistedPreviewFidelity(fidelity, glb) {
37224
37252
  var operationId = z17.string().regex(/^op_[a-f0-9-]{36}$/);
37225
37253
  var assetId = z17.string().regex(/^[a-z][a-z0-9_-]{0,79}$/);
37226
37254
  var REVIEW_ACTIONS = ["list", "get", "pin", "save"];
37227
- var REQUIREMENTS3 = {
37255
+ var REQUIREMENTS2 = {
37228
37256
  list: { required: [] },
37229
37257
  get: { required: ["operationId"] },
37230
37258
  pin: { required: ["operationId", "pinned"] },
@@ -37306,7 +37334,7 @@ function createKilnReviewDef(context) {
37306
37334
  },
37307
37335
  async run(raw) {
37308
37336
  const input = reviewToolInput.parse(raw);
37309
- requireActionFields("kiln_review", input.action, input, REQUIREMENTS3[input.action]);
37337
+ requireActionFields("kiln_review", input.action, input, REQUIREMENTS2[input.action]);
37310
37338
  if (input.action === "list") {
37311
37339
  const snapshot = await store.snapshot({ projectId: input.projectId });
37312
37340
  const offset = input.offset ?? 0;
@@ -37496,6 +37524,12 @@ function withWorkspaceContext(def, context) {
37496
37524
  };
37497
37525
  }
37498
37526
 
37527
+ // src/tools/operations.ts
37528
+ import { z as z21 } from "zod";
37529
+
37530
+ // src/tools/operation-contract.ts
37531
+ import { z as z20 } from "zod";
37532
+
37499
37533
  // src/build-cache.ts
37500
37534
  init_protocol();
37501
37535
  init_requirements_context();
@@ -37962,7 +37996,10 @@ function resolveViewRenderTimeoutMs(input) {
37962
37996
  // src/tools/registry.ts
37963
37997
  init_evidence_history();
37964
37998
  init_background();
37965
- var KILN_ASSET_WIDGET_URI = "ui://kiln/asset-v5.html";
37999
+
38000
+ // src/asset-widget-uri.ts
38001
+ var KILN_ASSET_WIDGET_URI = "ui://kiln/asset-v6.html";
38002
+ // src/tools/registry.ts
37966
38003
  function proceduralTextureMaterialContract(rendered, context) {
37967
38004
  const required = [...new Set(context.requiredProceduralTextureUsages ?? [])];
37968
38005
  if (required.length === 0)
@@ -38191,11 +38228,11 @@ function derivativeReviewFidelity(receipts) {
38191
38228
  ...reasonCodes.length ? { reasonCodes } : {}
38192
38229
  };
38193
38230
  }
38194
- var validateInput = z20.object({
38195
- code: z20.string().describe("Kiln source code (defines `meta` + `build()`, optional `animate()`).")
38231
+ var validateInput = z22.object({
38232
+ code: z22.string().describe("Kiln source code (defines `meta` + `build()`, optional `animate()`).")
38196
38233
  });
38197
- var renderInput = z20.object({
38198
- code: z20.string().describe("Kiln source code to execute and render to an in-memory GLB.")
38234
+ var renderInput = z22.object({
38235
+ code: z22.string().describe("Kiln source code to execute and render to an in-memory GLB.")
38199
38236
  });
38200
38237
  var renderViewsInput = renderInput.extend({ capture: captureInput, detail: reviewDetailInput });
38201
38238
  var reviewDetailOptions = (context) => ({
@@ -38208,26 +38245,26 @@ var reviewDetailOptions = (context) => ({
38208
38245
  }
38209
38246
  });
38210
38247
  var renderViewsBufferInput = renderViewsInput.omit({ code: true });
38211
- var screenshotAnimationInput = z20.object({
38248
+ var screenshotAnimationInput = z22.object({
38212
38249
  shot: cameraShotInput.optional(),
38213
- measureParts: z20.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."),
38214
- frames: z20.number().int().min(2).max(6).optional(),
38215
- frameTimes: z20.array(z20.number().min(0).max(1)).min(1).max(9).optional().describe("Ordered phase fractions 0..1; mutually exclusive with frames."),
38216
- framing: z20.enum(["locked", "follow"]).optional(),
38217
- size: z20.number().int().min(128).max(1024).optional().describe("Frame size in px; default 256."),
38250
+ measureParts: z22.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."),
38251
+ frames: z22.number().int().min(2).max(6).optional(),
38252
+ frameTimes: z22.array(z22.number().min(0).max(1)).min(1).max(9).optional().describe("Ordered phase fractions 0..1; mutually exclusive with frames."),
38253
+ framing: z22.enum(["locked", "follow"]).optional(),
38254
+ size: z22.number().int().min(128).max(1024).optional().describe("Frame size in px; default 256."),
38218
38255
  detail: reviewDetailInput,
38219
- code: z20.string().describe("Kiln source code to execute; must define animate() returning the named clip."),
38220
- clip: z20.string().describe('The animation clip to view, by name (e.g. "walk", "attack"). Must be one your animate() returns.'),
38221
- camera: z20.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."),
38222
- perFrame: z20.boolean().optional().describe("Return the frames as separate high-res images instead of one composite grid. Default false.")
38256
+ code: z22.string().describe("Kiln source code to execute; must define animate() returning the named clip."),
38257
+ clip: z22.string().describe('The animation clip to view, by name (e.g. "walk", "attack"). Must be one your animate() returns.'),
38258
+ camera: z22.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."),
38259
+ perFrame: z22.boolean().optional().describe("Return the frames as separate high-res images instead of one composite grid. Default false.")
38223
38260
  });
38224
38261
  var screenshotAnimationAdvertisedInput = screenshotAnimationInput.extend({
38225
38262
  shot: cameraShotRecordInput
38226
38263
  });
38227
- var viewInteriorInput = z20.object({
38264
+ var viewInteriorInput = z22.object({
38228
38265
  capture: advancedCaptureInput.optional(),
38229
- code: z20.string().describe("Kiln source code to execute and render with the roof hidden."),
38230
- nodeName: z20.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.')
38266
+ code: z22.string().describe("Kiln source code to execute and render with the roof hidden."),
38267
+ nodeName: z22.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.')
38231
38268
  });
38232
38269
  var viewInteriorAdvertisedInput = viewInteriorInput.extend({ capture: captureRecordInput });
38233
38270
  function runValidate(input, context) {
@@ -38242,11 +38279,11 @@ function runValidate(input, context) {
38242
38279
  warnings: result.warnings.map((w) => w.fixHint ? `${w.message} (${w.fixHint})` : w.message)
38243
38280
  };
38244
38281
  }
38245
- var partListInput = z20.object({
38246
- query: z20.string().max(4096).optional().describe("Case-insensitive substring of name or exact encoded path; not a regex."),
38247
- offset: z20.number().int().min(0).optional(),
38248
- limit: z20.number().int().min(1).max(100).optional(),
38249
- placement: z20.boolean().optional().describe("Add world position, rotation, scale, mirroring and bounds per part; pages of 50.")
38282
+ var partListInput = z22.object({
38283
+ query: z22.string().max(4096).optional().describe("Case-insensitive substring of name or exact encoded path; not a regex."),
38284
+ offset: z22.number().int().min(0).optional(),
38285
+ limit: z22.number().int().min(1).max(100).optional(),
38286
+ placement: z22.boolean().optional().describe("Add world position, rotation, scale, mirroring and bounds per part; pages of 50.")
38250
38287
  }).strict();
38251
38288
  var PLACEMENT_PAGE_LIMIT = 50;
38252
38289
  async function listPartNames2(root, options = {}) {
@@ -38713,35 +38750,35 @@ function createKilnViewInteriorDef(context = {}) {
38713
38750
  };
38714
38751
  }
38715
38752
  var kilnViewInteriorDef = createKilnViewInteriorDef();
38716
- var attachmentEndpointInput = z20.object({
38717
- subject: z20.object({ path: z20.string().optional(), name: z20.string().optional() }).strict(),
38753
+ var attachmentEndpointInput = z22.object({
38754
+ subject: z22.object({ path: z22.string().optional(), name: z22.string().optional() }).strict(),
38718
38755
  point: cameraVec3Input.optional()
38719
38756
  }).strict();
38720
- var surfacePairInput = z20.array(z20.string().max(4096)).length(2);
38721
- var inspectInput = z20.object({
38722
- image: z20.boolean().optional().describe("False: requires listParts/measure/surfacePairs/compare; no image or camera controls. Default true."),
38757
+ var surfacePairInput = z22.array(z22.string().max(4096)).length(2);
38758
+ var inspectInput = z22.object({
38759
+ image: z22.boolean().optional().describe("False: requires listParts/measure/surfacePairs/compare; no image or camera controls. Default true."),
38723
38760
  detail: reviewDetailInput,
38724
38761
  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."),
38725
- surfacePairs: z20.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."),
38726
- compare: z20.object({
38727
- programRef: z20.string().regex(programRefPattern),
38728
- offset: z20.number().int().min(0).optional(),
38729
- limit: z20.number().int().min(1).max(100).optional(),
38730
- paths: z20.array(z20.string().max(4096)).min(1).max(12).optional().describe("Exact baseline node paths, scene-prefixed without primitive children. Complete subtree summaries.")
38762
+ surfacePairs: z22.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."),
38763
+ compare: z22.object({
38764
+ programRef: z22.string().regex(programRefPattern),
38765
+ offset: z22.number().int().min(0).optional(),
38766
+ limit: z22.number().int().min(1).max(100).optional(),
38767
+ paths: z22.array(z22.string().max(4096)).min(1).max(12).optional().describe("Exact baseline node paths, scene-prefixed without primitive children. Complete subtree summaries.")
38731
38768
  }).strict().optional().describe("Static geometry/material/transform/bounds under current host settings. Follow nextOffset; paths adds complete subtrees."),
38732
- measure: z20.object({
38733
- mode: z20.enum(["anchors", "surface"]).optional(),
38769
+ measure: z22.object({
38770
+ mode: z22.enum(["anchors", "surface"]).optional(),
38734
38771
  from: attachmentEndpointInput,
38735
38772
  to: attachmentEndpointInput
38736
38773
  }).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."),
38737
38774
  shot: cameraShotInput.optional().describe("Exact shot; omit part/view/orbit controls."),
38738
- code: z20.string().describe("Kiln source code to execute and inspect."),
38739
- part: z20.string().optional().describe("Frame named part and descendants (case-insensitive, substring fallback). Omit for whole asset."),
38740
- view: z20.string().optional().describe("front/right/back/left/top/three-quarter (default). Orbit angles override."),
38741
- azimuthDeg: z20.number().optional().describe("Orbit degrees: 0 front, 90 right, 180 back, 270 left. Wraps."),
38742
- elevationDeg: z20.number().optional().describe("Elevation degrees: 0 eye level, positive above. Clamped -89..89."),
38743
- zoom: z20.number().optional().describe("Bounds padding 1..4; default 1.2. Larger = more context."),
38744
- isolate: z20.boolean().optional().describe("Hide surrounding geometry. Requires part; default false.")
38775
+ code: z22.string().describe("Kiln source code to execute and inspect."),
38776
+ part: z22.string().optional().describe("Frame named part and descendants (case-insensitive, substring fallback). Omit for whole asset."),
38777
+ view: z22.string().optional().describe("front/right/back/left/top/three-quarter (default). Orbit angles override."),
38778
+ azimuthDeg: z22.number().optional().describe("Orbit degrees: 0 front, 90 right, 180 back, 270 left. Wraps."),
38779
+ elevationDeg: z22.number().optional().describe("Elevation degrees: 0 eye level, positive above. Clamped -89..89."),
38780
+ zoom: z22.number().optional().describe("Bounds padding 1..4; default 1.2. Larger = more context."),
38781
+ isolate: z22.boolean().optional().describe("Hide surrounding geometry. Requires part; default false.")
38745
38782
  });
38746
38783
  var inspectBufferInput = inspectInput.omit({ code: true });
38747
38784
  var inspectAdvertisedInput = inspectInput.extend({ shot: cameraShotRecordInput });
@@ -38901,15 +38938,15 @@ function createKilnInspectDef(context = {}) {
38901
38938
  };
38902
38939
  }
38903
38940
  var kilnInspectDef = createKilnInspectDef();
38904
- var editOperationInput = z20.object({
38905
- oldString: z20.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."),
38906
- newString: z20.string().describe("The replacement text. Use an empty string to delete."),
38907
- replaceAll: z20.boolean().optional().describe("Replace every occurrence instead of failing when oldString matches more than once.")
38941
+ var editOperationInput = z22.object({
38942
+ oldString: z22.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."),
38943
+ newString: z22.string().describe("The replacement text. Use an empty string to delete."),
38944
+ replaceAll: z22.boolean().optional().describe("Replace every occurrence instead of failing when oldString matches more than once.")
38908
38945
  });
38909
- var editInput = z20.object({
38910
- code: z20.string().describe("The Kiln program to patch. The full current source."),
38911
- edits: z20.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."),
38912
- render: z20.boolean().optional().describe("Render the patched program and return the views (default true). false = patch only."),
38946
+ var editInput = z22.object({
38947
+ code: z22.string().describe("The Kiln program to patch. The full current source."),
38948
+ edits: z22.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."),
38949
+ render: z22.boolean().optional().describe("Render the patched program and return the views (default true). false = patch only."),
38913
38950
  capture: captureInput,
38914
38951
  detail: reviewDetailInput
38915
38952
  });
@@ -39135,24 +39172,27 @@ function withCaptureCache(context) {
39135
39172
  } : {}
39136
39173
  };
39137
39174
  }
39138
- var rendererInput = z20.strictObject({
39139
- action: z20.enum(["status", "reprobe"]).default("status")
39175
+ var rendererInput = z22.strictObject({
39176
+ action: z22.enum(["status", "reprobe"]).default("status")
39140
39177
  });
39141
- async function readSavedRevision(target, collection, assetId, revisionId) {
39178
+ async function readSavedRevision(target, collection, assetId, revisionId, listCall = `kiln_assets { action: 'list', collection: '${collection}' }`) {
39142
39179
  try {
39143
39180
  return await target.read(collection, assetId, revisionId);
39144
39181
  } catch (error) {
39145
39182
  if (error.code === "ENOENT")
39146
- throw new Error(`Unknown asset ${assetId} revision ${revisionId} in collection ${collection}. kiln_assets { action: 'list', collection: '${collection}' } lists the saved revisions.`);
39183
+ throw new Error(`Unknown asset ${assetId} revision ${revisionId} in collection ${collection}. ${listCall} lists the saved revisions.`);
39147
39184
  throw error;
39148
39185
  }
39149
39186
  }
39150
39187
  function createKilnProgramToolRegistry(suppliedContext = {}) {
39188
+ return createProgramDefs(suppliedContext, "grouped");
39189
+ }
39190
+ function createProgramDefs(suppliedContext, presentation) {
39151
39191
  toolRequirements(suppliedContext);
39152
39192
  const store = suppliedContext.programStore ?? new MemoryProgramStore;
39153
39193
  const context = withCaptureCache(withBuildCache({ ...suppliedContext, programStore: store }));
39154
39194
  return [
39155
- createKilnDiscoveryDef({ ...suppliedContext, programStore: store }),
39195
+ createKilnDiscoveryDef({ ...suppliedContext, programStore: store }, presentation),
39156
39196
  {
39157
39197
  name: "kiln_renderer",
39158
39198
  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.",
@@ -39192,7 +39232,7 @@ function createKilnProgramToolRegistry(suppliedContext = {}) {
39192
39232
  ].map((def) => withProgramReferences(def, store, context.readSourceFile)),
39193
39233
  createKilnSourceDef(store),
39194
39234
  ...context.projectStore ? [createKilnProjectDef(context.projectStore, context.projectBundleReader)] : [],
39195
- ...context.materialLibrary ? [createKilnMaterialDef(context.materialLibrary)] : [],
39235
+ ...context.materialLibrary ? [createKilnMaterialDef(context.materialLibrary, presentation)] : [],
39196
39236
  ...context.reviewStore && context.assetLibrary ? [
39197
39237
  createKilnReviewDef({
39198
39238
  reviewStore: context.reviewStore,
@@ -39200,7 +39240,7 @@ function createKilnProgramToolRegistry(suppliedContext = {}) {
39200
39240
  requirements: context.requirements
39201
39241
  })
39202
39242
  ] : [],
39203
- ...createKilnAssetDefs({ ...context, programStore: store })
39243
+ ...createKilnAssetDefs({ ...context, programStore: store }, presentation)
39204
39244
  ].map((def) => withWorkspaceContext(def, context)).map((def) => ({
39205
39245
  ...def,
39206
39246
  annotations: {
@@ -39220,14 +39260,14 @@ function createKilnNativeToolRegistry(suppliedContext, completion) {
39220
39260
  programStore: suppliedContext.programStore ?? new MemoryProgramStore,
39221
39261
  programArtifacts: suppliedContext.programArtifacts ?? new ProgramArtifactStore
39222
39262
  };
39223
- const inputSchema = z20.strictObject({
39224
- programRef: z20.string().regex(programRefPattern)
39263
+ const inputSchema = z22.strictObject({
39264
+ programRef: z22.string().regex(programRefPattern)
39225
39265
  });
39226
- const skillResourceInput = z20.strictObject({
39227
- skill: z20.string().min(1).max(64),
39228
- path: z20.string().min(1).max(240).optional(),
39229
- offset: z20.number().int().min(0).max(262144).default(0),
39230
- limit: z20.number().int().min(1).max(16000).default(12000)
39266
+ const skillResourceInput = z22.strictObject({
39267
+ skill: z22.string().min(1).max(64),
39268
+ path: z22.string().min(1).max(240).optional(),
39269
+ offset: z22.number().int().min(0).max(262144).default(0),
39270
+ limit: z22.number().int().min(1).max(16000).default(12000)
39231
39271
  });
39232
39272
  const delivery = new Set([
39233
39273
  "kiln_save",
@@ -39278,14 +39318,41 @@ function createKilnNativeToolRegistry(suppliedContext, completion) {
39278
39318
  ];
39279
39319
  }
39280
39320
  var assetSelector = {
39281
- collection: z20.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"),
39282
- assetId: z20.string().regex(/^[a-z][a-z0-9_-]{0,79}$/),
39283
- revisionId: z20.string().regex(/^[a-z][a-z0-9_-]{0,79}$/)
39321
+ collection: z22.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"),
39322
+ assetId: z22.string().regex(/^[a-z][a-z0-9_-]{0,79}$/),
39323
+ revisionId: z22.string().regex(/^[a-z][a-z0-9_-]{0,79}$/)
39324
+ };
39325
+ var ASSET_CONTRACT = {
39326
+ collections: {
39327
+ fields: [],
39328
+ required: [],
39329
+ description: "List configured asset storage collections. Collection is not project membership."
39330
+ },
39331
+ catalog: {
39332
+ fields: ["assetId", "query", "offset", "limit"],
39333
+ required: [],
39334
+ description: "Search saved assets across configured collections with pagination."
39335
+ },
39336
+ list: {
39337
+ fields: ["collection", "assetId", "query", "offset", "limit"],
39338
+ required: [],
39339
+ description: "Search saved assets in one collection with pagination."
39340
+ },
39341
+ get: {
39342
+ fields: ["collection", "assetId", "revisionId"],
39343
+ required: ["assetId"],
39344
+ description: "Read a saved revision and its download descriptors. Omit revisionId for the newest revision."
39345
+ },
39346
+ restore: {
39347
+ fields: ["collection", "assetId", "revisionId"],
39348
+ required: ["assetId"],
39349
+ 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."
39350
+ }
39284
39351
  };
39285
- async function newestRevision(target, collection, assetId) {
39352
+ async function newestRevision(target, collection, assetId, listCall = `kiln_assets { action: 'list', collection: '${collection}' }`) {
39286
39353
  const revisions = (await target.list(collection)).filter((a) => a.assetId === assetId);
39287
39354
  if (!revisions.length)
39288
- throw new Error(`Unknown asset ${assetId} in ${collection}; kiln_assets { action: 'list', collection: '${collection}' } lists them.`);
39355
+ throw new Error(`Unknown asset ${assetId} in ${collection}; ${listCall} lists them.`);
39289
39356
  const parents = new Set(revisions.map((a) => a.parentRevision).filter(Boolean));
39290
39357
  const heads = revisions.filter((a) => !parents.has(a.revisionId));
39291
39358
  const newest = (heads.length ? heads : revisions).sort((a, b) => a.createdAt < b.createdAt ? 1 : a.createdAt > b.createdAt ? -1 : 0);
@@ -39350,7 +39417,12 @@ async function buildProgramAssetDraft(code, context, backdrop) {
39350
39417
  }
39351
39418
  };
39352
39419
  }
39353
- function createKilnAssetDefs(context) {
39420
+ function createKilnAssetDefs(context, presentation = "grouped") {
39421
+ const listCall = (collection) => presentation === "operations" ? `kiln_assets_search({ collection: '${collection}' })` : `kiln_assets { action: 'list', collection: '${collection}' }`;
39422
+ const selector = presentation === "operations" ? {
39423
+ ...assetSelector,
39424
+ collection: assetSelector.collection.describe("Collection ID from kiln_assets_collections; default project.")
39425
+ } : assetSelector;
39354
39426
  const library = () => {
39355
39427
  if (!context.assetLibrary)
39356
39428
  throw new Error("No asset library configured. The local CLI/MCP host supplies workspace collections; embedded hosts must inject assetLibrary.");
@@ -39378,38 +39450,38 @@ function createKilnAssetDefs(context) {
39378
39450
  resources: (await Promise.resolve().then(() => (init_assets_resources(), exports_assets_resources))).assetLinks(collection, asset),
39379
39451
  downloadUrls: await context.assetDownloadUrls?.(collection, asset.assetId, asset.revisionId)
39380
39452
  });
39381
- const saveInput = z20.object({
39382
- collection: assetSelector.collection,
39383
- programRef: z20.string(),
39384
- name: z20.string().min(1).max(200),
39385
- assetId: assetSelector.assetId.optional(),
39386
- parentRevision: assetSelector.revisionId.optional(),
39387
- tags: z20.array(z20.string().max(80)).max(30).optional(),
39388
- brief: z20.string().max(8000).optional(),
39389
- description: z20.string().max(4000).optional(),
39390
- attribution: z20.object({
39391
- model: z20.string().max(200).optional(),
39392
- harness: z20.string().max(200).optional(),
39393
- author: z20.string().max(200).optional()
39453
+ const saveInput = z22.object({
39454
+ collection: selector.collection,
39455
+ programRef: z22.string(),
39456
+ name: z22.string().min(1).max(200),
39457
+ assetId: selector.assetId.optional(),
39458
+ parentRevision: selector.revisionId.optional(),
39459
+ tags: z22.array(z22.string().max(80)).max(30).optional(),
39460
+ brief: z22.string().max(8000).optional(),
39461
+ description: z22.string().max(4000).optional(),
39462
+ attribution: z22.object({
39463
+ model: z22.string().max(200).optional(),
39464
+ harness: z22.string().max(200).optional(),
39465
+ author: z22.string().max(200).optional()
39394
39466
  }).optional(),
39395
- backdrop: z20.enum(BACKDROP_IDS).optional().describe("Preview backdrop: the one the reviewed sheet used.")
39396
- });
39397
- const assetsInput = z20.object({
39398
- action: z20.enum(["collections", "catalog", "list", "get", "restore"]).default("list"),
39399
- collection: assetSelector.collection,
39400
- assetId: assetSelector.assetId.optional(),
39401
- revisionId: assetSelector.revisionId.optional().describe("get, restore: the saved revision; omitted, the newest."),
39402
- query: z20.string().max(200).optional(),
39403
- offset: z20.number().int().min(0).default(0),
39404
- limit: z20.number().int().min(1).max(50).default(20)
39405
- });
39406
- const exportInput = z20.object(assetSelector);
39467
+ backdrop: z22.enum(BACKDROP_IDS).optional().describe("Preview backdrop: the one the reviewed sheet used.")
39468
+ });
39469
+ const assetsInput = z22.object({
39470
+ action: z22.enum(["collections", "catalog", "list", "get", "restore"]).default("list"),
39471
+ collection: selector.collection,
39472
+ assetId: selector.assetId.optional(),
39473
+ revisionId: selector.revisionId.optional().describe("get, restore: the saved revision; omitted, the newest."),
39474
+ query: z22.string().max(200).optional(),
39475
+ offset: z22.number().int().min(0).default(0),
39476
+ limit: z22.number().int().min(1).max(50).default(20)
39477
+ });
39478
+ const exportInput = z22.object(selector);
39407
39479
  const profileExportInput = exportInput.extend({
39408
- profile: z20.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.")
39480
+ profile: z22.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.")
39409
39481
  });
39410
- const importInput = z20.object({
39411
- ...assetSelector,
39412
- sourceCollection: assetSelector.collection
39482
+ const importInput = z22.object({
39483
+ ...selector,
39484
+ sourceCollection: selector.collection
39413
39485
  });
39414
39486
  return [
39415
39487
  {
@@ -39425,7 +39497,7 @@ function createKilnAssetDefs(context) {
39425
39497
  requirements: activeRequirements.binding
39426
39498
  };
39427
39499
  if (input.assetId && input.parentRevision) {
39428
- const previous = await readSavedRevision(target, input.collection, input.assetId, input.parentRevision);
39500
+ const previous = await readSavedRevision(target, input.collection, input.assetId, input.parentRevision, listCall(input.collection));
39429
39501
  assertSavedRequirementsAuthorized(previous.manifest, activeRequirements);
39430
39502
  }
39431
39503
  const code = await context.programStore.get(input.programRef);
@@ -39440,6 +39512,7 @@ function createKilnAssetDefs(context) {
39440
39512
  name: "kiln_assets",
39441
39513
  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.",
39442
39514
  inputSchema: assetsInput,
39515
+ actionContract: ASSET_CONTRACT,
39443
39516
  run: async (raw) => {
39444
39517
  const input = assetsInput.parse(raw);
39445
39518
  const activeRequirements = toolRequirements(context);
@@ -39484,10 +39557,10 @@ function createKilnAssetDefs(context) {
39484
39557
  }))
39485
39558
  };
39486
39559
  }
39487
- if (!input.assetId)
39560
+ if (ASSET_CONTRACT[input.action].required.some((field) => !input[field]))
39488
39561
  throw new Error(`kiln_assets ${input.action} requires assetId; kiln_assets { action: 'list', collection: '${input.collection}' } lists them.`);
39489
- const revisionId = input.revisionId ?? await newestRevision(target, input.collection, input.assetId);
39490
- const record = await readSavedRevision(target, input.collection, input.assetId, revisionId);
39562
+ const revisionId = input.revisionId ?? await newestRevision(target, input.collection, input.assetId, listCall(input.collection));
39563
+ const record = await readSavedRevision(target, input.collection, input.assetId, revisionId, listCall(input.collection));
39491
39564
  if (input.action === "get")
39492
39565
  return links(input.collection, record.manifest);
39493
39566
  const saved = assertSavedRequirementsAuthorized(record.manifest, activeRequirements);
@@ -39507,9 +39580,9 @@ function createKilnAssetDefs(context) {
39507
39580
  name: "kiln_present",
39508
39581
  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.",
39509
39582
  inputSchema: exportInput,
39510
- outputSchema: z20.object({
39511
- ok: z20.literal(true),
39512
- collection: z20.string(),
39583
+ outputSchema: z22.object({
39584
+ ok: z22.literal(true),
39585
+ collection: z22.string(),
39513
39586
  asset: assetManifestSchema.pick({
39514
39587
  assetId: true,
39515
39588
  revisionId: true,
@@ -39520,25 +39593,25 @@ function createKilnAssetDefs(context) {
39520
39593
  editable: true,
39521
39594
  files: true
39522
39595
  }).extend({
39523
- build: z20.object({
39524
- engine: z20.string(),
39525
- rebuild: z20.enum(["engine-required", "external-dependencies-required"]),
39526
- warningCount: z20.number().int(),
39527
- warnings: z20.array(z20.string())
39596
+ build: z22.object({
39597
+ engine: z22.string(),
39598
+ rebuild: z22.enum(["engine-required", "external-dependencies-required"]),
39599
+ warningCount: z22.number().int(),
39600
+ warnings: z22.array(z22.string())
39528
39601
  }).optional()
39529
39602
  }),
39530
- resources: z20.array(z20.object({
39531
- type: z20.literal("resource_link"),
39532
- name: z20.string(),
39533
- uri: z20.string(),
39534
- mimeType: z20.string(),
39535
- size: z20.number().int().nonnegative(),
39536
- annotations: z20.object({
39537
- audience: z20.array(z20.enum(["user", "assistant"])),
39538
- priority: z20.number()
39603
+ resources: z22.array(z22.object({
39604
+ type: z22.literal("resource_link"),
39605
+ name: z22.string(),
39606
+ uri: z22.string(),
39607
+ mimeType: z22.string(),
39608
+ size: z22.number().int().nonnegative(),
39609
+ annotations: z22.object({
39610
+ audience: z22.array(z22.enum(["user", "assistant"])),
39611
+ priority: z22.number()
39539
39612
  })
39540
39613
  })),
39541
- downloadUrls: z20.record(z20.string(), z20.string()).optional()
39614
+ downloadUrls: z22.record(z22.string(), z22.string()).optional()
39542
39615
  }),
39543
39616
  ui: {
39544
39617
  resourceUri: KILN_ASSET_WIDGET_URI,
@@ -39555,7 +39628,7 @@ function createKilnAssetDefs(context) {
39555
39628
  inputSchema: profileExportInput,
39556
39629
  run: async (raw) => {
39557
39630
  const input = profileExportInput.parse(raw);
39558
- const record = await readSavedRevision(library(), input.collection, input.assetId, input.revisionId);
39631
+ const record = await readSavedRevision(library(), input.collection, input.assetId, input.revisionId, listCall(input.collection));
39559
39632
  await Promise.resolve().then(() => init_draw_diagnostics());
39560
39633
  if (input.profile === "runtime") {
39561
39634
  const output = await (await Promise.resolve().then(() => (init_asset_export(), exports_asset_export))).exportAssetGlb(record, {
@@ -39589,7 +39662,7 @@ function createKilnAssetDefs(context) {
39589
39662
  run: async (raw) => {
39590
39663
  const input = importInput.parse(raw);
39591
39664
  const target = library();
39592
- const record = await readSavedRevision(target, input.sourceCollection, input.assetId, input.revisionId);
39665
+ const record = await readSavedRevision(target, input.sourceCollection, input.assetId, input.revisionId, listCall(input.sourceCollection));
39593
39666
  await target.import(input.collection, [record]);
39594
39667
  return links(input.collection, record.manifest);
39595
39668
  }