@civitai/app-sdk 0.1.0 → 0.7.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 (39) hide show
  1. package/README.md +46 -1
  2. package/dist/blocks/defineBlock.d.ts +32 -0
  3. package/dist/blocks/defineBlock.d.ts.map +1 -0
  4. package/dist/blocks/defineBlock.js +270 -0
  5. package/dist/blocks/defineBlock.js.map +1 -0
  6. package/dist/blocks/index.d.ts +16 -0
  7. package/dist/blocks/index.d.ts.map +1 -0
  8. package/dist/blocks/index.js +12 -0
  9. package/dist/blocks/index.js.map +1 -0
  10. package/dist/blocks/messages.d.ts +289 -0
  11. package/dist/blocks/messages.d.ts.map +1 -0
  12. package/dist/blocks/messages.js +31 -0
  13. package/dist/blocks/messages.js.map +1 -0
  14. package/dist/blocks/scopes.d.ts +35 -0
  15. package/dist/blocks/scopes.d.ts.map +1 -0
  16. package/dist/blocks/scopes.js +33 -0
  17. package/dist/blocks/scopes.js.map +1 -0
  18. package/dist/blocks/types.d.ts +371 -0
  19. package/dist/blocks/types.d.ts.map +1 -0
  20. package/dist/blocks/types.js +8 -0
  21. package/dist/blocks/types.js.map +1 -0
  22. package/dist/oauth/token.d.ts +28 -0
  23. package/dist/oauth/token.d.ts.map +1 -1
  24. package/dist/oauth/token.js +28 -0
  25. package/dist/oauth/token.js.map +1 -1
  26. package/dist/orchestrator/index.d.ts +224 -0
  27. package/dist/orchestrator/index.d.ts.map +1 -1
  28. package/dist/orchestrator/index.js +207 -0
  29. package/dist/orchestrator/index.js.map +1 -1
  30. package/package.json +11 -5
  31. package/schemas/app-block/v1.json +184 -0
  32. package/dist/client/index.d.ts +0 -23
  33. package/dist/client/index.d.ts.map +0 -1
  34. package/dist/client/index.js +0 -19
  35. package/dist/client/index.js.map +0 -1
  36. package/dist/workflows/index.d.ts +0 -52
  37. package/dist/workflows/index.d.ts.map +0 -1
  38. package/dist/workflows/index.js +0 -77
  39. package/dist/workflows/index.js.map +0 -1
