@drawcall/market 0.1.31 → 0.1.33

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 (55) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +0 -2
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/search.d.ts +0 -1
  5. package/dist/commands/search.d.ts.map +1 -1
  6. package/dist/commands/search.js +1 -1
  7. package/dist/commands/search.js.map +1 -1
  8. package/dist/commands/upload.d.ts +1 -0
  9. package/dist/commands/upload.d.ts.map +1 -1
  10. package/dist/commands/upload.js +13 -4
  11. package/dist/commands/upload.js.map +1 -1
  12. package/dist/constants.d.ts +0 -2
  13. package/dist/constants.d.ts.map +1 -1
  14. package/dist/constants.js +0 -14
  15. package/dist/constants.js.map +1 -1
  16. package/dist/contract.d.ts +0 -4
  17. package/dist/contract.d.ts.map +1 -1
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/install.d.ts +1 -0
  23. package/dist/install.d.ts.map +1 -1
  24. package/dist/install.js +1 -0
  25. package/dist/install.js.map +1 -1
  26. package/dist/output.d.ts +1 -3
  27. package/dist/output.d.ts.map +1 -1
  28. package/dist/output.js +12 -13
  29. package/dist/output.js.map +1 -1
  30. package/dist/resolve.d.ts +1 -0
  31. package/dist/resolve.d.ts.map +1 -1
  32. package/dist/resolve.js +1 -0
  33. package/dist/resolve.js.map +1 -1
  34. package/dist/schemas.d.ts +3 -6
  35. package/dist/schemas.d.ts.map +1 -1
  36. package/dist/schemas.js +4 -3
  37. package/dist/schemas.js.map +1 -1
  38. package/dist/skill.d.ts +1 -1
  39. package/dist/skill.d.ts.map +1 -1
  40. package/dist/skill.js +2 -1
  41. package/dist/skill.js.map +1 -1
  42. package/package.json +1 -1
  43. package/src/cli.ts +0 -3
  44. package/src/commands/search.ts +1 -2
  45. package/src/commands/upload.ts +20 -4
  46. package/src/constants.ts +0 -15
  47. package/src/index.ts +1 -6
  48. package/src/install.ts +2 -0
  49. package/src/output.ts +13 -16
  50. package/src/resolve.ts +2 -0
  51. package/src/schemas.ts +5 -3
  52. package/src/skill.ts +2 -1
  53. package/tests/install-layout.test.ts +5 -1
  54. package/tests/output.test.ts +74 -5
  55. package/tests/upload-deps.test.ts +21 -2
package/dist/schemas.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- export declare const ASSET_TYPES: readonly ["model", "humanoid-model", "texture", "humanoid-animation", "template", "sound-effect", "background-music", "environment", "tutorial"];
2
+ export declare const ASSET_TYPES: readonly ["model", "humanoid-model", "texture", "humanoid-animation", "template", "sound-effect", "background-music", "environment"];
3
3
  export type AssetType = (typeof ASSET_TYPES)[number];
4
4
  export declare const assetTypeSchema: z.ZodEnum<{
5
5
  model: "model";
@@ -10,14 +10,15 @@ export declare const assetTypeSchema: z.ZodEnum<{
10
10
  "sound-effect": "sound-effect";
11
11
  "background-music": "background-music";
12
12
  environment: "environment";
13
- tutorial: "tutorial";
14
13
  }>;
15
14
  export declare const MAX_UPLOAD_ZIP_SIZE_BYTES: number;
15
+ export declare const MAX_ASSET_DESCRIPTION_LENGTH = 1000;
16
16
  export declare const semverSchema: z.ZodString;
17
17
  export declare const assetNameSchema: z.ZodString;
18
18
  export declare const npmDependenciesSchema: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
19
19
  export declare const assetDependenciesSchema: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
20
20
  export declare const skillDependenciesSchema: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
21
+ export declare const assetDescriptionSchema: z.ZodString;
21
22
  export declare const updateProfileSchema: z.ZodObject<{
22
23
  name: z.ZodOptional<z.ZodString>;
23
24
  image: z.ZodOptional<z.ZodString>;
@@ -34,7 +35,6 @@ export declare const listAssetsSchema: z.ZodObject<{
34
35
  "sound-effect": "sound-effect";
35
36
  "background-music": "background-music";
36
37
  environment: "environment";
37
- tutorial: "tutorial";
38
38
  }>>;
39
39
  query: z.ZodOptional<z.ZodString>;
40
40
  includeUnapproved: z.ZodDefault<z.ZodBoolean>;
@@ -55,7 +55,6 @@ export declare const exactAssetSchema: z.ZodObject<{
55
55
  "sound-effect": "sound-effect";
56
56
  "background-music": "background-music";
57
57
  environment: "environment";
58
- tutorial: "tutorial";
59
58
  }>>;
60
59
  includeUnapproved: z.ZodDefault<z.ZodBoolean>;
61
60
  }, z.core.$strip>;
@@ -70,7 +69,6 @@ export declare const uploadZipSchema: z.ZodObject<{
70
69
  "sound-effect": "sound-effect";
71
70
  "background-music": "background-music";
72
71
  environment: "environment";
73
- tutorial: "tutorial";
74
72
  }>;
75
73
  version: z.ZodString;
76
74
  description: z.ZodOptional<z.ZodString>;
@@ -94,7 +92,6 @@ export declare const generateAssetSchema: z.ZodObject<{
94
92
  "sound-effect": "sound-effect";
95
93
  "background-music": "background-music";
96
94
  environment: "environment";
97
- tutorial: "tutorial";
98
95
  }>>;
99
96
  }, z.core.$strip>;
