@instruktlabs/kiln 1.0.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/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +60 -3
- package/CONTRIBUTING.md +16 -7
- package/README.md +95 -381
- package/dist/agent-run.mjs +220 -150
- package/dist/build.json +40 -28
- package/dist/cli.mjs +242 -163
- package/dist/mcp-engine.mjs +412 -154
- package/dist/mcp-server.mjs +1 -1
- package/docs/architecture.md +6 -3
- package/docs/chatgpt.md +20 -5
- package/docs/examples.md +40 -170
- package/docs/install.md +100 -35
- package/docs/migration.md +20 -0
- package/docs/sdk.md +49 -5
- package/docs/tools-operations.md +1529 -0
- package/lib/asset-widget-uri.d.ts +9 -0
- package/lib/asset-widget-uri.js +9 -0
- package/lib/cli-render-mode.js +10 -3
- package/lib/discovery/index.d.ts +1 -1
- package/lib/discovery/index.js +2 -2
- package/lib/discovery/portable.d.ts +9 -0
- package/lib/discovery/portable.js +6 -0
- 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/evaluator/isolation.js +19 -5
- package/lib/evaluator/probe-invariants.d.ts +11 -0
- package/lib/evaluator/probe-invariants.js +36 -0
- package/lib/evaluator/probe-worker.js +16 -4
- package/lib/loopback.d.ts +6 -0
- package/lib/loopback.js +6 -0
- package/lib/mcp-core.d.ts +210 -0
- package/lib/mcp-core.js +279 -0
- package/lib/mcp-engine.d.ts +59 -0
- package/lib/mcp-engine.js +289 -0
- package/lib/mcp-manifest.d.ts +15 -0
- package/lib/mcp-manifest.js +65 -0
- package/lib/mcp.d.ts +5 -0
- package/lib/mcp.js +2 -0
- package/lib/render-service-host.js +1 -1
- 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 +23 -1
- package/plugin.json +1 -1
- package/plugins/kiln-engine/.claude-plugin/icon.png +0 -0
- package/plugins/kiln-engine/.claude-plugin/plugin.json +9 -3
- package/plugins/kiln-engine/PRIVACY.md +100 -0
- package/plugins/kiln-engine/README.md +103 -18
- package/plugins/kiln-engine/{scripts/setup-workspace.mjs → bin/kiln-setup-workspace.mjs} +37 -9
- package/plugins/kiln-engine/package-provenance.json +15 -8
- package/plugins/kiln-engine/plugin.json +10 -4
- package/plugins/kiln-engine/runtime.json +10 -1
- package/plugins/kiln-engine/skills/kiln-setup-workspace/SKILL.md +17 -18
- package/plugins/kiln-engine/skills/kiln-setup-workspace/references/plugin-install.md +28 -8
- package/plugins/kiln-engine/skills/kiln-setup-workspace/references/renderer-setup.md +11 -0
- package/scripts/create-workspace.mjs +71 -13
- package/scripts/workspace-config.mjs +239 -0
- package/scripts/workspace-project.mjs +384 -0
- package/scripts/workspace-transaction.mjs +504 -0
- package/skills/kiln-setup-workspace/SKILL.md +17 -18
- package/skills/kiln-setup-workspace/references/plugin-install.md +28 -8
- package/skills/kiln-setup-workspace/references/renderer-setup.md +11 -0
- package/src/cli-render-mode.ts +9 -9
- package/src/cli.ts +3 -3
- package/src/discovery/index.ts +2 -0
- package/src/discovery/portable.ts +9 -0
- package/src/discovery/service.ts +3 -1
- package/src/engine-identity.ts +1 -1
- package/src/evaluator/isolation.ts +27 -6
- package/src/evaluator/probe-invariants.ts +50 -0
- package/src/evaluator/probe-worker.ts +22 -4
- package/src/mcp-core.ts +3 -0
- package/src/mcp-engine.ts +11 -1
- package/src/mcp.ts +5 -0
- package/src/render-service-host.ts +1 -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
|
@@ -28525,7 +28525,7 @@ function isolatedWorkerUrls(moduleUrl) {
|
|
|
28525
28525
|
}
|
|
28526
28526
|
|
|
28527
28527
|
// src/evaluator/isolation.ts
|
|
28528
|
-
import { existsSync as existsSync3 } from "node:fs";
|
|
28528
|
+
import { existsSync as existsSync3, readlinkSync } from "node:fs";
|
|
28529
28529
|
import { posix } from "node:path";
|
|
28530
28530
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
28531
28531
|
function isolationUnavailable() {
|
|
@@ -28567,7 +28567,7 @@ function isolatedEvaluatorLaunchWithLoader(workerPath, host = {}, loader = "tsx"
|
|
|
28567
28567
|
const setprivPath = requiredAbsolutePath(host.setprivPath ?? DEFAULT_SETPRIV_PATH);
|
|
28568
28568
|
const prlimitPath = requiredAbsolutePath(host.prlimitPath ?? DEFAULT_PRLIMIT_PATH);
|
|
28569
28569
|
const nodePath = requiredAbsolutePath(host.nodePath ?? DEFAULT_NODE_PATH);
|
|
28570
|
-
for (const executable of [bwrapPath, setprivPath, prlimitPath, nodePath]) {
|
|
28570
|
+
for (const executable of [bwrapPath, setprivPath, prlimitPath, nodePath, ENV_PATH]) {
|
|
28571
28571
|
if (!pathExists(executable))
|
|
28572
28572
|
isolationUnavailable();
|
|
28573
28573
|
}
|
|
@@ -28603,11 +28603,11 @@ function isolatedEvaluatorLaunchWithLoader(workerPath, host = {}, loader = "tsx"
|
|
|
28603
28603
|
for (const mount of runtimeMounts(runtimeRoot, pathExists)) {
|
|
28604
28604
|
bwrapArgs.push("--ro-bind", mount, mount);
|
|
28605
28605
|
}
|
|
28606
|
-
const nodeArgs = [nodePath, "--max-old-space-size=512", "--disable-proto=
|
|
28606
|
+
const nodeArgs = [nodePath, "--max-old-space-size=512", "--disable-proto=delete"];
|
|
28607
28607
|
if (loader === "tsx")
|
|
28608
28608
|
nodeArgs.push("--import", "tsx");
|
|
28609
28609
|
nodeArgs.push(resolvedWorkerPath);
|
|
28610
|
-
bwrapArgs.push("--chdir", runtimeRoot, "--
|
|
28610
|
+
bwrapArgs.push("--chdir", runtimeRoot, "--", prlimitPath, "--cpu=65:65", "--as=6442450944:6442450944", "--fsize=100663296:100663296", "--nofile=64:64", "--nproc=64:64", "--", ENV_PATH, "-i", "NODE_ENV=production", "NO_COLOR=1", ...nodeArgs);
|
|
28611
28611
|
return {
|
|
28612
28612
|
command: setprivPath,
|
|
28613
28613
|
args: [
|
|
@@ -28631,7 +28631,7 @@ async function renderGLBViaIsolatedEvaluator(code, options = {}, controls = {})
|
|
|
28631
28631
|
const { host: _, ...processControls } = controls;
|
|
28632
28632
|
return renderGLBViaProcessLaunch(code, options, processControls, launch);
|
|
28633
28633
|
}
|
|
28634
|
-
var DEFAULT_RUNTIME_ROOT = "/app", DEFAULT_BWRAP_PATH = "/usr/local/bin/bwrap", DEFAULT_SETPRIV_PATH = "/usr/bin/setpriv", DEFAULT_PRLIMIT_PATH = "/usr/bin/prlimit", DEFAULT_NODE_PATH = "/usr/local/bin/node", MAX_READINESS_PROTOCOL_BYTES;
|
|
28634
|
+
var DEFAULT_RUNTIME_ROOT = "/app", DEFAULT_BWRAP_PATH = "/usr/local/bin/bwrap", DEFAULT_SETPRIV_PATH = "/usr/bin/setpriv", DEFAULT_PRLIMIT_PATH = "/usr/bin/prlimit", DEFAULT_NODE_PATH = "/usr/local/bin/node", ENV_PATH = "/usr/bin/env", MAX_READINESS_PROTOCOL_BYTES;
|
|
28635
28635
|
var init_isolation = __esm(() => {
|
|
28636
28636
|
init_subprocess();
|
|
28637
28637
|
MAX_READINESS_PROTOCOL_BYTES = 16 * 1024;
|
|
@@ -33769,8 +33769,7 @@ async function startLocalRenderService(dir = renderServiceDir(), environment = p
|
|
|
33769
33769
|
if (exited)
|
|
33770
33770
|
exitedAt ??= Date.now();
|
|
33771
33771
|
if (spawnError || exitedAt !== undefined && Date.now() - exitedAt >= 1500)
|
|
33772
|
-
throw new Error(`render service exited during startup${spawnError ? `: ${spawnError.message}` : ""}${stderr.trim() ? `: ${stderr.trim()
|
|
33773
|
-
`).slice(-3).join(" ")}` : windowsLaunch ? "; launch the renderer manually to inspect native-driver errors" : ""}`);
|
|
33772
|
+
throw new Error(`render service exited during startup${spawnError ? `: ${spawnError.message}` : ""}${stderr.trim() ? `: ${stderr.trim()}` : windowsLaunch ? "; launch the renderer manually to inspect native-driver errors" : ""}`);
|
|
33774
33773
|
await new Promise((done) => setTimeout(done, 250));
|
|
33775
33774
|
}
|
|
33776
33775
|
throw new Error(`render service health is unknown after ${budget}ms; inspect with \`kiln service reprobe\``);
|
|
@@ -33889,12 +33888,17 @@ function makeLazyRenderPort(start, token, sourceFingerprint, initialUrl) {
|
|
|
33889
33888
|
} catch (error) {
|
|
33890
33889
|
if (execution?.signal?.aborted || error.name === "TimeoutError")
|
|
33891
33890
|
throw error;
|
|
33892
|
-
if (
|
|
33891
|
+
if (resolving !== pending)
|
|
33892
|
+
return (await resolve()).port(req, execution);
|
|
33893
|
+
const health = await readRenderServiceHealth(url, {
|
|
33893
33894
|
token,
|
|
33894
33895
|
signal: execution?.signal
|
|
33895
|
-
})
|
|
33896
|
-
throw error;
|
|
33896
|
+
});
|
|
33897
33897
|
execution?.signal?.throwIfAborted();
|
|
33898
|
+
if (resolving !== pending)
|
|
33899
|
+
return (await resolve()).port(req, execution);
|
|
33900
|
+
if (health.kind !== "absent")
|
|
33901
|
+
throw error;
|
|
33898
33902
|
if (resolving === pending)
|
|
33899
33903
|
resolving = undefined;
|
|
33900
33904
|
return (await resolve()).port(req, execution);
|
|
@@ -36102,7 +36106,7 @@ import { readFile as readFile8 } from "node:fs/promises";
|
|
|
36102
36106
|
var KILN_ASSET_WIDGET_URI = "ui://kiln/asset-v5.html";
|
|
36103
36107
|
|
|
36104
36108
|
// src/engine-identity.ts
|
|
36105
|
-
var ENGINE_VERSION = "1.
|
|
36109
|
+
var ENGINE_VERSION = "1.2.0";
|
|
36106
36110
|
var ENGINE_INSTALL_URL = new URL("../", import.meta.url).href;
|
|
36107
36111
|
function engineIdentity() {
|
|
36108
36112
|
return { version: ENGINE_VERSION, installUrl: ENGINE_INSTALL_URL };
|
|
@@ -36113,6 +36117,7 @@ init_requirements_json();
|
|
|
36113
36117
|
var MCP_SERVER_NAME = "kiln";
|
|
36114
36118
|
var MCP_SERVER_VERSION = ENGINE_VERSION;
|
|
36115
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.";
|
|
36116
36121
|
var KILN_WIDGET_META = {
|
|
36117
36122
|
ui: { prefersBorder: true, csp: { connectDomains: [], resourceDomains: [] } },
|
|
36118
36123
|
"openai/widgetDescription": "Inspect the saved 3D asset and download its GLB or editable bundle.",
|
|
@@ -36239,7 +36244,7 @@ var PRE_HANDSHAKE_METHODS = new Set(["initialize", "ping"]);
|
|
|
36239
36244
|
// src/tools/registry.ts
|
|
36240
36245
|
init_capture_cache();
|
|
36241
36246
|
init_assets();
|
|
36242
|
-
import { z as
|
|
36247
|
+
import { z as z23 } from "zod";
|
|
36243
36248
|
|
|
36244
36249
|
// src/requirements-assets.ts
|
|
36245
36250
|
init_requirements_context();
|
|
@@ -40396,7 +40401,7 @@ var MAX_RESPONSE_BYTES = 64 * 1024;
|
|
|
40396
40401
|
var MAX_TEXT_CHARS = 16 * 1024;
|
|
40397
40402
|
var DETAIL_RESULT_BUDGET = 15000;
|
|
40398
40403
|
var compare2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
40399
|
-
function createDiscoveryService(source, index, capabilities, retirements = {}, notes = async () => []) {
|
|
40404
|
+
function createDiscoveryService(source, index, capabilities, retirements = {}, notes = async () => [], capabilitiesCall = "capabilities:true") {
|
|
40400
40405
|
const entries = parseCatalog(source);
|
|
40401
40406
|
const byId = new Map(entries.map((entry) => [entry.id, entry]));
|
|
40402
40407
|
const byName = new Map(entries.filter((entry) => entry.kind !== "recipe").map((entry) => [entry.name, entry]));
|
|
@@ -40419,7 +40424,7 @@ function createDiscoveryService(source, index, capabilities, retirements = {}, n
|
|
|
40419
40424
|
"Parts auto-add to opts.parent; do not wrap createPart in parent.add. Part rotation uses degrees.",
|
|
40420
40425
|
"Custom THREE.BufferGeometry and ordinary JavaScript functions remain available. Recipes offer guidance and never restrict modeling.",
|
|
40421
40426
|
"Send source once and reuse programRef for reads, edits, inspection and rendering. Review geometry, materials and destination constraints separately.",
|
|
40422
|
-
|
|
40427
|
+
`Search for the operation you need in ordinary language, then fetch exact contracts with ids. Use ${capabilitiesCall} for the current host.`
|
|
40423
40428
|
]
|
|
40424
40429
|
};
|
|
40425
40430
|
const error = (mode, code, message) => ({
|
|
@@ -40600,12 +40605,12 @@ var snapshot2;
|
|
|
40600
40605
|
function createDiscovery(capabilities = async () => ({
|
|
40601
40606
|
host: "No host capability provider was supplied.",
|
|
40602
40607
|
discovery: { mode: "lexical", offline: true, requiresModel: false }
|
|
40603
|
-
}), notes = async () => []) {
|
|
40608
|
+
}), notes = async () => [], capabilitiesCall = "capabilities:true") {
|
|
40604
40609
|
snapshot2 ??= (() => {
|
|
40605
40610
|
const entries = listDiscoveryEntries();
|
|
40606
40611
|
return { entries, index: createLexicalDiscoveryIndex(entries) };
|
|
40607
40612
|
})();
|
|
40608
|
-
return createDiscoveryService(snapshot2.entries, snapshot2.index, capabilities, REMOVED_AUTHORING_HELPERS, notes);
|
|
40613
|
+
return createDiscoveryService(snapshot2.entries, snapshot2.index, capabilities, REMOVED_AUTHORING_HELPERS, notes, capabilitiesCall);
|
|
40609
40614
|
}
|
|
40610
40615
|
|
|
40611
40616
|
// src/tools/discovery.ts
|
|
@@ -40614,8 +40619,8 @@ init_capture_limits();
|
|
|
40614
40619
|
init_geometry_export();
|
|
40615
40620
|
init_community_exporter();
|
|
40616
40621
|
init_material_resources();
|
|
40617
|
-
function createKilnDiscoveryDef(context) {
|
|
40618
|
-
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");
|
|
40619
40624
|
return {
|
|
40620
40625
|
name: "kiln_discover",
|
|
40621
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.",
|
|
@@ -40639,7 +40644,7 @@ function projectNotes(context) {
|
|
|
40639
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.`
|
|
40640
40645
|
] : [];
|
|
40641
40646
|
}
|
|
40642
|
-
async function currentCapabilities(context) {
|
|
40647
|
+
async function currentCapabilities(context, presentation) {
|
|
40643
40648
|
const externalEvaluator = Boolean(context.evaluatorPort) || context.evaluatorProfile === "evaluator-required";
|
|
40644
40649
|
const approvedTextures = context.approvedTextureResources ? context.approvedTextureResources() : externalEvaluator ? null : approvedTextureCatalogV1();
|
|
40645
40650
|
const textureSlots = approvedTextures === null ? null : {};
|
|
@@ -40668,7 +40673,7 @@ async function currentCapabilities(context) {
|
|
|
40668
40673
|
requiresModel: false
|
|
40669
40674
|
},
|
|
40670
40675
|
engine: engineIdentity(),
|
|
40671
|
-
project: {
|
|
40676
|
+
project: presentation === "operations" && !context.projectStore ? { available: false } : {
|
|
40672
40677
|
configured: configuredProject(context),
|
|
40673
40678
|
select: "projectId per call; omitted uses the configured project, null selects standalone work",
|
|
40674
40679
|
read: 'kiln_project { action: "get", projectId } returns the brief, design, inventory and material pins'
|
|
@@ -40687,7 +40692,7 @@ async function currentCapabilities(context) {
|
|
|
40687
40692
|
available: Boolean(context.assetLibrary),
|
|
40688
40693
|
collections: context.assetLibrary?.collections() ?? [],
|
|
40689
40694
|
save: "kiln_save persists exact GLB, source and provenance; draft renders do not populate collections",
|
|
40690
|
-
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`,
|
|
40691
40696
|
downloads: "kiln_export returns GLB/source/ZIP resource links; client presentation varies",
|
|
40692
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"
|
|
40693
40698
|
},
|
|
@@ -41076,13 +41081,39 @@ var MATERIAL_ACTIONS = [
|
|
|
41076
41081
|
"create-procedural",
|
|
41077
41082
|
"import"
|
|
41078
41083
|
];
|
|
41079
|
-
var
|
|
41080
|
-
presets: {
|
|
41081
|
-
|
|
41082
|
-
|
|
41083
|
-
|
|
41084
|
-
|
|
41085
|
-
|
|
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
|
+
}
|
|
41086
41117
|
};
|
|
41087
41118
|
var record7 = (description) => z18.record(z18.string(), z18.unknown()).optional().describe(description);
|
|
41088
41119
|
var tag = z18.string().min(1).max(80).optional().describe("presets, list: keep one tag.");
|
|
@@ -41104,13 +41135,13 @@ var materialResult = (material) => ({
|
|
|
41104
41135
|
material,
|
|
41105
41136
|
portableSpec: materialLibraryPortableSpec(material)
|
|
41106
41137
|
});
|
|
41107
|
-
var unknownMaterial = (materialId, revisionId) => new Error(`Unknown material ${materialId}${revisionId ? ` at ${revisionId}` : ""}.
|
|
41108
|
-
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) {
|
|
41109
41140
|
const revisions = (await library.list()).filter((material) => material.materialId === materialId).map((material) => material.revisionId).sort();
|
|
41110
41141
|
if (revisions.length === 1)
|
|
41111
41142
|
return revisions[0];
|
|
41112
41143
|
if (revisions.length === 0)
|
|
41113
|
-
throw unknownMaterial(materialId);
|
|
41144
|
+
throw unknownMaterial(materialId, undefined, listCall);
|
|
41114
41145
|
throw new Error(`Material ${materialId} has ${revisions.length} revisions: ${revisions.join(", ")}. Pass revisionId to get one.`);
|
|
41115
41146
|
}
|
|
41116
41147
|
function aliasMaterialId(raw) {
|
|
@@ -41123,11 +41154,13 @@ function aliasMaterialId(raw) {
|
|
|
41123
41154
|
throw new Error(`kiln_material: resourceId (${String(resourceId)}) and materialId (${String(rest.materialId)}) name different materials; pass materialId alone.`);
|
|
41124
41155
|
return { ...rest, materialId: resourceId };
|
|
41125
41156
|
}
|
|
41126
|
-
function createKilnMaterialDef(library) {
|
|
41157
|
+
function createKilnMaterialDef(library, presentation = "grouped") {
|
|
41158
|
+
const listCall = presentation === "operations" ? 'kiln_material_search({ scope: "saved" })' : "kiln_material { action: 'list' }";
|
|
41127
41159
|
return {
|
|
41128
41160
|
name: "kiln_material",
|
|
41129
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.",
|
|
41130
41162
|
inputSchema: materialToolInput,
|
|
41163
|
+
actionContract: MATERIAL_CONTRACT,
|
|
41131
41164
|
annotations: {
|
|
41132
41165
|
readOnlyHint: false,
|
|
41133
41166
|
destructiveHint: false,
|
|
@@ -41137,7 +41170,7 @@ function createKilnMaterialDef(library) {
|
|
|
41137
41170
|
async run(raw) {
|
|
41138
41171
|
assertMaterialJson(raw);
|
|
41139
41172
|
const input = materialToolInput.parse(aliasMaterialId(raw));
|
|
41140
|
-
requireActionFields("kiln_material", input.action, input,
|
|
41173
|
+
requireActionFields("kiln_material", input.action, input, MATERIAL_CONTRACT[input.action]);
|
|
41141
41174
|
switch (input.action) {
|
|
41142
41175
|
case "presets":
|
|
41143
41176
|
return {
|
|
@@ -41173,12 +41206,12 @@ function createKilnMaterialDef(library) {
|
|
|
41173
41206
|
};
|
|
41174
41207
|
}
|
|
41175
41208
|
case "get": {
|
|
41176
|
-
const revisionId = input.revisionId ?? await onlyRevision(library, input.materialId);
|
|
41209
|
+
const revisionId = input.revisionId ?? await onlyRevision(library, input.materialId, listCall);
|
|
41177
41210
|
try {
|
|
41178
41211
|
return materialResult((await library.read(input.materialId, revisionId)).manifest);
|
|
41179
41212
|
} catch (error) {
|
|
41180
41213
|
if (error.code === "ENOENT")
|
|
41181
|
-
throw unknownMaterial(input.materialId, revisionId);
|
|
41214
|
+
throw unknownMaterial(input.materialId, revisionId, listCall);
|
|
41182
41215
|
throw error;
|
|
41183
41216
|
}
|
|
41184
41217
|
}
|
|
@@ -41229,7 +41262,7 @@ async function persistedPreviewFidelity(fidelity, glb) {
|
|
|
41229
41262
|
var operationId = z19.string().regex(/^op_[a-f0-9-]{36}$/);
|
|
41230
41263
|
var assetId = z19.string().regex(/^[a-z][a-z0-9_-]{0,79}$/);
|
|
41231
41264
|
var REVIEW_ACTIONS = ["list", "get", "pin", "save"];
|
|
41232
|
-
var
|
|
41265
|
+
var REQUIREMENTS2 = {
|
|
41233
41266
|
list: { required: [] },
|
|
41234
41267
|
get: { required: ["operationId"] },
|
|
41235
41268
|
pin: { required: ["operationId", "pinned"] },
|
|
@@ -41311,7 +41344,7 @@ function createKilnReviewDef(context) {
|
|
|
41311
41344
|
},
|
|
41312
41345
|
async run(raw) {
|
|
41313
41346
|
const input = reviewToolInput.parse(raw);
|
|
41314
|
-
requireActionFields("kiln_review", input.action, input,
|
|
41347
|
+
requireActionFields("kiln_review", input.action, input, REQUIREMENTS2[input.action]);
|
|
41315
41348
|
if (input.action === "list") {
|
|
41316
41349
|
const snapshot = await store.snapshot({ projectId: input.projectId });
|
|
41317
41350
|
const offset = input.offset ?? 0;
|
|
@@ -41483,6 +41516,191 @@ function withWorkspaceContext(def, context) {
|
|
|
41483
41516
|
};
|
|
41484
41517
|
}
|
|
41485
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
|
+
|
|
41486
41704
|
// src/tools/registry.ts
|
|
41487
41705
|
init_validation();
|
|
41488
41706
|
init_source_check();
|
|
@@ -41948,11 +42166,11 @@ function derivativeReviewFidelity(receipts) {
|
|
|
41948
42166
|
...reasonCodes.length ? { reasonCodes } : {}
|
|
41949
42167
|
};
|
|
41950
42168
|
}
|
|
41951
|
-
var validateInput =
|
|
41952
|
-
code:
|
|
42169
|
+
var validateInput = z23.object({
|
|
42170
|
+
code: z23.string().describe("Kiln source code (defines `meta` + `build()`, optional `animate()`).")
|
|
41953
42171
|
});
|
|
41954
|
-
var renderInput =
|
|
41955
|
-
code:
|
|
42172
|
+
var renderInput = z23.object({
|
|
42173
|
+
code: z23.string().describe("Kiln source code to execute and render to an in-memory GLB.")
|
|
41956
42174
|
});
|
|
41957
42175
|
var renderViewsInput = renderInput.extend({ capture: captureInput, detail: reviewDetailInput });
|
|
41958
42176
|
var reviewDetailOptions = (context) => ({
|
|
@@ -41965,26 +42183,26 @@ var reviewDetailOptions = (context) => ({
|
|
|
41965
42183
|
}
|
|
41966
42184
|
});
|
|
41967
42185
|
var renderViewsBufferInput = renderViewsInput.omit({ code: true });
|
|
41968
|
-
var screenshotAnimationInput =
|
|
42186
|
+
var screenshotAnimationInput = z23.object({
|
|
41969
42187
|
shot: cameraShotInput.optional(),
|
|
41970
|
-
measureParts:
|
|
41971
|
-
frames:
|
|
41972
|
-
frameTimes:
|
|
41973
|
-
framing:
|
|
41974
|
-
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."),
|
|
41975
42193
|
detail: reviewDetailInput,
|
|
41976
|
-
code:
|
|
41977
|
-
clip:
|
|
41978
|
-
camera:
|
|
41979
|
-
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.")
|
|
41980
42198
|
});
|
|
41981
42199
|
var screenshotAnimationAdvertisedInput = screenshotAnimationInput.extend({
|
|
41982
42200
|
shot: cameraShotRecordInput
|
|
41983
42201
|
});
|
|
41984
|
-
var viewInteriorInput =
|
|
42202
|
+
var viewInteriorInput = z23.object({
|
|
41985
42203
|
capture: advancedCaptureInput.optional(),
|
|
41986
|
-
code:
|
|
41987
|
-
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.')
|
|
41988
42206
|
});
|
|
41989
42207
|
var viewInteriorAdvertisedInput = viewInteriorInput.extend({ capture: captureRecordInput });
|
|
41990
42208
|
function runValidate(input, context) {
|
|
@@ -41999,11 +42217,11 @@ function runValidate(input, context) {
|
|
|
41999
42217
|
warnings: result.warnings.map((w) => w.fixHint ? `${w.message} (${w.fixHint})` : w.message)
|
|
42000
42218
|
};
|
|
42001
42219
|
}
|
|
42002
|
-
var partListInput =
|
|
42003
|
-
query:
|
|
42004
|
-
offset:
|
|
42005
|
-
limit:
|
|
42006
|
-
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.")
|
|
42007
42225
|
}).strict();
|
|
42008
42226
|
var PLACEMENT_PAGE_LIMIT = 50;
|
|
42009
42227
|
async function listPartNames2(root, options = {}) {
|
|
@@ -42470,35 +42688,35 @@ function createKilnViewInteriorDef(context = {}) {
|
|
|
42470
42688
|
};
|
|
42471
42689
|
}
|
|
42472
42690
|
var kilnViewInteriorDef = createKilnViewInteriorDef();
|
|
42473
|
-
var attachmentEndpointInput =
|
|
42474
|
-
subject:
|
|
42691
|
+
var attachmentEndpointInput = z23.object({
|
|
42692
|
+
subject: z23.object({ path: z23.string().optional(), name: z23.string().optional() }).strict(),
|
|
42475
42693
|
point: cameraVec3Input.optional()
|
|
42476
42694
|
}).strict();
|
|
42477
|
-
var surfacePairInput =
|
|
42478
|
-
var inspectInput =
|
|
42479
|
-
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."),
|
|
42480
42698
|
detail: reviewDetailInput,
|
|
42481
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."),
|
|
42482
|
-
surfacePairs:
|
|
42483
|
-
compare:
|
|
42484
|
-
programRef:
|
|
42485
|
-
offset:
|
|
42486
|
-
limit:
|
|
42487
|
-
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.")
|
|
42488
42706
|
}).strict().optional().describe("Static geometry/material/transform/bounds under current host settings. Follow nextOffset; paths adds complete subtrees."),
|
|
42489
|
-
measure:
|
|
42490
|
-
mode:
|
|
42707
|
+
measure: z23.object({
|
|
42708
|
+
mode: z23.enum(["anchors", "surface"]).optional(),
|
|
42491
42709
|
from: attachmentEndpointInput,
|
|
42492
42710
|
to: attachmentEndpointInput
|
|
42493
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."),
|
|
42494
42712
|
shot: cameraShotInput.optional().describe("Exact shot; omit part/view/orbit controls."),
|
|
42495
|
-
code:
|
|
42496
|
-
part:
|
|
42497
|
-
view:
|
|
42498
|
-
azimuthDeg:
|
|
42499
|
-
elevationDeg:
|
|
42500
|
-
zoom:
|
|
42501
|
-
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.")
|
|
42502
42720
|
});
|
|
42503
42721
|
var inspectBufferInput = inspectInput.omit({ code: true });
|
|
42504
42722
|
var inspectAdvertisedInput = inspectInput.extend({ shot: cameraShotRecordInput });
|
|
@@ -42658,15 +42876,15 @@ function createKilnInspectDef(context = {}) {
|
|
|
42658
42876
|
};
|
|
42659
42877
|
}
|
|
42660
42878
|
var kilnInspectDef = createKilnInspectDef();
|
|
42661
|
-
var editOperationInput =
|
|
42662
|
-
oldString:
|
|
42663
|
-
newString:
|
|
42664
|
-
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.")
|
|
42665
42883
|
});
|
|
42666
|
-
var editInput =
|
|
42667
|
-
code:
|
|
42668
|
-
edits:
|
|
42669
|
-
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."),
|
|
42670
42888
|
capture: captureInput,
|
|
42671
42889
|
detail: reviewDetailInput
|
|
42672
42890
|
});
|
|
@@ -42892,24 +43110,27 @@ function withCaptureCache(context) {
|
|
|
42892
43110
|
} : {}
|
|
42893
43111
|
};
|
|
42894
43112
|
}
|
|
42895
|
-
var rendererInput =
|
|
42896
|
-
action:
|
|
43113
|
+
var rendererInput = z23.strictObject({
|
|
43114
|
+
action: z23.enum(["status", "reprobe"]).default("status")
|
|
42897
43115
|
});
|
|
42898
|
-
async function readSavedRevision(target, collection, assetId, revisionId) {
|
|
43116
|
+
async function readSavedRevision(target, collection, assetId, revisionId, listCall = `kiln_assets { action: 'list', collection: '${collection}' }`) {
|
|
42899
43117
|
try {
|
|
42900
43118
|
return await target.read(collection, assetId, revisionId);
|
|
42901
43119
|
} catch (error) {
|
|
42902
43120
|
if (error.code === "ENOENT")
|
|
42903
|
-
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.`);
|
|
42904
43122
|
throw error;
|
|
42905
43123
|
}
|
|
42906
43124
|
}
|
|
42907
43125
|
function createKilnProgramToolRegistry(suppliedContext = {}) {
|
|
43126
|
+
return createProgramDefs(suppliedContext, "grouped");
|
|
43127
|
+
}
|
|
43128
|
+
function createProgramDefs(suppliedContext, presentation) {
|
|
42908
43129
|
toolRequirements(suppliedContext);
|
|
42909
43130
|
const store = suppliedContext.programStore ?? new MemoryProgramStore;
|
|
42910
43131
|
const context = withCaptureCache(withBuildCache({ ...suppliedContext, programStore: store }));
|
|
42911
43132
|
return [
|
|
42912
|
-
createKilnDiscoveryDef({ ...suppliedContext, programStore: store }),
|
|
43133
|
+
createKilnDiscoveryDef({ ...suppliedContext, programStore: store }, presentation),
|
|
42913
43134
|
{
|
|
42914
43135
|
name: "kiln_renderer",
|
|
42915
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.",
|
|
@@ -42949,7 +43170,7 @@ function createKilnProgramToolRegistry(suppliedContext = {}) {
|
|
|
42949
43170
|
].map((def) => withProgramReferences(def, store, context.readSourceFile)),
|
|
42950
43171
|
createKilnSourceDef(store),
|
|
42951
43172
|
...context.projectStore ? [createKilnProjectDef(context.projectStore, context.projectBundleReader)] : [],
|
|
42952
|
-
...context.materialLibrary ? [createKilnMaterialDef(context.materialLibrary)] : [],
|
|
43173
|
+
...context.materialLibrary ? [createKilnMaterialDef(context.materialLibrary, presentation)] : [],
|
|
42953
43174
|
...context.reviewStore && context.assetLibrary ? [
|
|
42954
43175
|
createKilnReviewDef({
|
|
42955
43176
|
reviewStore: context.reviewStore,
|
|
@@ -42957,7 +43178,7 @@ function createKilnProgramToolRegistry(suppliedContext = {}) {
|
|
|
42957
43178
|
requirements: context.requirements
|
|
42958
43179
|
})
|
|
42959
43180
|
] : [],
|
|
42960
|
-
...createKilnAssetDefs({ ...context, programStore: store })
|
|
43181
|
+
...createKilnAssetDefs({ ...context, programStore: store }, presentation)
|
|
42961
43182
|
].map((def) => withWorkspaceContext(def, context)).map((def) => ({
|
|
42962
43183
|
...def,
|
|
42963
43184
|
annotations: {
|
|
@@ -42969,15 +43190,45 @@ function createKilnProgramToolRegistry(suppliedContext = {}) {
|
|
|
42969
43190
|
}
|
|
42970
43191
|
}));
|
|
42971
43192
|
}
|
|
43193
|
+
function createKilnOperationToolRegistry(context = {}) {
|
|
43194
|
+
return projectOperationDefs(createProgramDefs(context, "operations"), context);
|
|
43195
|
+
}
|
|
42972
43196
|
var assetSelector = {
|
|
42973
|
-
collection:
|
|
42974
|
-
assetId:
|
|
42975
|
-
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}$/)
|
|
42976
43200
|
};
|
|
42977
|
-
|
|
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}' }`) {
|
|
42978
43229
|
const revisions = (await target.list(collection)).filter((a) => a.assetId === assetId);
|
|
42979
43230
|
if (!revisions.length)
|
|
42980
|
-
throw new Error(`Unknown asset ${assetId} in ${collection};
|
|
43231
|
+
throw new Error(`Unknown asset ${assetId} in ${collection}; ${listCall} lists them.`);
|
|
42981
43232
|
const parents = new Set(revisions.map((a) => a.parentRevision).filter(Boolean));
|
|
42982
43233
|
const heads = revisions.filter((a) => !parents.has(a.revisionId));
|
|
42983
43234
|
const newest = (heads.length ? heads : revisions).sort((a, b) => a.createdAt < b.createdAt ? 1 : a.createdAt > b.createdAt ? -1 : 0);
|
|
@@ -43042,7 +43293,12 @@ async function buildProgramAssetDraft(code, context, backdrop) {
|
|
|
43042
43293
|
}
|
|
43043
43294
|
};
|
|
43044
43295
|
}
|
|
43045
|
-
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;
|
|
43046
43302
|
const library = () => {
|
|
43047
43303
|
if (!context.assetLibrary)
|
|
43048
43304
|
throw new Error("No asset library configured. The local CLI/MCP host supplies workspace collections; embedded hosts must inject assetLibrary.");
|
|
@@ -43070,38 +43326,38 @@ function createKilnAssetDefs(context) {
|
|
|
43070
43326
|
resources: (await Promise.resolve().then(() => (init_assets_resources(), exports_assets_resources))).assetLinks(collection, asset),
|
|
43071
43327
|
downloadUrls: await context.assetDownloadUrls?.(collection, asset.assetId, asset.revisionId)
|
|
43072
43328
|
});
|
|
43073
|
-
const saveInput =
|
|
43074
|
-
collection:
|
|
43075
|
-
programRef:
|
|
43076
|
-
name:
|
|
43077
|
-
assetId:
|
|
43078
|
-
parentRevision:
|
|
43079
|
-
tags:
|
|
43080
|
-
brief:
|
|
43081
|
-
description:
|
|
43082
|
-
attribution:
|
|
43083
|
-
model:
|
|
43084
|
-
harness:
|
|
43085
|
-
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()
|
|
43086
43342
|
}).optional(),
|
|
43087
|
-
backdrop:
|
|
43088
|
-
});
|
|
43089
|
-
const assetsInput =
|
|
43090
|
-
action:
|
|
43091
|
-
collection:
|
|
43092
|
-
assetId:
|
|
43093
|
-
revisionId:
|
|
43094
|
-
query:
|
|
43095
|
-
offset:
|
|
43096
|
-
limit:
|
|
43097
|
-
});
|
|
43098
|
-
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);
|
|
43099
43355
|
const profileExportInput = exportInput.extend({
|
|
43100
|
-
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.")
|
|
43101
43357
|
});
|
|
43102
|
-
const importInput =
|
|
43103
|
-
...
|
|
43104
|
-
sourceCollection:
|
|
43358
|
+
const importInput = z23.object({
|
|
43359
|
+
...selector,
|
|
43360
|
+
sourceCollection: selector.collection
|
|
43105
43361
|
});
|
|
43106
43362
|
return [
|
|
43107
43363
|
{
|
|
@@ -43117,7 +43373,7 @@ function createKilnAssetDefs(context) {
|
|
|
43117
43373
|
requirements: activeRequirements.binding
|
|
43118
43374
|
};
|
|
43119
43375
|
if (input.assetId && input.parentRevision) {
|
|
43120
|
-
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));
|
|
43121
43377
|
assertSavedRequirementsAuthorized(previous.manifest, activeRequirements);
|
|
43122
43378
|
}
|
|
43123
43379
|
const code = await context.programStore.get(input.programRef);
|
|
@@ -43132,6 +43388,7 @@ function createKilnAssetDefs(context) {
|
|
|
43132
43388
|
name: "kiln_assets",
|
|
43133
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.",
|
|
43134
43390
|
inputSchema: assetsInput,
|
|
43391
|
+
actionContract: ASSET_CONTRACT,
|
|
43135
43392
|
run: async (raw) => {
|
|
43136
43393
|
const input = assetsInput.parse(raw);
|
|
43137
43394
|
const activeRequirements = toolRequirements(context);
|
|
@@ -43176,10 +43433,10 @@ function createKilnAssetDefs(context) {
|
|
|
43176
43433
|
}))
|
|
43177
43434
|
};
|
|
43178
43435
|
}
|
|
43179
|
-
if (
|
|
43436
|
+
if (ASSET_CONTRACT[input.action].required.some((field) => !input[field]))
|
|
43180
43437
|
throw new Error(`kiln_assets ${input.action} requires assetId; kiln_assets { action: 'list', collection: '${input.collection}' } lists them.`);
|
|
43181
|
-
const revisionId = input.revisionId ?? await newestRevision(target, input.collection, input.assetId);
|
|
43182
|
-
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));
|
|
43183
43440
|
if (input.action === "get")
|
|
43184
43441
|
return links(input.collection, record.manifest);
|
|
43185
43442
|
const saved = assertSavedRequirementsAuthorized(record.manifest, activeRequirements);
|
|
@@ -43199,9 +43456,9 @@ function createKilnAssetDefs(context) {
|
|
|
43199
43456
|
name: "kiln_present",
|
|
43200
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.",
|
|
43201
43458
|
inputSchema: exportInput,
|
|
43202
|
-
outputSchema:
|
|
43203
|
-
ok:
|
|
43204
|
-
collection:
|
|
43459
|
+
outputSchema: z23.object({
|
|
43460
|
+
ok: z23.literal(true),
|
|
43461
|
+
collection: z23.string(),
|
|
43205
43462
|
asset: assetManifestSchema.pick({
|
|
43206
43463
|
assetId: true,
|
|
43207
43464
|
revisionId: true,
|
|
@@ -43212,25 +43469,25 @@ function createKilnAssetDefs(context) {
|
|
|
43212
43469
|
editable: true,
|
|
43213
43470
|
files: true
|
|
43214
43471
|
}).extend({
|
|
43215
|
-
build:
|
|
43216
|
-
engine:
|
|
43217
|
-
rebuild:
|
|
43218
|
-
warningCount:
|
|
43219
|
-
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())
|
|
43220
43477
|
}).optional()
|
|
43221
43478
|
}),
|
|
43222
|
-
resources:
|
|
43223
|
-
type:
|
|
43224
|
-
name:
|
|
43225
|
-
uri:
|
|
43226
|
-
mimeType:
|
|
43227
|
-
size:
|
|
43228
|
-
annotations:
|
|
43229
|
-
audience:
|
|
43230
|
-
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()
|
|
43231
43488
|
})
|
|
43232
43489
|
})),
|
|
43233
|
-
downloadUrls:
|
|
43490
|
+
downloadUrls: z23.record(z23.string(), z23.string()).optional()
|
|
43234
43491
|
}),
|
|
43235
43492
|
ui: {
|
|
43236
43493
|
resourceUri: KILN_ASSET_WIDGET_URI2,
|
|
@@ -43247,7 +43504,7 @@ function createKilnAssetDefs(context) {
|
|
|
43247
43504
|
inputSchema: profileExportInput,
|
|
43248
43505
|
run: async (raw) => {
|
|
43249
43506
|
const input = profileExportInput.parse(raw);
|
|
43250
|
-
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));
|
|
43251
43508
|
await Promise.resolve().then(() => init_draw_diagnostics());
|
|
43252
43509
|
if (input.profile === "runtime") {
|
|
43253
43510
|
const output = await (await Promise.resolve().then(() => (init_asset_export(), exports_asset_export))).exportAssetGlb(record, {
|
|
@@ -43281,7 +43538,7 @@ function createKilnAssetDefs(context) {
|
|
|
43281
43538
|
run: async (raw) => {
|
|
43282
43539
|
const input = importInput.parse(raw);
|
|
43283
43540
|
const target = library();
|
|
43284
|
-
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));
|
|
43285
43542
|
await target.import(input.collection, [record]);
|
|
43286
43543
|
return links(input.collection, record.manifest);
|
|
43287
43544
|
}
|
|
@@ -43405,7 +43662,7 @@ function createKilnToolHost(context = {}, options = {}) {
|
|
|
43405
43662
|
};
|
|
43406
43663
|
}
|
|
43407
43664
|
};
|
|
43408
|
-
const defs = kilnMcpToolDefs(requestContext);
|
|
43665
|
+
const defs = options.toolPresentation === "operations" ? createKilnOperationToolRegistry(requestContext) : kilnMcpToolDefs(requestContext);
|
|
43409
43666
|
const byName = new Map(defs.map((def) => [def.name, def]));
|
|
43410
43667
|
return {
|
|
43411
43668
|
defs,
|
|
@@ -43472,6 +43729,7 @@ function resourceText(name, bytes) {
|
|
|
43472
43729
|
function createKilnMcpServer(context = {}, options = {}) {
|
|
43473
43730
|
const host = createKilnToolHost(context, options);
|
|
43474
43731
|
return createKilnServer({
|
|
43732
|
+
...options.toolPresentation === "operations" ? { instructions: MCP_OPERATION_INSTRUCTIONS } : {},
|
|
43475
43733
|
manifest: buildMcpManifest(host.defs, context),
|
|
43476
43734
|
host: async () => host
|
|
43477
43735
|
});
|