@instruktlabs/kiln 1.0.0 → 1.1.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.
Files changed (68) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/CHANGELOG.md +48 -3
  5. package/CONTRIBUTING.md +16 -7
  6. package/README.md +95 -381
  7. package/dist/agent-run.mjs +1 -1
  8. package/dist/build.json +40 -28
  9. package/dist/cli.mjs +18 -14
  10. package/dist/mcp-engine.mjs +15 -11
  11. package/dist/mcp-server.mjs +1 -1
  12. package/docs/architecture.md +6 -3
  13. package/docs/chatgpt.md +20 -5
  14. package/docs/examples.md +40 -170
  15. package/docs/install.md +100 -35
  16. package/docs/migration.md +20 -0
  17. package/docs/sdk.md +26 -5
  18. package/lib/asset-widget-uri.d.ts +9 -0
  19. package/lib/asset-widget-uri.js +9 -0
  20. package/lib/cli-render-mode.js +10 -3
  21. package/lib/discovery/portable.d.ts +9 -0
  22. package/lib/discovery/portable.js +6 -0
  23. package/lib/engine-identity.d.ts +1 -1
  24. package/lib/engine-identity.js +1 -1
  25. package/lib/evaluator/isolation.js +19 -5
  26. package/lib/evaluator/probe-invariants.d.ts +11 -0
  27. package/lib/evaluator/probe-invariants.js +36 -0
  28. package/lib/evaluator/probe-worker.js +16 -4
  29. package/lib/loopback.d.ts +6 -0
  30. package/lib/loopback.js +6 -0
  31. package/lib/mcp-core.d.ts +209 -0
  32. package/lib/mcp-core.js +278 -0
  33. package/lib/mcp-engine.d.ts +57 -0
  34. package/lib/mcp-engine.js +284 -0
  35. package/lib/mcp-manifest.d.ts +15 -0
  36. package/lib/mcp-manifest.js +65 -0
  37. package/lib/mcp.d.ts +5 -0
  38. package/lib/mcp.js +2 -0
  39. package/lib/render-service-host.js +1 -1
  40. package/package.json +22 -1
  41. package/plugin.json +1 -1
  42. package/plugins/kiln-engine/.claude-plugin/icon.png +0 -0
  43. package/plugins/kiln-engine/.claude-plugin/plugin.json +9 -3
  44. package/plugins/kiln-engine/PRIVACY.md +100 -0
  45. package/plugins/kiln-engine/README.md +103 -18
  46. package/plugins/kiln-engine/{scripts/setup-workspace.mjs → bin/kiln-setup-workspace.mjs} +37 -9
  47. package/plugins/kiln-engine/package-provenance.json +15 -8
  48. package/plugins/kiln-engine/plugin.json +10 -4
  49. package/plugins/kiln-engine/runtime.json +10 -1
  50. package/plugins/kiln-engine/skills/kiln-setup-workspace/SKILL.md +17 -18
  51. package/plugins/kiln-engine/skills/kiln-setup-workspace/references/plugin-install.md +28 -8
  52. package/plugins/kiln-engine/skills/kiln-setup-workspace/references/renderer-setup.md +11 -0
  53. package/scripts/create-workspace.mjs +71 -13
  54. package/scripts/workspace-config.mjs +239 -0
  55. package/scripts/workspace-project.mjs +384 -0
  56. package/scripts/workspace-transaction.mjs +504 -0
  57. package/skills/kiln-setup-workspace/SKILL.md +17 -18
  58. package/skills/kiln-setup-workspace/references/plugin-install.md +28 -8
  59. package/skills/kiln-setup-workspace/references/renderer-setup.md +11 -0
  60. package/src/cli-render-mode.ts +9 -9
  61. package/src/cli.ts +3 -3
  62. package/src/discovery/portable.ts +9 -0
  63. package/src/engine-identity.ts +1 -1
  64. package/src/evaluator/isolation.ts +27 -6
  65. package/src/evaluator/probe-invariants.ts +50 -0
  66. package/src/evaluator/probe-worker.ts +22 -4
  67. package/src/mcp.ts +5 -0
  68. package/src/render-service-host.ts +1 -1
package/dist/build.json CHANGED
@@ -2,12 +2,12 @@
2
2
  "schemaVersion": 1,
