@call-me-sensei/toonlab 0.4.21 → 0.4.22

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 (31) hide show
  1. package/NPM-LIBRARY.md +51 -2
  2. package/README.md +4 -3
  3. package/agents/PROMPTS.md +1 -1
  4. package/database/apply-one-catalog-seed.mjs +63 -0
  5. package/database/seeds/catalog/0005_2026-08-c8-first12.sql +1101 -0
  6. package/database/seeds/catalog/0006_2026-09-c8-first100.sql +14245 -0
  7. package/database/seeds/catalog/0007_2026-09-c8-first100-primary-model.sql +14845 -0
  8. package/package.json +4 -2
  9. package/src/catalog/officialCatalog.js +1 -0
  10. package/src/catalog/officialCatalogAssetRuntime.js +98 -1
  11. package/src/catalog/officialCatalogLod.js +160 -16
  12. package/src/catalog/officialCatalogPlacement.js +52 -12
  13. package/src/catalog/officialCatalogProvider.js +79 -8
  14. package/src/catalog/officialCatalogRockPackage.js +172 -0
  15. package/src/rock-shader/rockMaterial.js +205 -28
  16. package/src/rock-shader/rockShaderRuntime.js +17 -1
  17. package/src/rock-shader/rockShaderSettings.js +16 -0
  18. package/src/rockgen/lod/index.js +1 -0
  19. package/src/rockgen/lod/rockDenseFieldPolicy.js +143 -0
  20. package/src/rockgen/rockDocument.js +604 -26
  21. package/src/version.js +1 -1
  22. package/types/catalog/officialCatalog.d.ts +1 -0
  23. package/types/catalog/officialCatalogPlacement.d.ts +4 -0
  24. package/types/catalog/officialCatalogRockPackage.d.ts +68 -0
  25. package/types/index.d.ts +24 -0
  26. package/types/rock-shader/rockMaterial.d.ts +3 -0
  27. package/types/rock-shader/rockShaderSettings.d.ts +2 -0
  28. package/types/rockgen/lod/index.d.ts +1 -0
  29. package/types/rockgen/lod/rockDenseFieldPolicy.d.ts +181 -0
  30. package/types/rockgen/rockDocument.d.ts +579 -68
  31. package/types/version.d.ts +1 -1
package/NPM-LIBRARY.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # ToonLab npm library guide
2
2
 
3
3
  This guide is included in `@call-me-sensei/toonlab`. It is the package-first
4
- reference for version 0.4.21 and does not require access to the source
4
+ reference for version 0.4.22 and does not require access to the source
5
5
  repository.
6
6
 
7
7
  ## Install
@@ -124,6 +124,55 @@ The host application still owns renderer creation, geometry and XZ layout,
124
124
  cameras, controls, gameplay, dynamic physics, navigation, persistence, and the
125
125
  frame loop. ToonLab does not turn a prompt into a finished world.
126
126
 
127
+ ## Load Nature Reference Rocks
128
+
129
+ Version 0.4.22 understands both the original `rock-0001`–`rock-0480`
130
+ identities and the `rock-c8-*` Nature Reference Rocks. Acquiring an asset
131
+ directly returns its realistic PBR GLB. The one-call placement path additionally
132
+ loads that asset's reviewed geology maps and `call_me_sensei` material settings
133
+ before applying the selected style bundle.
134
+
135
+ ```js
136
+ import {
137
+ createOfficialCatalogAssetRuntime,
138
+ createOfficialCatalogProvider,
139
+ createOfficialCatalogRockEditorDescriptor,
140
+ loadOfficialCatalogAsset,
141
+ } from '@call-me-sensei/toonlab/official-catalog';
142
+ import { CALL_ME_SENSEI_STYLE_BUNDLE } from '@call-me-sensei/toonlab/styles';
143
+
144
+ const provider = createOfficialCatalogProvider({
145
+ baseUrl: 'https://toonlab.io/',
146
+ transport: 'public-rock',
147
+ });
148
+ const assets = createOfficialCatalogAssetRuntime({ provider, renderer });
149
+
150
+ // Raw acquisition keeps the realistic PBR model.
151
+ const realistic = await assets.acquireAsset('rock-c8-arch-sandstone');
152
+ scene.add(realistic.root);
153
+
154
+ // Placement loads the same rock's geology maps and applies Call Me Sensei.
155
+ const stylized = await loadOfficialCatalogAsset({
156
+ assetId: 'rock-c8-arch-sandstone',
157
+ assetRuntime: assets,
158
+ parent: scene,
159
+ styleBundle: CALL_ME_SENSEI_STYLE_BUNDLE,
160
+ });
161
+
162
+ // Rock Lab/editor integrations receive the non-destructive authoring contract.
163
+ const rockPackage = await assets.getRockPackage('rock-c8-arch-sandstone');
164
+ const editorSource = createOfficialCatalogRockEditorDescriptor(
165
+ rockPackage.asset,
166
+ rockPackage,
167
+ );
168
+ ```
169
+
170
+ `editorSource` exposes `control.glb`, retained high detail, LOD0–LOD4,
171
+ collision, recipe, material configuration, and the required post-sculpt
172
+ reprojection/rebake/rebuild flags. These are immutable R2 URLs; the package
173
+ does not embed any rock media. Release acquired handles and dispose the runtime
174
+ when their scene lifetime ends.
175
+
127
176
  ## Install the agent guidance
128
177
 