100
97
  //# sourceMappingURL=schemas.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,WAAW,kJAUd,CAAA;AACV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAEpD,eAAO,MAAM,eAAe;;;;;;;;;;EAAsB,CAAA;AAElD,eAAO,MAAM,yBAAyB,QAAqB,CAAA;AAE3D,eAAO,MAAM,YAAY,aAKtB,CAAA;AAEH,eAAO,MAAM,eAAe,aAUxB,CAAA;AAEJ,eAAO,MAAM,qBAAqB,qDAA+C,CAAA;AAEjF,eAAO,MAAM,uBAAuB,qDAA+C,CAAA;AAKnF,eAAO,MAAM,uBAAuB,qDAA+C,CAAA;AAEnF,eAAO,MAAM,mBAAmB;;;iBAG9B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;iBAO3B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;iBAI3B,CAAA;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;iBAS1B,CAAA;AAEF,eAAO,MAAM,iBAAiB;;;iBAG5B,CAAA;AAEF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;iBAG9B,CAAA"}
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,WAAW,sIASd,CAAA;AACV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAEpD,eAAO,MAAM,eAAe;;;;;;;;;EAAsB,CAAA;AAElD,eAAO,MAAM,yBAAyB,QAAqB,CAAA;AAC3D,eAAO,MAAM,4BAA4B,OAAO,CAAA;AAEhD,eAAO,MAAM,YAAY,aAKtB,CAAA;AAEH,eAAO,MAAM,eAAe,aAUxB,CAAA;AAEJ,eAAO,MAAM,qBAAqB,qDAA+C,CAAA;AAEjF,eAAO,MAAM,uBAAuB,qDAA+C,CAAA;AAKnF,eAAO,MAAM,uBAAuB,qDAA+C,CAAA;AAEnF,eAAO,MAAM,sBAAsB,aAA+C,CAAA;AAElF,eAAO,MAAM,mBAAmB;;;iBAG9B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;iBAO3B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;iBAI3B,CAAA;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;iBAS1B,CAAA;AAEF,eAAO,MAAM,iBAAiB;;;iBAG5B,CAAA;AAEF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;iBAG9B,CAAA"}
package/dist/schemas.js CHANGED
@@ -8,10 +8,10 @@ export const ASSET_TYPES = [
8
8
  'sound-effect',
9
9
  'background-music',
10
10
  'environment',
11
- 'tutorial',
12
11
  ];
13
12
  export const assetTypeSchema = z.enum(ASSET_TYPES);
14
13
  export const MAX_UPLOAD_ZIP_SIZE_BYTES = 1024 * 1024 * 1024;
14
+ export const MAX_ASSET_DESCRIPTION_LENGTH = 1000;
15
15
  export const semverSchema = z
16
16
  .string()
17
17
  .regex(/^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?(\+[a-zA-Z0-9.]+)?$/, 'Must be a valid semver version (e.g. 1.0.0)');
