@drawcall/market 0.1.53 → 0.1.55

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 (47) hide show
  1. package/dist/commands/list.js +1 -1
  2. package/dist/commands/list.js.map +1 -1
  3. package/dist/commands/pack.d.ts +1 -0
  4. package/dist/commands/pack.d.ts.map +1 -1
  5. package/dist/commands/pack.js +5 -0
  6. package/dist/commands/pack.js.map +1 -1
  7. package/dist/commands/upload.d.ts.map +1 -1
  8. package/dist/commands/upload.js +1 -0
  9. package/dist/commands/upload.js.map +1 -1
  10. package/dist/contract.d.ts +5 -0
  11. package/dist/contract.d.ts.map +1 -1
  12. package/dist/contract.js +6 -1
  13. package/dist/contract.js.map +1 -1
  14. package/dist/index.d.ts +2 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +1 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/install.d.ts.map +1 -1
  19. package/dist/install.js +2 -5
  20. package/dist/install.js.map +1 -1
  21. package/dist/market-lock.d.ts +2 -3
  22. package/dist/market-lock.d.ts.map +1 -1
  23. package/dist/market-lock.js +7 -3
  24. package/dist/market-lock.js.map +1 -1
  25. package/dist/pack.d.ts +7 -0
  26. package/dist/pack.d.ts.map +1 -1
  27. package/dist/pack.js +41 -31
  28. package/dist/pack.js.map +1 -1
  29. package/dist/schemas.d.ts +10 -0
  30. package/dist/schemas.d.ts.map +1 -1
  31. package/dist/schemas.js +4 -0
  32. package/dist/schemas.js.map +1 -1
  33. package/dist/skill.d.ts +1 -1
  34. package/dist/skill.d.ts.map +1 -1
  35. package/dist/skill.js +2 -2
  36. package/package.json +1 -1
  37. package/skills/market/SKILL.md +2 -2
  38. package/src/commands/list.ts +1 -1
  39. package/src/commands/pack.ts +6 -0
  40. package/src/commands/upload.ts +1 -0
  41. package/src/contract.ts +8 -0
  42. package/src/index.ts +2 -0
  43. package/src/install.ts +11 -20
  44. package/src/market-lock.ts +10 -7
  45. package/src/pack.ts +56 -30
  46. package/src/schemas.ts +12 -0
  47. package/src/skill.ts +2 -2
package/dist/schemas.d.ts CHANGED
@@ -94,6 +94,16 @@ export declare const downloadZipSchema: z.ZodObject<{
94
94
  name: z.ZodString;
95
95
  version: z.ZodString;
96
96
  }, z.core.$strip>;
