@drawcall/market 0.8.30 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +19 -1
  2. package/dist/auth.d.ts +4 -0
  3. package/dist/auth.d.ts.map +1 -0
  4. package/dist/auth.js +32 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/cli.js +2 -2
  7. package/dist/cli.js.map +1 -1
  8. package/dist/command.d.ts +0 -1
  9. package/dist/command.d.ts.map +1 -1
  10. package/dist/command.js +2 -36
  11. package/dist/command.js.map +1 -1
  12. package/dist/commands/preview.d.ts +1 -1
  13. package/dist/commands/preview.d.ts.map +1 -1
  14. package/dist/commands/preview.js +2 -2
  15. package/dist/commands/preview.js.map +1 -1
  16. package/dist/commands/urls.js +2 -2
  17. package/dist/commands/urls.js.map +1 -1
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +2 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/mcp/agent.d.ts +4 -0
  23. package/dist/mcp/agent.d.ts.map +1 -0
  24. package/dist/mcp/agent.js +27 -0
  25. package/dist/mcp/agent.js.map +1 -0
  26. package/dist/mcp/asset.d.ts +4 -0
  27. package/dist/mcp/asset.d.ts.map +1 -0
  28. package/dist/mcp/asset.js +124 -0
  29. package/dist/mcp/asset.js.map +1 -0
  30. package/dist/mcp/generation.d.ts +4 -0
  31. package/dist/mcp/generation.d.ts.map +1 -0
  32. package/dist/mcp/generation.js +28 -0
  33. package/dist/mcp/generation.js.map +1 -0
  34. package/dist/mcp/index.d.ts +3 -0
  35. package/dist/mcp/index.d.ts.map +1 -0
  36. package/dist/mcp/index.js +2 -0
  37. package/dist/mcp/index.js.map +1 -0
  38. package/dist/mcp/instructions.d.ts +3 -0
  39. package/dist/mcp/instructions.d.ts.map +1 -0
  40. package/dist/mcp/instructions.js +16 -0
  41. package/dist/mcp/instructions.js.map +1 -0
  42. package/dist/mcp/register.d.ts +4 -0
  43. package/dist/mcp/register.d.ts.map +1 -0
  44. package/dist/mcp/register.js +13 -0
  45. package/dist/mcp/register.js.map +1 -0
  46. package/dist/mcp/result.d.ts +4 -0
  47. package/dist/mcp/result.d.ts.map +1 -0
  48. package/dist/mcp/result.js +14 -0
  49. package/dist/mcp/result.js.map +1 -0
  50. package/dist/mcp/types.d.ts +39 -0
  51. package/dist/mcp/types.d.ts.map +1 -0
  52. package/dist/mcp/types.js +2 -0
  53. package/dist/mcp/types.js.map +1 -0
  54. package/dist/refs.d.ts +6 -0
  55. package/dist/refs.d.ts.map +1 -1
  56. package/dist/refs.js +17 -1
  57. package/dist/refs.js.map +1 -1
  58. package/dist/skill.generated.d.ts +3 -0
  59. package/dist/skill.generated.d.ts.map +1 -0
  60. package/dist/skill.generated.js +4 -0
  61. package/dist/skill.generated.js.map +1 -0
  62. package/dist/standalone.d.ts +4 -0
  63. package/dist/standalone.d.ts.map +1 -0
  64. package/dist/standalone.js +8 -0
  65. package/dist/standalone.js.map +1 -0
  66. package/package.json +14 -2
  67. package/skills/market/SKILL.md +34 -29
  68. package/src/auth.ts +42 -0
  69. package/src/cli.ts +2 -2
  70. package/src/command.ts +2 -43
  71. package/src/commands/preview.ts +2 -3
  72. package/src/commands/urls.ts +2 -2
  73. package/src/index.ts +10 -0
  74. package/src/mcp/agent.ts +39 -0
  75. package/src/mcp/asset.ts +158 -0
  76. package/src/mcp/generation.ts +41 -0
  77. package/src/mcp/index.ts +7 -0
  78. package/src/mcp/instructions.ts +22 -0
  79. package/src/mcp/register.ts +17 -0
  80. package/src/mcp/result.ts +18 -0
  81. package/src/mcp/types.ts +43 -0
  82. package/src/refs.ts +32 -1
  83. package/src/skill.generated.ts +5 -0
  84. package/src/standalone.ts +9 -0
  85. package/dist/commands/asset-ref.d.ts +0 -9
  86. package/dist/commands/asset-ref.d.ts.map +0 -1
  87. package/dist/commands/asset-ref.js +0 -19
  88. package/dist/commands/asset-ref.js.map +0 -1
  89. package/dist/skill.d.ts +0 -2
  90. package/dist/skill.d.ts.map +0 -1
  91. package/dist/skill.js +0 -60
  92. package/dist/skill.js.map +0 -1
  93. package/src/commands/asset-ref.ts +0 -35
  94. package/src/skill.ts +0 -59