@@ -29,6 +29,7 @@ export const assetDependenciesSchema = z.record(z.string(), z.string()).default(
29
29
  // git/HTTP URL, tree/<branch>/<subpath>) or a local path to a skill directory
30
30
  // shipped inside the asset.
31
31
  export const skillDependenciesSchema = z.record(z.string(), z.string()).default({});
32
+ export const assetDescriptionSchema = z.string().max(MAX_ASSET_DESCRIPTION_LENGTH);
32
33
  export const updateProfileSchema = z.object({
33
34
  name: z.string().min(1).max(100).optional(),
34
35
  image: z.string().url().optional(),
@@ -50,7 +51,7 @@ export const uploadZipSchema = z.object({
50
51
  name: assetNameSchema,
51
52
  type: assetTypeSchema,
52
53
  version: semverSchema,
53
- description: z.string().max(1000).optional(),
54
+ description: assetDescriptionSchema.optional(),
54
55
  npmDependencies: npmDependenciesSchema,
55
56
  assetDependencies: assetDependenciesSchema,
56
57
  skillDependencies: skillDependenciesSchema,
@@ -61,7 +62,7 @@ export const downloadZipSchema = z.object({
61
62
  version: semverSchema,
62
63
  });
63
64
  export const generateAssetSchema = z.object({
64
- description: z.string().min(3).max(1000),
65
+ description: assetDescriptionSchema.min(3),
65
66
  type: assetTypeSchema.optional(),
66
67
  });
67
68
  //# sourceMappingURL=schemas.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"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"}
package/dist/skill.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const marketSkill = "---\nname: market\ndescription: Find, preview, install, generate, and publish Drawcall Market assets from a coding agent.\n---\n\n# Drawcall Market\n\nUse the `market` CLI. Keep commands short and read the summary lines.\n\n## Quick Start\n\n```sh\nmarket search \"wooden chair\" --type model --limit 3\nmarket install wooden-chair --cwd \"$PWD\"\nmarket preview wooden-chair --out /tmp/wooden-chair.png\n```\n\n## Workflow\n\n1. Search first unless the user already gave an exact asset name. `search` requires `--type`; use `model` unless the user names another supported type: `humanoid-model`, `texture`, `humanoid-animation`, `template`, `sound-effect`, `background-music`, or `environment`.\n2. Use `--limit 1` for lookup, `--limit 3` for choice. Search caps at 5. Add `--verbose` only when the one-line descriptions are not enough.\n3. `install` takes one or more exact asset names (optionally `name@range`); it does not search or generate. Find names with `search` first. No `--type` is needed \u2014 asset names are unique.\n4. `preview <name>` saves the preview image; no `--type` is needed. Not every type has previews (e.g. `humanoid-animation`, `template`, `sound-effect`, `background-music`); the CLI reports when one is unavailable.\n5. Use `--unapproved` only when the user asks for unapproved/private/admin assets. Do not install unapproved assets without explicit acceptance.\n6. `generate --type <type> \"<prompt>\"` creates a new asset; it requires login and a type that supports generation. No asset type currently supports generation.\n7. Upload only when publishing is requested: `market upload <name> <zip> \"<description>\" --type <type>`. Declare dependencies with repeatable flags: `--npm name@range`, `--asset name@range`, `--skill label=source`. A skill source is a `skills add` argument: a whole repo (`owner/repo` or a git URL), a single skill via the full URL form `https://github.com/owner/repo/tree/<branch>/<subpath>` (the `tree/<branch>/<subpath>` shorthand needs the full URL, not `owner/repo`), or a local path to a skill directory inside the zip. Example: `market upload my-scene scene.zip \"A scene\" --type model --npm three@^0.178.0 --skill web-design=https://github.com/vercel-labs/agent-skills/tree/main/skills/web-design-guidelines`.\n8. Installed `environment` assets contain `public/environment/<name>.hdr` for Three.js IBL lighting and `public/environment/<name>-background.webp` for the visible equirectangular background. Use `market preview` to fetch the preview image separately.\n\n## Output\n\nCommands print concise, line-oriented summaries:\n\n```text\nResults: 2/8 query=\"wooden chair\" type=model approval=approved\n- wooden-chair@1.0.0 | model | approved | Low-poly wooden chair\nInstalled:\n- wooden-chair@1.0.0 (asset)\n files:\n public/model\n \u2514\u2500 wooden-chair.glb\n- three@^0.178.0 (npm)\n- web-design \u2190 https://github.com/vercel-labs/agent-skills/tree/main/skills/web-design-guidelines (skill)\nSaved preview for wooden-chair@1.0.0: /tmp/wooden-chair.png\n```\n\nAssets may also declare `skill` dependencies, installed for you via the `skills` CLI (`skills add`) during `install`. Sources are either a GitHub/git ref or a local path to a skill directory shipped inside the asset. This requires `npx` to be available.\n\nIf search returns no results, try one broader noun phrase. If a command returns `Error: Not logged in...`, ask before running `market login`.\n";
1
+ export declare const marketSkill = "---\nname: market\ndescription: Find, preview, install, generate, and publish Drawcall Market assets from a coding agent.\n---\n\n# Drawcall Market\n\nUse the `market` CLI. Keep commands short and read the summary lines.\n\n## Quick Start\n\n```sh\nmarket search \"wooden chair\" --type model --limit 3\nmarket install wooden-chair --cwd \"$PWD\"\nmarket preview wooden-chair --out /tmp/wooden-chair.png\n```\n\n## Workflow\n\n1. Search first unless the user already gave an exact asset name. `search` requires `--type`; use `model` unless the user names another supported type: `humanoid-model`, `texture`, `humanoid-animation`, `template`, `sound-effect`, `background-music`, or `environment`.\n2. Use `--limit 1` for lookup, `--limit 3` for choice. Search caps at 5 and prints full descriptions.\n3. `install` takes one or more exact asset names (optionally `name@range`); it does not search or generate. Find names with `search` first. No `--type` is needed \u2014 asset names are unique.\n4. `preview <name>` saves the preview image; no `--type` is needed. Not every type has previews (e.g. `humanoid-animation`, `template`, `sound-effect`, `background-music`); the CLI reports when one is unavailable.\n5. Use `--unapproved` only when the user asks for unapproved/private/admin assets. Do not install unapproved assets without explicit acceptance.\n6. `generate --type <type> \"<prompt>\"` creates a new asset; it requires login and a type that supports generation. No asset type currently supports generation.\n7. Upload only when publishing is requested: `market upload <name> <zip> \"<description>\" --type <type>`. Declare dependencies with repeatable flags: `--npm name@range`, `--asset name@range`, `--skill label=source`. A skill source is a `skills add` argument: a whole repo (`owner/repo` or a git URL), a single skill via the full URL form `https://github.com/owner/repo/tree/<branch>/<subpath>` (the `tree/<branch>/<subpath>` shorthand needs the full URL, not `owner/repo`), or a local path to a skill directory inside the zip. Example: `market upload my-scene scene.zip \"A scene\" --type model --npm three@^0.178.0 --skill web-design=https://github.com/vercel-labs/agent-skills/tree/main/skills/web-design-guidelines`.\n8. Installed `environment` assets contain `public/environment/<name>.hdr` for Three.js IBL lighting and `public/environment/<name>-background.webp` for the visible equirectangular background. Use `market preview` to fetch the preview image separately.\n\n## Output\n\nCommands print concise, line-oriented summaries:\n\n```text\nResults: 2/8 query=\"wooden chair\" type=model approval=approved\n- wooden-chair@1.0.0 | model | approved | Low-poly wooden chair\nInstalled:\n- wooden-chair@1.0.0 (asset)\n description: Low-poly wooden chair\n files:\n public/model\n \u2514\u2500 wooden-chair.glb\n- three@^0.178.0 (npm)\n- web-design \u2190 https://github.com/vercel-labs/agent-skills/tree/main/skills/web-design-guidelines (skill)\nSaved preview for wooden-chair@1.0.0: /tmp/wooden-chair.png\n```\n\nAssets may also declare `skill` dependencies, installed for you via the `skills` CLI (`skills add`) during `install`. Sources are either a GitHub/git ref or a local path to a skill directory shipped inside the asset. This requires `npx` to be available.\n\nIf search returns no results, try one broader noun phrase. If a command returns `Error: Not logged in...`, ask before running `market login`.\n";
2
2
  //# sourceMappingURL=skill.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,63GAgDvB,CAAA"}
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,43GAiDvB,CAAA"}
package/dist/skill.js CHANGED
@@ -18,7 +18,7 @@ market preview wooden-chair --out /tmp/wooden-chair.png
18
18
  ## Workflow
19
19
 
20
20
  1. Search first unless the user already gave an exact asset name. \`search\` requires \`--type\`; use \`model\` unless the user names another supported type: \`humanoid-model\`, \`texture\`, \`humanoid-animation\`, \`template\`, \`sound-effect\`, \`background-music\`, or \`environment\`.
21
- 2. Use \`--limit 1\` for lookup, \`--limit 3\` for choice. Search caps at 5. Add \`--verbose\` only when the one-line descriptions are not enough.
21
+ 2. Use \`--limit 1\` for lookup, \`--limit 3\` for choice. Search caps at 5 and prints full descriptions.
22
22
  3. \`install\` takes one or more exact asset names (optionally \`name@range\`); it does not search or generate. Find names with \`search\` first. No \`--type\` is needed — asset names are unique.
23
23
  4. \`preview <name>\` saves the preview image; no \`--type\` is needed. Not every type has previews (e.g. \`humanoid-animation\`, \`template\`, \`sound-effect\`, \`background-music\`); the CLI reports when one is unavailable.
24
24
  5. Use \`--unapproved\` only when the user asks for unapproved/private/admin assets. Do not install unapproved assets without explicit acceptance.
@@ -35,6 +35,7 @@ Results: 2/8 query="wooden chair" type=model approval=approved
35
35
  - wooden-chair@1.0.0 | model | approved | Low-poly wooden chair
36
36
  Installed:
37
37
  - wooden-chair@1.0.0 (asset)
38
+ description: Low-poly wooden chair
38
39
  files:
39
40
  public/model
40
41
  └─ wooden-chair.glb
package/dist/skill.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgD1B,CAAA"}
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiD1B,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawcall/market",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/drawcall-ai/market",
package/src/cli.ts CHANGED
@@ -96,7 +96,6 @@ program
96
96
  .addOption(apiOption)
97
97
  .option('--unapproved', 'Include unapproved versions', false)
98
98
  .option('--limit <n>', 'Max results, 1-5', parseSearchLimit, 5)
99
- .option('--verbose', 'Show longer descriptions', false)
100
99
  .action(
101
100
  async (
102
101
  query: string,
@@ -105,7 +104,6 @@ program
105
104
  api?: string
106
105
  unapproved: boolean
107
106
  limit: number
108
- verbose: boolean
109
107
  },
110
108
  ) => {
111
109
  requireType(opts.type, 'Search')
@@ -114,7 +112,6 @@ program
114
112
  baseUrl: opts.api,
115
113
  unapproved: opts.unapproved,
116
114
  limit: opts.limit,
117
- verbose: opts.verbose,
118
115
  })
119
116
  },
120
117
  )
@@ -10,7 +10,6 @@ export interface SearchCommandOptions {
10
10
  unapproved?: boolean
11
11
  baseUrl?: string
12
12
  limit?: number
13
- verbose?: boolean
14
13
  }
15
14
 
16
15
  export async function searchCommand(query: string, opts: SearchCommandOptions): Promise<void> {
@@ -52,6 +51,6 @@ export async function searchCommand(query: string, opts: SearchCommandOptions):
52
51
  }
53
52
 
54
53
  for (const item of results.items) {
55
- console.log(assetSearchResultLine(item, { verbose: opts.verbose ?? false }))
54
+ console.log(assetSearchResultLine(item))
56
55
  }
57
56
  }
@@ -3,9 +3,14 @@ import * as path from 'path'
3
3
  import ora from 'ora'
4
4
  import semver from 'semver'
5
5
  import { getCliClient } from '../cli-client.js'
6
- import { MAX_UPLOAD_ZIP_SIZE_BYTES } from '../schemas.js'
6
+ import { MAX_ASSET_DESCRIPTION_LENGTH, MAX_UPLOAD_ZIP_SIZE_BYTES } from '../schemas.js'
7
7
  import { unchangedUploadResult, uploadResult } from '../output.js'
8
- import { assetNameSchema, semverSchema, type AssetType } from '../schemas.js'
8
+ import {
9
+ assetDescriptionSchema,
10
+ assetNameSchema,
11
+ semverSchema,
12
+ type AssetType,
13
+ } from '../schemas.js'
9
14
 
10
15
  export interface UploadCommandOptions {
11
16
  type: AssetType
@@ -35,6 +40,7 @@ export async function uploadCommand(
35
40
  try {
36
41
  const parsedName = assetNameSchema.parse(name)
37
42
  const parsedVersion = opts.version ? semverSchema.parse(opts.version) : undefined
43
+ const parsedDescription = parseUploadDescription(description)
38
44
  // Parse dep flags before any network work so a malformed spec fails fast.
39
45
  const npmDependencies = parseVersionedDeps(opts.npm ?? [], 'npm')
40
46
  const assetDependencies = parseVersionedDeps(opts.asset ?? [], 'asset')
@@ -69,7 +75,7 @@ export async function uploadCommand(
69
75
  })
70
76
  const latestBytes = new Uint8Array(await latestZip.arrayBuffer())
71
77
  if (
72
- existing.description === description &&
78
+ existing.description === parsedDescription &&
73
79
  depsEqual(existing.npmDependencies, npmDependencies) &&
74
80
  depsEqual(existing.assetDependencies, assetDependencies) &&
75
81
  depsEqual(existing.skillDependencies, skillDependencies) &&
@@ -87,7 +93,7 @@ export async function uploadCommand(
87
93
  name: parsedName,
88
94
  type,
89
95
  version,
90
- description,
96
+ description: parsedDescription,
91
97
  npmDependencies,
92
98
  assetDependencies,
93
99
  skillDependencies,
@@ -105,6 +111,16 @@ export async function uploadCommand(
105
111
  }
106
112
  }
107
113
 
114
+ export function parseUploadDescription(description: string): string {
115
+ try {
116
+ return assetDescriptionSchema.parse(description)
117
+ } catch {
118
+ throw new Error(
119
+ `Asset description must be ${MAX_ASSET_DESCRIPTION_LENGTH} characters or fewer.`,
120
+ )
121
+ }
122
+ }
123
+
108
124
  /**
109
125
  * Parse `name@range` specs (npm or asset deps) into a name→range record. The
110
126
  * range is optional and defaults to `*`. A leading `@` is treated as a scope
package/src/constants.ts CHANGED
@@ -11,7 +11,6 @@ export const ALLOWED_EXTENSIONS: Record<AssetType, string[]> = {
11
11
  'sound-effect': ['.zip'],
12
12
  'background-music': ['.zip'],
13
13
  environment: ['.zip'],
14
- tutorial: ['.zip'],
15
14
  }
16
15
 
17
16
  export const ASSET_TYPE_LABELS: Record<AssetType, string> = {
@@ -23,18 +22,4 @@ export const ASSET_TYPE_LABELS: Record<AssetType, string> = {
23
22
  'sound-effect': 'Sound Effect',
24
23
  'background-music': 'Background Music',
25
24
  environment: 'Environment',
26
- tutorial: 'Tutorial',
27
- }
28
-
29
- /** Human-facing category each asset type belongs to, for browsing the market. */
30
- export const ASSET_TYPE_CATEGORIES: Record<AssetType, string> = {
31
- model: 'Models',
32
- 'humanoid-model': 'Models',
33
- 'humanoid-animation': 'Animations',
34
- texture: 'Materials',
35
- environment: 'Environments',
36
- 'sound-effect': 'Audio',
37
- 'background-music': 'Audio',
38
- template: 'Templates',
39
- tutorial: 'Tutorials',
40
25
  }
package/src/index.ts CHANGED
@@ -54,9 +54,4 @@ export {
54
54
  export type { AssetType } from './schemas.js'
55
55
 
56
56
  // Constants
57
- export {
58
- MAX_FILE_SIZE,
59
- ALLOWED_EXTENSIONS,
60
- ASSET_TYPE_LABELS,
61
- ASSET_TYPE_CATEGORIES,
62
- } from './constants.js'
57
+ export { MAX_FILE_SIZE, ALLOWED_EXTENSIONS, ASSET_TYPE_LABELS } from './constants.js'
package/src/install.ts CHANGED
@@ -42,6 +42,7 @@ export interface InstalledAsset {
42
42
  name: string
43
43
  type: string
44
44
  version: string
45
+ description: string | null
45
46
  files: string[]
46
47
  }
47
48
 
@@ -139,6 +140,7 @@ async function downloadAssets(
139
140
  name: asset.name,
140
141
  type: asset.type,
141
142
  version: asset.version,
143
+ description: asset.description,
142
144
  files: installedFiles,
143
145
  })
144
146
 
package/src/output.ts CHANGED
@@ -24,13 +24,8 @@ export function searchSummary(input: {
24
24
  return `Results: ${input.count}/${input.total} ${scope}`
25
25
  }
26
26
 
27
- export function assetSearchResultLine(
28
- item: AssetSearchResult,
29
- opts: { verbose?: boolean } = {},
30
- ): string {
31
- const description = item.description
32
- ? ` | ${compact(item.description, opts.verbose ? 160 : 80)}`
33
- : ''
27
+ export function assetSearchResultLine(item: AssetSearchResult): string {
28
+ const description = item.description ? ` | ${normalizeInline(item.description)}` : ''
34
29
  return `- ${assetVersionRef(item.name, item.latestVersion)} | ${item.type} | ${assetApproval(
35
30
  item.approved,
36
31
  )}${description}`
@@ -47,12 +42,15 @@ export function installResult(
47
42
  for (const asset of result.assets) {
48
43
  const files = unique(asset.files)
49
44
  lines.push(`- ${assetVersionRef(asset.name, asset.version)} (${asset.type})`)
45
+ if (asset.description) {
46
+ lines.push(...block(' description: ', asset.description))
47
+ }
50
48
  if (files.length > 0) {
51
49
  lines.push(' files:', ...indent(fileTree(files), ' '))
52
50
  }
53
51
  const message = postInstallMessages[asset.type]
54
52
  if (message) {
55
- lines.push(...note(message))
53
+ lines.push(...block(' note: ', message))
56
54
  }
57
55
  }
58
56
 
@@ -76,14 +74,9 @@ export function installResult(
76
74
  return lines.join('\n')
77
75
  }
78
76
 
79
- /**
80
- * Render an asset's post-install message as a `note:` block, word-wrapped with a
81
- * hanging indent so continuation lines align under the message text.
82
- */
83
- function note(message: string, width = 68): string[] {
84
- const label = ' note: '
77
+ function block(label: string, message: string, width = 68): string[] {
85
78
  const hang = ' '.repeat(label.length)
86
- const words = message.split(/\s+/).filter(Boolean)
79
+ const words = normalizeInline(message).split(' ').filter(Boolean)
87
80
 
88
81
  const wrapped: string[] = []
89
82
  let line = ''
@@ -129,10 +122,14 @@ export function errorResult(message: string): string {
129
122
  }
130
123
 
131
124
  export function compact(value: string, max = 96): string {
132
- const normalized = value.replace(/\s+/g, ' ').trim()
125
+ const normalized = normalizeInline(value)
133
126
  return normalized.length > max ? normalized.slice(0, max - 3) + '...' : normalized
134
127
  }
135
128
 
129
+ function normalizeInline(value: string): string {
130
+ return value.replace(/\s+/g, ' ').trim()
131
+ }
132
+
136
133
  interface FileTreeNode {
137
134
  children: Map<string, FileTreeNode>
138
135
  }
package/src/resolve.ts CHANGED
@@ -17,6 +17,7 @@ export interface ResolvedAsset {
17
17
  name: string
18
18
  type: string
19
19
  version: string
20
+ description: string | null
20
21
  npmDependencies: Record<string, string>
21
22
  assetDependencies: Record<string, string>
22
23
  skillDependencies: Record<string, string>
@@ -88,6 +89,7 @@ export async function resolve(
88
89
  name: assetName,
89
90
  type: meta.type,
90
91
  version: meta.latestVersion,
92
+ description: meta.description,
91
93
  npmDependencies: npmDeps,
92
94
  assetDependencies: assetDeps,
93
95
  skillDependencies: skillDeps,
package/src/schemas.ts CHANGED
@@ -9,13 +9,13 @@ export const ASSET_TYPES = [
9
9
  'sound-effect',
10
10
  'background-music',
11
11
  'environment',
12
- 'tutorial',
13
12
  ] as const
14
13
  export type AssetType = (typeof ASSET_TYPES)[number]
15
14
 
16
15
  export const assetTypeSchema = z.enum(ASSET_TYPES)
17
16
 
18
17
  export const MAX_UPLOAD_ZIP_SIZE_BYTES = 1024 * 1024 * 1024
18
+ export const MAX_ASSET_DESCRIPTION_LENGTH = 1000
19
19
 
20
20
  export const semverSchema = z
21
21
  .string()
@@ -45,6 +45,8 @@ export const assetDependenciesSchema = z.record(z.string(), z.string()).default(
45
45
  // shipped inside the asset.
46
46
  export const skillDependenciesSchema = z.record(z.string(), z.string()).default({})
47
47
 
48
+ export const assetDescriptionSchema = z.string().max(MAX_ASSET_DESCRIPTION_LENGTH)
49
+
48
50
  export const updateProfileSchema = z.object({
49
51
  name: z.string().min(1).max(100).optional(),
50
52
  image: z.string().url().optional(),
@@ -69,7 +71,7 @@ export const uploadZipSchema = z.object({
69
71
  name: assetNameSchema,
70
72
  type: assetTypeSchema,
71
73
  version: semverSchema,
72
- description: z.string().max(1000).optional(),
74
+ description: assetDescriptionSchema.optional(),
73
75
  npmDependencies: npmDependenciesSchema,
74
76
  assetDependencies: assetDependenciesSchema,
75
77
  skillDependencies: skillDependenciesSchema,
@@ -82,6 +84,6 @@ export const downloadZipSchema = z.object({
82
84
  })
83
85
 
84
86
  export const generateAssetSchema = z.object({
85
- description: z.string().min(3).max(1000),
87
+ description: assetDescriptionSchema.min(3),
86
88
  type: assetTypeSchema.optional(),
87
89
  })
package/src/skill.ts CHANGED
@@ -18,7 +18,7 @@ market preview wooden-chair --out /tmp/wooden-chair.png
18
18
  ## Workflow
19
19
 
20
20
  1. Search first unless the user already gave an exact asset name. \`search\` requires \`--type\`; use \`model\` unless the user names another supported type: \`humanoid-model\`, \`texture\`, \`humanoid-animation\`, \`template\`, \`sound-effect\`, \`background-music\`, or \`environment\`.
21
- 2. Use \`--limit 1\` for lookup, \`--limit 3\` for choice. Search caps at 5. Add \`--verbose\` only when the one-line descriptions are not enough.
21
+ 2. Use \`--limit 1\` for lookup, \`--limit 3\` for choice. Search caps at 5 and prints full descriptions.
22
22
  3. \`install\` takes one or more exact asset names (optionally \`name@range\`); it does not search or generate. Find names with \`search\` first. No \`--type\` is needed — asset names are unique.
23
23
  4. \`preview <name>\` saves the preview image; no \`--type\` is needed. Not every type has previews (e.g. \`humanoid-animation\`, \`template\`, \`sound-effect\`, \`background-music\`); the CLI reports when one is unavailable.
24
24
  5. Use \`--unapproved\` only when the user asks for unapproved/private/admin assets. Do not install unapproved assets without explicit acceptance.
@@ -35,6 +35,7 @@ Results: 2/8 query="wooden chair" type=model approval=approved
35
35
  - wooden-chair@1.0.0 | model | approved | Low-poly wooden chair
36
36
  Installed:
37
37
  - wooden-chair@1.0.0 (asset)
38
+ description: Low-poly wooden chair
38
39
  files:
39
40
  public/model
40
41
  └─ wooden-chair.glb
@@ -29,6 +29,7 @@ test('install writes zip files into the package root', async () => {
29
29
  name: 'idle-loop',
30
30
  type: 'humanoid-animation',
31
31
  version: '1.0.0',
32
+ description: 'Idle loop animation',
32
33
  npmDependencies: {},
33
34
  assetDependencies: {},
34
35
  skillDependencies: {},
@@ -46,6 +47,7 @@ test('install writes zip files into the package root', async () => {
46
47
  name: 'idle-loop',
47
48
  type: 'humanoid-animation',
48
49
  version: '1.0.0',
50
+ description: 'Idle loop animation',
49
51
  files: ['public/humanoid-animation/idle-loop.glb', 'src/generated/idle-loop.ts'],
50
52
  },
51
53
  ],
@@ -77,8 +79,9 @@ test('install rejects zip paths that escape through parent segments', async () =
77
79
  assets: [
78
80
  {
79
81
  name: 'bad-path',
80
- type: 'template',
82
+ type: 'template',
81
83
  version: '1.0.0',
84
+ description: null,
82
85
  npmDependencies: {},
83
86
  assetDependencies: {},
84
87
  skillDependencies: {},
@@ -112,6 +115,7 @@ test('install runs the skills runner per dependency, resolving local paths again
112
115
  name: 'with-skills',
113
116
  type: 'template',
114
117
  version: '1.0.0',
118
+ description: null,
115
119
  npmDependencies: {},
116
120
  assetDependencies: {},
117
121
  skillDependencies: {},
@@ -1,6 +1,30 @@
1
1
  import assert from 'node:assert/strict'
2
2
  import test from 'node:test'
3
- import { installResult } from '../src/output.js'
3
+ import { assetSearchResultLine, installResult } from '../src/output.js'
4
+
5
+ test('assetSearchResultLine prints the full description', () => {
6
+ const description =
7
+ 'A detailed model description that is intentionally longer than the old one-line search cap, with material notes, scale guidance, and usage context.'
8
+
9
+ assert.equal(
10
+ assetSearchResultLine({
11
+ id: 'asset-1',
12
+ name: 'wooden-chair',
13
+ type: 'model',
14
+ description,
15
+ ownerId: 'user-1',
16
+ createdAt: new Date('2026-01-01T00:00:00.000Z'),
17
+ updatedAt: new Date('2026-01-01T00:00:00.000Z'),
18
+ latestVersion: '1.2.0',
19
+ approved: true,
20
+ npmDependencies: '{}',
21
+ assetDependencies: '{}',
22
+ skillDependencies: '{}',
23
+ previewUrl: null,
24
+ }),
25
+ `- wooden-chair@1.2.0 | model | approved | ${description}`,
26
+ )
27
+ })
4
28
 
5
29
  test('installResult prints asset type, file tree, and npm list', () => {
6
30
  assert.equal(
@@ -10,12 +34,14 @@ test('installResult prints asset type, file tree, and npm list', () => {
10
34
  name: 'wooden-chair',
11
35
  type: 'model',
12
36
  version: '1.2.0',
37
+ description: null,
13
38
  files: ['public/models/wooden-chair.glb'],
14
39
  },
15
40
  {
16
41
  name: 'oak-material',
17
42
  type: 'texture',
18
43
  version: '1.0.0',
44
+ description: null,
19
45
  files: ['public/textures/oak/basecolor.png', 'public/textures/oak/normal.png'],
20
46
  },
21
47
  ],
@@ -44,8 +70,20 @@ test('installResult attaches each post-install note under its asset', () => {
44
70
  installResult(
45
71
  {
46
72
  assets: [
47
- { name: 'wooden-chair', type: 'model', version: '1.2.0', files: [] },
48
- { name: 'beep', type: 'sound-effect', version: '1.0.0', files: [] },
73
+ {
74
+ name: 'wooden-chair',
75
+ type: 'model',
76
+ version: '1.2.0',
77
+ description: null,
78
+ files: [],
79
+ },
80
+ {
81
+ name: 'beep',
82
+ type: 'sound-effect',
83
+ version: '1.0.0',
84
+ description: null,
85
+ files: [],
86
+ },
49
87
  ],
50
88
  npmDependencies: {},
51
89
  skillDependencies: {},
@@ -66,7 +104,7 @@ test('installResult word-wraps a long note with a hanging indent', () => {
66
104
  const message = Array(20).fill('word').join(' ')
67
105
  const output = installResult(
68
106
  {
69
- assets: [{ name: 'thing', type: 'model', version: '1.0.0', files: [] }],
107
+ assets: [{ name: 'thing', type: 'model', version: '1.0.0', description: null, files: [] }],
70
108
  npmDependencies: {},
71
109
  skillDependencies: {},
72
110
  },
@@ -85,7 +123,15 @@ test('installResult word-wraps a long note with a hanging indent', () => {
85
123
  test('installResult lists installed skills with their source', () => {
86
124
  assert.equal(
87
125
  installResult({
88
- assets: [{ name: 'wooden-chair', type: 'model', version: '1.2.0', files: [] }],
126
+ assets: [
127
+ {
128
+ name: 'wooden-chair',
129
+ type: 'model',
130
+ version: '1.2.0',
131
+ description: null,
132
+ files: [],
133
+ },
134
+ ],
89
135
  npmDependencies: {},
90
136
  skillDependencies: {
91
137
  'web-design-guidelines': 'vercel-labs/agent-skills/tree/main/skills/web-design-guidelines',
@@ -98,3 +144,26 @@ test('installResult lists installed skills with their source', () => {
98
144
  - web-design-guidelines ← vercel-labs/agent-skills/tree/main/skills/web-design-guidelines (skill)`,
99
145
  )
100
146
  })
147
+
148
+ test('installResult shows each installed asset description', () => {
149
+ assert.equal(
150
+ installResult({
151
+ assets: [
152
+ {
153
+ name: 'wooden-chair',
154
+ type: 'model',
155
+ version: '1.2.0',
156
+ description:
157
+ 'A game-ready chair with baked texture detail and clean origin placement for room scenes.',
158
+ files: [],
159
+ },
160
+ ],
161
+ npmDependencies: {},
162
+ skillDependencies: {},
163
+ }),
164
+ `Installed:
165
+ - wooden-chair@1.2.0 (model)
166
+ description: A game-ready chair with baked texture detail and clean origin
167
+ placement for room scenes.`,
168
+ )
169
+ })