97
+ export declare const fileManifestSchema: z.ZodObject<{
98
+ name: z.ZodString;
99
+ version: z.ZodString;
100
+ }, z.core.$strip>;
101
+ /**
102
+ * The content hash of every file in an asset version, keyed by its install path — sha256 hex, the
103
+ * same digest the CLI computes locally. Lets a caller check whether a local file is identical to the
104
+ * canonical asset without keeping hashes itself (see `pack` omit-unchanged).
105
+ */
106
+ export type AssetFileManifest = Record<string, string>;
97
107
  export declare const generateAssetSchema: z.ZodObject<{
98
108
  description: z.ZodString;
99
109
  type: z.ZodOptional<z.ZodEnum<{
@@ -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;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;AAKlF,eAAO,MAAM,iBAAiB;;;EAAgC,CAAA;AAC9D,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAE3D,eAAO,MAAM,mBAAmB;;;iBAG9B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;iBAO3B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;iBAI3B,CAAA;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;iBAY1B,CAAA;AAEF,eAAO,MAAM,iBAAiB;;;iBAG5B,CAAA;AAEF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;iBAK9B,CAAA;AAGF,eAAO,MAAM,oBAAoB;;;iBAG/B,CAAA;AAKF,eAAO,MAAM,sBAAsB;;;;;;;6BAGjC,CAAA;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAErE,eAAO,MAAM,yBAAyB;;iBAEpC,CAAA;AAIF,eAAO,MAAM,uBAAuB;;;;;;;;;6BAIlC,CAAA;AACF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAKvE,eAAO,MAAM,gBAAgB;;;iBAG3B,CAAA;AAEF,eAAO,MAAM,iBAAiB;;iBAE5B,CAAA;AAIF,eAAO,MAAM,sBAAsB;;;;iBAIjC,CAAA;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAKrE,eAAO,MAAM,iBAAiB;;;;;;;iBAG5B,CAAA;AACF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAK3D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;6BAI/B,CAAA;AACF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,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,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;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;AAKlF,eAAO,MAAM,iBAAiB;;;EAAgC,CAAA;AAC9D,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAE3D,eAAO,MAAM,mBAAmB;;;iBAG9B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;iBAO3B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;iBAI3B,CAAA;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;iBAY1B,CAAA;AAEF,eAAO,MAAM,iBAAiB;;;iBAG5B,CAAA;AAEF,eAAO,MAAM,kBAAkB;;;iBAG7B,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEtD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;iBAK9B,CAAA;AAGF,eAAO,MAAM,oBAAoB;;;iBAG/B,CAAA;AAKF,eAAO,MAAM,sBAAsB;;;;;;;6BAGjC,CAAA;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAErE,eAAO,MAAM,yBAAyB;;iBAEpC,CAAA;AAIF,eAAO,MAAM,uBAAuB;;;;;;;;;6BAIlC,CAAA;AACF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAKvE,eAAO,MAAM,gBAAgB;;;iBAG3B,CAAA;AAEF,eAAO,MAAM,iBAAiB;;iBAE5B,CAAA;AAIF,eAAO,MAAM,sBAAsB;;;;iBAIjC,CAAA;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAKrE,eAAO,MAAM,iBAAiB;;;;;;;iBAG5B,CAAA;AACF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAK3D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;6BAI/B,CAAA;AACF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA"}
package/dist/schemas.js CHANGED
@@ -69,6 +69,10 @@ export const downloadZipSchema = z.object({
69
69
  name: assetNameSchema,
70
70
  version: semverSchema,
71
71
  });
72
+ export const fileManifestSchema = z.object({
73
+ name: assetNameSchema,
74
+ version: semverSchema,
75
+ });
72
76
  export const generateAssetSchema = z.object({
73
77
  description: assetDescriptionSchema.min(3),
74
78
  type: assetTypeSchema.optional(),
@@ -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 list --cwd \"$PWD\"\nmarket preview wooden-chair --out /tmp/wooden-chair.png\nmarket pack scene.zip --out scene.packed.zip\n```\n\n## Workflow\n\n1. In an existing repo, run `list --cwd \"$PWD\"` first to see installed local assets from `.drawcall/market-lock.json`. Use the listed names with `preview <name>` when you want preview images.\n2. 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`, `environment`, or `flipbook`.\n3. Use `--limit 1` for lookup, `--limit 3` for choice. Search caps at 5 and prints full descriptions.\n4. `install` takes zero or more exact asset names (optionally `name@range`). With names, it installs those assets; with no names, it installs `assetDependencies` from the nearest `package.json`. It does not search or generate. Find names with `search` first. No `--type` is needed \u2014 asset names are unique. Use `--force` only when the user agrees to overwrite changed local files.\n5. `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.\n6. Use `--unapproved` only when the user asks for unapproved/private/admin assets. Do not install unapproved assets without explicit acceptance.\n7. `generate --type <type> \"<prompt>\"` creates and installs a generated asset when that asset type has a generator; it requires login. Currently supported generated types are `sound-effect`, `background-music`, `flipbook`, `humanoid-model`, and `environment` (a fitting HDRI sky + equirectangular background, generated in ~1-2 min). Generation is provider-specific: prompt style, generated files, indexing fields, and install layout are owned by the asset type. If a type does not support generation yet, the CLI reports unsupported generation. Add `--access public` to publish the generated asset publicly, or `--access private` to keep it owner-only; when omitted the server defaults to private if you hold the `market:private` entitlement, else public (`--access private` requires that entitlement). `generate` waits for the asset and installs it \u2014 one command for quick types. For a long one (e.g. `humanoid-model`, >2 min) the call returns after ~2 min with a job id instead of hanging your shell; run `market generate install <jobId>` to continue \u2014 it resumes the SAME job where the last call left off and installs when ready. Just re-run `generate install <jobId>` until it prints \"Generated and installed\" (it exits 0 while still generating, 1 on failure). No type is flagged \"slow\" \u2014 anything that outlasts one wait just continues on the next call.\n8. Use `pack <zip>` to create the same Market asset zip that `upload` sends. `pack` runs offline, infers template packing from a root `package.json`, and accepts `--type` only when you need to override that inference. `upload` runs the shared pack step internally, then publishes: `market upload <name> <zip> \"<description>\" --type <type>`. Declare dependencies with repeatable flags on either command: `--npm name@range`, `--asset name@range`, `--skill label=source`. Template pack/upload also reads root `package.json.assetDependencies`; `--asset` flags are additive and must not conflict. Template pack/upload omits installed dependency files whose hashes still match `.drawcall/market-lock.json`, so edited local files stay in the template. 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`.\n9. 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.\n10. Installed `flipbook` assets contain `public/flipbook/<name>.ktx2`. Render them with `@drawcall/flipbook`'s `Flipbook` class and Three.js `KTX2Loader` for Basis-compressed files; `market preview` fetches the middle frame from the flipbook.\n\n## Humanoid animations\n\n`humanoid-animation` assets are single-clip GLBs \u2014 one motion per asset (one idle, one walk-forward, one jump, one attack) on a normalized skeleton that retargets onto any humanoid, whatever its role. A behaving character is therefore a *set* of clips, not one asset: from what the character actually does, budget the clips it needs \u2014 an idle, its locomotion (walk/run, often split by direction: fwd/bwd/left/right), and one clip per distinct action and reaction it performs \u2014 then search for each separately.\n\n`humanoid-model` assets share that same normalized skeleton and are authored to a **consistent real-world scale** \u2014 they come in at roughly the same height as each other. So you do **not** need to rescale one humanoid to match another (player vs. enemy vs. NPC); dropped in as-is they already stand at a consistent size. Avoid the trap of measuring one character's height and scaling others to it \u2014 besides being unnecessary, measuring a rigged/animated character's bounding box is unreliable and produces giants (see the `math` skill on `Box3` and skinned meshes). If you ever do need a deliberate size difference (a boss, a child NPC), apply an explicit chosen multiplier, not a measured one.\n\nSearch one motion per query, named by the motion, because results rank by keyword overlap: a query naming several motions at once is dominated by whichever word matches the most assets and buries the others, so real clips look like a gap when they exist. Names describe the motion, not the character \u2014 so search the motion (`\"walk forward\"`, `\"reload\"`, `\"jump\"`), not the role (`\"player run\"`, `\"boss attack\"`). If a motion finds nothing, retry with synonyms (run/jog/sprint, attack/swing/strike).\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)\nInstalled assets: 1\n- wooden-chair@1.0.0 (model)\n files:\n public/model\n \u2514\u2500 wooden-chair.glb\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\nInstalled non-template assets are saved to `package.json.assetDependencies`; templates are scaffolds and are not saved as project asset dependencies. Exact installed versions and file hashes are recorded in `.drawcall/market-lock.json`.\n\n`list` is offline: it reads `.drawcall/market-lock.json` from the nearest package root and prints exact installed names, versions, types, and installed file paths.\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 list --cwd \"$PWD\"\nmarket preview wooden-chair --out /tmp/wooden-chair.png\nmarket pack scene.zip --out scene.packed.zip\n```\n\n## Workflow\n\n1. In an existing repo, run `list --cwd \"$PWD\"` first to see installed local assets from `.drawcall/market-lock.json`. Use the listed names with `preview <name>` when you want preview images.\n2. 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`, `environment`, or `flipbook`.\n3. Use `--limit 1` for lookup, `--limit 3` for choice. Search caps at 5 and prints full descriptions.\n4. `install` takes zero or more exact asset names (optionally `name@range`). With names, it installs those assets; with no names, it installs `assetDependencies` from the nearest `package.json`. It does not search or generate. Find names with `search` first. No `--type` is needed \u2014 asset names are unique. Use `--force` only when the user agrees to overwrite changed local files.\n5. `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.\n6. Use `--unapproved` only when the user asks for unapproved/private/admin assets. Do not install unapproved assets without explicit acceptance.\n7. `generate --type <type> \"<prompt>\"` creates and installs a generated asset when that asset type has a generator; it requires login. Currently supported generated types are `sound-effect`, `background-music`, `flipbook`, `humanoid-model`, and `environment` (a fitting HDRI sky + equirectangular background, generated in ~1-2 min). Generation is provider-specific: prompt style, generated files, indexing fields, and install layout are owned by the asset type. If a type does not support generation yet, the CLI reports unsupported generation. Add `--access public` to publish the generated asset publicly, or `--access private` to keep it owner-only; when omitted the server defaults to private if you hold the `market:private` entitlement, else public (`--access private` requires that entitlement). `generate` waits for the asset and installs it \u2014 one command for quick types. For a long one (e.g. `humanoid-model`, >2 min) the call returns after ~2 min with a job id instead of hanging your shell; run `market generate install <jobId>` to continue \u2014 it resumes the SAME job where the last call left off and installs when ready. Just re-run `generate install <jobId>` until it prints \"Generated and installed\" (it exits 0 while still generating, 1 on failure). No type is flagged \"slow\" \u2014 anything that outlasts one wait just continues on the next call.\n8. Use `pack <zip>` to create the same Market asset zip that `upload` sends. `pack` runs offline, infers template packing from a root `package.json`, and accepts `--type` only when you need to override that inference. `upload` runs the shared pack step internally, then publishes: `market upload <name> <zip> \"<description>\" --type <type>`. Declare dependencies with repeatable flags on either command: `--npm name@range`, `--asset name@range`, `--skill label=source`. Template pack/upload also reads root `package.json.assetDependencies`; `--asset` flags are additive and must not conflict. Template pack/upload omits installed dependency files that still match the installed dependency's canonical content (its file hashes are fetched from the server, not stored locally), so edited local files stay in the template; this omit step needs the API, but simple non-template packs stay offline. 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`.\n9. 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.\n10. Installed `flipbook` assets contain `public/flipbook/<name>.ktx2`. Render them with `@drawcall/flipbook`'s `Flipbook` class and Three.js `KTX2Loader` for Basis-compressed files; `market preview` fetches the middle frame from the flipbook.\n\n## Humanoid animations\n\n`humanoid-animation` assets are single-clip GLBs \u2014 one motion per asset (one idle, one walk-forward, one jump, one attack) on a normalized skeleton that retargets onto any humanoid, whatever its role. A behaving character is therefore a *set* of clips, not one asset: from what the character actually does, budget the clips it needs \u2014 an idle, its locomotion (walk/run, often split by direction: fwd/bwd/left/right), and one clip per distinct action and reaction it performs \u2014 then search for each separately.\n\n`humanoid-model` assets share that same normalized skeleton and are authored to a **consistent real-world scale** \u2014 they come in at roughly the same height as each other. So you do **not** need to rescale one humanoid to match another (player vs. enemy vs. NPC); dropped in as-is they already stand at a consistent size. Avoid the trap of measuring one character's height and scaling others to it \u2014 besides being unnecessary, measuring a rigged/animated character's bounding box is unreliable and produces giants (see the `math` skill on `Box3` and skinned meshes). If you ever do need a deliberate size difference (a boss, a child NPC), apply an explicit chosen multiplier, not a measured one.\n\nSearch one motion per query, named by the motion, because results rank by keyword overlap: a query naming several motions at once is dominated by whichever word matches the most assets and buries the others, so real clips look like a gap when they exist. Names describe the motion, not the character \u2014 so search the motion (`\"walk forward\"`, `\"reload\"`, `\"jump\"`), not the role (`\"player run\"`, `\"boss attack\"`). If a motion finds nothing, retry with synonyms (run/jog/sprint, attack/swing/strike).\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)\nInstalled assets: 1\n- wooden-chair@1.0.0 (model)\n files:\n public/model\n \u2514\u2500 wooden-chair.glb\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\nInstalled non-template assets are saved to `package.json.assetDependencies`; templates are scaffolds and are not saved as project asset dependencies. Exact installed versions and file paths are recorded in `.drawcall/market-lock.json`; file content hashes now come from the server (`asset.fileManifest`), not the lock.\n\n`list` is offline: it reads `.drawcall/market-lock.json` from the nearest package root and prints exact installed names, versions, types, and installed file paths.\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,yhQAsEvB,CAAA"}
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,+vQAsEvB,CAAA"}
package/dist/skill.js CHANGED
@@ -26,7 +26,7 @@ market pack scene.zip --out scene.packed.zip
26
26
  5. \`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.
27
27
  6. Use \`--unapproved\` only when the user asks for unapproved/private/admin assets. Do not install unapproved assets without explicit acceptance.
28
28
  7. \`generate --type <type> "<prompt>"\` creates and installs a generated asset when that asset type has a generator; it requires login. Currently supported generated types are \`sound-effect\`, \`background-music\`, \`flipbook\`, \`humanoid-model\`, and \`environment\` (a fitting HDRI sky + equirectangular background, generated in ~1-2 min). Generation is provider-specific: prompt style, generated files, indexing fields, and install layout are owned by the asset type. If a type does not support generation yet, the CLI reports unsupported generation. Add \`--access public\` to publish the generated asset publicly, or \`--access private\` to keep it owner-only; when omitted the server defaults to private if you hold the \`market:private\` entitlement, else public (\`--access private\` requires that entitlement). \`generate\` waits for the asset and installs it — one command for quick types. For a long one (e.g. \`humanoid-model\`, >2 min) the call returns after ~2 min with a job id instead of hanging your shell; run \`market generate install <jobId>\` to continue — it resumes the SAME job where the last call left off and installs when ready. Just re-run \`generate install <jobId>\` until it prints "Generated and installed" (it exits 0 while still generating, 1 on failure). No type is flagged "slow" — anything that outlasts one wait just continues on the next call.
29
- 8. Use \`pack <zip>\` to create the same Market asset zip that \`upload\` sends. \`pack\` runs offline, infers template packing from a root \`package.json\`, and accepts \`--type\` only when you need to override that inference. \`upload\` runs the shared pack step internally, then publishes: \`market upload <name> <zip> "<description>" --type <type>\`. Declare dependencies with repeatable flags on either command: \`--npm name@range\`, \`--asset name@range\`, \`--skill label=source\`. Template pack/upload also reads root \`package.json.assetDependencies\`; \`--asset\` flags are additive and must not conflict. Template pack/upload omits installed dependency files whose hashes still match \`.drawcall/market-lock.json\`, so edited local files stay in the template. 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\`.
29
+ 8. Use \`pack <zip>\` to create the same Market asset zip that \`upload\` sends. \`pack\` runs offline, infers template packing from a root \`package.json\`, and accepts \`--type\` only when you need to override that inference. \`upload\` runs the shared pack step internally, then publishes: \`market upload <name> <zip> "<description>" --type <type>\`. Declare dependencies with repeatable flags on either command: \`--npm name@range\`, \`--asset name@range\`, \`--skill label=source\`. Template pack/upload also reads root \`package.json.assetDependencies\`; \`--asset\` flags are additive and must not conflict. Template pack/upload omits installed dependency files that still match the installed dependency's canonical content (its file hashes are fetched from the server, not stored locally), so edited local files stay in the template; this omit step needs the API, but simple non-template packs stay offline. 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\`.
30
30
  9. 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.
31
31
  10. Installed \`flipbook\` assets contain \`public/flipbook/<name>.ktx2\`. Render them with \`@drawcall/flipbook\`'s \`Flipbook\` class and Three.js \`KTX2Loader\` for Basis-compressed files; \`market preview\` fetches the middle frame from the flipbook.
32
32
 
@@ -63,7 +63,7 @@ Saved preview for wooden-chair@1.0.0: /tmp/wooden-chair.png
63
63
 
64
64
  Assets 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.
65
65
 
66
- Installed non-template assets are saved to \`package.json.assetDependencies\`; templates are scaffolds and are not saved as project asset dependencies. Exact installed versions and file hashes are recorded in \`.drawcall/market-lock.json\`.
66
+ Installed non-template assets are saved to \`package.json.assetDependencies\`; templates are scaffolds and are not saved as project asset dependencies. Exact installed versions and file paths are recorded in \`.drawcall/market-lock.json\`; file content hashes now come from the server (\`asset.fileManifest\`), not the lock.
67
67
 
68
68
  \`list\` is offline: it reads \`.drawcall/market-lock.json\` from the nearest package root and prints exact installed names, versions, types, and installed file paths.
69
69
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawcall/market",
3
- "version": "0.1.53",
3
+ "version": "0.1.55",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/drawcall-ai/market",
@@ -26,7 +26,7 @@ npx @drawcall/market pack scene.zip --out scene.packed.zip
26
26
  5. `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.
27
27
  6. Use `--unapproved` only when the user asks for unapproved/private/admin assets. Do not install unapproved assets without explicit acceptance.
28
28
  7. `generate --type <type> "<prompt>"` creates and installs a generated asset when that asset type has a generator; it requires login. Currently supported generated types are `sound-effect`, `background-music`, `flipbook`, `humanoid-model`, and `environment` (a fitting HDRI sky + equirectangular background, generated in ~1-2 min). Generation is provider-specific: prompt style, generated files, indexing fields, and install layout are owned by the asset type. If a type does not support generation yet, the CLI reports unsupported generation. Add `--access public` to publish the generated asset publicly, or `--access private` to keep it owner-only; when omitted the server defaults to private if you hold the `market:private` entitlement, else public (`--access private` requires that entitlement). `generate` waits for the asset and installs it — one command for quick types. For a long one (e.g. `humanoid-model`, >2 min) the call returns after ~2 min with a job id instead of hanging your shell; run `market generate install <jobId>` to continue — it resumes the SAME job where the last call left off and installs when ready. Just re-run `generate install <jobId>` until it prints "Generated and installed" (it exits 0 while still generating, 1 on failure). No type is flagged "slow" — anything that outlasts one wait just continues on the next call.
29
- 8. Use `pack <zip>` to create the same Market asset zip that `upload` sends. `pack` runs offline, infers template packing from a root `package.json`, and accepts `--type` only when you need to override that inference. `upload` runs the shared pack step internally, then publishes: `market upload <name> <zip> "<description>" --type <type>`. Declare dependencies with repeatable flags on either command: `--npm name@range`, `--asset name@range`, `--skill label=source`. Use `--access public|private` on upload to set visibility (same default rule as generate): a private asset is visible and installable only by you. Template pack/upload also reads root `package.json.assetDependencies`; `--asset` flags are additive and must not conflict. Template pack/upload omits installed dependency files whose hashes still match `.drawcall/market-lock.json`, so edited local files stay in the template. 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`.
29
+ 8. Use `pack <zip>` to create the same Market asset zip that `upload` sends. `pack` runs offline, infers template packing from a root `package.json`, and accepts `--type` only when you need to override that inference. `upload` runs the shared pack step internally, then publishes: `market upload <name> <zip> "<description>" --type <type>`. Declare dependencies with repeatable flags on either command: `--npm name@range`, `--asset name@range`, `--skill label=source`. Use `--access public|private` on upload to set visibility (same default rule as generate): a private asset is visible and installable only by you. Template pack/upload also reads root `package.json.assetDependencies`; `--asset` flags are additive and must not conflict. Template pack/upload omits installed dependency files that still match the installed dependency's canonical content (its file hashes are fetched from the server, not stored locally), so edited local files stay in the template; this omit step needs the API, but simple non-template packs stay offline. 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`.
30
30
  9. 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.
31
31
  10. Installed `flipbook` assets contain `public/flipbook/<name>.ktx2`. Render them with `@drawcall/flipbook`'s `Flipbook` class and Three.js `KTX2Loader` for Basis-compressed files; `market preview` fetches the middle frame from the flipbook.
32
32
 
@@ -63,7 +63,7 @@ Saved preview for wooden-chair@1.0.0: /tmp/wooden-chair.png
63
63
 
64
64
  Assets 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.
65
65
 
66
- Installed non-template assets are saved to `package.json.assetDependencies`; templates are scaffolds and are not saved as project asset dependencies. Exact installed versions and file hashes are recorded in `.drawcall/market-lock.json`.
66
+ Installed non-template assets are saved to `package.json.assetDependencies`; templates are scaffolds and are not saved as project asset dependencies. Exact installed versions and file paths are recorded in `.drawcall/market-lock.json`; file content hashes now come from the server (`asset.fileManifest`), not the lock.
67
67
 
68
68
  `list` is offline: it reads `.drawcall/market-lock.json` from the nearest package root and prints exact installed names, versions, types, and installed file paths.
69
69
 
@@ -35,7 +35,7 @@ export async function listInstalledAssets(
35
35
  name,
36
36
  version: asset.version,
37
37
  type: asset.type,
38
- files: Object.keys(asset.files).sort((a, b) => a.localeCompare(b)),
38
+ files: [...asset.files].sort((a, b) => a.localeCompare(b)),
39
39
  }))
40
40
  .sort((a, b) => a.name.localeCompare(b.name))
41
41
 
@@ -1,6 +1,7 @@
1
1
  import * as fs from 'fs/promises'
2
2
  import * as path from 'path'
3
3
  import ora from 'ora'
4
+ import { getCliClient } from '../cli-client.js'
4
5
  import { packAsset, packPolicyForType, parsePackDependencies } from '../pack.js'
5
6
  import { packResult } from '../output.js'
6
7
  import type { AssetType } from '../schemas.js'
@@ -9,6 +10,7 @@ export interface PackCommandOptions {
9
10
  type?: AssetType
10
11
  cwd?: string
11
12
  out?: string
13
+ baseUrl?: string
12
14
  /** npm dependencies, each `name@range` (range defaults to `*`). */
13
15
  npm?: string[]
14
16
  /** asset dependencies, each `name@range` (range defaults to `*`). */
@@ -26,6 +28,9 @@ export async function packCommand(zipFilter: string, opts: PackCommandOptions):
26
28
 
27
29
  try {
28
30
  const cwd = opts.cwd ?? process.cwd()
31
+ // A client is only used to omit unchanged installed dependency files (templates); it needs no
32
+ // auth for public assets and is never called for non-template packs, which stay fully offline.
33
+ const { client } = await getCliClient({ baseUrl: opts.baseUrl })
29
34
  const packed = await packAsset(zipFilter, {
30
35
  cwd,
31
36
  dependencies: parsePackDependencies({
@@ -34,6 +39,7 @@ export async function packCommand(zipFilter: string, opts: PackCommandOptions):
34
39
  skill: opts.skill,
35
40
  }),
36
41
  policy: packPolicyForType(opts.type),
42
+ fetchFileManifest: (name, version) => client.asset.fileManifest({ name, version }),
37
43
  })
38
44
  const out = opts.out ? path.resolve(cwd, opts.out) : defaultPackPath(packed.sourcePath)
39
45
 
@@ -57,6 +57,7 @@ export async function uploadCommand(
57
57
  cwd,
58
58
  dependencies,
59
59
  policy: packPolicyFromInstallMetadata(installMetadata[type]),
60
+ fetchFileManifest: (name, version) => client.asset.fileManifest({ name, version }),
60
61
  })
61
62
  const { zip, npmDependencies, assetDependencies, skillDependencies } = packed
62
63
  const profile = await client.user.getProfile()
package/src/contract.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { oc } from '@orpc/contract'
2
2
  import { z } from 'zod'
3
+ import type { AssetFileManifest } from './schemas.js'
3
4
  import {
4
5
  MAX_UPLOAD_ZIP_SIZE_BYTES,
5
6
  agentRunStatusSchema,
@@ -7,6 +8,7 @@ import {
7
8
  agentStatusSchema,
8
9
  downloadZipSchema,
9
10
  exactAssetSchema,
11
+ fileManifestSchema,
10
12
  generateAssetSchema,
11
13
  generateJobStatusSchema,
12
14
  generateResponseSchema,
@@ -115,6 +117,12 @@ export const contract = {
115
117
 
116
118
  downloadZip: oc.input(downloadZipSchema).output(z.instanceof(Blob)),
117
119
 
120
+ // The content hashes of a version's files, keyed by install path. Computed once from the stored
121
+ // source zip and cached, so a caller (e.g. `pack`) can tell whether a local file is an unchanged
122
+ // copy of an installed asset without keeping any hashes itself. Private assets are owner-only,
123
+ // same as download.
124
+ fileManifest: oc.input(fileManifestSchema).output(z.custom<AssetFileManifest>()),
125
+
118
126
  // Generation is a caller-polled job. `generate` starts it and answers immediately: `completed`
119
127
  // for fast providers that finish inline, or `pending` with a jobId for slow ones (the humanoid
120
128
  // model runs for minutes upstream). `generateStatus` polls that jobId until it settles. Nothing
package/src/index.ts CHANGED
@@ -61,6 +61,7 @@ export {
61
61
  uploadZipSchema,
62
62
  downloadZipSchema,
63
63
  exactAssetSchema,
64
+ fileManifestSchema,
64
65
  generateAssetSchema,
65
66
  updateProfileSchema,
66
67
  listAssetsSchema,
@@ -77,6 +78,7 @@ export {
77
78
  export type {
78
79
  AssetType,
79
80
  AssetAccess,
81
+ AssetFileManifest,
80
82
  AgentResultAsset,
81
83
  AgentResult,
82
84
  AgentRunStatus,
package/src/install.ts CHANGED
@@ -17,7 +17,7 @@ import { unzipSync } from 'fflate'
17
17
  import { detectPackageManager, installDependencies } from 'nypm'
18
18
  import type { MarketClient } from './client.js'
19
19
  import type { AssetInstallMetadata } from './contract.js'
20
- import { readMarketLock, sha256, writeMarketLock } from './market-lock.js'
20
+ import { readMarketLock, writeMarketLock } from './market-lock.js'
21
21
  import { parsePackageJson, type PackageJson } from './package-json.js'
22
22
  import type { ResolveResult } from './resolve.js'
23
23
 
@@ -66,12 +66,8 @@ export interface InstallResult {
66
66
  warnings: string[]
67
67
  }
68
68
 
69
- interface DownloadedAsset extends InstalledAsset {
70
- fileHashes: Record<string, { sha256: string }>
71
- }
72
-
73
69
  interface DownloadResult {
74
- assets: DownloadedAsset[]
70
+ assets: InstalledAsset[]
75
71
  wrotePackageJson: boolean
76
72
  warnings: string[]
77
73
  }
@@ -157,10 +153,8 @@ async function downloadAssets(
157
153
  baseUrl?: string
158
154
  },
159
155
  ): Promise<DownloadResult> {
160
- const perAsset = await mapWithConcurrency(
161
- resolution.assets,
162
- DOWNLOAD_CONCURRENCY,
163
- (asset) => downloadOneAsset(client, asset, projectRoot, opts),
156
+ const perAsset = await mapWithConcurrency(resolution.assets, DOWNLOAD_CONCURRENCY, (asset) =>
157
+ downloadOneAsset(client, asset, projectRoot, opts),
164
158
  )
165
159
 
166
160
  return {
@@ -177,14 +171,13 @@ async function downloadOneAsset(
177
171
  asset: ResolveResult['assets'][number],
178
172
  projectRoot: string,
179
173
  opts: { force: boolean; log: (msg: string) => void; baseUrl?: string },
180
- ): Promise<{ asset: DownloadedAsset; wrotePackageJson: boolean; warnings: string[] }> {
174
+ ): Promise<{ asset: InstalledAsset; wrotePackageJson: boolean; warnings: string[] }> {
181
175
  opts.log(`Downloading ${asset.name}@${asset.version}...`)
182
176
 
183
177
  // Only the network fetch is retried — the download is the sole transient step; unzip and file
184
178
  // writes are deterministic local work and a failure there is a real error, not worth re-attempting.
185
179
  const files = unzipSync(new Uint8Array(await fetchAssetZipBytes(client, asset, opts)))
186
180
  const installedFiles: string[] = []
187
- const fileHashes: Record<string, { sha256: string }> = {}
188
181
  const warnings: string[] = []
189
182
  let wrotePackageJson = false
190
183
 
@@ -225,7 +218,6 @@ async function downloadOneAsset(
225
218
  }
226
219
 
227
220
  installedFiles.push(normalizedPath)
228
- fileHashes[normalizedPath] = { sha256: sha256(content) }
229
221
  }
230
222
 
231
223
  opts.log(`Downloaded ${installedFiles.length} files from ${asset.name}@${asset.version}.`)
@@ -236,7 +228,6 @@ async function downloadOneAsset(
236
228
  version: asset.version,
237
229
  description: asset.description,
238
230
  files: installedFiles,
239
- fileHashes,
240
231
  },
241
232
  wrotePackageJson,
242
233
  warnings,
@@ -262,7 +253,9 @@ async function fetchAssetZipBytes(
262
253
  onRetry: (msg) => opts.log(`Downloading ${label} (streaming): ${msg}`),
263
254
  })
264
255
  } catch (error) {
265
- opts.log(`Downloading ${label}: streaming download failed (${errorMessage(error)}); using downloadZip`)
256
+ opts.log(
257
+ `Downloading ${label}: streaming download failed (${errorMessage(error)}); using downloadZip`,
258
+ )
266
259
  }
267
260
  }
268
261
  return withRetry(
@@ -305,9 +298,7 @@ async function mapWithConcurrency<T, R>(
305
298
  results[index] = await fn(items[index], index)
306
299
  }
307
300
  }
308
- await Promise.all(
309
- Array.from({ length: Math.min(concurrency, items.length) }, () => worker()),
310
- )
301
+ await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()))
311
302
  return results
312
303
  }
313
304
 
@@ -423,14 +414,14 @@ async function runPackageManagerInstall(projectRoot: string, log: (msg: string)
423
414
 
424
415
  async function writeInstalledAssetLock(
425
416
  projectRoot: string,
426
- assets: DownloadedAsset[],
417
+ assets: InstalledAsset[],
427
418
  ): Promise<void> {
428
419
  const lock = await readMarketLock(projectRoot)
429
420
  for (const asset of assets) {
430
421
  lock.assets[asset.name] = {
431
422
  version: asset.version,
432
423
  type: asset.type,
433
- files: asset.fileHashes,
424
+ files: asset.files,
434
425
  }
435
426
  }
436
427
  await writeMarketLock(projectRoot, lock)
@@ -8,7 +8,8 @@ export const MARKET_LOCK_PATH = '.drawcall/market-lock.json'
8
8
  export interface MarketLockAsset {
9
9
  version: string
10
10
  type: string
11
- files: Record<string, { sha256: string }>
11
+ /** Install paths of the asset's files. Content hashes now live on the server (`asset.fileManifest`). */
12
+ files: string[]
12
13
  }
13
14
 
14
15
  export interface MarketLock {
@@ -16,6 +17,13 @@ export interface MarketLock {
16
17
  assets: Record<string, MarketLockAsset>
17
18
  }
18
19
 
20
+ // Content hashes moved to the server, so the lock records only install paths. It still reads the
21
+ // legacy `{ path: { sha256 } }` shape and normalizes it to a path list, so an existing lock keeps
22
+ // working and is rewritten to the slim form on the next install.
23
+ const filesSchema = z
24
+ .union([z.array(z.string()), z.record(z.string(), z.object({ sha256: z.string() }))])
25
+ .transform((files) => (Array.isArray(files) ? files : Object.keys(files)))
26
+
19
27
  const marketLockSchema = z.object({
20
28
  version: z.literal(1),
21
29
  assets: z.record(
@@ -23,12 +31,7 @@ const marketLockSchema = z.object({
23
31
  z.object({
24
32
  version: z.string(),
25
33
  type: z.string(),
26
- files: z.record(
27
- z.string(),
28
- z.object({
29
- sha256: z.string(),
30
- }),
31
- ),
34
+ files: filesSchema,
32
35
  }),
33
36
  ),
34
37
  })
package/src/pack.ts CHANGED
@@ -28,10 +28,18 @@ export interface PackPolicy {
28
28
  omitUnchangedInstalledFiles: boolean
29
29
  }
30
30
 
31
+ export type FetchFileManifest = (name: string, version: string) => Promise<Record<string, string>>
32
+
31
33
  export interface PackAssetOptions {
32
34
  cwd?: string
33
35
  dependencies: ParsedPackDependencies
34
36
  policy?: PackPolicy
37
+ /**
38
+ * Fetch the server's content hashes for an installed dependency version (see `asset.fileManifest`),
39
+ * so a template omits its unchanged installed dependency files. Content hashes are no longer stored
40
+ * locally, so omitting needs the API — omit this (or a failing fetch) and those files are kept.
41
+ */
42
+ fetchFileManifest?: FetchFileManifest
35
43
  }
36
44
 
37
45
  export interface PackedAsset {
@@ -81,7 +89,12 @@ export async function packAsset(zipFilter: string, opts: PackAssetOptions): Prom
81
89
  // count means something was dropped; re-zip only then.
82
90
  const { kept: withoutIgnored, gitignored } = applyGitignore(sourceFiles)
83
91
  const files = policy.omitUnchangedInstalledFiles
84
- ? await withoutUnchangedInstalledFiles(withoutIgnored, assetDependencies, cwd)
92
+ ? await withoutUnchangedInstalledFiles(
93
+ withoutIgnored,
94
+ assetDependencies,
95
+ cwd,
96
+ opts.fetchFileManifest,
97
+ )
85
98
  : withoutIgnored
86
99
 
87
100
  const originalCount = Object.keys(sourceFiles).length
@@ -130,17 +143,11 @@ async function packDirectory(dir: string, opts: PackAssetOptions): Promise<Packe
130
143
  ...opts.dependencies.npmDependencies,
131
144
  }
132
145
 
133
- // Hashes of installed dependency files, so an unchanged one is dropped after a single read.
134
- const hashesByPath = new Map<string, string>()
135
- if (policy.omitUnchangedInstalledFiles && Object.keys(assetDependencies).length > 0) {
136
- const installRoot = await findInstallRoot(dir)
137
- const lock = await readMarketLock(installRoot)
138
- for (const [name, asset] of Object.entries(lock.assets)) {
139
- if (!(name in assetDependencies)) continue
140
- for (const [file, metadata] of Object.entries(asset.files))
141
- hashesByPath.set(file, metadata.sha256)
142
- }
143
- }
146
+ // Content hashes of installed dependency files (from the server), so an unchanged one is dropped
147
+ // after a single read.
148
+ const hashesByPath = policy.omitUnchangedInstalledFiles
149
+ ? await installedDependencyHashes(dir, assetDependencies, opts.fetchFileManifest)
150
+ : new Map<string, string>()
144
151
 
145
152
  const files: Record<string, Uint8Array> = {}
146
153
  let omittedInstalled = 0
@@ -366,40 +373,59 @@ function inferPackPolicy(files: Record<string, Uint8Array>): PackPolicy {
366
373
  }
367
374
  }
368
375
 
369
- // Drop dependency files whose bytes still match what `.drawcall/market-lock.json` recorded as
370
- // installed, so a template ships only its own (edited or new) files. Returns the surviving entries.
376
+ // Drop dependency files whose bytes still match the installed asset's canonical content, so a
377
+ // template ships only its own (edited or new) files. Returns the surviving entries.
371
378
  async function withoutUnchangedInstalledFiles(
372
379
  files: Record<string, Uint8Array>,
373
380
  assetDependencies: Record<string, string>,
374
381
  cwd: string,
382
+ fetchFileManifest: FetchFileManifest | undefined,
375
383
  ): Promise<Record<string, Uint8Array>> {
376
- const dependencyNames = new Set(Object.keys(assetDependencies))
377
- if (dependencyNames.size === 0) return files
378
-
379
- const installRoot = await findInstallRoot(cwd)
380
- const lock = await readMarketLock(installRoot)
381
- const hashesByPath = new Map<string, string>()
382
-
383
- for (const [name, asset] of Object.entries(lock.assets)) {
384
- if (!dependencyNames.has(name)) continue
385
- for (const [file, metadata] of Object.entries(asset.files)) {
386
- hashesByPath.set(file, metadata.sha256)
387
- }
388
- }
389
-
384
+ const hashesByPath = await installedDependencyHashes(cwd, assetDependencies, fetchFileManifest)
390
385
  if (hashesByPath.size === 0) return files
391
386
 
392
387
  const kept: Record<string, Uint8Array> = {}
393
388
  for (const [file, content] of Object.entries(files)) {
394
389
  const normalizedPath = normalizedZipPath(file)
395
- const lockedHash = normalizedPath ? hashesByPath.get(normalizedPath) : undefined
396
- if (lockedHash && lockedHash === sha256(content)) continue
390
+ const canonicalHash = normalizedPath ? hashesByPath.get(normalizedPath) : undefined
391
+ if (canonicalHash && canonicalHash === sha256(content)) continue
397
392
  kept[file] = content
398
393
  }
399
394
 
400
395
  return kept
401
396
  }
402
397
 
398
+ /**
399
+ * The canonical content hash of every file belonging to a declared asset dependency, keyed by install
400
+ * path. Read the installed version of each dependency from the lock, then fetch that version's hashes
401
+ * from the server (`asset.fileManifest`). Returns an empty map when there's nothing to omit or no way
402
+ * to fetch (offline / no client) — pack then keeps all files rather than guessing.
403
+ */
404
+ async function installedDependencyHashes(
405
+ root: string,
406
+ assetDependencies: Record<string, string>,
407
+ fetchFileManifest: FetchFileManifest | undefined,
408
+ ): Promise<Map<string, string>> {
409
+ const hashesByPath = new Map<string, string>()
410
+ const dependencyNames = Object.keys(assetDependencies)
411
+ if (!fetchFileManifest || dependencyNames.length === 0) return hashesByPath
412
+
413
+ const lock = await readMarketLock(await findInstallRoot(root))
414
+ for (const name of dependencyNames) {
415
+ const installed = lock.assets[name]
416
+ if (!installed) continue
417
+ let manifest: Record<string, string>
418
+ try {
419
+ manifest = await fetchFileManifest(name, installed.version)
420
+ } catch {
421
+ // Can't reach the server for this dependency — keep its files rather than wrongly omitting them.
422
+ continue
423
+ }
424
+ for (const [file, hash] of Object.entries(manifest)) hashesByPath.set(file, hash)
425
+ }
426
+ return hashesByPath
427
+ }
428
+
403
429
  function normalizedZipPath(file: string): string | null {
404
430
  const zipPath = file.replace(/\\/g, '/')
405
431
  if (
package/src/schemas.ts CHANGED
@@ -93,6 +93,18 @@ export const downloadZipSchema = z.object({
93
93
  version: semverSchema,
94
94
  })
95
95
 
96
+ export const fileManifestSchema = z.object({
97
+ name: assetNameSchema,
98
+ version: semverSchema,
99
+ })
100
+
101
+ /**
102
+ * The content hash of every file in an asset version, keyed by its install path — sha256 hex, the
103
+ * same digest the CLI computes locally. Lets a caller check whether a local file is identical to the
104
+ * canonical asset without keeping hashes itself (see `pack` omit-unchanged).
105
+ */
106
+ export type AssetFileManifest = Record<string, string>
107
+
96
108
  export const generateAssetSchema = z.object({
97
109
  description: assetDescriptionSchema.min(3),
98
110
  type: assetTypeSchema.optional(),
package/src/skill.ts CHANGED
@@ -26,7 +26,7 @@ market pack scene.zip --out scene.packed.zip
26
26
  5. \`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.
27
27
  6. Use \`--unapproved\` only when the user asks for unapproved/private/admin assets. Do not install unapproved assets without explicit acceptance.
28
28
  7. \`generate --type <type> "<prompt>"\` creates and installs a generated asset when that asset type has a generator; it requires login. Currently supported generated types are \`sound-effect\`, \`background-music\`, \`flipbook\`, \`humanoid-model\`, and \`environment\` (a fitting HDRI sky + equirectangular background, generated in ~1-2 min). Generation is provider-specific: prompt style, generated files, indexing fields, and install layout are owned by the asset type. If a type does not support generation yet, the CLI reports unsupported generation. Add \`--access public\` to publish the generated asset publicly, or \`--access private\` to keep it owner-only; when omitted the server defaults to private if you hold the \`market:private\` entitlement, else public (\`--access private\` requires that entitlement). \`generate\` waits for the asset and installs it — one command for quick types. For a long one (e.g. \`humanoid-model\`, >2 min) the call returns after ~2 min with a job id instead of hanging your shell; run \`market generate install <jobId>\` to continue — it resumes the SAME job where the last call left off and installs when ready. Just re-run \`generate install <jobId>\` until it prints "Generated and installed" (it exits 0 while still generating, 1 on failure). No type is flagged "slow" — anything that outlasts one wait just continues on the next call.
29
- 8. Use \`pack <zip>\` to create the same Market asset zip that \`upload\` sends. \`pack\` runs offline, infers template packing from a root \`package.json\`, and accepts \`--type\` only when you need to override that inference. \`upload\` runs the shared pack step internally, then publishes: \`market upload <name> <zip> "<description>" --type <type>\`. Declare dependencies with repeatable flags on either command: \`--npm name@range\`, \`--asset name@range\`, \`--skill label=source\`. Template pack/upload also reads root \`package.json.assetDependencies\`; \`--asset\` flags are additive and must not conflict. Template pack/upload omits installed dependency files whose hashes still match \`.drawcall/market-lock.json\`, so edited local files stay in the template. 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\`.
29
+ 8. Use \`pack <zip>\` to create the same Market asset zip that \`upload\` sends. \`pack\` runs offline, infers template packing from a root \`package.json\`, and accepts \`--type\` only when you need to override that inference. \`upload\` runs the shared pack step internally, then publishes: \`market upload <name> <zip> "<description>" --type <type>\`. Declare dependencies with repeatable flags on either command: \`--npm name@range\`, \`--asset name@range\`, \`--skill label=source\`. Template pack/upload also reads root \`package.json.assetDependencies\`; \`--asset\` flags are additive and must not conflict. Template pack/upload omits installed dependency files that still match the installed dependency's canonical content (its file hashes are fetched from the server, not stored locally), so edited local files stay in the template; this omit step needs the API, but simple non-template packs stay offline. 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\`.
30
30
  9. 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.
31
31
  10. Installed \`flipbook\` assets contain \`public/flipbook/<name>.ktx2\`. Render them with \`@drawcall/flipbook\`'s \`Flipbook\` class and Three.js \`KTX2Loader\` for Basis-compressed files; \`market preview\` fetches the middle frame from the flipbook.
32
32
 
@@ -63,7 +63,7 @@ Saved preview for wooden-chair@1.0.0: /tmp/wooden-chair.png
63
63
 
64
64
  Assets 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.
65
65
 
66
- Installed non-template assets are saved to \`package.json.assetDependencies\`; templates are scaffolds and are not saved as project asset dependencies. Exact installed versions and file hashes are recorded in \`.drawcall/market-lock.json\`.
66
+ Installed non-template assets are saved to \`package.json.assetDependencies\`; templates are scaffolds and are not saved as project asset dependencies. Exact installed versions and file paths are recorded in \`.drawcall/market-lock.json\`; file content hashes now come from the server (\`asset.fileManifest\`), not the lock.
67
67
 
68
68
  \`list\` is offline: it reads \`.drawcall/market-lock.json\` from the nearest package root and prints exact installed names, versions, types, and installed file paths.
69
69