@@ -0,0 +1,39 @@
1
+ import { agentStartSchema, agentStatusSchema } from '../schemas.js'
2
+ import type { MarketV1Client } from '../v1/client.js'
3
+ import { result } from './result.js'
4
+ import type { MarketMcpServer } from './types.js'
5
+
6
+ export function registerAgentTools(server: MarketMcpServer, client: MarketV1Client): void {
7
+ server.registerTool(
8
+ 'start_market_agent_run',
9
+ {
10
+ title: 'Start Market agent run',
11
+ description:
12
+ 'Start a Market agent run that plans, finds, judges, and generates a coherent set of assets for a goal.',
13
+ inputSchema: agentStartSchema,
14
+ annotations: {
15
+ readOnlyHint: false,
16
+ destructiveHint: false,
17
+ openWorldHint: true,
18
+ idempotentHint: false,
19
+ },
20
+ },
21
+ async (input) => result({ run: await client.asset.agent.start(input) }),
22
+ )
23
+
24
+ server.registerTool(
25
+ 'get_market_agent_run',
26
+ {
27
+ title: 'Get Market agent run',
28
+ description: 'Get the current state and result of a Market agent run.',
29
+ inputSchema: agentStatusSchema,
30
+ annotations: {
31
+ readOnlyHint: true,
32
+ destructiveHint: false,
33
+ openWorldHint: true,
34
+ idempotentHint: true,
35
+ },
36
+ },
37
+ async (input) => result({ run: await client.asset.agent.status(input) }),
38
+ )
39
+ }
@@ -0,0 +1,158 @@
1
+ import { z } from 'zod'
2
+ import { resolveAsset } from '../refs.js'
3
+ import { assetTypeSchema } from '../schemas.js'
4
+ import type { MarketV1Client } from '../v1/client.js'
5
+ import { base64, result } from './result.js'
6
+ import type { MarketMcpServer } from './types.js'
7
+
8
+ const searchMarketSchema = z
9
+ .object({
10
+ query: z.string().min(1).max(200),
11
+ type: assetTypeSchema,
12
+ limit: z.coerce.number().int().min(1).max(5).default(3),
13
+ includeUnapproved: z.boolean().default(false),
14
+ })
15
+ .strict()
16
+
17
+ const assetRefSchema = z.string().min(1).describe('Asset name or exact name@version')
18
+ const assetInput = z
19
+ .object({
20
+ asset: assetRefSchema,
21
+ includeUnapproved: z.boolean().default(false),
22
+ key: z.string().min(1).max(128).optional(),
23
+ })
24
+ .strict()
25
+
26
+ export function registerAssetTools(
27
+ server: MarketMcpServer,
28
+ client: MarketV1Client,
29
+ fetcher: typeof globalThis.fetch,
30
+ ): void {
31
+ server.registerTool(
32
+ 'list_market_asset_types',
33
+ {
34
+ title: 'List Market asset types',
35
+ description:
36
+ 'List current Drawcall Market asset types with their search, generation, and installation guidance.',
37
+ annotations: {
38
+ readOnlyHint: true,
39
+ destructiveHint: false,
40
+ openWorldHint: true,
41
+ idempotentHint: true,
42
+ },
43
+ },
44
+ async () => result({ types: await client.asset.installMetadata() }),
45
+ )
46
+
47
+ server.registerTool(
48
+ 'search_market',
49
+ {
50
+ title: 'Search Market',
51
+ description:
52
+ 'Search Drawcall Market for assets matching one concrete need. Returns exact name@version references; call get_market_asset before selecting one.',
53
+ inputSchema: searchMarketSchema,
54
+ annotations: {
55
+ readOnlyHint: true,
56
+ destructiveHint: false,
57
+ openWorldHint: true,
58
+ idempotentHint: true,
59
+ },
60
+ },
61
+ async ({ query, type, limit, includeUnapproved }) => {
62
+ const response = await client.asset.search({
63
+ query,
64
+ type,
65
+ limit,
66
+ page: 1,
67
+ includeUnapproved,
68
+ })
69
+ if (!('items' in response)) {
70
+ throw new Error('Market search unexpectedly returned an exact asset result')
71
+ }
72
+ return result({
73
+ assets: response.items.map((asset) => ({
74
+ asset: `${asset.name}@${asset.latestVersion}`,
75
+ name: asset.name,
76
+ version: asset.latestVersion,
77
+ type: asset.type,
78
+ description: asset.description,
79
+ approved: asset.approved,
80
+ access: asset.access,
81
+ previewUrl: asset.previewUrl,
82
+ })),
83
+ total: response.total,
84
+ })
85
+ },
86
+ )
87
+
88
+ server.registerTool(
89
+ 'get_market_asset',
90
+ {
91
+ title: 'Get Market asset',
92
+ description:
93
+ 'Get one exact Drawcall Market asset manifest with its version history, dependencies, files, preview URL, and zip URL.',
94
+ inputSchema: assetInput,
95
+ annotations: {
96
+ readOnlyHint: true,
97
+ destructiveHint: false,
98
+ openWorldHint: true,
99
+ idempotentHint: true,
100
+ },
101
+ },
102
+ async ({ asset, includeUnapproved, key }) =>
103
+ result({
104
+ asset: await resolveAsset(client.asset, asset, {
105
+ includeUnapproved,
106
+ ...(key ? { key } : {}),
107
+ }),
108
+ }),
109
+ )
110
+
111
+ server.registerTool(
112
+ 'get_market_asset_preview',
113
+ {
114
+ title: 'Get Market asset preview',
115
+ description: 'Return the preview image for one exact Drawcall Market asset.',
116
+ inputSchema: assetInput,
117
+ annotations: {
118
+ readOnlyHint: true,
119
+ destructiveHint: false,
120
+ openWorldHint: true,
121
+ idempotentHint: true,
122
+ },
123
+ },
124
+ async ({ asset: ref, includeUnapproved, key }) => {
125
+ const asset = await resolveAsset(client.asset, ref, {
126
+ includeUnapproved,
127
+ ...(key ? { key } : {}),
128
+ })
129
+ if (!asset.previewUrl) throw new Error(`Asset "${ref}" has no preview image`)
130
+
131
+ const response = await fetcher(asset.previewUrl)
132
+ if (!response.ok) {
133
+ throw new Error(
134
+ `Could not read preview ${asset.previewUrl}: ${response.status} ${response.statusText}`,
135
+ )
136
+ }
137
+ const mimeType = response.headers.get('content-type')?.split(';', 1)[0]
138
+ if (!mimeType?.startsWith('image/')) {
139
+ throw new Error(`Preview ${asset.previewUrl} returned ${mimeType ?? 'no media type'}`)
140
+ }
141
+
142
+ return {
143
+ content: [
144
+ {
145
+ type: 'image',
146
+ data: base64(new Uint8Array(await response.arrayBuffer())),
147
+ mimeType,
148
+ },
149
+ ],
150
+ structuredContent: {
151
+ asset: `${asset.name}@${asset.version}`,
152
+ url: asset.previewUrl,
153
+ mediaType: mimeType,
154
+ },
155
+ }
156
+ },
157
+ )
158
+ }
@@ -0,0 +1,41 @@
1
+ import { assetTypeSchema, generateAssetSchema, generateStatusInputSchema } from '../schemas.js'
2
+ import type { MarketV1Client } from '../v1/client.js'
3
+ import { result } from './result.js'
4
+ import type { MarketMcpServer } from './types.js'
5
+
6
+ const generateMarketAssetSchema = generateAssetSchema.extend({ type: assetTypeSchema }).strict()
7
+
8
+ export function registerGenerationTools(server: MarketMcpServer, client: MarketV1Client): void {
9
+ server.registerTool(
10
+ 'generate_market_asset',
11
+ {
12
+ title: 'Generate Market asset',
13
+ description:
14
+ 'Generate one Drawcall Market asset. A slow provider returns a jobId to pass to get_market_asset_generation.',
15
+ inputSchema: generateMarketAssetSchema,
16
+ annotations: {
17
+ readOnlyHint: false,
18
+ destructiveHint: false,
19
+ openWorldHint: true,
20
+ idempotentHint: false,
21
+ },
22
+ },
23
+ async (input) => result({ generation: await client.asset.generate(input) }),
24
+ )
25
+
26
+ server.registerTool(
27
+ 'get_market_asset_generation',
28
+ {
29
+ title: 'Get Market asset generation',
30
+ description: 'Get the current state of a Market asset generation job.',
31
+ inputSchema: generateStatusInputSchema.strict(),
32
+ annotations: {
33
+ readOnlyHint: true,
34
+ destructiveHint: false,
35
+ openWorldHint: true,
36
+ idempotentHint: true,
37
+ },
38
+ },
39
+ async (input) => result({ generation: await client.asset.generateStatus(input) }),
40
+ )
41
+ }
@@ -0,0 +1,7 @@
1
+ export { registerMarketTools } from './register.js'
2
+ export type {
3
+ MarketMcpCapabilities,
4
+ MarketMcpOptions,
5
+ MarketMcpServer,
6
+ MarketMcpToolResult,
7
+ } from './types.js'
@@ -0,0 +1,22 @@
1
+ import { z } from 'zod'
2
+ import { mcpMarketSkill } from '../skill.generated.js'
3
+ import type { MarketMcpServer } from './types.js'
4
+
5
+ export function registerInstructions(server: MarketMcpServer): void {
6
+ server.registerTool(
7
+ 'get_market_instructions',
8
+ {
9
+ title: 'Get Market instructions',
10
+ description:
11
+ 'Return instructions for finding, inspecting, generating, and using Drawcall Market assets.',
12
+ inputSchema: z.object({}).strict(),
13
+ annotations: {
14
+ readOnlyHint: true,
15
+ destructiveHint: false,
16
+ openWorldHint: false,
17
+ idempotentHint: true,
18
+ },
19
+ },
20
+ async () => ({ content: [{ type: 'text', text: mcpMarketSkill }] }),
21
+ )
22
+ }
@@ -0,0 +1,17 @@
1
+ import type { MarketV1Client } from '../v1/client.js'
2
+ import { registerAgentTools } from './agent.js'
3
+ import { registerAssetTools } from './asset.js'
4
+ import { registerGenerationTools } from './generation.js'
5
+ import { registerInstructions } from './instructions.js'
6
+ import type { MarketMcpOptions, MarketMcpServer } from './types.js'
7
+
8
+ export function registerMarketTools(
9
+ server: MarketMcpServer,
10
+ client: MarketV1Client,
11
+ options: MarketMcpOptions = {},
12
+ ): void {
13
+ registerInstructions(server)
14
+ registerAssetTools(server, client, options.fetch ?? globalThis.fetch)
15
+ if (options.capabilities?.generate) registerGenerationTools(server, client)
16
+ if (options.capabilities?.agent) registerAgentTools(server, client)
17
+ }
@@ -0,0 +1,18 @@
1
+ import type { MarketMcpToolResult } from './types.js'
2
+
3
+ export function result<Structured extends Record<string, unknown>>(
4
+ structuredContent: Structured,
5
+ ): MarketMcpToolResult {
6
+ return {
7
+ content: [{ type: 'text', text: JSON.stringify(structuredContent) }],
8
+ structuredContent,
9
+ }
10
+ }
11
+
12
+ export function base64(bytes: Uint8Array): string {
13
+ let binary = ''
14
+ for (let offset = 0; offset < bytes.length; offset += 32_768) {
15
+ binary += String.fromCharCode(...bytes.subarray(offset, offset + 32_768))
16
+ }
17
+ return btoa(binary)
18
+ }
@@ -0,0 +1,43 @@
1
+ import type { z } from 'zod'
2
+
3
+ export interface MarketMcpToolResult {
4
+ [key: string]: unknown
5
+ content: Array<{ type: 'text'; text: string } | { type: 'image'; data: string; mimeType: string }>
6
+ structuredContent?: Record<string, unknown>
7
+ }
8
+
9
+ interface MarketMcpToolAnnotations {
10
+ readOnlyHint?: boolean
11
+ destructiveHint?: boolean
12
+ idempotentHint?: boolean
13
+ openWorldHint?: boolean
14
+ }
15
+
16
+ interface MarketMcpToolConfig<Input extends z.ZodType | undefined> {
17
+ title?: string
18
+ description?: string
19
+ inputSchema?: Input
20
+ annotations?: MarketMcpToolAnnotations
21
+ }
22
+
23
+ type MarketMcpToolHandler<Input extends z.ZodType | undefined> = Input extends z.ZodType
24
+ ? (input: z.output<Input>) => Promise<MarketMcpToolResult>
25
+ : () => Promise<MarketMcpToolResult>
26
+
27
+ export interface MarketMcpServer {
28
+ registerTool<Input extends z.ZodType | undefined = undefined>(
29
+ name: string,
30
+ config: MarketMcpToolConfig<Input>,
31
+ handler: MarketMcpToolHandler<Input>,
32
+ ): unknown
33
+ }
34
+
35
+ export interface MarketMcpCapabilities {
36
+ generate?: boolean
37
+ agent?: boolean
38
+ }
39
+
40
+ export interface MarketMcpOptions {
41
+ fetch?: typeof globalThis.fetch
42
+ capabilities?: MarketMcpCapabilities
43
+ }
package/src/refs.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { MarketClient } from './client.js'
2
- import { MAX_ASSET_REFS_QUERY_LENGTH } from './schemas.js'
2
+ import { assetNameSchema, MAX_ASSET_REFS_QUERY_LENGTH, semverSchema } from './schemas.js'
3
3
  import type { AssetRefEntry } from './v1/index.js'