3
3
  "entries": {
4
4
  "worker": {
5
- "identity": "sha256:81875ff0bc5f7b4b952f2bb32ffa11d9b4e2ee7067f1ccd458f6ec0aec455538",
6
- "engineVersion": "1.0.0",
5
+ "identity": "sha256:adbc219831fef0d5cac0d2050a8171a3fd11860bb632b0e27545ed1cd571acfc",
6
+ "engineVersion": "1.1.0",
7
7
  "toolchain": "bun@1.4.2",
8
- "sourceHash": "83b57574766f2e278eeee58d8b923b9bfc642a6832f2d1c137408b2b389acc7f",
8
+ "sourceHash": "31bf69f080bbcca05a98b7c485b5642e90e7f63625f4b03d89a91fbbb5f81e9c",
9
9
  "rendererSourceHash": "27927c48b377f7694251a76c0cecd05216fcbbb8a7d03e8bf2bd681dabb5573a",
10
- "dependencyHash": "182eedef24fb67faae8fed2506e5ad51afee511fdcbce8fb8c709c3cc6fd91f9",
10
+ "dependencyHash": "bb179f2715f8fd9059898ef3a2028947e8f5f7e7979ad7eafe59d7a464c18f9f",
11
11
  "dependencies": {
12
12
  "@gltf-transform/core": "4.5.1",
13
13
  "@gltf-transform/extensions": "4.5.1",
@@ -19,10 +19,12 @@
19
19
  "acorn": "^8.18.0",
20
20
  "acorn-walk": "^8.3.5",
21
21
  "gltf-validator": "2.0.0-dev.3.10",
22
+ "jsonc-parser": "3.3.1",
22
23
  "manifold-3d": "^3.5.4",
23
24
  "minisearch": "7.2.0",
24
25
  "pngjs": "7.0.0",
25
26
  "sharp": "^0.35.5",
27
+ "smol-toml": "1.9.0",
26
28
  "three": "0.186.1",
27
29
  "three-subdivide": "1.1.5",
28
30
  "xatlasjs": "^0.2.0",
@@ -37,12 +39,12 @@
37
39
  "bundleHash": "sha256:37098a17b5304a5f5746131c9652498d937a5181c0fb0975861dec999721d5be"
38
40
  },
39
41
  "agent-run": {
40
- "identity": "sha256:81875ff0bc5f7b4b952f2bb32ffa11d9b4e2ee7067f1ccd458f6ec0aec455538",
41
- "engineVersion": "1.0.0",
42
+ "identity": "sha256:adbc219831fef0d5cac0d2050a8171a3fd11860bb632b0e27545ed1cd571acfc",
43
+ "engineVersion": "1.1.0",
42
44
  "toolchain": "bun@1.4.2",
43
- "sourceHash": "83b57574766f2e278eeee58d8b923b9bfc642a6832f2d1c137408b2b389acc7f",
45
+ "sourceHash": "31bf69f080bbcca05a98b7c485b5642e90e7f63625f4b03d89a91fbbb5f81e9c",
44
46
  "rendererSourceHash": "27927c48b377f7694251a76c0cecd05216fcbbb8a7d03e8bf2bd681dabb5573a",
45
- "dependencyHash": "182eedef24fb67faae8fed2506e5ad51afee511fdcbce8fb8c709c3cc6fd91f9",
47
+ "dependencyHash": "bb179f2715f8fd9059898ef3a2028947e8f5f7e7979ad7eafe59d7a464c18f9f",
46
48
  "dependencies": {
47
49
  "@gltf-transform/core": "4.5.1",
48
50
  "@gltf-transform/extensions": "4.5.1",
@@ -54,10 +56,12 @@
54
56
  "acorn": "^8.18.0",
55
57
  "acorn-walk": "^8.3.5",
56
58
  "gltf-validator": "2.0.0-dev.3.10",
59
+ "jsonc-parser": "3.3.1",
57
60
  "manifold-3d": "^3.5.4",
58
61
  "minisearch": "7.2.0",
59
62
  "pngjs": "7.0.0",
60
63
  "sharp": "^0.35.5",
64
+ "smol-toml": "1.9.0",
61
65
  "three": "0.186.1",
62
66
  "three-subdivide": "1.1.5",
63
67
  "xatlasjs": "^0.2.0",
@@ -69,15 +73,15 @@
69
73
  },
70
74
  "target": "node",
71
75
  "file": "agent-run.mjs",
72
- "bundleHash": "sha256:60946cbf1ddfbc28e60829013354fd069947892c1698c9597e14c672730f8628"
76
+ "bundleHash": "sha256:3fdb17224ded3a55afff6cf0b84f3de902728834d32ffe6e0c449ed3b71ac641"
73
77
  },
74
78
  "agent-providers": {
75
- "identity": "sha256:81875ff0bc5f7b4b952f2bb32ffa11d9b4e2ee7067f1ccd458f6ec0aec455538",
76
- "engineVersion": "1.0.0",
79
+ "identity": "sha256:adbc219831fef0d5cac0d2050a8171a3fd11860bb632b0e27545ed1cd571acfc",
80
+ "engineVersion": "1.1.0",
77
81
  "toolchain": "bun@1.4.2",
78
- "sourceHash": "83b57574766f2e278eeee58d8b923b9bfc642a6832f2d1c137408b2b389acc7f",
82
+ "sourceHash": "31bf69f080bbcca05a98b7c485b5642e90e7f63625f4b03d89a91fbbb5f81e9c",
79
83
  "rendererSourceHash": "27927c48b377f7694251a76c0cecd05216fcbbb8a7d03e8bf2bd681dabb5573a",
80
- "dependencyHash": "182eedef24fb67faae8fed2506e5ad51afee511fdcbce8fb8c709c3cc6fd91f9",
84
+ "dependencyHash": "bb179f2715f8fd9059898ef3a2028947e8f5f7e7979ad7eafe59d7a464c18f9f",
81
85
  "dependencies": {
82
86
  "@gltf-transform/core": "4.5.1",
83
87
  "@gltf-transform/extensions": "4.5.1",
@@ -89,10 +93,12 @@
89
93
  "acorn": "^8.18.0",
90
94
  "acorn-walk": "^8.3.5",
91
95
  "gltf-validator": "2.0.0-dev.3.10",
96
+ "jsonc-parser": "3.3.1",
92
97
  "manifold-3d": "^3.5.4",
93
98
  "minisearch": "7.2.0",
94
99
  "pngjs": "7.0.0",
95
100
  "sharp": "^0.35.5",
101
+ "smol-toml": "1.9.0",
96
102
  "three": "0.186.1",
97
103
  "three-subdivide": "1.1.5",
98
104
  "xatlasjs": "^0.2.0",
@@ -107,12 +113,12 @@
107
113
  "bundleHash": "sha256:9d6faf03d307321bc2e3bd5ce5bdee0bbbf61e0ebed8bfebfa1fb072287b83fa"
108
114
  },
109
115
  "mcp": {
110
- "identity": "sha256:81875ff0bc5f7b4b952f2bb32ffa11d9b4e2ee7067f1ccd458f6ec0aec455538",
111
- "engineVersion": "1.0.0",
116
+ "identity": "sha256:adbc219831fef0d5cac0d2050a8171a3fd11860bb632b0e27545ed1cd571acfc",
117
+ "engineVersion": "1.1.0",
112
118
  "toolchain": "bun@1.4.2",
113
- "sourceHash": "83b57574766f2e278eeee58d8b923b9bfc642a6832f2d1c137408b2b389acc7f",
119
+ "sourceHash": "31bf69f080bbcca05a98b7c485b5642e90e7f63625f4b03d89a91fbbb5f81e9c",
114
120
  "rendererSourceHash": "27927c48b377f7694251a76c0cecd05216fcbbb8a7d03e8bf2bd681dabb5573a",
115
- "dependencyHash": "182eedef24fb67faae8fed2506e5ad51afee511fdcbce8fb8c709c3cc6fd91f9",
121
+ "dependencyHash": "bb179f2715f8fd9059898ef3a2028947e8f5f7e7979ad7eafe59d7a464c18f9f",
116
122
  "dependencies": {
117
123
  "@gltf-transform/core": "4.5.1",
118
124
  "@gltf-transform/extensions": "4.5.1",
@@ -124,10 +130,12 @@
124
130
  "acorn": "^8.18.0",
125
131
  "acorn-walk": "^8.3.5",
126
132
  "gltf-validator": "2.0.0-dev.3.10",
133
+ "jsonc-parser": "3.3.1",
127
134
  "manifold-3d": "^3.5.4",
128
135
  "minisearch": "7.2.0",
129
136
  "pngjs": "7.0.0",
130
137
  "sharp": "^0.35.5",
138
+ "smol-toml": "1.9.0",
131
139
  "three": "0.186.1",
132
140
  "three-subdivide": "1.1.5",
133
141
  "xatlasjs": "^0.2.0",
@@ -139,15 +147,15 @@
139
147
  },
140
148
  "target": "node",
141
149
  "file": "mcp-server.mjs",
142
- "bundleHash": "sha256:1f0727c7d63590d950d964e4dd15e303fdd27a79c97bf864aaaee5d7a7b9289e"
150
+ "bundleHash": "sha256:8de0309a6995e5d49ed2c261b9e7cb7ab6d7eab13c2f2f16f12511d8fd703a27"
143
151
  },
144
152
  "cli": {
145
- "identity": "sha256:81875ff0bc5f7b4b952f2bb32ffa11d9b4e2ee7067f1ccd458f6ec0aec455538",
146
- "engineVersion": "1.0.0",
153
+ "identity": "sha256:adbc219831fef0d5cac0d2050a8171a3fd11860bb632b0e27545ed1cd571acfc",
154
+ "engineVersion": "1.1.0",
147
155
  "toolchain": "bun@1.4.2",
148
- "sourceHash": "83b57574766f2e278eeee58d8b923b9bfc642a6832f2d1c137408b2b389acc7f",
156
+ "sourceHash": "31bf69f080bbcca05a98b7c485b5642e90e7f63625f4b03d89a91fbbb5f81e9c",
149
157
  "rendererSourceHash": "27927c48b377f7694251a76c0cecd05216fcbbb8a7d03e8bf2bd681dabb5573a",
150
- "dependencyHash": "182eedef24fb67faae8fed2506e5ad51afee511fdcbce8fb8c709c3cc6fd91f9",
158
+ "dependencyHash": "bb179f2715f8fd9059898ef3a2028947e8f5f7e7979ad7eafe59d7a464c18f9f",
151
159
  "dependencies": {
152
160
  "@gltf-transform/core": "4.5.1",
153
161
  "@gltf-transform/extensions": "4.5.1",
@@ -159,10 +167,12 @@
159
167
  "acorn": "^8.18.0",
160
168
  "acorn-walk": "^8.3.5",
161
169
  "gltf-validator": "2.0.0-dev.3.10",
170
+ "jsonc-parser": "3.3.1",
162
171
  "manifold-3d": "^3.5.4",
163
172
  "minisearch": "7.2.0",
164
173
  "pngjs": "7.0.0",
165
174
  "sharp": "^0.35.5",
175
+ "smol-toml": "1.9.0",
166
176
  "three": "0.186.1",
167
177
  "three-subdivide": "1.1.5",
168
178
  "xatlasjs": "^0.2.0",
@@ -174,15 +184,15 @@
174
184
  },
175
185
  "target": "node",
176
186
  "file": "cli.mjs",
177
- "bundleHash": "sha256:bfe2e039974e093486b4d92af795235ac20c2d3772424237c90eb16455db47c5"
187
+ "bundleHash": "sha256:d7ebfce5b290a5da221c5890778ddc3ceaec1beb5022360aef12a82e1a193685"
178
188
  },
179
189
  "engine": {
180
- "identity": "sha256:81875ff0bc5f7b4b952f2bb32ffa11d9b4e2ee7067f1ccd458f6ec0aec455538",
181
- "engineVersion": "1.0.0",
190
+ "identity": "sha256:adbc219831fef0d5cac0d2050a8171a3fd11860bb632b0e27545ed1cd571acfc",
191
+ "engineVersion": "1.1.0",
182
192
  "toolchain": "bun@1.4.2",
183
- "sourceHash": "83b57574766f2e278eeee58d8b923b9bfc642a6832f2d1c137408b2b389acc7f",
193
+ "sourceHash": "31bf69f080bbcca05a98b7c485b5642e90e7f63625f4b03d89a91fbbb5f81e9c",
184
194
  "rendererSourceHash": "27927c48b377f7694251a76c0cecd05216fcbbb8a7d03e8bf2bd681dabb5573a",
185
- "dependencyHash": "182eedef24fb67faae8fed2506e5ad51afee511fdcbce8fb8c709c3cc6fd91f9",
195
+ "dependencyHash": "bb179f2715f8fd9059898ef3a2028947e8f5f7e7979ad7eafe59d7a464c18f9f",
186
196
  "dependencies": {
187
197
  "@gltf-transform/core": "4.5.1",
188
198
  "@gltf-transform/extensions": "4.5.1",
@@ -194,10 +204,12 @@
194
204
  "acorn": "^8.18.0",
195
205
  "acorn-walk": "^8.3.5",
196
206
  "gltf-validator": "2.0.0-dev.3.10",
207
+ "jsonc-parser": "3.3.1",
197
208
  "manifold-3d": "^3.5.4",
198
209
  "minisearch": "7.2.0",
199
210
  "pngjs": "7.0.0",
200
211
  "sharp": "^0.35.5",
212
+ "smol-toml": "1.9.0",
201
213
  "three": "0.186.1",
202
214
  "three-subdivide": "1.1.5",
203
215
  "xatlasjs": "^0.2.0",
@@ -209,7 +221,7 @@
209
221
  },
210
222
  "target": "node",
211
223
  "file": "mcp-engine.mjs",
212
- "bundleHash": "sha256:c86e0280590c819d12baad3173fa0acc788cc6feb376e53cebf11abb44814d35"
224
+ "bundleHash": "sha256:3cb423f905dddc8b3c248db00304b2da976e69c0c899e0f63bbdf065f9af8f08"
213
225
  }
214
226
  }
215
227
  }
package/dist/cli.mjs CHANGED
@@ -29342,7 +29342,7 @@ function isolatedWorkerUrls(moduleUrl) {
29342
29342
  }
29343
29343
 
29344
29344
  // src/evaluator/isolation.ts
29345
- import { existsSync } from "node:fs";
29345
+ import { existsSync, readlinkSync } from "node:fs";
29346
29346
  import { posix } from "node:path";
29347
29347
  import { fileURLToPath as fileURLToPath2 } from "node:url";
29348
29348
  function isolationUnavailable() {
@@ -29384,7 +29384,7 @@ function isolatedEvaluatorLaunchWithLoader(workerPath, host = {}, loader = "tsx"
29384
29384
  const setprivPath = requiredAbsolutePath(host.setprivPath ?? DEFAULT_SETPRIV_PATH);
29385
29385
  const prlimitPath = requiredAbsolutePath(host.prlimitPath ?? DEFAULT_PRLIMIT_PATH);
29386
29386
  const nodePath = requiredAbsolutePath(host.nodePath ?? DEFAULT_NODE_PATH);
29387
- for (const executable of [bwrapPath, setprivPath, prlimitPath, nodePath]) {
29387
+ for (const executable of [bwrapPath, setprivPath, prlimitPath, nodePath, ENV_PATH]) {
29388
29388
  if (!pathExists(executable))
29389
29389
  isolationUnavailable();
29390
29390
  }
@@ -29420,11 +29420,11 @@ function isolatedEvaluatorLaunchWithLoader(workerPath, host = {}, loader = "tsx"
29420
29420
  for (const mount of runtimeMounts(runtimeRoot, pathExists)) {
29421
29421
  bwrapArgs.push("--ro-bind", mount, mount);
29422
29422
  }
29423
- const nodeArgs = [nodePath, "--max-old-space-size=512", "--disable-proto=throw"];
29423
+ const nodeArgs = [nodePath, "--max-old-space-size=512", "--disable-proto=delete"];
29424
29424
  if (loader === "tsx")
29425
29425
  nodeArgs.push("--import", "tsx");
29426
29426
  nodeArgs.push(resolvedWorkerPath);
29427
- bwrapArgs.push("--chdir", runtimeRoot, "--preserve-fds", "1", "--", prlimitPath, "--cpu=65:65", "--as=6442450944:6442450944", "--fsize=100663296:100663296", "--nofile=64:64", "--nproc=64:64", "--", ...nodeArgs);
29427
+ 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);
29428
29428
  return {
29429
29429
  command: setprivPath,
29430
29430
  args: [
@@ -29448,7 +29448,7 @@ async function renderGLBViaIsolatedEvaluator(code, options = {}, controls = {})
29448
29448
  const { host: _, ...processControls } = controls;
29449
29449
  return renderGLBViaProcessLaunch(code, options, processControls, launch);
29450
29450
  }
29451
- 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;
29451
+ 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;
29452
29452
  var init_isolation = __esm(() => {
29453
29453
  init_subprocess();
29454
29454
  MAX_READINESS_PROTOCOL_BYTES = 16 * 1024;
@@ -36171,7 +36171,7 @@ var init_program_artifacts = __esm(() => {
36171
36171
  function engineIdentity() {
36172
36172
  return { version: ENGINE_VERSION, installUrl: ENGINE_INSTALL_URL };
36173
36173
  }
36174
- var ENGINE_VERSION = "1.0.0", ENGINE_INSTALL_URL;
36174
+ var ENGINE_VERSION = "1.1.0", ENGINE_INSTALL_URL;
36175
36175
  var init_engine_identity = __esm(() => {
36176
36176
  ENGINE_INSTALL_URL = new URL("../", import.meta.url).href;
36177
36177
  });
@@ -44428,8 +44428,7 @@ async function startLocalRenderService(dir = renderServiceDir(), environment = p
44428
44428
  if (exited)
44429
44429
  exitedAt ??= Date.now();
44430
44430
  if (spawnError || exitedAt !== undefined && Date.now() - exitedAt >= 1500)
44431
- throw new Error(`render service exited during startup${spawnError ? `: ${spawnError.message}` : ""}${stderr.trim() ? `: ${stderr.trim().split(`
44432
- `).slice(-3).join(" ")}` : windowsLaunch ? "; launch the renderer manually to inspect native-driver errors" : ""}`);
44431
+ 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" : ""}`);
44433
44432
  await new Promise((done) => setTimeout(done, 250));
44434
44433
  }
44435
44434
  throw new Error(`render service health is unknown after ${budget}ms; inspect with \`kiln service reprobe\``);
@@ -44558,12 +44557,17 @@ function makeLazyRenderPort(start, token, sourceFingerprint, initialUrl) {
44558
44557
  } catch (error) {
44559
44558
  if (execution?.signal?.aborted || error.name === "TimeoutError")
44560
44559
  throw error;
44561
- if ((await readRenderServiceHealth(url, {
44560
+ if (resolving !== pending)
44561
+ return (await resolve()).port(req, execution);
44562
+ const health = await readRenderServiceHealth(url, {
44562
44563
  token,
44563
44564
  signal: execution?.signal
44564
- })).kind !== "absent")
44565
- throw error;
44565
+ });
44566
44566
  execution?.signal?.throwIfAborted();
44567
+ if (resolving !== pending)
44568
+ return (await resolve()).port(req, execution);
44569
+ if (health.kind !== "absent")
44570
+ throw error;
44567
44571
  if (resolving === pending)
44568
44572
  resolving = undefined;
44569
44573
  return (await resolve()).port(req, execution);
@@ -47448,11 +47452,11 @@ EXPORT ENVIRONMENT
47448
47452
  KILN_INDEX_POLICY indexed (default) | asBuilt (requires optimization off)
47449
47453
 
47450
47454
  EXAMPLES
47451
- kiln render examples/crate.kiln.js --out crate.glb --views sheet.png
47455
+ kiln render my-asset.kiln.js --out asset.glb --views sheet.png
47452
47456
  kiln generate "a weathered wooden crate" --out crate.glb --views sheet.png
47453
- kiln render examples/crate.kiln.js --render cpu --views sheet.png
47457
+ kiln render my-asset.kiln.js --render cpu --views sheet.png
47454
47458
  kiln render p_RETURNED_HANDLE --capture cameras.json --views chosen.png
47455
- kiln render examples/crate.kiln.js --views sheet.png --backdrop light
47459
+ kiln render my-asset.kiln.js --views sheet.png --backdrop light
47456
47460
  `;
47457
47461
  function parseArgs(argv) {
47458
47462
  let renderOption;
@@ -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=throw"];
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, "--preserve-fds", "1", "--", prlimitPath, "--cpu=65:65", "--as=6442450944:6442450944", "--fsize=100663296:100663296", "--nofile=64:64", "--nproc=64:64", "--", ...nodeArgs);
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().split(`
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 ((await readRenderServiceHealth(url, {
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
- })).kind !== "absent")
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.0.0";
36109
+ var ENGINE_VERSION = "1.1.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 };
@@ -2085,7 +2085,7 @@ import { readFile } from "node:fs/promises";
2085
2085
  var KILN_ASSET_WIDGET_URI = "ui://kiln/asset-v5.html";
2086
2086
 
2087
2087
  // src/engine-identity.ts
2088
- var ENGINE_VERSION = "1.0.0";
2088
+ var ENGINE_VERSION = "1.1.0";
2089
2089
  var ENGINE_INSTALL_URL = new URL("../", import.meta.url).href;
2090
2090
 
2091
2091
  // src/requirements-json.ts
@@ -4,11 +4,11 @@ Kiln builds JavaScript programs into GLB assets, validates structure, and render
4
4
 
5
5
  ## Entry points
6
6
 
7
- The v1 checkout prepares `@instruktlabs/kiln` with compiled ESM and TypeScript
7
+ The npm package `@instruktlabs/kiln` ships compiled ESM and TypeScript
8
8
  declarations. Node consumers need no source loader. Build the SDK on a fresh source
9
9
  checkout before using package imports; the installed archive already contains it.
10
10
  See the [SDK contract](sdk.md) for runtime and experimental-feature boundaries.
11
- There is no published npm release yet.
11
+ See [installation](install.md) for package, source-checkout and plugin setup.
12
12
 
13
13
  | Subpath | Purpose |
14
14
  |---|---|
@@ -66,12 +66,15 @@ CPU render paths are deterministic for the same inputs. GPU images can vary by d
66
66
  ## Development
67
67
 
68
68
  ```bash
69
+ node scripts/example-archive.mjs --fetch
69
70
  bun run typecheck
70
71
  bun run lint
71
72
  bun run test
72
73
  bun run test:coverage
73
74
  ```
74
75
 
75
- Offline tests pin CPU rendering and exercise the checked-in example programs. The coverage ratchet lives in [scripts/check-coverage.mjs](https://github.com/instruktlabs/kiln/blob/main/scripts/check-coverage.mjs). Threshold decreases require an explicit measured rationale. Live provider tests require an explicit opt-in.
76
+ Prepare the pinned historical corpus once with the explicit fetch command above.
77
+ Subsequent tests stay offline, pin CPU rendering and include those archived programs.
78
+ The coverage ratchet lives in [scripts/check-coverage.mjs](https://github.com/instruktlabs/kiln/blob/main/scripts/check-coverage.mjs). Threshold decreases require an explicit measured rationale. Live provider tests require an explicit opt-in.
76
79
 
77
80
  Core dependencies include Three.js, glTF Transform, Manifold, Acorn, and Zod. The agent SDK is an optional peer. Keep provider adapters compatible with the SDK's declared interface version; a TypeScript cast cannot fix a runtime protocol mismatch.
package/docs/chatgpt.md CHANGED
@@ -2,17 +2,27 @@
2
2
 
3
3
  Kiln's local CLI and stdio MCP server share the same collection store and tool registry. ChatGPT web needs a reachable MCP connection: a private Secure MCP Tunnel can carry this existing stdio server without making a public endpoint. The tunnel process must remain running while ChatGPT discovers or calls tools.
4
4
 
5
+ This is an owner-managed development connection. Kiln's public hosted service and
6
+ directory listing are deferred. Local CLI/MCP use needs no Kiln account; the
7
+ optional OpenAI tunnel separately requires Platform access and a runtime API key.
8
+
5
9
  ## Connect a private development server
6
10
 
7
- 1. Build with the supported toolchain: `bun run build:runtime`.
8
- 2. Create a tunnel in OpenAI Platform, scoped to the intended ChatGPT workspace. The account needs Tunnels Read and Manage; its runtime API key needs Read and Use. Existing organization roles may already grant these. Do not broaden other permissions.
9
- 3. Download a pinned official `openai/tunnel-client` release and verify its release digest. This dogfood used Windows amd64 v0.0.14. Keep credentials in the environment or a supported secret reference, never in the plugin.
11
+ 1. [Install Kiln](install.md) and create a dedicated asset workspace. The npm package already contains the built server; an engine checkout needs `bun run build:runtime` first.
12
+ 2. Create a tunnel in OpenAI Platform and associate it with the intended ChatGPT workspace and Platform organization. Creating it requires Tunnels Read and Manage; running or selecting it requires Read and Use. ChatGPT workspace policy also applies.
13
+ 3. Obtain the client through the [official tunnel setup guide](https://developers.openai.com/api/docs/guides/secure-mcp-tunnels#set-up-tunnel-client). Record the version you test. Keep credentials outside the plugin and source repository.
10
14
  4. Configure the tunnel's stdio command to launch `node /absolute/path/dist/mcp-server.mjs` in a dedicated asset workspace. Set `KILN_PROGRAM_STORE` and `KILN_COLLECTIONS` explicitly. The server does not need provider keys. The tunnel control process needs its OpenAI key, which should not be inherited by the MCP child.
11
- 5. Run `tunnel-client doctor`, then `tunnel-client run` with the configured profile. In ChatGPT's Plugins page choose Create app, Tunnel, the intended tunnel, and No Auth for the stdio server. Access is still controlled by the private tunnel; this does not create a public unauthenticated service.
15
+ 5. Run `tunnel-client doctor --profile NAME --explain`, then `tunnel-client run --profile NAME`. In ChatGPT Plugins, use the plus button, Add custom MCP server, then Tunnel. Select your tunnel, configure authentication, review the warning and create the plugin. Kiln's local stdio server has no separate OAuth; access is controlled by the private tunnel.
12
16
  6. Verify the seventeen-tool MCP surface appears, including `kiln_discover`, `kiln_renderer`, `kiln_present` and `kiln_project`. Test source submission, actual render-image visibility, save/list, copy, restore/edit, and exact revision export. Refresh connector metadata after changing tools.
13
17
 
14
18
  Local subprocess evaluation has deadlines and a sanitized environment; it is not the Linux isolated evaluator's OS security boundary. This setup is for an owner-controlled development test. A hosted multi-user deployment needs tenant-scoped storage, authentication, and the isolated evaluator posture.
15
19
 
20
+ A private tunnel is not eligible as a public plugin endpoint. OpenAI's
21
+ [connection guide](https://developers.openai.com/plugins/deploy/connect-chatgpt)
22
+ requires a public HTTPS endpoint for submission. The steps above were checked
23
+ against official documentation on 7 October 2026; that is a documentation check,
24
+ not a new end-to-end ChatGPT qualification.
25
+
16
26
  ## Expose the skills
17
27
 
18
28
  Keep `skills/*/SKILL.md` and their adjacent `references/` directories as the maintained source. Skill descriptions provide discovery; instructions load on selection, and reference files provide modeling detail when needed. Avoid pasting the complete modeling catalog into every tool description or prompt.
@@ -45,4 +55,9 @@ The local viewer (`kiln view`) provides browser downloads, revision selection, c
45
55
 
46
56
  The Node and Bun JavaScript runtimes can produce tiny floating-point differences in regenerated GLB JSON. Preserve the original artifact for byte-exact delivery and rebuild with the recorded engine's supported Node toolchain for reproducibility. ZIP import/export preserves original bytes regardless of runtime.
47
57
 
48
- Official references checked September 6, 2026: [Connect ChatGPT](https://developers.openai.com/plugins/deploy/connect-chatgpt), [Secure MCP Tunnels](https://developers.openai.com/api/docs/guides/secure-mcp-tunnels), and [Package plugins](https://developers.openai.com/plugins/build/plugins). Surface availability can change; verify the actual host before claiming installation or download support.
58
+ The uploader and download observations above are historical tests from September 6,
59
+ 2026, not claims about every current account. Check the actual client's installation,
60
+ image display and file download behavior before advertising support. See
61
+ [Connect ChatGPT](https://developers.openai.com/plugins/deploy/connect-chatgpt),
62
+ [Secure MCP Tunnels](https://developers.openai.com/api/docs/guides/secure-mcp-tunnels)
63
+ and [Package plugins](https://developers.openai.com/plugins/build/plugins).