@drawcall/market 0.1.85 → 0.1.87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.d.ts CHANGED
@@ -1,10 +1,19 @@
1
1
  import type { ContractRouterClient } from '@orpc/contract';
2
2
  import type { AppContract } from './contract.js';
3
3
  export type MarketClient = ContractRouterClient<AppContract>;
4
+ type RequestFetch = (request: Request, init?: {
5
+ redirect?: Request['redirect'];
6
+ }) => Promise<Response>;
4
7
  export interface MarketClientOptions {
5
8
  baseUrl?: string;
6
- fetch?: typeof globalThis.fetch;
9
+ fetch?: RequestFetch;
7
10
  authToken?: string;
8
11
  }
12
+ interface RetryOptions {
13
+ attempts?: number;
14
+ delayMs?: number;
15
+ }
9
16
  export declare function createMarketClient(opts?: MarketClientOptions): MarketClient;
17
+ export declare function createRetryingFetch(fetchImpl: RequestFetch, options?: RetryOptions): RequestFetch;
18
+ export {};
10
19
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,MAAM,MAAM,YAAY,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAA;AAI5D,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAMD,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,mBAAwB,GAAG,YAAY,CAQ/E"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,MAAM,MAAM,YAAY,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAA;AAC5D,KAAK,YAAY,GAAG,CAClB,OAAO,EAAE,OAAO,EAChB,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;CAAE,KACtC,OAAO,CAAC,QAAQ,CAAC,CAAA;AAgBtB,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,UAAU,YAAY;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAMD,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,mBAAwB,GAAG,YAAY,CAY/E;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,YAAY,EACvB,OAAO,GAAE,YAAiB,GACzB,YAAY,CA2Bd"}
package/dist/client.js CHANGED
@@ -1,16 +1,65 @@
1
1
  import { createORPCClient } from '@orpc/client';
2
2
  import { RPCLink } from '@orpc/client/fetch';
3
3
  const DEFAULT_BASE_URL = 'https://market.drawcall.ai';
4
+ const RETRYABLE_RPC_PATHS = new Set([
5
+ '/api/rpc/asset/search',
6
+ '/api/rpc/asset/exact',
7
+ '/api/rpc/asset/downloadZip',
8
+ '/api/rpc/asset/files',
9
+ '/api/rpc/asset/fileManifest',
10
+ '/api/rpc/asset/generateStatus',
11
+ '/api/rpc/asset/installMetadata',
12
+ '/api/rpc/asset/agent/status',
13
+ '/api/rpc/user/getProfile',
14
+ '/api/rpc/user/getAuthToken',
15
+ ]);
4
16
  function buildHeaders(authToken) {
5
17
  return authToken ? { authorization: `Bearer ${authToken}` } : undefined;
6
18
  }
7
19
  export function createMarketClient(opts = {}) {
8
20
  const baseUrl = opts.baseUrl ?? DEFAULT_BASE_URL;
21
+ const fetch = opts.fetch ??
22
+ ((request, init) => globalThis.fetch(new Request(request), init));
9
23
  const link = new RPCLink({
10
24
  url: new URL('/api/rpc', baseUrl).href,
11
- fetch: opts.fetch,
25
+ fetch: createRetryingFetch(fetch),
12
26
  headers: buildHeaders(opts.authToken),
13
27
  });
14
28
  return createORPCClient(link);
15
29
  }
