@series-inc/stowkit-cli 0.6.20 → 0.6.21
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/dist/cli.js +35 -5
- package/dist/server.js +33 -1
- package/dist/store.d.ts +1 -0
- package/dist/store.js +3 -1
- package/package.json +2 -2
- package/skill.md +25 -9
package/dist/cli.js
CHANGED
|
@@ -110,6 +110,7 @@ Options:
|
|
|
110
110
|
--dry-run Show what would be published without uploading
|
|
111
111
|
--json Output store results as JSON (for AI agents)
|
|
112
112
|
--type Filter store search by asset type
|
|
113
|
+
--limit Max number of results to return (default: all)
|
|
113
114
|
--help Show this help message
|
|
114
115
|
`.trim());
|
|
115
116
|
}
|
|
@@ -167,6 +168,8 @@ async function main() {
|
|
|
167
168
|
const bucket = bucketIdx >= 0 ? args[bucketIdx + 1] : undefined;
|
|
168
169
|
const typeIdx = args.indexOf('--type');
|
|
169
170
|
const typeFilter = typeIdx >= 0 ? args[typeIdx + 1] : undefined;
|
|
171
|
+
const limitIdx = args.indexOf('--limit');
|
|
172
|
+
const limitFilter = limitIdx >= 0 ? parseInt(args[limitIdx + 1], 10) : undefined;
|
|
170
173
|
const opts = { force, verbose };
|
|
171
174
|
try {
|
|
172
175
|
switch (command) {
|
|
@@ -301,17 +304,37 @@ async function main() {
|
|
|
301
304
|
break;
|
|
302
305
|
case 'store': {
|
|
303
306
|
const subCmd = args[1];
|
|
304
|
-
const
|
|
307
|
+
const serverUrl = `http://localhost:${port}`;
|
|
308
|
+
const serverUp = await isStowKitRunning(port);
|
|
305
309
|
if (subCmd === 'search') {
|
|
306
310
|
const query = args.filter(a => !a.startsWith('-') && a !== 'store' && a !== 'search').join(' ');
|
|
307
311
|
if (!query) {
|
|
308
|
-
console.error('Usage: stowkit store search <query> [--type <type>] [--json]');
|
|
312
|
+
console.error('Usage: stowkit store search <query> [--type <type>] [--limit <n>] [--json]');
|
|
309
313
|
process.exit(1);
|
|
310
314
|
}
|
|
311
|
-
|
|
315
|
+
if (serverUp) {
|
|
316
|
+
const params = new URLSearchParams({ q: query });
|
|
317
|
+
if (typeFilter)
|
|
318
|
+
params.set('type', typeFilter);
|
|
319
|
+
if (limitFilter)
|
|
320
|
+
params.set('limit', String(limitFilter));
|
|
321
|
+
const res = await fetch(`${serverUrl}/api/asset-store/search?${params}`);
|
|
322
|
+
const results = await res.json();
|
|
323
|
+
console.log(JSON.stringify(results, null, 2));
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
await storeSearch(query, { json: jsonOutput, bucket, type: typeFilter, limit: limitFilter });
|
|
327
|
+
}
|
|
312
328
|
}
|
|
313
329
|
else if (subCmd === 'list') {
|
|
314
|
-
|
|
330
|
+
if (serverUp) {
|
|
331
|
+
const res = await fetch(`${serverUrl}/api/asset-store/packages`);
|
|
332
|
+
const packages = await res.json();
|
|
333
|
+
console.log(JSON.stringify(packages, null, 2));
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
await storeList({ json: jsonOutput, bucket });
|
|
337
|
+
}
|
|
315
338
|
}
|
|
316
339
|
else if (subCmd === 'info') {
|
|
317
340
|
const pkgName = args.find(a => !a.startsWith('-') && a !== 'store' && a !== 'info');
|
|
@@ -319,7 +342,14 @@ async function main() {
|
|
|
319
342
|
console.error('Usage: stowkit store info <package-name> [--json]');
|
|
320
343
|
process.exit(1);
|
|
321
344
|
}
|
|
322
|
-
|
|
345
|
+
if (serverUp) {
|
|
346
|
+
const res = await fetch(`${serverUrl}/api/asset-store/package/${encodeURIComponent(pkgName)}`);
|
|
347
|
+
const info = await res.json();
|
|
348
|
+
console.log(JSON.stringify(info, null, 2));
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
await storeInfo(pkgName, { json: jsonOutput, bucket });
|
|
352
|
+
}
|
|
323
353
|
}
|
|
324
354
|
else {
|
|
325
355
|
console.error('Usage: stowkit store <search|list|info> [args]');
|
package/dist/server.js
CHANGED
|
@@ -1785,9 +1785,13 @@ async function handleRequest(req, res, staticApps) {
|
|
|
1785
1785
|
const type = url.searchParams.get('type') ?? undefined;
|
|
1786
1786
|
const pkg = url.searchParams.get('package') ?? undefined;
|
|
1787
1787
|
const bucketParam = url.searchParams.get('bucket') ?? undefined;
|
|
1788
|
+
const limitParam = url.searchParams.get('limit');
|
|
1789
|
+
const limit = limitParam ? parseInt(limitParam, 10) : undefined;
|
|
1788
1790
|
const { fetchRegistry, searchAssets } = await import('./store.js');
|
|
1789
1791
|
const registry = await fetchRegistry(bucketParam);
|
|
1790
|
-
|
|
1792
|
+
let results = searchAssets(registry, query, { type, package: pkg });
|
|
1793
|
+
if (limit && limit > 0)
|
|
1794
|
+
results = results.slice(0, limit);
|
|
1791
1795
|
json(res, results);
|
|
1792
1796
|
}
|
|
1793
1797
|
catch (err) {
|
|
@@ -1809,6 +1813,34 @@ async function handleRequest(req, res, staticApps) {
|
|
|
1809
1813
|
}
|
|
1810
1814
|
return;
|
|
1811
1815
|
}
|
|
1816
|
+
// GET /api/asset-store/package/:name — get package details
|
|
1817
|
+
if (pathname.startsWith('/api/asset-store/package/') && req.method === 'GET') {
|
|
1818
|
+
try {
|
|
1819
|
+
const packageName = decodeURIComponent(pathname.slice('/api/asset-store/package/'.length));
|
|
1820
|
+
const bucketParam = url.searchParams.get('bucket') ?? undefined;
|
|
1821
|
+
const { fetchRegistry } = await import('./store.js');
|
|
1822
|
+
const registry = await fetchRegistry(bucketParam);
|
|
1823
|
+
const pkg = registry.packages[packageName];
|
|
1824
|
+
if (!pkg) {
|
|
1825
|
+
json(res, { error: `Package "${packageName}" not found` }, 404);
|
|
1826
|
+
return;
|
|
1827
|
+
}
|
|
1828
|
+
const ver = pkg.versions[pkg.latest];
|
|
1829
|
+
json(res, {
|
|
1830
|
+
name: packageName,
|
|
1831
|
+
description: pkg.description,
|
|
1832
|
+
author: pkg.author,
|
|
1833
|
+
tags: pkg.tags ?? [],
|
|
1834
|
+
latest: pkg.latest,
|
|
1835
|
+
versions: Object.keys(pkg.versions),
|
|
1836
|
+
assets: ver?.assets ?? [],
|
|
1837
|
+
});
|
|
1838
|
+
}
|
|
1839
|
+
catch (err) {
|
|
1840
|
+
json(res, { error: err.message }, 500);
|
|
1841
|
+
}
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1812
1844
|
// POST /api/asset-store/download — download assets (with transitive deps) into project
|
|
1813
1845
|
if (pathname === '/api/asset-store/download' && req.method === 'POST') {
|
|
1814
1846
|
if (!projectConfig) {
|
package/dist/store.d.ts
CHANGED
package/dist/store.js
CHANGED
|
@@ -219,7 +219,9 @@ export function resolveAssetDeps(registry, packageName, stringIds, version) {
|
|
|
219
219
|
// ─── CLI Commands ────────────────────────────────────────────────────────────
|
|
220
220
|
export async function storeSearch(query, opts) {
|
|
221
221
|
const registry = await fetchRegistry(opts?.bucket);
|
|
222
|
-
|
|
222
|
+
let results = searchAssets(registry, query, { type: opts?.type });
|
|
223
|
+
if (opts?.limit && opts.limit > 0)
|
|
224
|
+
results = results.slice(0, opts.limit);
|
|
223
225
|
if (opts?.json) {
|
|
224
226
|
console.log(JSON.stringify(results, null, 2));
|
|
225
227
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@series-inc/stowkit-cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.21",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"stowkit": "./dist/cli.js"
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"dev": "tsc --watch"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@series-inc/stowkit-packer-gui": "^0.1.
|
|
20
|
+
"@series-inc/stowkit-packer-gui": "^0.1.21",
|
|
21
21
|
"@series-inc/stowkit-editor": "^0.1.8",
|
|
22
22
|
"draco3d": "^1.5.7",
|
|
23
23
|
"fbx-parser": "^2.1.3",
|
package/skill.md
CHANGED
|
@@ -68,6 +68,7 @@ All commands default to the current directory.
|
|
|
68
68
|
- `--verbose` / `-v` — Detailed output
|
|
69
69
|
- `--json` — Output store results as JSON (for programmatic/AI use)
|
|
70
70
|
- `--type <type>` — Filter store search by asset type (e.g. `staticMesh`, `texture`)
|
|
71
|
+
- `--limit <n>` — Max number of store search results to return
|
|
71
72
|
- `--port <number>` — Server port (default 3210)
|
|
72
73
|
- `--schema <name>` — Material schema template for `create-material` (default: `pbr`)
|
|
73
74
|
|
|
@@ -561,19 +562,34 @@ Then run `stowkit publish` from the packer GUI's Publish modal, or programmatica
|
|
|
561
562
|
|
|
562
563
|
**Version management:** Bump the `version` field in `assets-package.json` before each publish. Publishing the same version again requires `--force`.
|
|
563
564
|
|
|
564
|
-
### Searching the store (
|
|
565
|
+
### Searching the store (REST API — preferred for AI)
|
|
566
|
+
|
|
567
|
+
When the StowKit server is running, use the REST endpoints directly for clean JSON — no CLI parsing needed:
|
|
568
|
+
|
|
569
|
+
```
|
|
570
|
+
GET /api/asset-store/search?q=coral&limit=10 # Search assets, returns JSON array
|
|
571
|
+
GET /api/asset-store/search?q=ocean&type=texture # Filter by type
|
|
572
|
+
GET /api/asset-store/search?q=boss,idle&limit=5 # AND search (comma-separated)
|
|
573
|
+
GET /api/asset-store/packages # List all packages
|
|
574
|
+
GET /api/asset-store/package/<name> # Package details + all assets
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
All responses are JSON. Search results include `thumbnailUrl` for assets that have thumbnails.
|
|
578
|
+
|
|
579
|
+
### Searching the store (CLI fallback)
|
|
580
|
+
|
|
581
|
+
If the server isn't running, the CLI falls back to direct registry fetch:
|
|
565
582
|
|
|
566
583
|
```bash
|
|
567
584
|
stowkit store search coral # Find assets matching "coral"
|
|
568
585
|
stowkit store search "boss, idle" # AND search — both terms must match
|
|
569
586
|
stowkit store search ocean --type texture # Find textures tagged/named "ocean"
|
|
570
|
-
stowkit store search
|
|
587
|
+
stowkit store search sword --json --limit 10 # Top 10 results as JSON
|
|
571
588
|
stowkit store list # List all published packages
|
|
572
|
-
stowkit store info ninja-adventure # Show all assets in a package
|
|
573
589
|
stowkit store info ninja-adventure --json # Full package details as JSON
|
|
574
590
|
```
|
|
575
591
|
|
|
576
|
-
|
|
592
|
+
When the server IS running, CLI store commands automatically proxy through it and always output JSON.
|
|
577
593
|
|
|
578
594
|
### Search scoring algorithm
|
|
579
595
|
|
|
@@ -720,11 +736,11 @@ This is useful for verifying build output, checking which assets ended up in whi
|
|
|
720
736
|
- **Clean orphaned files:** `stowkit clean`
|
|
721
737
|
- **Set up with engine:** `stowkit init --with-engine` (installs `@series-inc/rundot-3d-engine` + `three`)
|
|
722
738
|
- **Update CLI + skill files:** `stowkit update`
|
|
723
|
-
- **Search the asset store:** `
|
|
724
|
-
- **AND search:** `
|
|
725
|
-
- **Find all meshes
|
|
726
|
-
- **List all
|
|
727
|
-
- **Get package details:** `
|
|
739
|
+
- **Search the asset store (REST):** `curl http://localhost:3210/api/asset-store/search?q=sword&limit=10` (returns JSON array with thumbnailUrls)
|
|
740
|
+
- **AND search (REST):** `curl "http://localhost:3210/api/asset-store/search?q=boss,idle&limit=10"` (both terms must match)
|
|
741
|
+
- **Find all meshes (REST):** `curl "http://localhost:3210/api/asset-store/search?q=mesh&type=staticMesh&limit=10"`
|
|
742
|
+
- **List all packages (REST):** `curl http://localhost:3210/api/asset-store/packages`
|
|
743
|
+
- **Get package details (REST):** `curl http://localhost:3210/api/asset-store/package/ocean_pack`
|
|
728
744
|
- **Show a thumbnail to the user:** Use the `thumbnailUrl` from search results — it's a public URL
|
|
729
745
|
- **Add a pack thumbnail:** Place `thumbnail.webp` (or `.png`/`.jpg`) in the project root before publishing
|
|
730
746
|
- **Publish a pack:** Open the packer GUI (`stowkit packer`), click Publish, fill in version/description/tags, and publish
|