@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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +28 -0
- package/dist/agent-run.mjs +224 -151
- package/dist/build.json +22 -22
- package/dist/cli.mjs +229 -151
- package/dist/mcp-engine.mjs +400 -147
- package/dist/mcp-server.mjs +6 -6
- package/dist/viewer/app.js +180 -180
- package/dist/viewer/chat.html +183 -183
- package/docs/sdk.md +23 -0
- package/docs/tools-operations.md +1529 -0
- package/lib/asset-widget-uri.d.ts +1 -1
- package/lib/asset-widget-uri.js +1 -1
- package/lib/discovery/index.d.ts +1 -1
- package/lib/discovery/index.js +2 -2
- package/lib/discovery/service.d.ts +3 -1
- package/lib/discovery/service.js +4 -2
- package/lib/engine-identity.d.ts +1 -1
- package/lib/engine-identity.js +1 -1
- package/lib/mcp-core.d.ts +2 -1
- package/lib/mcp-core.js +1 -0
- package/lib/mcp-engine.d.ts +2 -0
- package/lib/mcp-engine.js +8 -3
- package/lib/tools/discovery.d.ts +1 -1
- package/lib/tools/discovery.js +11 -9
- package/lib/tools/materials.d.ts +1 -1
- package/lib/tools/materials.js +44 -14
- package/lib/tools/operation-contract.d.ts +8 -0
- package/lib/tools/operation-contract.js +37 -0
- package/lib/tools/operations.d.ts +3 -0
- package/lib/tools/operations.js +154 -0
- package/lib/tools/registry.d.ts +7 -4
- package/lib/tools/registry.js +73 -24
- package/package.json +2 -1
- package/plugin.json +1 -1
- package/plugins/kiln-engine/.claude-plugin/plugin.json +1 -1
- package/plugins/kiln-engine/README.md +3 -3
- package/plugins/kiln-engine/package-provenance.json +6 -6
- package/plugins/kiln-engine/plugin.json +1 -1
- package/plugins/kiln-engine/runtime.json +1 -1
- package/src/asset-widget-uri.ts +1 -1
- package/src/discovery/index.ts +2 -0
- package/src/discovery/service.ts +3 -1
- package/src/engine-identity.ts +1 -1
- package/src/generated/mcp-manifest.json +4 -4
- package/src/mcp-core.ts +3 -0
- package/src/mcp-engine.ts +11 -1
- package/src/tools/discovery.ts +20 -10
- package/src/tools/materials.ts +59 -15
- package/src/tools/operation-contract.ts +51 -0
- package/src/tools/operations.ts +177 -0
- package/src/tools/registry.ts +102 -21
- package/src/viewer/chat-app.ts +6 -2
- package/src/viewer/glb-loader.ts +78 -0
- package/src/viewer/scene.ts +9 -26
package/lib/tools/registry.js
CHANGED
|
@@ -13,6 +13,7 @@ import { createKilnMaterialDef } from "./materials.js";
|
|
|
13
13
|
import { createKilnReviewDef } from "./review.js";
|
|
14
14
|
import { withWorkspaceContext } from "./workspace.js";
|
|
15
15
|
import { describeInputError } from "./actions.js";
|
|
16
|
+
import { projectOperationDefs } from "./operations.js";
|
|
16
17
|
import { advancedCaptureInput, cameraShotInput, cameraShotRecordInput, cameraVec3Input, captureInput, captureRecordInput, } from "./capture-input.js";
|
|
17
18
|
import { compactEditResult, compactReviewResult, partsHint, requestedDetail, reviewDetailInput, } from "./review-detail.js";
|
|
18
19
|
import { createCachedEvaluatorPort, MemoryBuildCache } from "../build-cache.js";
|
|
@@ -34,7 +35,8 @@ import { persistedPreviewFidelity } from "./preview-fidelity.js";
|
|
|
34
35
|
// =============================================================================
|
|
35
36
|
// Tool definition contract
|
|
36
37
|
// =============================================================================
|
|
37
|
-
export
|
|
38
|
+
export { KILN_ASSET_WIDGET_URI } from "../asset-widget-uri.js";
|
|
39
|
+
import { KILN_ASSET_WIDGET_URI } from "../asset-widget-uri.js";
|
|
38
40
|
function proceduralTextureMaterialContract(rendered, context) {
|
|
39
41
|
const required = [...new Set(context.requiredProceduralTextureUsages ?? [])];
|
|
40
42
|
if (required.length === 0)
|
|
@@ -1605,22 +1607,25 @@ const rendererInput = z.strictObject({
|
|
|
1605
1607
|
action: z.enum(['status', 'reprobe']).default('status'),
|
|
1606
1608
|
});
|
|
1607
1609
|
/** A saved-revision read whose failure names the listing call instead of a filesystem path (rule 9). */
|
|
1608
|
-
async function readSavedRevision(target, collection, assetId, revisionId) {
|
|
1610
|
+
async function readSavedRevision(target, collection, assetId, revisionId, listCall = `kiln_assets { action: 'list', collection: '${collection}' }`) {
|
|
1609
1611
|
try {
|
|
1610
1612
|
return await target.read(collection, assetId, revisionId);
|
|
1611
1613
|
}
|
|
1612
1614
|
catch (error) {
|
|
1613
1615
|
if (error.code === 'ENOENT')
|
|
1614
|
-
throw new Error(`Unknown asset ${assetId} revision ${revisionId} in collection ${collection}.
|
|
1616
|
+
throw new Error(`Unknown asset ${assetId} revision ${revisionId} in collection ${collection}. ${listCall} lists the saved revisions.`);
|
|
1615
1617
|
throw error;
|
|
1616
1618
|
}
|
|
1617
1619
|
}
|
|
1618
1620
|
export function createKilnProgramToolRegistry(suppliedContext = {}) {
|
|
1621
|
+
return createProgramDefs(suppliedContext, 'grouped');
|
|
1622
|
+
}
|
|
1623
|
+
function createProgramDefs(suppliedContext, presentation) {
|
|
1619
1624
|
toolRequirements(suppliedContext);
|
|
1620
1625
|
const store = suppliedContext.programStore ?? new MemoryProgramStore();
|
|
1621
1626
|
const context = withCaptureCache(withBuildCache({ ...suppliedContext, programStore: store }));
|
|
1622
1627
|
return [
|
|
1623
|
-
createKilnDiscoveryDef({ ...suppliedContext, programStore: store }),
|
|
1628
|
+
createKilnDiscoveryDef({ ...suppliedContext, programStore: store }, presentation),
|
|
1624
1629
|
{
|
|
1625
1630
|
name: 'kiln_renderer',
|
|
1626
1631
|
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.',
|
|
@@ -1665,7 +1670,9 @@ export function createKilnProgramToolRegistry(suppliedContext = {}) {
|
|
|
1665
1670
|
...(context.projectStore
|
|
1666
1671
|
? [createKilnProjectDef(context.projectStore, context.projectBundleReader)]
|
|
1667
1672
|
: []),
|
|
1668
|
-
...(context.materialLibrary
|
|
1673
|
+
...(context.materialLibrary
|
|
1674
|
+
? [createKilnMaterialDef(context.materialLibrary, presentation)]
|
|
1675
|
+
: []),
|
|
1669
1676
|
...(context.reviewStore && context.assetLibrary
|
|
1670
1677
|
? [
|
|
1671
1678
|
createKilnReviewDef({
|
|
@@ -1675,7 +1682,7 @@ export function createKilnProgramToolRegistry(suppliedContext = {}) {
|
|
|
1675
1682
|
}),
|
|
1676
1683
|
]
|
|
1677
1684
|
: []),
|
|
1678
|
-
...createKilnAssetDefs({ ...context, programStore: store }),
|
|
1685
|
+
...createKilnAssetDefs({ ...context, programStore: store }, presentation),
|
|
1679
1686
|
]
|
|
1680
1687
|
.map((def) => withWorkspaceContext(def, context))
|
|
1681
1688
|
.map((def) => ({
|
|
@@ -1689,6 +1696,10 @@ export function createKilnProgramToolRegistry(suppliedContext = {}) {
|
|
|
1689
1696
|
},
|
|
1690
1697
|
}));
|
|
1691
1698
|
}
|
|
1699
|
+
/** Opt-in named domain operations; grouped local/native contracts remain unchanged. */
|
|
1700
|
+
export function createKilnOperationToolRegistry(context = {}) {
|
|
1701
|
+
return projectOperationDefs(createProgramDefs(context, 'operations'), context);
|
|
1702
|
+
}
|
|
1692
1703
|
/** Canonical native workflow: shared definitions plus one host-owned terminal. */
|
|
1693
1704
|
export function createKilnNativeToolRegistry(suppliedContext, completion) {
|
|
1694
1705
|
const active = toolRequirements(suppliedContext);
|
|
@@ -1772,15 +1783,42 @@ const assetSelector = {
|
|
|
1772
1783
|
assetId: z.string().regex(/^[a-z][a-z0-9_-]{0,79}$/),
|
|
1773
1784
|
revisionId: z.string().regex(/^[a-z][a-z0-9_-]{0,79}$/),
|
|
1774
1785
|
};
|
|
1786
|
+
const ASSET_CONTRACT = {
|
|
1787
|
+
collections: {
|
|
1788
|
+
fields: [],
|
|
1789
|
+
required: [],
|
|
1790
|
+
description: 'List configured asset storage collections. Collection is not project membership.',
|
|
1791
|
+
},
|
|
1792
|
+
catalog: {
|
|
1793
|
+
fields: ['assetId', 'query', 'offset', 'limit'],
|
|
1794
|
+
required: [],
|
|
1795
|
+
description: 'Search saved assets across configured collections with pagination.',
|
|
1796
|
+
},
|
|
1797
|
+
list: {
|
|
1798
|
+
fields: ['collection', 'assetId', 'query', 'offset', 'limit'],
|
|
1799
|
+
required: [],
|
|
1800
|
+
description: 'Search saved assets in one collection with pagination.',
|
|
1801
|
+
},
|
|
1802
|
+
get: {
|
|
1803
|
+
fields: ['collection', 'assetId', 'revisionId'],
|
|
1804
|
+
required: ['assetId'],
|
|
1805
|
+
description: 'Read a saved revision and its download descriptors. Omit revisionId for the newest revision.',
|
|
1806
|
+
},
|
|
1807
|
+
restore: {
|
|
1808
|
+
fields: ['collection', 'assetId', 'revisionId'],
|
|
1809
|
+
required: ['assetId'],
|
|
1810
|
+
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.',
|
|
1811
|
+
},
|
|
1812
|
+
};
|
|
1775
1813
|
/**
|
|
1776
1814
|
* The revision a get or restore without `revisionId` means: the newest, the
|
|
1777
1815
|
* one no later revision names as its parent, ties to the latest `createdAt`
|
|
1778
1816
|
* (c40 of 1 October 2026 called get with the asset id alone and was refused).
|
|
1779
1817
|
*/
|
|
1780
|
-
export async function newestRevision(target, collection, assetId) {
|
|
1818
|
+
export async function newestRevision(target, collection, assetId, listCall = `kiln_assets { action: 'list', collection: '${collection}' }`) {
|
|
1781
1819
|
const revisions = (await target.list(collection)).filter((a) => a.assetId === assetId);
|
|
1782
1820
|
if (!revisions.length)
|
|
1783
|
-
throw new Error(`Unknown asset ${assetId} in ${collection};
|
|
1821
|
+
throw new Error(`Unknown asset ${assetId} in ${collection}; ${listCall} lists them.`);
|
|
1784
1822
|
const parents = new Set(revisions.map((a) => a.parentRevision).filter(Boolean));
|
|
1785
1823
|
const heads = revisions.filter((a) => !parents.has(a.revisionId));
|
|
1786
1824
|
const newest = (heads.length ? heads : revisions).sort((a, b) => a.createdAt < b.createdAt ? 1 : a.createdAt > b.createdAt ? -1 : 0);
|
|
@@ -1857,7 +1895,16 @@ export async function buildProgramAssetDraft(code, context, backdrop) {
|
|
|
1857
1895
|
};
|
|
1858
1896
|
}
|
|
1859
1897
|
/** All asset operation schemas live here, alongside the existing tool definitions. */
|
|
1860
|
-
export function createKilnAssetDefs(context) {
|
|
1898
|
+
export function createKilnAssetDefs(context, presentation = 'grouped') {
|
|
1899
|
+
const listCall = (collection) => presentation === 'operations'
|
|
1900
|
+
? `kiln_assets_search({ collection: '${collection}' })`
|
|
1901
|
+
: `kiln_assets { action: 'list', collection: '${collection}' }`;
|
|
1902
|
+
const selector = presentation === 'operations'
|
|
1903
|
+
? {
|
|
1904
|
+
...assetSelector,
|
|
1905
|
+
collection: assetSelector.collection.describe('Collection ID from kiln_assets_collections; default project.'),
|
|
1906
|
+
}
|
|
1907
|
+
: assetSelector;
|
|
1861
1908
|
const library = () => {
|
|
1862
1909
|
if (!context.assetLibrary)
|
|
1863
1910
|
throw new Error('No asset library configured. The local CLI/MCP host supplies workspace collections; embedded hosts must inject assetLibrary.');
|
|
@@ -1886,11 +1933,11 @@ export function createKilnAssetDefs(context) {
|
|
|
1886
1933
|
downloadUrls: await context.assetDownloadUrls?.(collection, asset.assetId, asset.revisionId),
|
|
1887
1934
|
});
|
|
1888
1935
|
const saveInput = z.object({
|
|
1889
|
-
collection:
|
|
1936
|
+
collection: selector.collection,
|
|
1890
1937
|
programRef: z.string(),
|
|
1891
1938
|
name: z.string().min(1).max(200),
|
|
1892
|
-
assetId:
|
|
1893
|
-
parentRevision:
|
|
1939
|
+
assetId: selector.assetId.optional(),
|
|
1940
|
+
parentRevision: selector.revisionId.optional(),
|
|
1894
1941
|
tags: z.array(z.string().max(80)).max(30).optional(),
|
|
1895
1942
|
brief: z.string().max(8000).optional(),
|
|
1896
1943
|
description: z.string().max(4000).optional(),
|
|
@@ -1908,16 +1955,16 @@ export function createKilnAssetDefs(context) {
|
|
|
1908
1955
|
});
|
|
1909
1956
|
const assetsInput = z.object({
|
|
1910
1957
|
action: z.enum(['collections', 'catalog', 'list', 'get', 'restore']).default('list'),
|
|
1911
|
-
collection:
|
|
1912
|
-
assetId:
|
|
1913
|
-
revisionId:
|
|
1958
|
+
collection: selector.collection,
|
|
1959
|
+
assetId: selector.assetId.optional(),
|
|
1960
|
+
revisionId: selector.revisionId
|
|
1914
1961
|
.optional()
|
|
1915
1962
|
.describe('get, restore: the saved revision; omitted, the newest.'),
|
|
1916
1963
|
query: z.string().max(200).optional(),
|
|
1917
1964
|
offset: z.number().int().min(0).default(0),
|
|
1918
1965
|
limit: z.number().int().min(1).max(50).default(20),
|
|
1919
1966
|
});
|
|
1920
|
-
const exportInput = z.object(
|
|
1967
|
+
const exportInput = z.object(selector);
|
|
1921
1968
|
const profileExportInput = exportInput.extend({
|
|
1922
1969
|
profile: z
|
|
1923
1970
|
.enum(['editable', 'runtime'])
|
|
@@ -1925,8 +1972,8 @@ export function createKilnAssetDefs(context) {
|
|
|
1925
1972
|
.describe('editable preserves canonical source/GLB/build resources. runtime returns a standalone GLB and versioned review-metadata sidecar; no source bundle or geometry optimization.'),
|
|
1926
1973
|
});
|
|
1927
1974
|
const importInput = z.object({
|
|
1928
|
-
...
|
|
1929
|
-
sourceCollection:
|
|
1975
|
+
...selector,
|
|
1976
|
+
sourceCollection: selector.collection,
|
|
1930
1977
|
});
|
|
1931
1978
|
return [
|
|
1932
1979
|
{
|
|
@@ -1942,7 +1989,7 @@ export function createKilnAssetDefs(context) {
|
|
|
1942
1989
|
requirements: activeRequirements.binding,
|
|
1943
1990
|
};
|
|
1944
1991
|
if (input.assetId && input.parentRevision) {
|
|
1945
|
-
const previous = await readSavedRevision(target, input.collection, input.assetId, input.parentRevision);
|
|
1992
|
+
const previous = await readSavedRevision(target, input.collection, input.assetId, input.parentRevision, listCall(input.collection));
|
|
1946
1993
|
assertSavedRequirementsAuthorized(previous.manifest, activeRequirements);
|
|
1947
1994
|
}
|
|
1948
1995
|
const code = await context.programStore.get(input.programRef);
|
|
@@ -1957,6 +2004,7 @@ export function createKilnAssetDefs(context) {
|
|
|
1957
2004
|
name: 'kiln_assets',
|
|
1958
2005
|
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.',
|
|
1959
2006
|
inputSchema: assetsInput,
|
|
2007
|
+
actionContract: ASSET_CONTRACT,
|
|
1960
2008
|
run: async (raw) => {
|
|
1961
2009
|
const input = assetsInput.parse(raw);
|
|
1962
2010
|
const activeRequirements = toolRequirements(context);
|
|
@@ -2005,10 +2053,11 @@ export function createKilnAssetDefs(context) {
|
|
|
2005
2053
|
})),
|
|
2006
2054
|
};
|
|
2007
2055
|
}
|
|
2008
|
-
if (
|
|
2056
|
+
if (ASSET_CONTRACT[input.action].required.some((field) => !input[field]))
|
|
2009
2057
|
throw new Error(`kiln_assets ${input.action} requires assetId; kiln_assets { action: 'list', collection: '${input.collection}' } lists them.`);
|
|
2010
|
-
const revisionId = input.revisionId ??
|
|
2011
|
-
|
|
2058
|
+
const revisionId = input.revisionId ??
|
|
2059
|
+
(await newestRevision(target, input.collection, input.assetId, listCall(input.collection)));
|
|
2060
|
+
const record = await readSavedRevision(target, input.collection, input.assetId, revisionId, listCall(input.collection));
|
|
2012
2061
|
if (input.action === 'get')
|
|
2013
2062
|
return links(input.collection, record.manifest);
|
|
2014
2063
|
const saved = assertSavedRequirementsAuthorized(record.manifest, activeRequirements);
|
|
@@ -2080,7 +2129,7 @@ export function createKilnAssetDefs(context) {
|
|
|
2080
2129
|
inputSchema: profileExportInput,
|
|
2081
2130
|
run: async (raw) => {
|
|
2082
2131
|
const input = profileExportInput.parse(raw);
|
|
2083
|
-
const record = await readSavedRevision(library(), input.collection, input.assetId, input.revisionId);
|
|
2132
|
+
const record = await readSavedRevision(library(), input.collection, input.assetId, input.revisionId, listCall(input.collection));
|
|
2084
2133
|
const { inspectDrawDiagnostics } = await import("../draw-diagnostics.js");
|
|
2085
2134
|
if (input.profile === 'runtime') {
|
|
2086
2135
|
const output = await (await import("../asset-export.js")).exportAssetGlb(record, {
|
|
@@ -2114,7 +2163,7 @@ export function createKilnAssetDefs(context) {
|
|
|
2114
2163
|
run: async (raw) => {
|
|
2115
2164
|
const input = importInput.parse(raw);
|
|
2116
2165
|
const target = library();
|
|
2117
|
-
const record = await readSavedRevision(target, input.sourceCollection, input.assetId, input.revisionId);
|
|
2166
|
+
const record = await readSavedRevision(target, input.sourceCollection, input.assetId, input.revisionId, listCall(input.sourceCollection));
|
|
2118
2167
|
await target.import(input.collection, [record]);
|
|
2119
2168
|
return links(input.collection, record.manifest);
|
|
2120
2169
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instruktlabs/kiln",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Create and refine procedural 3D assets with JavaScript, image feedback, and reusable source revisions.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Matthew Kissinger",
|
|
@@ -299,6 +299,7 @@
|
|
|
299
299
|
"docs/runtime.md",
|
|
300
300
|
"docs/sdk.md",
|
|
301
301
|
"docs/tools.md",
|
|
302
|
+
"docs/tools-operations.md",
|
|
302
303
|
"README.md",
|
|
303
304
|
"CONTRIBUTING.md",
|
|
304
305
|
"LICENSE",
|
package/plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "kiln",
|
|
3
3
|
"displayName": "Kiln",
|
|
4
4
|
"description": "Build and revise 3D assets with your coding agent. Write JavaScript, inspect selected views, edit saved source revisions, and export GLB files locally.",
|
|
5
|
-
"version": "1.1
|
|
5
|
+
"version": "1.2.1",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/instruktlabs/kiln",
|
|
8
8
|
"keywords": [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Kiln local plugin
|
|
2
2
|
|
|
3
|
-
Plugin version 1.1
|
|
4
|
-
This plugin pins engine 1.1.
|
|
3
|
+
Plugin version 1.2.1, maintained by Instrukt Labs under the MIT license.
|
|
4
|
+
This plugin pins engine 1.2.1. Registry setup requires that exact version
|
|
5
5
|
to be published. Use a published release tag for normal installation or a reviewed
|
|
6
6
|
local archive for development qualification. The installation ID remains
|
|
7
7
|
`kiln-engine@instruktlabs`.
|
|
@@ -31,7 +31,7 @@ codex plugin add kiln-engine@instruktlabs
|
|
|
31
31
|
Restart or reload your coding agent's plugins as its installation message directs.
|
|
32
32
|
Then ask it to set up a Kiln workspace. The maintained setup skill runs this
|
|
33
33
|
plugin's `bin/kiln-setup-workspace.mjs` with Node, installs
|
|
34
|
-
`@instruktlabs/kiln@1.1
|
|
34
|
+
`@instruktlabs/kiln@1.2.1` outside the project and configures your chosen
|
|
35
35
|
workspace. The same initializer supports existing projects and new workspaces.
|
|
36
36
|
|
|
37
37
|
The plugin registers setup only. The workspace supplies authoring skills and one
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"kind": "kiln-local-plugin",
|
|
4
|
-
"pluginVersion": "1.1
|
|
5
|
-
"engineVersion": "1.1
|
|
4
|
+
"pluginVersion": "1.2.1",
|
|
5
|
+
"engineVersion": "1.2.1",
|
|
6
6
|
"executables": [
|
|
7
7
|
"bin/kiln-setup-workspace.mjs"
|
|
8
8
|
],
|
|
9
9
|
"files": {
|
|
10
10
|
".claude-plugin/icon.png": "sha256:b4b651c402793b7e27cab780f04b14f80daec6d0cd5b7e4e90313930581a54e9",
|
|
11
|
-
".claude-plugin/plugin.json": "sha256:
|
|
11
|
+
".claude-plugin/plugin.json": "sha256:bef717ea5e0c96411c2db93d54e298dc3798512df9909ba74c950a6c1c03f6cb",
|
|
12
12
|
"bin/kiln-setup-workspace.mjs": "sha256:3d9a30236919a6ca91acb6b26f808cec442e6edc3dd88fe010645b010d76e838",
|
|
13
13
|
"LICENSE": "sha256:cdba278ebf1d6de618869936226bf03be4887179c128efc7aaa13d22034826a5",
|
|
14
|
-
"plugin.json": "sha256:
|
|
14
|
+
"plugin.json": "sha256:9ef79b862a25ae3efe86c03a37e09cd622912b97a0165a08fdf55cff8b71a010",
|
|
15
15
|
"PRIVACY.md": "sha256:5f58d981667e40441e21c2dec411f269a9a67a6141cec61976d27088fb12573b",
|
|
16
|
-
"README.md": "sha256:
|
|
17
|
-
"runtime.json": "sha256:
|
|
16
|
+
"README.md": "sha256:029732d7bb9e04561105727f8e46118d3106f513b4575a8d74d57cbd1bb68e7a",
|
|
17
|
+
"runtime.json": "sha256:b6d078f1223cb5ed3a522b0ef5a3cb778e051afc0115237cfd9cfe04c1f42025",
|
|
18
18
|
"skills/kiln-setup-workspace/references/plugin-install.md": "sha256:c338fb792e7fad0364c3e1a13c94c506afa1395489ec1b6e83b36d04728935fb",
|
|
19
19
|
"skills/kiln-setup-workspace/references/renderer-setup.md": "sha256:b743b1b2827fa814385990e1e5b849391cb427413e9c016d273aa19cebd46031",
|
|
20
20
|
"skills/kiln-setup-workspace/SKILL.md": "sha256:65ed926b3503a33f4fe793e84e4a045ce36e3967f0e6b340e456a15dd010ce54"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "kiln-engine",
|
|
4
|
-
"version": "1.1
|
|
4
|
+
"version": "1.2.1",
|
|
5
5
|
"description": "Set up a local Kiln workspace to create, inspect and revise editable 3D assets with Claude Code or Codex.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Instrukt Labs",
|
package/src/asset-widget-uri.ts
CHANGED
package/src/discovery/index.ts
CHANGED
|
@@ -21,6 +21,7 @@ export function createDiscovery(
|
|
|
21
21
|
discovery: { mode: 'lexical', offline: true, requiresModel: false },
|
|
22
22
|
}),
|
|
23
23
|
notes: () => Promise<string[]> = async () => [],
|
|
24
|
+
capabilitiesCall = 'capabilities:true',
|
|
24
25
|
) {
|
|
25
26
|
snapshot ??= (() => {
|
|
26
27
|
const entries = listDiscoveryEntries();
|
|
@@ -32,5 +33,6 @@ export function createDiscovery(
|
|
|
32
33
|
capabilities,
|
|
33
34
|
REMOVED_AUTHORING_HELPERS,
|
|
34
35
|
notes,
|
|
36
|
+
capabilitiesCall,
|
|
35
37
|
);
|
|
36
38
|
}
|
package/src/discovery/service.ts
CHANGED
|
@@ -63,6 +63,8 @@ export function createDiscoveryService(
|
|
|
63
63
|
retirements: Readonly<Record<string, string>> = {},
|
|
64
64
|
/** Host notes for the overview, such as the project an omitted `projectId` selects. */
|
|
65
65
|
notes: () => Promise<string[]> = async () => [],
|
|
66
|
+
/** Host-selected capability entrypoint, never a model-provided instruction. */
|
|
67
|
+
capabilitiesCall = 'capabilities:true',
|
|
66
68
|
): (input: unknown) => Promise<DiscoveryResponse> {
|
|
67
69
|
const entries = parseCatalog(source);
|
|
68
70
|
const byId = new Map(entries.map((entry) => [entry.id, entry]));
|
|
@@ -94,7 +96,7 @@ export function createDiscoveryService(
|
|
|
94
96
|
'Parts auto-add to opts.parent; do not wrap createPart in parent.add. Part rotation uses degrees.',
|
|
95
97
|
'Custom THREE.BufferGeometry and ordinary JavaScript functions remain available. Recipes offer guidance and never restrict modeling.',
|
|
96
98
|
'Send source once and reuse programRef for reads, edits, inspection and rendering. Review geometry, materials and destination constraints separately.',
|
|
97
|
-
|
|
99
|
+
`Search for the operation you need in ordinary language, then fetch exact contracts with ids. Use ${capabilitiesCall} for the current host.`,
|
|
98
100
|
],
|
|
99
101
|
};
|
|
100
102
|
const error = (
|
package/src/engine-identity.ts
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* `src/__tests__/package-contents.test.ts` fails if it disagrees with the manifest
|
|
28
28
|
* or with any plugin manifest, which is what keeps the literal honest.
|
|
29
29
|
*/
|
|
30
|
-
export const ENGINE_VERSION = '1.1
|
|
30
|
+
export const ENGINE_VERSION = '1.2.1';
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Where this engine was loaded from, as a `file://` URL of the package root.
|
|
@@ -1733,13 +1733,13 @@
|
|
|
1733
1733
|
},
|
|
1734
1734
|
"_meta": {
|
|
1735
1735
|
"ui": {
|
|
1736
|
-
"resourceUri": "ui://kiln/asset-
|
|
1736
|
+
"resourceUri": "ui://kiln/asset-v6.html",
|
|
1737
1737
|
"visibility": [
|
|
1738
1738
|
"model"
|
|
1739
1739
|
]
|
|
1740
1740
|
},
|
|
1741
|
-
"openai/outputTemplate": "ui://kiln/asset-
|
|
1742
|
-
"ui/resourceUri": "ui://kiln/asset-
|
|
1741
|
+
"openai/outputTemplate": "ui://kiln/asset-v6.html",
|
|
1742
|
+
"ui/resourceUri": "ui://kiln/asset-v6.html"
|
|
1743
1743
|
},
|
|
1744
1744
|
"outputSchema": {
|
|
1745
1745
|
"type": "object",
|
|
@@ -2018,7 +2018,7 @@
|
|
|
2018
2018
|
],
|
|
2019
2019
|
"resources": [
|
|
2020
2020
|
{
|
|
2021
|
-
"uri": "ui://kiln/asset-
|
|
2021
|
+
"uri": "ui://kiln/asset-v6.html",
|
|
2022
2022
|
"name": "kiln-asset-viewer",
|
|
2023
2023
|
"mimeType": "text/html;profile=mcp-app",
|
|
2024
2024
|
"description": "Interactive Kiln asset viewer and downloads",
|
package/src/mcp-core.ts
CHANGED
|
@@ -65,6 +65,9 @@ export const MCP_SERVER_VERSION = ENGINE_VERSION;
|
|
|
65
65
|
export const MCP_SERVER_INSTRUCTIONS =
|
|
66
66
|
"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.";
|
|
67
67
|
|
|
68
|
+
export const MCP_OPERATION_INSTRUCTIONS =
|
|
69
|
+
'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.';
|
|
70
|
+
|
|
68
71
|
/** One MCP content block. Mirrors the SDK's `CallToolResult['content']` element. */
|
|
69
72
|
export type KilnContentBlock =
|
|
70
73
|
| AssetLink
|
package/src/mcp-engine.ts
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
type KilnResourceContents,
|
|
27
27
|
type KilnToolResult,
|
|
28
28
|
withoutLocalPaths,
|
|
29
|
+
MCP_OPERATION_INSTRUCTIONS,
|
|
29
30
|
} from './mcp-core';
|
|
30
31
|
import { buildMcpManifest } from './mcp-manifest';
|
|
31
32
|
import { localProgramStore } from './program-store-node';
|
|
@@ -33,6 +34,7 @@ import { validateRequirementsBinding } from './requirements-context';
|
|
|
33
34
|
import { describeInputError, schemaFields } from './tools/actions';
|
|
34
35
|
import {
|
|
35
36
|
createKilnProgramToolRegistry,
|
|
37
|
+
createKilnOperationToolRegistry,
|
|
36
38
|
type KilnToolContext,
|
|
37
39
|
type KilnToolDef,
|
|
38
40
|
} from './tools/registry';
|
|
@@ -42,6 +44,8 @@ export type { KilnToolResult } from './mcp-core';
|
|
|
42
44
|
|
|
43
45
|
/** Optional wire features whose support is not negotiated by core MCP. */
|
|
44
46
|
export type KilnMcpCompatibilityOptions = {
|
|
47
|
+
/** Opt-in domain operation presentation generated from the shared registry. */
|
|
48
|
+
toolPresentation?: 'grouped' | 'operations';
|
|
45
49
|
/**
|
|
46
50
|
* Add core `resource_link` blocks for saved artifact files.
|
|
47
51
|
*
|
|
@@ -160,7 +164,10 @@ export function createKilnToolHost(
|
|
|
160
164
|
};
|
|
161
165
|
},
|
|
162
166
|
};
|
|
163
|
-
const defs =
|
|
167
|
+
const defs =
|
|
168
|
+
options.toolPresentation === 'operations'
|
|
169
|
+
? createKilnOperationToolRegistry(requestContext)
|
|
170
|
+
: kilnMcpToolDefs(requestContext);
|
|
164
171
|
const byName = new Map(defs.map((def) => [def.name, def] as const));
|
|
165
172
|
return {
|
|
166
173
|
defs,
|
|
@@ -259,6 +266,9 @@ export function createKilnMcpServer(
|
|
|
259
266
|
): Server {
|
|
260
267
|
const host = createKilnToolHost(context, options);
|
|
261
268
|
return createKilnServer({
|
|
269
|
+
...(options.toolPresentation === 'operations'
|
|
270
|
+
? { instructions: MCP_OPERATION_INSTRUCTIONS }
|
|
271
|
+
: {}),
|
|
262
272
|
manifest: buildMcpManifest(host.defs, context),
|
|
263
273
|
host: async () => host,
|
|
264
274
|
});
|
package/src/tools/discovery.ts
CHANGED
|
@@ -11,10 +11,14 @@ import { resolveGltfExporter } from '../community-exporter';
|
|
|
11
11
|
import { approvedTextureCatalogV1 } from '../material-resources';
|
|
12
12
|
|
|
13
13
|
/** Shared native tool definition; all transports use the same Discovery service. */
|
|
14
|
-
export function createKilnDiscoveryDef(
|
|
14
|
+
export function createKilnDiscoveryDef(
|
|
15
|
+
context: KilnToolContext,
|
|
16
|
+
presentation: 'grouped' | 'operations' = 'grouped',
|
|
17
|
+
): KilnToolDef {
|
|
15
18
|
const run = createDiscovery(
|
|
16
|
-
() => currentCapabilities(context),
|
|
19
|
+
() => currentCapabilities(context, presentation),
|
|
17
20
|
async () => projectNotes(context),
|
|
21
|
+
presentation === 'operations' ? 'kiln_capabilities({})' : 'capabilities:true',
|
|
18
22
|
);
|
|
19
23
|
return {
|
|
20
24
|
name: 'kiln_discover',
|
|
@@ -48,7 +52,10 @@ function projectNotes(context: KilnToolContext): string[] {
|
|
|
48
52
|
: [];
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
async function currentCapabilities(
|
|
55
|
+
async function currentCapabilities(
|
|
56
|
+
context: KilnToolContext,
|
|
57
|
+
presentation: 'grouped' | 'operations',
|
|
58
|
+
) {
|
|
52
59
|
const externalEvaluator =
|
|
53
60
|
Boolean(context.evaluatorPort) || context.evaluatorProfile === 'evaluator-required';
|
|
54
61
|
const approvedTextures = context.approvedTextureResources
|
|
@@ -102,12 +109,15 @@ async function currentCapabilities(context: KilnToolContext) {
|
|
|
102
109
|
// you -- so the workspace guide's "do not substitute it silently" had
|
|
103
110
|
// nothing to check against. Compare with `runtime` in .kiln/workspace.json.
|
|
104
111
|
engine: engineIdentity(),
|
|
105
|
-
project:
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
project:
|
|
113
|
+
presentation === 'operations' && !context.projectStore
|
|
114
|
+
? { available: false }
|
|
115
|
+
: {
|
|
116
|
+
configured: configuredProject(context),
|
|
117
|
+
select:
|
|
118
|
+
'projectId per call; omitted uses the configured project, null selects standalone work',
|
|
119
|
+
read: 'kiln_project { action: "get", projectId } returns the brief, design, inventory and material pins',
|
|
120
|
+
},
|
|
111
121
|
renderer,
|
|
112
122
|
execution:
|
|
113
123
|
context.localExecution ??
|
|
@@ -128,7 +138,7 @@ async function currentCapabilities(context: KilnToolContext) {
|
|
|
128
138
|
available: Boolean(context.assetLibrary),
|
|
129
139
|
collections: context.assetLibrary?.collections() ?? [],
|
|
130
140
|
save: 'kiln_save persists exact GLB, source and provenance; draft renders do not populate collections',
|
|
131
|
-
resume: 'kiln_assets action=restore imports a saved revision into the current program store
|
|
141
|
+
resume: `${presentation === 'operations' ? 'kiln_assets_restore' : 'kiln_assets action=restore'} imports a saved revision into the current program store`,
|
|
132
142
|
downloads: 'kiln_export returns GLB/source/ZIP resource links; client presentation varies',
|
|
133
143
|
viewer:
|
|
134
144
|
'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',
|