129
178
  Everything in this section is present in the installed npm package.
@@ -169,7 +218,7 @@ it uses the disk workspace passed through `--workspace`; no account is needed.
169
218
  "command": "npx",
170
219
  "args": [
171
220
  "-y",
172
- "@call-me-sensei/toonlab@0.4.21",
221
+ "@call-me-sensei/toonlab@0.4.22",
173
222
  "--workspace",
174
223
  "/absolute/path/to/your-game/.toonlab"
175
224
  ],
package/README.md CHANGED
@@ -19,7 +19,7 @@ Use ToonLab as a focused runtime library (`@call-me-sensei/toonlab` on npm), as
19
19
  an asset/preset authoring workspace, or as an asset-discovery service—not as a
20
20
  one-shot world generator.
21
21
 
22
- ## Versioned expectation: 0.4.21
22
+ ## Versioned expectation: 0.4.22
23
23
 
24
24
  For a correctly constructed and semantically labeled scene, one strict Call Me
25
25
  Sensei bundle application is expected to establish the supported visual
@@ -277,8 +277,9 @@ Catalog data therefore does **not** use a separate downloadable “current
277
277
  seed,” and new datasets are **not** schema migrations. Keeping every released
278
278
  batch in the repository gives fresh and upgraded installations the same final
279
279
  catalog while preserving a simple, auditable upgrade path. The checked-in
280
- catalog currently contains 8,163 official assets: 480 first-party ToonLab
281
- rocks plus 7,683 verified open assets.
280
+ catalog includes the original 480 first-party Stylized rocks, the 100-item
281
+ Nature Reference Rocks by ToonLab collection, and the verified open-asset
282
+ release. The two ToonLab rock collections keep distinct searchable identities.
282
283
 
283
284
  Applied filenames and SHA-256 digests are recorded in `schema_migrations` and
284
285
  `catalog_seed_batches`. Never edit, rename, or replace a released migration or
package/agents/PROMPTS.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # ToonLab agent prompts
2
2
 
3
3
  These prompts are included with the npm package. They use only the supported
4
- 0.4.21 runtime, agent skills, and MCP workflows.
4
+ 0.4.22 runtime, agent skills, and MCP workflows.
5
5
 
6
6
  ## Existing-scene integration
7
7
 
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { createHash } from 'node:crypto';
4
+ import { readFile } from 'node:fs/promises';
5
+ import path from 'node:path';
6
+
7
+ import { closeDatabase, getPool, withTransaction } from './client.mjs';
8
+
9
+ const fileArgument = process.argv[2];
10
+ if (!fileArgument) throw new Error('Usage: node database/apply-one-catalog-seed.mjs database/seeds/catalog/NNNN_release.sql');
11
+ const file = path.resolve(fileArgument);
12
+ const catalogSeedRoot = `${path.resolve('database/seeds/catalog')}${path.sep}`;
13
+ if (!file.startsWith(catalogSeedRoot) || !/^\d{4}_[a-z0-9._-]+\.sql$/iu.test(path.basename(file))) {
14
+ throw new Error('Only one numbered catalog seed below database/seeds/catalog may be applied.');
15
+ }
16
+
17
+ const sql = await readFile(file, 'utf8');
18
+ const hash = createHash('sha256').update(sql).digest('hex');
19
+ const name = path.basename(file);
20
+ const release = sql.match(/^-- Release: ([a-z0-9._-]+)$/im)?.[1];
21
+ const assetCount = Number(sql.match(/^-- Asset count: (\d+)$/m)?.[1]);
22
+ if (!release || !Number.isSafeInteger(assetCount) || assetCount < 0) {
23
+ throw new Error(`${name}: missing generated release metadata.`);
24
+ }
25
+
26
+ try {
27
+ const pool = await getPool();
28
+ await pool.query(
29
+ `create table if not exists catalog_seed_batches (
30
+ name text primary key,
31
+ sha256 text not null,
32
+ release text,
33
+ asset_count integer not null default 0,
34
+ applied_at timestamptz not null default now()
35
+ )`,
36
+ );
37
+ const result = await withTransaction(async (client) => {
38
+ await client.query('select pg_advisory_xact_lock(hashtext($1))', ['toonlab:catalog_seed_batches']);
39
+ const existing = await client.query('select sha256 from catalog_seed_batches where name = $1', [name]);
40
+ if (existing.rowCount) {
41
+ if (existing.rows[0].sha256 !== hash) throw new Error(`${name} changed after it was applied`);
42
+ return { status: 'unchanged' };
43
+ }
44
+ await client.query(sql);
45
+ await client.query(
46
+ `insert into catalog_seed_batches (name, sha256, release, asset_count)
47
+ values ($1, $2, $3, $4)`,
48
+ [name, hash, release, assetCount],
49
+ );
50
+ const published = await client.query(
51
+ `select count(*)::int as count from catalog_assets
52
+ where release = $1 and availability_status = 'active'`,
53
+ [release],
54
+ );
55
+ if (Number(published.rows[0].count) !== assetCount) {
56
+ throw new Error(`${release}: expected ${assetCount} active assets after seed.`);
57
+ }
58
+ return { published: Number(published.rows[0].count), status: 'applied' };
59
+ });
60
+ process.stdout.write(`${JSON.stringify({ assetCount, hash, name, release, ...result }, null, 2)}\n`);
61
+ } finally {
62
+ await closeDatabase();
63
+ }