30
+ export function createRetryingFetch(fetchImpl, options = {}) {
31
+ const attempts = options.attempts ?? 4;
32
+ const delayMs = options.delayMs ?? 250;
33
+ return async (request, init) => {
34
+ if (!RETRYABLE_RPC_PATHS.has(new URL(request.url).pathname)) {
35
+ return fetchImpl(request, init);
36
+ }
37
+ const body = request.body ? new Uint8Array(await request.clone().arrayBuffer()) : undefined;
38
+ const nextRequest = () => new Request(request.url, {
39
+ method: request.method,
40
+ headers: request.headers,
41
+ body,
42
+ credentials: request.credentials,
43
+ signal: request.signal,
44
+ });
45
+ for (let attempt = 1;; attempt += 1) {
46
+ try {
47
+ const response = await fetchImpl(nextRequest(), init);
48
+ if (attempt === attempts || !isTransientStatus(response.status))
49
+ return response;
50
+ }
51
+ catch (error) {
52
+ if (attempt === attempts)
53
+ throw error;
54
+ }
55
+ await delay(delayMs * 2 ** (attempt - 1));
56
+ }
57
+ };
58
+ }
59
+ function isTransientStatus(status) {
60
+ return status === 429 || status >= 500;
61
+ }
62
+ function delay(ms) {
63
+ return new Promise((resolve) => setTimeout(resolve, ms));
64
+ }
16
65
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAM5C,MAAM,gBAAgB,GAAG,4BAA4B,CAAA;AAQrD,SAAS,YAAY,CAAC,SAAkB;IACtC,OAAO,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AACzE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAA4B,EAAE;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,gBAAgB,CAAA;IAChD,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC;QACvB,GAAG,EAAE,IAAI,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI;QACtC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC;KACtC,CAAC,CAAA;IACF,OAAO,gBAAgB,CAAe,IAAI,CAAC,CAAA;AAC7C,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAU5C,MAAM,gBAAgB,GAAG,4BAA4B,CAAA;AACrD,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,uBAAuB;IACvB,sBAAsB;IACtB,4BAA4B;IAC5B,sBAAsB;IACtB,6BAA6B;IAC7B,+BAA+B;IAC/B,gCAAgC;IAChC,6BAA6B;IAC7B,0BAA0B;IAC1B,4BAA4B;CAC7B,CAAC,CAAA;AAaF,SAAS,YAAY,CAAC,SAAkB;IACtC,OAAO,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AACzE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAA4B,EAAE;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,gBAAgB,CAAA;IAChD,MAAM,KAAK,GACT,IAAI,CAAC,KAAK;QACV,CAAC,CAAC,OAAgB,EAAE,IAAyC,EAAE,EAAE,CAC/D,UAAU,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA;IACjD,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC;QACvB,GAAG,EAAE,IAAI,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI;QACtC,KAAK,EAAE,mBAAmB,CAAC,KAAK,CAAC;QACjC,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC;KACtC,CAAC,CAAA;IACF,OAAO,gBAAgB,CAAe,IAAI,CAAC,CAAA;AAC7C,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,SAAuB,EACvB,UAAwB,EAAE;IAE1B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAA;IACtC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,GAAG,CAAA;IAEtC,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC7B,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5D,OAAO,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;QACjC,CAAC;QACD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAC3F,MAAM,WAAW,GAAG,GAAG,EAAE,CACvB,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;YACvB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,IAAI;YACJ,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAA;QACJ,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,IAAI,CAAC,EAAE,CAAC;YACrC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,CAAA;gBACrD,IAAI,OAAO,KAAK,QAAQ,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAAE,OAAO,QAAQ,CAAA;YAClF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,OAAO,KAAK,QAAQ;oBAAE,MAAM,KAAK,CAAA;YACvC,CAAC;YACD,MAAM,KAAK,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAA;QAC3C,CAAC;IACH,CAAC,CAAA;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAc;IACvC,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,IAAI,GAAG,CAAA;AACxC,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;AAC1D,CAAC"}
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\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\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. 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 from `.drawcall/market-lock.json`. Add `--files` only when exact paths for previously installed assets are needed; fresh install and generation already print their paths.\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\nAdd repeatable `--reference-image <file-or-url>` when the result should match given images; `types` shows which asset types accept reference images. A humanoid-model keeps the face and distinctive features of the person shown (at most 2 images); an environment matches the look of the references (at most 4). Types without reference image support reject them.\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 unchanged installed dependency files. 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";
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\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\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. 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 from `.drawcall/market-lock.json`. Add `--files` only when exact paths for previously installed assets are needed; fresh install and generation already print their paths.\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. A humanoid-model keeps the face and distinctive features of the person shown (at most 2 images); describe one isolated full-body character in one pose/view, with no companions. An environment matches the look of the references (at most 4). Types without reference image support reject them.\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 unchanged installed dependency files. 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
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,mqGA4CvB,CAAA"}
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,unHA8CvB,CAAA"}
package/dist/skill.js CHANGED
@@ -33,7 +33,9 @@ Install prints the exact files it wrote. It never searches or generates. With no
33
33
 