4
4
 
5
5
  export interface AssetRef {
@@ -12,6 +12,11 @@ export interface RefsReader {
12
12
  search: MarketClient['asset']['search']
13
13
  }
14
14
 
15
+ export interface ResolveAssetOptions {
16
+ includeUnapproved?: boolean
17
+ key?: string
18
+ }
19
+
15
20
  /** The server accepts up to 100 refs and 4,000 characters per read. */
16
21
  const MAX_REFS_PER_CALL = 100
17
22
 
@@ -41,6 +46,32 @@ export async function lookupAssets(
41
46
  return results.flat()
42
47
  }
43
48
 
49
+ /** Resolve a bare asset name or exact name@version without accepting semver ranges. */
50
+ export async function resolveAsset(
51
+ client: RefsReader,
52
+ ref: string,
53
+ opts: ResolveAssetOptions = {},
54
+ ): Promise<AssetRefEntry> {
55
+ const separator = ref.indexOf('@')
56
+ const name = assetNameSchema.parse(separator === -1 ? ref : ref.slice(0, separator))
57
+ const requestedVersion =
58
+ separator === -1 ? undefined : semverSchema.parse(ref.slice(separator + 1))
59
+ const [asset] = await lookupAssets(
60
+ client,
61
+ [{ name, ...(requestedVersion ? { version: requestedVersion } : {}) }],
62
+ {
63
+ includeUnapproved: opts.includeUnapproved ?? false,
64
+ ...(opts.key ? { key: opts.key } : {}),
65
+ },
66
+ )
67
+
68
+ if (!asset) throw new Error(`Asset "${ref}" not found`)
69
+ if (requestedVersion && asset.version !== requestedVersion) {
70
+ throw new Error(`Market API did not return requested version "${ref}"`)
71
+ }
72
+ return asset
73
+ }
74
+
44
75
  function chunkRefs(refs: AssetRef[]): string[] {
45
76
  const chunks: string[] = []
46
77
  let chunk: string[] = []
@@ -0,0 +1,5 @@
1
+ // Generated from skill/SKILL.template.md.
2
+ export const cliMarketSkill =
3
+ '---\nname: market\ndescription: Find, inspect, generate, and use Drawcall Market assets from a coding agent.\n---\n\n# Drawcall Market\n\n## CLI transport\n\nRun commands as `npx @drawcall/market <command>`; do not assume a global `market` binary or switch to MCP after a CLI failure. Use `npx @drawcall/market skill` when these instructions are not already available.\n\nDiscover the current vocabulary and choose an asset:\n\n```sh\nnpx @drawcall/market types\nnpx @drawcall/market search "<query>" --type <type> --limit 3\nnpx @drawcall/market preview <name@version> --out /tmp/<name>.png\nnpx @drawcall/market urls <name@version>\n```\n\n`urls` prints one base URL, file subpaths, and a preview URL without changing the project. Install exact refs together when the project needs local files:\n\n```sh\nnpx @drawcall/market install <name@range...> --cwd "$PWD"\n```\n\nInstall records `assetDependencies` in the nearest `package.json`. `list --cwd "$PWD"` reads that inventory without network access. Run `sync --cwd "$PWD"` after moving installed files so aliases continue to resolve. Use `--force` only with permission to overwrite changed files.\n\nGenerate and install one asset with:\n\n```sh\nnpx @drawcall/market generate --type <type> "<description>"\n```\n\nIf it returns a continuation, run the printed `generate install <jobId>` command. The Market agent can source a coherent set of assets from a broader goal:\n\n```sh\nnpx @drawcall/market agent "<goal>"\n```\n\nPublish only when asked. `pack <source> --out <zip>` creates a Market archive and `upload <name> <source> "<description>" --type <type>` publishes it. Use command help for dependency and visibility options. If authentication is required, ask before running `npx @drawcall/market login`.\n\n## Choose assets\n\nSearch one concrete need at a time. Use one result for an exact lookup and up to three when the user should choose. If nothing fits, try one broader noun phrase before generating a replacement.\n\nThe exact `name@version` returned by Market is authoritative. Copy it verbatim. Generated identifiers can legitimately end mid-word at the catalog limit; never expand, normalize, or reconstruct one from its description.\n\nPreview a finalist when appearance determines whether it fits. File, preview, and zip URLs returned by Market are opaque. Capability-bearing private URLs are secrets; never derive a URL from an asset name or preview metadata.\n\n## Generate\n\nGeneration creates one Market asset from a description. The description is provider input, not the eventual asset name. A fast provider may return the asset immediately; a slow provider returns a continuation ID for the matching status operation. Resume that job instead of starting the same generation again.\n\nReference images must be direct fetchable image URLs or image data, never webpage URLs. The current asset-type metadata says which types support references and how many they accept.\n\nA generated humanoid model is one expressive, animation-ready biped: one head, two arms, two legs, open empty hands, and no companions or scene. Describe identity, theme, silhouette, clothing, colors, and materials. Express topology outside the shared skeleton as costume or body-surface design so the result remains riggable.\n\nRequest public or private access only when visibility matters. Private generation requires the account\'s `market:private` entitlement.\n\n## Failures\n\nAn error means the operation did not happen. Correct invalid inputs, refresh an exact reference after a not-found response, and retry one upstream failure once. Never repeat an unchanged failed generation. Use unapproved assets only when the user explicitly requests and accepts them.\n'
4
+ export const mcpMarketSkill =
5
+ "---\nname: market\ndescription: Find, inspect, generate, and use Drawcall Market assets from a coding agent.\n---\n\n# Drawcall Market\n\n## MCP transport\n\nMCP tools are the only Market transport in this environment. Do not invoke the CLI, make direct API requests, or switch transports after a failed call.\n\nUse the same conceptual workflow as the Market CLI:\n\n```text\nlist_market_asset_types\nsearch_market\nget_market_asset\nget_market_asset_preview\n```\n\n`search_market` requires an asset type and returns exact `name@version` references. Inspect the exact manifest with `get_market_asset`; request its preview only when visual evidence matters. Remote MCP tools return immutable references and fetch-ready URLs. They do not install files into the caller's local project.\n\nWhen generation is available, call `generate_market_asset`. If it returns a `jobId`, continue with `get_market_asset_generation`. Do not start the same generation again.\n\nWhen the Market agent is available, call `start_market_agent_run` with the full goal and continue its returned `runId` with `get_market_agent_run`.\n\nUse an exact Market reference with `create_design_frame` when the selected asset belongs in Drawcall Design.\n\n## Choose assets\n\nSearch one concrete need at a time. Use one result for an exact lookup and up to three when the user should choose. If nothing fits, try one broader noun phrase before generating a replacement.\n\nThe exact `name@version` returned by Market is authoritative. Copy it verbatim. Generated identifiers can legitimately end mid-word at the catalog limit; never expand, normalize, or reconstruct one from its description.\n\nPreview a finalist when appearance determines whether it fits. File, preview, and zip URLs returned by Market are opaque. Capability-bearing private URLs are secrets; never derive a URL from an asset name or preview metadata.\n\n## Generate\n\nGeneration creates one Market asset from a description. The description is provider input, not the eventual asset name. A fast provider may return the asset immediately; a slow provider returns a continuation ID for the matching status operation. Resume that job instead of starting the same generation again.\n\nReference images must be direct fetchable image URLs or image data, never webpage URLs. The current asset-type metadata says which types support references and how many they accept.\n\nA generated humanoid model is one expressive, animation-ready biped: one head, two arms, two legs, open empty hands, and no companions or scene. Describe identity, theme, silhouette, clothing, colors, and materials. Express topology outside the shared skeleton as costume or body-surface design so the result remains riggable.\n\nRequest public or private access only when visibility matters. Private generation requires the account's `market:private` entitlement.\n\n## Failures\n\nAn error means the operation did not happen. Correct invalid inputs, refresh an exact reference after a not-found response, and retry one upstream failure once. Never repeat an unchanged failed generation. Use unapproved assets only when the user explicitly requests and accepts them.\n"
@@ -0,0 +1,9 @@
1
+ import type { Command } from 'commander'
2
+ import { createLoginCommand, createLogoutCommand } from './auth.js'
3
+ import { createMarketCommand, type MarketCommandOptions } from './command.js'
4
+
5
+ export function createMarketCli(options: MarketCommandOptions = {}): Command {
6
+ return createMarketCommand(options)
7
+ .addCommand(createLoginCommand())
8
+ .addCommand(createLogoutCommand())
9
+ }
@@ -1,9 +0,0 @@
1
- import type { RefsReader } from '../refs.js';
2
- import type { AssetRefEntry } from '../v1/index.js';
3
- export interface ResolveAssetRefOptions {
4
- includeUnapproved?: boolean;
5
- key?: string;
6
- }
7
- /** Resolve a bare asset name or exact name@version without accepting semver ranges. */
8
- export declare function resolveAssetRef(client: RefsReader, ref: string, opts?: ResolveAssetRefOptions): Promise<AssetRefEntry>;
9
- //# sourceMappingURL=asset-ref.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"asset-ref.d.ts","sourceRoot":"","sources":["../../src/commands/asset-ref.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAG5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD,MAAM,WAAW,sBAAsB;IACrC,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,uFAAuF;AACvF,wBAAsB,eAAe,CACnC,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,sBAA2B,GAChC,OAAO,CAAC,aAAa,CAAC,CAmBxB"}
@@ -1,19 +0,0 @@
1
- import { lookupAssets } from '../refs.js';
2
- import { assetNameSchema, semverSchema } from '../schemas.js';
3
- /** Resolve a bare asset name or exact name@version without accepting semver ranges. */
4
- export async function resolveAssetRef(client, ref, opts = {}) {
5
- const separator = ref.indexOf('@');
6
- const name = assetNameSchema.parse(separator === -1 ? ref : ref.slice(0, separator));
7
- const requestedVersion = separator === -1 ? undefined : semverSchema.parse(ref.slice(separator + 1));
8
- const [asset] = await lookupAssets(client, [{ name, ...(requestedVersion ? { version: requestedVersion } : {}) }], {
9
- includeUnapproved: opts.includeUnapproved ?? false,
10
- ...(opts.key ? { key: opts.key } : {}),
11
- });
12
- if (!asset)
13
- throw new Error(`Asset "${ref}" not found`);
14
- if (requestedVersion && asset.version !== requestedVersion) {
15
- throw new Error(`Market API did not return requested version "${ref}"`);
16
- }
17
- return asset;
18
- }
19
- //# sourceMappingURL=asset-ref.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"asset-ref.js","sourceRoot":"","sources":["../../src/commands/asset-ref.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAQ7D,uFAAuF;AACvF,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAkB,EAClB,GAAW,EACX,OAA+B,EAAE;IAEjC,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAClC,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAA;IACpF,MAAM,gBAAgB,GACpB,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAA;IAC7E,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,YAAY,CAChC,MAAM,EACN,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACtE;QACE,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,IAAI,KAAK;QAClD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvC,CACF,CAAA;IAED,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,aAAa,CAAC,CAAA;IACvD,IAAI,gBAAgB,IAAI,KAAK,CAAC,OAAO,KAAK,gBAAgB,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,gDAAgD,GAAG,GAAG,CAAC,CAAA;IACzE,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
package/dist/skill.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export declare const marketSkill = "---\nname: market\ndescription: Find, preview, remotely reference, install, generate, and publish Drawcall Market assets from a coding agent.\n---\n\n# Drawcall Market\n\nRun commands as `npx @drawcall/market <command>`; do not assume a global `market` binary. Use only the parts of this guide needed for the task.\n\n## Choose and install\n\nRun `npx @drawcall/market types` when you need the current asset types, generation support, or type-specific search guidance.\n\nSearch one concrete need at a time:\n\n`npx @drawcall/market search \"<query>\" --type <type> --limit 3`\n\nUse `--limit 1` for an exact lookup and `--limit 3` for a choice. Search requires `--type` and prints full descriptions. If nothing fits, try one broader noun phrase.\n\nPreview a finalist when the type supports it:\n\n`npx @drawcall/market preview <name@version> --out /tmp/<name>.png`\n\nWhen the codebase cannot accept local asset files, resolve fetch-ready remote URLs without writing to the project:\n\n`npx @drawcall/market urls <name@version>`\n\n`urls` prints one `base`, URL-ready file subpaths, and a `preview`; each file URL is the base plus its indented subpath. Capability-bearing private URLs are secrets. Otherwise, search and preview only select an asset\u2014a local consumer path is valid only after install or generation succeeds. Never derive a browser path from an asset name or preview metadata.\n\nThe exact `name@version` token printed before the first `|` in a search result is authoritative. Copy it verbatim. Generated identifiers can legitimately end mid-word at the catalog limit; never expand, normalize, or reconstruct one from the description beside it.\n\nInstall exact refs together in one call; names need no `--type`:\n\n`npx @drawcall/market install <name@range...> --cwd \"$PWD\"`\n\nInstall prints the exact files it wrote and records the dependency so packing and later rebuilds can restore it. It never searches or generates. With no refs it installs `assetDependencies` from the nearest `package.json`. Assets may install declared skill dependencies with `npx skills add`. Use `--force` only with permission to overwrite changed local files.\n\n`list --cwd \"$PWD\"` is an offline, compact inventory of the `assetDependencies` in the nearest `package.json`, including file aliases. When selected refs are already installed, read this inventory instead of reinstalling them.\n\nAn `assetDependencies` entry is either a range string or `{ \"version\": \"<range>\", \"alias\": { \"<canonical path>\": \"<current path>\" } }`. An alias records where the project keeps a renamed installed file: install writes the file at the aliased path, and packing omits exactly that one copy (extra duplicates ship as project content). Run `sync --cwd \"$PWD\"` after renaming installed files to record aliases in `package.json`; template packing runs the same update automatically.\n\n## Generate\n\n`npx @drawcall/market generate --type <type> \"<description>\"` creates and installs one provider-supported asset. It requires login and normally waits through provider generation before printing exact installed paths and type-specific usage guidance. Unsupported types report an error. If an unusually long job returns a continuation, run the printed `generate install <jobId>`; it resumes the same server-side job rather than generating again.\n\nThe description is provider input, not the installed filename. The command's successful output is the source of truth for consumer paths, so update a consumer with its exact printed browser path after success. If generation fails, leave the current path unchanged.\n\nAdd repeatable `--reference-image <file-or-url>` when the result should match given images; `types` shows which asset types accept reference images. A remote ref must be a direct fetchable image URL, never a webpage URL; use the page only to find its underlying image. An environment matches the look of the references (at most 4). Types without reference image support reject them.\n\nA generated humanoid-model is one expressive, animation-ready biped asset: one head, two arms, two legs, open empty hands, and no companions or scene. Describe its identity, theme, silhouette, clothing, colors, and materials rather than adding generation instructions. Keep imaginative species, creature, robotic, and fantasy ideas; express topology outside the shared skeleton as worn, costume, or body-surface design. A person or humanoid reference preserves the main subject's identity and distinctive features, while a non-person reference supplies visual language such as shapes, colors, and materials (at most 2 references). This boundary keeps the asset riggable without reducing it to a generic human.\n\nAdd `--access public` or `--access private` when visibility matters. Omitted access follows the account entitlement; private generation requires `market:private`.\n\n## Publish only when asked\n\nUse `pack <source> --out <zip>` to create a Market zip and `upload <name> <source> \"<description>\" --type <type>` to publish it. Both accept repeatable `--npm name@range`, `--asset name@range`, and `--skill label=source` dependencies. Template packing reads root `assetDependencies` and may use the API to omit installed dependency files matched by content hash \u2014 even when renamed \u2014 recording renames as aliases. A skill source is `owner/repo`, a git URL, a full GitHub `tree/<branch>/<subpath>` URL, or a local skill directory inside the zip. Use the command's `--help` for syntax.\n\nUse `--unapproved` only when explicitly requested. Do not install an unapproved asset without acceptance. If login is required, ask before running `npx @drawcall/market login`.\n";
2
- //# sourceMappingURL=skill.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,okLA0DvB,CAAA"}
package/dist/skill.js DELETED
@@ -1,60 +0,0 @@
1
- export const marketSkill = `---
2
- name: market
3
- description: Find, preview, remotely reference, install, generate, and publish Drawcall Market assets from a coding agent.
4
- ---
5
-
6
- # Drawcall Market
7
-
8
- Run commands as \`npx @drawcall/market <command>\`; do not assume a global \`market\` binary. Use only the parts of this guide needed for the task.
9
-
10
- ## Choose and install
11
-
12
- Run \`npx @drawcall/market types\` when you need the current asset types, generation support, or type-specific search guidance.
13
-
14
- Search one concrete need at a time:
15
-
16
- \`npx @drawcall/market search "<query>" --type <type> --limit 3\`
17
-
18
- Use \`--limit 1\` for an exact lookup and \`--limit 3\` for a choice. Search requires \`--type\` and prints full descriptions. If nothing fits, try one broader noun phrase.
19
-
20
- Preview a finalist when the type supports it:
21
-
22
- \`npx @drawcall/market preview <name@version> --out /tmp/<name>.png\`
23
-
24
- When the codebase cannot accept local asset files, resolve fetch-ready remote URLs without writing to the project:
25
-
26
- \`npx @drawcall/market urls <name@version>\`
27
-
28
- \`urls\` prints one \`base\`, URL-ready file subpaths, and a \`preview\`; each file URL is the base plus its indented subpath. Capability-bearing private URLs are secrets. Otherwise, search and preview only select an asset—a local consumer path is valid only after install or generation succeeds. Never derive a browser path from an asset name or preview metadata.
29
-
30
- The exact \`name@version\` token printed before the first \`|\` in a search result is authoritative. Copy it verbatim. Generated identifiers can legitimately end mid-word at the catalog limit; never expand, normalize, or reconstruct one from the description beside it.
31
-
32
- Install exact refs together in one call; names need no \`--type\`:
33
-
34
- \`npx @drawcall/market install <name@range...> --cwd "$PWD"\`
35
-
36
- Install prints the exact files it wrote and records the dependency so packing and later rebuilds can restore it. It never searches or generates. With no refs it installs \`assetDependencies\` from the nearest \`package.json\`. Assets may install declared skill dependencies with \`npx skills add\`. Use \`--force\` only with permission to overwrite changed local files.
37
-
38
- \`list --cwd "$PWD"\` is an offline, compact inventory of the \`assetDependencies\` in the nearest \`package.json\`, including file aliases. When selected refs are already installed, read this inventory instead of reinstalling them.
39
-
40
- An \`assetDependencies\` entry is either a range string or \`{ "version": "<range>", "alias": { "<canonical path>": "<current path>" } }\`. An alias records where the project keeps a renamed installed file: install writes the file at the aliased path, and packing omits exactly that one copy (extra duplicates ship as project content). Run \`sync --cwd "$PWD"\` after renaming installed files to record aliases in \`package.json\`; template packing runs the same update automatically.
41
-
42
- ## Generate
43
-
44
- \`npx @drawcall/market generate --type <type> "<description>"\` creates and installs one provider-supported asset. It requires login and normally waits through provider generation before printing exact installed paths and type-specific usage guidance. Unsupported types report an error. If an unusually long job returns a continuation, run the printed \`generate install <jobId>\`; it resumes the same server-side job rather than generating again.
45
-
46
- The description is provider input, not the installed filename. The command's successful output is the source of truth for consumer paths, so update a consumer with its exact printed browser path after success. If generation fails, leave the current path unchanged.
47
-
48
- Add repeatable \`--reference-image <file-or-url>\` when the result should match given images; \`types\` shows which asset types accept reference images. A remote ref must be a direct fetchable image URL, never a webpage URL; use the page only to find its underlying image. An environment matches the look of the references (at most 4). Types without reference image support reject them.
49
-
50
- A generated humanoid-model is one expressive, animation-ready biped asset: one head, two arms, two legs, open empty hands, and no companions or scene. Describe its identity, theme, silhouette, clothing, colors, and materials rather than adding generation instructions. Keep imaginative species, creature, robotic, and fantasy ideas; express topology outside the shared skeleton as worn, costume, or body-surface design. A person or humanoid reference preserves the main subject's identity and distinctive features, while a non-person reference supplies visual language such as shapes, colors, and materials (at most 2 references). This boundary keeps the asset riggable without reducing it to a generic human.
51
-
52
- Add \`--access public\` or \`--access private\` when visibility matters. Omitted access follows the account entitlement; private generation requires \`market:private\`.
53
-
54
- ## Publish only when asked
55
-
56
- Use \`pack <source> --out <zip>\` to create a Market zip and \`upload <name> <source> "<description>" --type <type>\` to publish it. Both accept repeatable \`--npm name@range\`, \`--asset name@range\`, and \`--skill label=source\` dependencies. Template packing reads root \`assetDependencies\` and may use the API to omit installed dependency files matched by content hash — even when renamed — recording renames as aliases. A skill source is \`owner/repo\`, a git URL, a full GitHub \`tree/<branch>/<subpath>\` URL, or a local skill directory inside the zip. Use the command's \`--help\` for syntax.
57
-
58
- Use \`--unapproved\` only when explicitly requested. Do not install an unapproved asset without acceptance. If login is required, ask before running \`npx @drawcall/market login\`.
59
- `;
60
- //# sourceMappingURL=skill.js.map
package/dist/skill.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0D1B,CAAA"}
@@ -1,35 +0,0 @@
1
- import type { RefsReader } from '../refs.js'
2
- import { lookupAssets } from '../refs.js'
3
- import { assetNameSchema, semverSchema } from '../schemas.js'
4
- import type { AssetRefEntry } from '../v1/index.js'
5
-
6
- export interface ResolveAssetRefOptions {
7
- includeUnapproved?: boolean
8
- key?: string
9
- }
10
-
11
- /** Resolve a bare asset name or exact name@version without accepting semver ranges. */
12
- export async function resolveAssetRef(
13
- client: RefsReader,
14
- ref: string,
15
- opts: ResolveAssetRefOptions = {},
16
- ): Promise<AssetRefEntry> {
17
- const separator = ref.indexOf('@')
18
- const name = assetNameSchema.parse(separator === -1 ? ref : ref.slice(0, separator))
19
- const requestedVersion =
20
- separator === -1 ? undefined : semverSchema.parse(ref.slice(separator + 1))
21
- const [asset] = await lookupAssets(
22
- client,
23
- [{ name, ...(requestedVersion ? { version: requestedVersion } : {}) }],
24
- {
25
- includeUnapproved: opts.includeUnapproved ?? false,
26
- ...(opts.key ? { key: opts.key } : {}),
27
- },
28
- )
29
-
30
- if (!asset) throw new Error(`Asset "${ref}" not found`)
31
- if (requestedVersion && asset.version !== requestedVersion) {
32
- throw new Error(`Market API did not return requested version "${ref}"`)
33
- }
34
- return asset
35
- }