@@ -0,0 +1,184 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://civitai.com/schemas/app-block/v1.json",
4
+ "title": "Civitai App Block Manifest v1",
5
+ "description": "Manifest shape for a Civitai App Block. Mirrors the runtime check performed by defineBlock() in @civitai/app-sdk/blocks.",
6
+ "type": "object",
7
+ "required": [
8
+ "$schema",
9
+ "appId",
10
+ "blockId",
11
+ "version",
12
+ "name",
13
+ "type",
14
+ "targets",
15
+ "scopes",
16
+ "iframe",
17
+ "contentRating",
18
+ "minApiVersion"
19
+ ],
20
+ "additionalProperties": true,
21
+ "properties": {
22
+ "$schema": {
23
+ "type": "string",
24
+ "const": "https://civitai.com/schemas/app-block/v1.json"
25
+ },
26
+ "appId": {
27
+ "type": "string",
28
+ "minLength": 1
29
+ },
30
+ "blockId": {
31
+ "type": "string",
32
+ "pattern": "^[a-z0-9-]{3,64}$",
33
+ "description": "Immutable block identifier. Lowercase letters, digits, and hyphens; 3-64 characters."
34
+ },
35
+ "version": {
36
+ "type": "string",
37
+ "pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$",
38
+ "description": "Semver."
39
+ },
40
+ "name": {
41
+ "type": "string",
42
+ "minLength": 1,
43
+ "maxLength": 80
44
+ },
45
+ "type": {
46
+ "type": "string",
47
+ "enum": ["block", "embed"]
48
+ },
49
+ "targets": {
50
+ "type": "array",
51
+ "minItems": 1,
52
+ "items": {
53
+ "type": "object",
54
+ "required": ["slotId", "priority"],
55
+ "properties": {
56
+ "slotId": { "type": "string", "minLength": 1 },
57
+ "priority": { "type": "integer" },
58
+ "requiredContext": {
59
+ "type": "array",
60
+ "items": { "type": "string" }
61
+ }
62
+ }
63
+ }
64
+ },
65
+ "scopes": {
66
+ "type": "array",
67
+ "minItems": 1,
68
+ "items": {
69
+ "type": "string",
70
+ "pattern": "^[a-z]+:[a-z]+:[a-z]+$",
71
+ "description": "Colon-separated lowercase, e.g. models:read:self. PascalCase is rejected."
72
+ }
73
+ },
74
+ "iframe": {
75
+ "type": "object",
76
+ "required": ["src", "minHeight", "resizable", "sandbox"],
77
+ "properties": {
78
+ "src": {
79
+ "type": "string",
80
+ "description": "HTTPS URL of the block app. http://localhost or http://127.0.0.1 also accepted for local dev."
81
+ },
82
+ "minHeight": { "type": "integer", "exclusiveMinimum": 0 },
83
+ "maxHeight": { "type": ["integer", "null"] },
84
+ "resizable": { "type": "boolean" },
85
+ "sandbox": {
86
+ "type": "string",
87
+ "allOf": [
88
+ {
89
+ "not": { "pattern": "(^|\\s)allow-same-origin(\\s|$)" },
90
+ "description": "Must not contain allow-same-origin — combined with allow-scripts it defeats the sandbox."
91
+ },
92
+ {
93
+ "not": { "pattern": "(^|\\s)allow-top-navigation(\\s|$)" },
94
+ "description": "Must not contain allow-top-navigation — use the NAVIGATE postMessage instead."
95
+ },
96
+ {
97
+ "not": { "pattern": "(^|\\s)allow-top-navigation-by-user-activation(\\s|$)" },
98
+ "description": "Must not contain allow-top-navigation-by-user-activation — same threat as allow-top-navigation, gated on a user gesture."
99
+ },
100
+ {
101
+ "not": { "pattern": "(^|\\s)allow-top-navigation-to-custom-protocols(\\s|$)" },
102
+ "description": "Must not contain allow-top-navigation-to-custom-protocols — same threat as allow-top-navigation, restricted to non-fetch schemes."
103
+ }
104
+ ]
105
+ }
106
+ }
107
+ },
108
+ "assets": {
109
+ "type": "array",
110
+ "items": {
111
+ "type": "object",
112
+ "required": ["url", "integrity"],
113
+ "properties": {
114
+ "url": { "type": "string" },
115
+ "integrity": {
116
+ "type": "string",
117
+ "pattern": "^sha(256|384|512)-[A-Za-z0-9+/=]+$"
118
+ }
119
+ }
120
+ }
121
+ },
122
+ "settings": {
123
+ "type": "array",
124
+ "items": {
125
+ "type": "object",
126
+ "required": ["id", "type", "label"],
127
+ "properties": {
128
+ "id": { "type": "string", "minLength": 1 },
129
+ "type": { "type": "string", "enum": ["string", "number", "boolean", "select"] },
130
+ "label": { "type": "string", "minLength": 1 },
131
+ "default": {},
132
+ "options": {
133
+ "type": "array",
134
+ "items": {
135
+ "type": "object",
136
+ "required": ["value", "label"],
137
+ "properties": {
138
+ "value": { "type": "string" },
139
+ "label": { "type": "string" }
140
+ }
141
+ }
142
+ },
143
+ "min": { "type": "number" },
144
+ "max": { "type": "number" },
145
+ "required": { "type": "boolean" }
146
+ }
147
+ }
148
+ },
149
+ "contentRating": {
150
+ "type": "string",
151
+ "enum": ["g", "pg", "pg13", "r", "x"]
152
+ },
153
+ "preview": {
154
+ "type": "object",
155
+ "required": ["thumbnail", "description"],
156
+ "properties": {
157
+ "thumbnail": { "type": "string" },
158
+ "description": { "type": "string" },
159
+ "screenshots": {
160
+ "type": "array",
161
+ "items": { "type": "string" }
162
+ }
163
+ }
164
+ },
165
+ "promotionEligible": { "type": "boolean" },
166
+ "minApiVersion": { "type": "string" },
167
+ "renderMode": {
168
+ "type": "string",
169
+ "enum": ["iframe", "inline", "hybrid"],
170
+ "description": "Optional. Defaults to iframe. v1 manifests may omit."
171
+ },
172
+ "assetBundle": {
173
+ "type": "object",
174
+ "properties": {
175
+ "url": { "type": ["string", "null"] },
176
+ "sha256": { "type": ["string", "null"] }
177
+ }
178
+ },
179
+ "trustTier": {
180
+ "type": "string",
181
+ "enum": ["unverified", "verified", "internal"]
182
+ }
183
+ }
184
+ }
@@ -1,23 +0,0 @@
1
- import { createCivitaiClient } from '@civitai/client';
2
- /** The orchestrator client returned by `createCivitaiClient`. */
3
- export type CivitaiClient = ReturnType<typeof createCivitaiClient>;
4
- export interface CreateAppClientOptions {
5
- /** OAuth access token or personal API key. Used as Bearer credential. */
6
- token: string;
7
- /** Orchestrator base URL. Defaults to Civitai's prod orchestrator. */
8
- baseUrl?: string;
9
- /** SDK env mode. Defaults to 'prod'. */
10
- env?: 'dev' | 'prod';
11
- }
12
- /**
13
- * Create a typed Civitai orchestrator client authenticated with the user's
14
- * OAuth access token (or a personal API key — same Bearer scheme).
15
- *
16
- * Wraps `@civitai/client`'s factory with sensible defaults. The returned
17
- * client is the same shape `@civitai/client` produces — pass it to the
18
- * SDK's standalone functions (`submitWorkflow({ client, body })`, etc.)
19
- * or to the wrappers in `@civitai/app-sdk/workflows`.
20
- */
21
- export declare function createAppClient(opts: CreateAppClientOptions): CivitaiClient;
22
- export type AppClient = CivitaiClient;
23
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,iEAAiE;AACjE,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEnE,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CACtB;AAID;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,sBAAsB,GAAG,aAAa,CAM3E;AAED,MAAM,MAAM,SAAS,GAAG,aAAa,CAAC"}
@@ -1,19 +0,0 @@
1
- import { createCivitaiClient } from '@civitai/client';
2
- const DEFAULT_ORCHESTRATOR_BASE_URL = 'https://orchestration-new.civitai.com';
3
- /**
4
- * Create a typed Civitai orchestrator client authenticated with the user's
5
- * OAuth access token (or a personal API key — same Bearer scheme).
6
- *
7
- * Wraps `@civitai/client`'s factory with sensible defaults. The returned
8
- * client is the same shape `@civitai/client` produces — pass it to the
9
- * SDK's standalone functions (`submitWorkflow({ client, body })`, etc.)
10
- * or to the wrappers in `@civitai/app-sdk/workflows`.
11
- */
12
- export function createAppClient(opts) {
13
- return createCivitaiClient({
14
- baseUrl: opts.baseUrl ?? DEFAULT_ORCHESTRATOR_BASE_URL,
15
- env: opts.env ?? 'prod',
16
- auth: opts.token,
17
- });
18
- }
19
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AActD,MAAM,6BAA6B,GAAG,uCAAuC,CAAC;AAE9E;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,IAA4B;IAC1D,OAAO,mBAAmB,CAAC;QACzB,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,6BAA6B;QACtD,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,MAAM;QACvB,IAAI,EAAE,IAAI,CAAC,KAAK;KACjB,CAAC,CAAC;AACL,CAAC"}
@@ -1,52 +0,0 @@
1
- import { type SubmitWorkflowData, type Workflow } from '@civitai/client';
2
- import type { AppClient } from '../client/index.js';
3
- /**
4
- * Thin wrappers around the orchestrator's workflow endpoints with conventions
5
- * suited to third-party app starters. All calls use the user's OAuth token
6
- * (or API key) carried by the `AppClient` — the orchestrator debits Buzz
7
- * from whoever owns that token.
8
- */
9
- export type WorkflowBody = NonNullable<SubmitWorkflowData['body']>;
10
- export interface CostEstimate {
11
- /** Buzz cost. Pulled from the workflow's `cost.total` field. */
12
- total: number;
13
- /** Full workflow response (validation result, queue placement, etc.). */
14
- raw: Workflow;
15
- }
16
- declare class WorkflowError extends Error {
17
- readonly status: number | undefined;
18
- readonly detail: unknown;
19
- readonly name = "WorkflowError";
20
- constructor(message: string, status: number | undefined, detail: unknown);
21
- }
22
- /**
23
- * Cost preview ("what if") — runs the workflow validation/pricing pipeline
24
- * without committing any Buzz. Use this to show the user "this will cost X
25
- * Buzz" before they confirm submission.
26
- *
27
- * NOTE: per Civitai's docs, `whatif=true` validates and prices but does not
28
- * apply per-app spending caps to the response — a successful whatif can still
29
- * be denied at submit time if the user has set tight caps or insufficient
30
- * funds. Treat `whatif` as "this is the price" not "this is approved."
31
- */
32
- export declare function estimateCost(client: AppClient, body: WorkflowBody): Promise<CostEstimate>;
33
- /** Submit a workflow for real execution. Debits the token-owner's Buzz. */
34
- export declare function submitWorkflow(client: AppClient, body: WorkflowBody): Promise<Workflow>;
35
- export declare function getWorkflow(client: AppClient, workflowId: string): Promise<Workflow>;
36
- export interface PollWorkflowOptions {
37
- /** Polling interval in ms. Default 2000. */
38
- intervalMs?: number;
39
- /** Max total time to poll in ms. Default 5 minutes. */
40
- timeoutMs?: number;
41
- /** Optional progress callback fired on every poll tick. */
42
- onTick?: (snapshot: Workflow) => void;
43
- /** Optional abort signal. */
44
- signal?: AbortSignal;
45
- }
46
- /**
47
- * Poll a workflow until it reaches a terminal status (`Succeeded`, `Failed`,
48
- * `Canceled`) or the timeout elapses. Returns the final snapshot.
49
- */
50
- export declare function pollWorkflow(client: AppClient, workflowId: string, opts?: PollWorkflowOptions): Promise<Workflow>;
51
- export { WorkflowError };
52
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/workflows/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,QAAQ,EACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;;;;GAKG;AAEH,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;AAEnE,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,GAAG,EAAE,QAAQ,CAAC;CACf;AAED,cAAM,aAAc,SAAQ,KAAK;IAI7B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IACnC,QAAQ,CAAC,MAAM,EAAE,OAAO;IAJ1B,SAAkB,IAAI,mBAAmB;gBAEvC,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,OAAO;CAI3B;AAkBD;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAQ/F;AAED,2EAA2E;AAC3E,wBAAsB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAG7F;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAM1F;AAED,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IACtC,6BAA6B;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAID;;;GAGG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,mBAAwB,GAC7B,OAAO,CAAC,QAAQ,CAAC,CAmBnB;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -1,77 +0,0 @@
1
- import { getWorkflow as sdkGetWorkflow, submitWorkflow as sdkSubmitWorkflow, } from '@civitai/client';
2
- class WorkflowError extends Error {
3
- status;
4
- detail;
5
- name = 'WorkflowError';
6
- constructor(message, status, detail) {
7
- super(message);
8
- this.status = status;
9
- this.detail = detail;
10
- }
11
- }
12
- function unwrap(result) {
13
- if (result.error || !result.data) {
14
- const status = result.response?.status;
15
- const detail = result.error && typeof result.error === 'object' && 'detail' in result.error
16
- ? result.error.detail
17
- : result.error;
18
- throw new WorkflowError(`Civitai workflow request failed${status ? ` (HTTP ${status})` : ''}`, status, detail);
19
- }
20
- return result.data;
21
- }
22
- /**
23
- * Cost preview ("what if") — runs the workflow validation/pricing pipeline
24
- * without committing any Buzz. Use this to show the user "this will cost X
25
- * Buzz" before they confirm submission.
26
- *
27
- * NOTE: per Civitai's docs, `whatif=true` validates and prices but does not
28
- * apply per-app spending caps to the response — a successful whatif can still
29
- * be denied at submit time if the user has set tight caps or insufficient
30
- * funds. Treat `whatif` as "this is the price" not "this is approved."
31
- */
32
- export async function estimateCost(client, body) {
33
- const result = await sdkSubmitWorkflow({
34
- client,
35
- body,
36
- query: { whatif: true },
37
- });
38
- const workflow = unwrap(result);
39
- return { total: workflow?.cost?.total ?? 0, raw: workflow };
40
- }
41
- /** Submit a workflow for real execution. Debits the token-owner's Buzz. */
42
- export async function submitWorkflow(client, body) {
43
- const result = await sdkSubmitWorkflow({ client, body });
44
- return unwrap(result);
45
- }
46
- export async function getWorkflow(client, workflowId) {
47
- const result = await sdkGetWorkflow({
48
- client,
49
- path: { workflowId },
50
- });
51
- return unwrap(result);
52
- }
53
- const TERMINAL_STATUSES = new Set(['Succeeded', 'Failed', 'Canceled']);
54
- /**
55
- * Poll a workflow until it reaches a terminal status (`Succeeded`, `Failed`,
56
- * `Canceled`) or the timeout elapses. Returns the final snapshot.
57
- */
58
- export async function pollWorkflow(client, workflowId, opts = {}) {
59
- const interval = opts.intervalMs ?? 2000;
60
- const timeout = opts.timeoutMs ?? 5 * 60 * 1000;
61
- const deadline = Date.now() + timeout;
62
- while (true) {
63
- if (opts.signal?.aborted)
64
- throw new Error('pollWorkflow aborted');
65
- const snapshot = await getWorkflow(client, workflowId);
66
- opts.onTick?.(snapshot);
67
- if (snapshot.status && TERMINAL_STATUSES.has(String(snapshot.status))) {
68
- return snapshot;
69
- }
70
- if (Date.now() >= deadline) {
71
- throw new Error(`pollWorkflow timed out after ${timeout}ms (last status: ${String(snapshot.status)})`);
72
- }
73
- await new Promise((resolve) => setTimeout(resolve, interval));
74
- }
75
- }
76
- export { WorkflowError };
77
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/workflows/index.ts"],"names":[],"mappings":"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"}