34
34
  \`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.
35
35
 
36
- Add repeatable \`--reference-image <file-or-url>\` when the result should match given images; \`types\` shows which asset types accept reference images. A humanoid-model keeps the face and distinctive features of the person shown (at most 2 images); an environment matches the look of the references (at most 4). Types without reference image support reject them.
36
+ 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.
37
+
38
+ 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. A humanoid-model keeps the face and distinctive features of the person shown (at most 2 images); describe one isolated full-body character in one pose/view, with no companions. An environment matches the look of the references (at most 4). Types without reference image support reject them.
37
39
 
38
40
  Add \`--access public\` or \`--access private\` when visibility matters. Omitted access follows the account entitlement; private generation requires \`market:private\`.
39
41
 
package/dist/skill.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4C1B,CAAA"}
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8C1B,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawcall/market",
3
- "version": "0.1.85",
3
+ "version": "0.1.87",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/drawcall-ai/market",
@@ -35,7 +35,7 @@ Install prints the exact files it wrote. It never searches or generates. With no
35
35
 
36
36
  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.
37
37
 
38
- Add repeatable `--reference-image <file-or-url>` when the result should match given images; `types` shows which asset types accept reference images. A humanoid-model keeps the face and distinctive features of the person shown (at most 2 images); an environment matches the look of the references (at most 4). Types without reference image support reject them.
38
+ 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. A humanoid-model keeps the face and distinctive features of the person shown (at most 2 images); describe one isolated full-body character in one pose/view, with no companions. An environment matches the look of the references (at most 4). Types without reference image support reject them.
39
39
 
40
40
  Add `--access public` or `--access private` when visibility matters. Omitted access follows the account entitlement; private generation requires `market:private`.
41
41
 
package/src/client.ts CHANGED
@@ -4,25 +4,90 @@ import type { ContractRouterClient } from '@orpc/contract'
4
4
  import type { AppContract } from './contract.js'
5
5
 
6
6
  export type MarketClient = ContractRouterClient<AppContract>
7
+ type RequestFetch = (
8
+ request: Request,
9
+ init?: { redirect?: Request['redirect'] },
10
+ ) => Promise<Response>
7
11
 
8
12
  const DEFAULT_BASE_URL = 'https://market.drawcall.ai'
13
+ const RETRYABLE_RPC_PATHS = new Set([
14
+ '/api/rpc/asset/search',
15
+ '/api/rpc/asset/exact',
16
+ '/api/rpc/asset/downloadZip',
17
+ '/api/rpc/asset/files',
18
+ '/api/rpc/asset/fileManifest',
19
+ '/api/rpc/asset/generateStatus',
20
+ '/api/rpc/asset/installMetadata',
21
+ '/api/rpc/asset/agent/status',
22
+ '/api/rpc/user/getProfile',
23
+ '/api/rpc/user/getAuthToken',
24
+ ])
9
25
 
10
26
  export interface MarketClientOptions {
11
27
  baseUrl?: string
12
- fetch?: typeof globalThis.fetch
28
+ fetch?: RequestFetch
13
29
  authToken?: string
14
30
  }
15
31
 
32
+ interface RetryOptions {
33
+ attempts?: number
34
+ delayMs?: number
35
+ }
36
+
16
37
  function buildHeaders(authToken?: string): Record<string, string> | undefined {
17
38
  return authToken ? { authorization: `Bearer ${authToken}` } : undefined
18
39
  }
19
40
 
20
41
  export function createMarketClient(opts: MarketClientOptions = {}): MarketClient {
21
42
  const baseUrl = opts.baseUrl ?? DEFAULT_BASE_URL
43
+ const fetch =
44
+ opts.fetch ??
45
+ ((request: Request, init?: { redirect?: Request['redirect'] }) =>
46
+ globalThis.fetch(new Request(request), init))
22
47
  const link = new RPCLink({
23
48
  url: new URL('/api/rpc', baseUrl).href,
24
- fetch: opts.fetch,
49
+ fetch: createRetryingFetch(fetch),
25
50
  headers: buildHeaders(opts.authToken),
26
51
  })
27
52
  return createORPCClient<MarketClient>(link)
28
53
  }
54
+
55
+ export function createRetryingFetch(
56
+ fetchImpl: RequestFetch,
57
+ options: RetryOptions = {},
58
+ ): RequestFetch {
59
+ const attempts = options.attempts ?? 4
60
+ const delayMs = options.delayMs ?? 250
61
+
62
+ return async (request, init) => {
63
+ if (!RETRYABLE_RPC_PATHS.has(new URL(request.url).pathname)) {
64
+ return fetchImpl(request, init)
65
+ }
66
+ const body = request.body ? new Uint8Array(await request.clone().arrayBuffer()) : undefined
67
+ const nextRequest = () =>
68
+ new Request(request.url, {
69
+ method: request.method,
70
+ headers: request.headers,
71
+ body,
72
+ credentials: request.credentials,
73
+ signal: request.signal,
74
+ })
75
+ for (let attempt = 1; ; attempt += 1) {
76
+ try {
77
+ const response = await fetchImpl(nextRequest(), init)
78
+ if (attempt === attempts || !isTransientStatus(response.status)) return response
79
+ } catch (error) {
80
+ if (attempt === attempts) throw error
81
+ }
82
+ await delay(delayMs * 2 ** (attempt - 1))
83
+ }
84
+ }
85
+ }
86
+
87
+ function isTransientStatus(status: number): boolean {
88
+ return status === 429 || status >= 500
89
+ }
90
+
91
+ function delay(ms: number): Promise<void> {
92
+ return new Promise((resolve) => setTimeout(resolve, ms))
93
+ }
package/src/skill.ts CHANGED
@@ -33,7 +33,9 @@ Install prints the exact files it wrote. It never searches or generates. With no
33
33
 
34
34
  \`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.
35
35
 
36
- Add repeatable \`--reference-image <file-or-url>\` when the result should match given images; \`types\` shows which asset types accept reference images. A humanoid-model keeps the face and distinctive features of the person shown (at most 2 images); an environment matches the look of the references (at most 4). Types without reference image support reject them.
36
+ 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.
37
+
38
+ 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. A humanoid-model keeps the face and distinctive features of the person shown (at most 2 images); describe one isolated full-body character in one pose/view, with no companions. An environment matches the look of the references (at most 4). Types without reference image support reject them.
37
39
 
38
40
  Add \`--access public\` or \`--access private\` when visibility matters. Omitted access follows the account entitlement; private generation requires \`market:private\`.
39
41