@vivix-labs/project-studio 0.0.0-stage → 1.0.0-beta

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 (61) hide show
  1. package/dist/Inter-LICENSE.txt +93 -0
  2. package/dist/UI-LICENSE.txt +21 -0
  3. package/dist/assets/35a50-G5EJUNOC.svg +6 -0
  4. package/dist/assets/369ca-BISNKZ3M.svg +6 -0
  5. package/dist/assets/441bc-BCMNQ72W.svg +6 -0
  6. package/dist/assets/483f0-T6ZAGTDG.svg +6 -0
  7. package/dist/assets/6911b-ESLYKSC6.svg +6 -0
  8. package/dist/assets/Inter-LICENSE.txt +93 -0
  9. package/dist/assets/UI-system-LICENSE.txt +21 -0
  10. package/dist/assets/add-JY533O73.svg +5 -0
  11. package/dist/assets/area-P2WOMBT5.svg +9 -0
  12. package/dist/assets/b70bb-BTTOKPOH.svg +6 -0
  13. package/dist/assets/b9919-3S3O6YOT.svg +6 -0
  14. package/dist/assets/calendar-JI6USFRJ.svg +1 -0
  15. package/dist/assets/check-JSRRIXN5.svg +5 -0
  16. package/dist/assets/check-on-content-FQUVG3IZ.svg +5 -0
  17. package/dist/assets/chevron-down-K7YKS2EY.svg +5 -0
  18. package/dist/assets/chevron-left-JQCLK2WZ.svg +3 -0
  19. package/dist/assets/chevron-right-TNE35DBJ.svg +3 -0
  20. package/dist/assets/chevron-up-VBHYAJVB.svg +5 -0
  21. package/dist/assets/clear-XNEZJKFC.svg +5 -0
  22. package/dist/assets/close-GO5F7YFS.svg +10 -0
  23. package/dist/assets/dccd4-CZJXWICW.svg +6 -0
  24. package/dist/assets/dd163-3S3O6YOT.svg +6 -0
  25. package/dist/assets/draw-FOFX5TOM.svg +6 -0
  26. package/dist/assets/e8aed-CZJXWICW.svg +6 -0
  27. package/dist/assets/ea990-CZJXWICW.svg +6 -0
  28. package/dist/assets/expand-IAV75AFA.svg +6 -0
  29. package/dist/assets/fullscreen-L2JCXIN2.svg +6 -0
  30. package/dist/assets/grid-TLG5JYWB.svg +8 -0
  31. package/dist/assets/import-AFBUV2VV.svg +4 -0
  32. package/dist/assets/inter-latin-400-normal-55WT6UWF.woff2 +0 -0
  33. package/dist/assets/inter-latin-500-normal-W62DVTXI.woff2 +0 -0
  34. package/dist/assets/inter-latin-600-normal-R6Y2SZCR.woff2 +0 -0
  35. package/dist/assets/list-5VUAOZUH.svg +9 -0
  36. package/dist/assets/magic-OMME7FOV.svg +9 -0
  37. package/dist/assets/more-AEJ5MHWV.svg +5 -0
  38. package/dist/assets/mute-SXOSCR2U.svg +6 -0
  39. package/dist/assets/pause-2E4UY4FW.svg +6 -0
  40. package/dist/assets/play-WIIT3XQK.svg +5 -0
  41. package/dist/assets/reset-JESMTEMV.svg +6 -0
  42. package/dist/assets/search-JUOSGQRM.svg +6 -0
  43. package/dist/assets/select-VU7WR7B4.svg +7 -0
  44. package/dist/assets/sound-file-YYY6VNYN.svg +3 -0
  45. package/dist/assets/volume-2TYGJL6F.svg +6 -0
  46. package/dist/client.bundle.js +1373 -0
  47. package/dist/client.css +1900 -0
  48. package/dist/client.d.ts +19 -0
  49. package/dist/client.js +3 -0
  50. package/dist/events.d.ts +102 -0
  51. package/dist/events.js +244 -0
  52. package/dist/server.d.ts +16 -0
  53. package/dist/server.js +3502 -0
  54. package/dist/shared-BUdviVVD.d.ts +263 -0
  55. package/dist/shared.d.ts +510 -0
  56. package/dist/shared.js +228 -0
  57. package/package.json +50 -3
  58. package/schemas/billing-notice.json +16 -0
  59. package/schemas/task-notice.json +57 -0
  60. package/studio-plugin.json +40 -0
  61. package/README.md +0 -3
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+ import { StudioConfig } from './shared.js';
3
+ export { studioConfig as Config } from './shared.js';
4
+ import { ClientContext } from 'vivix-studio/sdk/client';
5
+ import 'vivix-studio/sdk/shared';
6
+ import './shared-BUdviVVD.js';
7
+
8
+ declare function AssetPreview({ location, kind }: {
9
+ location: any;
10
+ kind: string;
11
+ }): React.JSX.Element;
12
+ declare function AssetProperties({ record }: {
13
+ record: any;
14
+ }): React.JSX.Element;
15
+
16
+ declare const dependencies: (config: StudioConfig) => string[];
17
+ declare function activate(client: ClientContext<StudioConfig>): void;
18
+
19
+ export { AssetPreview, AssetProperties, activate as default, dependencies };
package/dist/client.js ADDED
@@ -0,0 +1,3 @@
1
+ import './client.css';
2
+ export * from './client.bundle.js';
3
+ export { default } from './client.bundle.js';
@@ -0,0 +1,102 @@
1
+ import { R as RecordValue, J as JSONValue, S as Scope } from './shared-BUdviVVD.js';
2
+ import { z, EventDefinition, Events } from 'vivix-studio/sdk/shared';
3
+
4
+ declare const taskEventNames: readonly ["project-studio/task.completed", "project-studio/task.failed", "project-studio/task.cancelled", "project-studio/billing.updated"];
5
+ declare const taskNotice: z.ZodObject<{
6
+ taskId: z.ZodString;
7
+ attemptId: z.ZodString;
8
+ revision: z.ZodNumber;
9
+ requestedCount: z.ZodNullable<z.ZodNumber>;
10
+ resultCount: z.ZodNullable<z.ZodNumber>;
11
+ partialResults: z.ZodNullable<z.ZodBoolean>;
12
+ results: z.ZodArray<z.ZodObject<{
13
+ remoteTaskId: z.ZodString;
14
+ outputIndex: z.ZodNumber;
15
+ assetId: z.ZodOptional<z.ZodString>;
16
+ }, z.core.$strict>>;
17
+ }, z.core.$strict>;
18
+ declare const billingNotice: z.ZodObject<{
19
+ taskId: z.ZodString;
20
+ attemptId: z.ZodString;
21
+ billingRecordId: z.ZodString;
22
+ revision: z.ZodNumber;
23
+ }, z.core.$strict>;
24
+ declare const eventDefinitions: readonly EventDefinition[];
25
+ type RemoteOutcome = 'succeeded' | 'failed' | 'cancelled' | 'unknown';
26
+ interface TaskStateProjection {
27
+ format: 1;
28
+ remote: {
29
+ status: RemoteOutcome;
30
+ revision: number;
31
+ requestedCount: number | null;
32
+ resultCount: number | null;
33
+ partialResults: boolean | null;
34
+ resultSignature?: string;
35
+ };
36
+ billing?: {
37
+ billingRecordId: string;
38
+ revision: number;
39
+ semanticDigest: string;
40
+ };
41
+ }
42
+ interface BillingView {
43
+ billingRecordId: string;
44
+ taskId: string;
45
+ attemptId: string;
46
+ revision: number;
47
+ status: 'pending' | 'settled' | 'released' | 'unavailable';
48
+ amount: {
49
+ value: string;
50
+ unit: string;
51
+ } | null;
52
+ }
53
+ declare function readableResults(record: RecordValue): {
54
+ remoteTaskId: string;
55
+ outputIndex: number;
56
+ }[];
57
+ declare function taskState(record: RecordValue): TaskStateProjection;
58
+ declare function stateMetadata(before: RecordValue, data: any, observation?: {
59
+ status?: string;
60
+ resultCount: number | null;
61
+ }): Record<string, JSONValue>;
62
+ declare function taskProjection(record: RecordValue): {
63
+ projection: {
64
+ attemptId: string;
65
+ remoteOutcome: {
66
+ status: RemoteOutcome;
67
+ revision: number;
68
+ requestedCount: number | null;
69
+ resultCount: number | null;
70
+ partialResults: boolean | null;
71
+ resultSignature?: string;
72
+ };
73
+ localPersistence: string;
74
+ billing: BillingView;
75
+ };
76
+ storeId: string;
77
+ scope: Scope;
78
+ objectId: string;
79
+ typeId: string;
80
+ schemaVersion: number;
81
+ revision: number;
82
+ data: any;
83
+ metadata: Record<string, JSONValue>;
84
+ createdAt: string;
85
+ updatedAt: string;
86
+ deletedAt: string | null;
87
+ };
88
+ /** I4 integration seam. It accepts only the I4 contract, never estimates or task state. */
89
+ declare function billingViewFromI4(record: RecordValue, cost: {
90
+ status: string;
91
+ credits: string | null;
92
+ }, revision: number): BillingView;
93
+ declare function taskBillingView(record: RecordValue): BillingView;
94
+ /** Integrates accepted fees without replacing the remote semantic projection. */
95
+ declare function billingMetadata(before: RecordValue, cost: {
96
+ status: string;
97
+ credits: string | null;
98
+ }): Record<string, JSONValue>;
99
+ /** Call only after the synchronous business transaction has committed. */
100
+ declare function notifyCommitted(events: () => Events, before: RecordValue, after: RecordValue, diagnostic?: (code: string) => void): void;
101
+
102
+ export { type BillingView, type RemoteOutcome, type TaskStateProjection, billingMetadata, billingNotice, billingViewFromI4, eventDefinitions, notifyCommitted, readableResults, stateMetadata, taskBillingView, taskEventNames, taskNotice, taskProjection, taskState };
package/dist/events.js ADDED
@@ -0,0 +1,244 @@
1
+ // packages/project-studio/src/events.ts
2
+ import { z as z2 } from "vivix-studio/sdk/shared";
3
+
4
+ // packages/vivix-api/src/billing.ts
5
+ import { z } from "vivix-studio/sdk/shared";
6
+ var taskBilling = z.object({
7
+ status: z.enum(["pending", "settled", "released", "unavailable"]),
8
+ credits: z.string().regex(/^\d+(?:\.\d+)?$/).nullable()
9
+ }).strict().refine(
10
+ (value) => value.status === "settled" ? value.credits !== null : value.status === "released" ? value.credits === "0" : value.credits === null
11
+ );
12
+ function readTaskBilling(response) {
13
+ const parsed = taskBilling.safeParse(response?.billing);
14
+ return parsed.success ? parsed.data : { status: "unavailable", credits: null };
15
+ }
16
+
17
+ // packages/project-studio/src/events.ts
18
+ var taskEventNames = [
19
+ "project-studio/task.completed",
20
+ "project-studio/task.failed",
21
+ "project-studio/task.cancelled",
22
+ "project-studio/billing.updated"
23
+ ];
24
+ var result = z2.object({
25
+ remoteTaskId: z2.string(),
26
+ outputIndex: z2.number().int().nonnegative(),
27
+ assetId: z2.string().optional()
28
+ }).strict();
29
+ var taskNotice = z2.object({
30
+ taskId: z2.string(),
31
+ attemptId: z2.string(),
32
+ revision: z2.number().int().positive(),
33
+ requestedCount: z2.number().int().positive().nullable(),
34
+ resultCount: z2.number().int().nonnegative().nullable(),
35
+ partialResults: z2.boolean().nullable(),
36
+ results: z2.array(result)
37
+ }).strict();
38
+ var billingNotice = z2.object({
39
+ taskId: z2.string(),
40
+ attemptId: z2.string(),
41
+ billingRecordId: z2.string(),
42
+ revision: z2.number().int().positive()
43
+ }).strict();
44
+ var eventDefinitions = taskEventNames.map((name) => ({
45
+ name,
46
+ version: 1,
47
+ mode: "notification",
48
+ schema: name.endsWith("billing.updated") ? "schemas/billing-notice.json" : "schemas/task-notice.json",
49
+ scope: "project"
50
+ }));
51
+ var stateKey = "project-studio.state";
52
+ function saved(record) {
53
+ const value = record.metadata?.[stateKey];
54
+ return value?.format === 1 && value.remote && Number.isSafeInteger(value.remote.revision) ? value : void 0;
55
+ }
56
+ function readableResults(record) {
57
+ if (typeof record.data.remoteTaskId !== "string" || !record.data.remoteTaskId) return [];
58
+ return (record.data.remoteOutputs || []).flatMap((value, outputIndex) => {
59
+ if (!value || typeof value !== "object") return [];
60
+ const output = value;
61
+ return ["asset_id", "file_id", "id", "url", "download_url", "content", "text"].some(
62
+ (k) => typeof output[k] === "string" && Boolean(output[k])
63
+ ) ? [{ remoteTaskId: record.data.remoteTaskId, outputIndex }] : [];
64
+ });
65
+ }
66
+ function outcome(record) {
67
+ const d = record.data;
68
+ if (d.remoteStatus === "succeeded" && readableResults(record).length) return "succeeded";
69
+ if (d.remoteStatus === "failed") return "failed";
70
+ if (["cancelled", "canceled"].includes(d.remoteStatus) || d.state === "canceled" && !d.submittedAt && !d.remoteTaskId && d.attemptCount === 0)
71
+ return "cancelled";
72
+ return "unknown";
73
+ }
74
+ function taskState(record) {
75
+ const old = saved(record), status = outcome(record);
76
+ const requestedCount = Number.isInteger(record.data.inputSnapshot?.outputCount) ? record.data.inputSnapshot.outputCount : null;
77
+ const resultSignature = JSON.stringify(readableResults(record));
78
+ const storedCount = Array.isArray(record.data.remoteOutputs) ? record.data.remoteOutputs.length : null;
79
+ const unchanged = old?.remote.status === status && old.remote.requestedCount === requestedCount && old.remote.resultSignature === resultSignature && (old.remote.resultCount === null || old.remote.resultCount === storedCount);
80
+ const resultCount = status === "unknown" ? null : unchanged ? old.remote.resultCount : record.data.remoteOutputs?.length ? record.data.remoteOutputs.length : null;
81
+ return {
82
+ format: 1,
83
+ remote: {
84
+ status,
85
+ revision: unchanged ? old.remote.revision : record.revision,
86
+ requestedCount,
87
+ resultCount,
88
+ partialResults: requestedCount !== null && resultCount !== null ? resultCount < requestedCount : null,
89
+ resultSignature
90
+ },
91
+ billing: currentBilling(record, old?.billing)
92
+ };
93
+ }
94
+ function stateMetadata(before, data, observation) {
95
+ const previous = taskState(before), next = taskState({ ...before, data, metadata: {} });
96
+ if (observation && next.remote.status !== "unknown")
97
+ next.remote.resultCount = observation.resultCount;
98
+ else if (previous.remote.status === next.remote.status)
99
+ next.remote.resultCount = previous.remote.resultCount;
100
+ next.remote.partialResults = next.remote.requestedCount !== null && next.remote.resultCount !== null ? next.remote.resultCount < next.remote.requestedCount : null;
101
+ const signature = ({ revision: _, ...r }) => JSON.stringify(r);
102
+ next.remote.revision = signature(next.remote) === signature(previous.remote) ? previous.remote.revision : before.revision + 1;
103
+ const view = billingViewFromI4(
104
+ before,
105
+ data.cost ?? { status: "unavailable", credits: null },
106
+ before.revision + 1
107
+ );
108
+ const semanticDigest = billingDigest(view);
109
+ next.billing = {
110
+ billingRecordId: view.billingRecordId,
111
+ semanticDigest,
112
+ revision: previous.billing?.semanticDigest === semanticDigest ? previous.billing.revision : before.revision + 1
113
+ };
114
+ return { ...before.metadata, [stateKey]: next };
115
+ }
116
+ function taskProjection(record) {
117
+ const s = taskState(record), d = record.data;
118
+ const localPersistence = d.state === "succeeded" ? "saved" : d.state === "partial" ? "partial" : d.state === "save_failed" ? "failed" : d.state === "saving" && d.outputRefs?.length ? "partial" : "pending";
119
+ return {
120
+ ...record,
121
+ projection: {
122
+ attemptId: record.objectId,
123
+ remoteOutcome: s.remote,
124
+ localPersistence,
125
+ billing: taskBillingView(record)
126
+ }
127
+ };
128
+ }
129
+ function billingViewFromI4(record, cost, revision) {
130
+ const { status, credits } = readTaskBilling({
131
+ billing: { status: cost.status, credits: cost.credits }
132
+ });
133
+ return {
134
+ billingRecordId: JSON.stringify([
135
+ record.storeId,
136
+ record.scope?.id,
137
+ record.objectId,
138
+ "task.cost"
139
+ ]),
140
+ taskId: record.objectId,
141
+ attemptId: record.objectId,
142
+ revision,
143
+ status,
144
+ amount: status === "settled" || status === "released" ? { value: credits.replace(/^0+(?=\d)/, ""), unit: "credits" } : null
145
+ };
146
+ }
147
+ function normalizeDecimal(value) {
148
+ const [whole, fraction = ""] = value.split(".");
149
+ const trimmed = fraction.replace(/0+$/, "");
150
+ return whole.replace(/^0+(?=\d)/, "") + (trimmed ? "." + trimmed : "");
151
+ }
152
+ function billingDigest(view) {
153
+ return JSON.stringify([
154
+ view.status,
155
+ view.amount && { ...view.amount, value: normalizeDecimal(view.amount.value) }
156
+ ]);
157
+ }
158
+ function currentBilling(record, old) {
159
+ const view = billingViewFromI4(
160
+ record,
161
+ record.data.cost ?? { status: "unavailable", credits: null },
162
+ record.revision
163
+ );
164
+ const semanticDigest = billingDigest(view);
165
+ return {
166
+ billingRecordId: view.billingRecordId,
167
+ semanticDigest,
168
+ revision: old?.semanticDigest === semanticDigest ? old.revision : record.revision
169
+ };
170
+ }
171
+ function taskBillingView(record) {
172
+ const state = taskState(record);
173
+ return billingViewFromI4(
174
+ record,
175
+ record.data.cost ?? { status: "unavailable", credits: null },
176
+ state.billing?.revision ?? record.revision
177
+ );
178
+ }
179
+ function billingMetadata(before, cost) {
180
+ const state = taskState(before), view = billingViewFromI4(before, cost, before.revision + 1), semanticDigest = billingDigest(view);
181
+ state.billing = {
182
+ billingRecordId: view.billingRecordId,
183
+ semanticDigest,
184
+ revision: state.billing?.semanticDigest === semanticDigest ? state.billing.revision : before.revision + 1
185
+ };
186
+ return { ...before.metadata, [stateKey]: state };
187
+ }
188
+ function notifyCommitted(events, before, after, diagnostic = (code) => console.error(code)) {
189
+ void (async () => {
190
+ const old = structuredClone(before), committed = structuredClone(after);
191
+ const a = taskState(old), b = taskState(committed), scope = events();
192
+ if (b.remote.status !== "unknown" && (a.remote.status !== b.remote.status || a.remote.revision !== b.remote.revision)) {
193
+ const name = b.remote.status === "succeeded" ? taskEventNames[0] : b.remote.status === "failed" ? taskEventNames[1] : taskEventNames[2];
194
+ const results = readableResults(committed);
195
+ await scope.emit(name, {
196
+ version: 1,
197
+ occurredAt: committed.updatedAt,
198
+ correlation: { taskId: committed.objectId, attemptId: committed.objectId },
199
+ entity: { type: "task", id: committed.objectId, revision: b.remote.revision },
200
+ payload: {
201
+ taskId: committed.objectId,
202
+ attemptId: committed.objectId,
203
+ revision: b.remote.revision,
204
+ requestedCount: b.remote.requestedCount,
205
+ resultCount: b.remote.resultCount,
206
+ partialResults: b.remote.partialResults,
207
+ results
208
+ }
209
+ });
210
+ }
211
+ if (b.billing && b.billing.revision !== a.billing?.revision)
212
+ await scope.emit(taskEventNames[3], {
213
+ version: 1,
214
+ occurredAt: committed.updatedAt,
215
+ correlation: { taskId: committed.objectId, attemptId: committed.objectId },
216
+ entity: { type: "billing", id: b.billing.billingRecordId, revision: b.billing.revision },
217
+ payload: {
218
+ taskId: committed.objectId,
219
+ attemptId: committed.objectId,
220
+ billingRecordId: b.billing.billingRecordId,
221
+ revision: b.billing.revision
222
+ }
223
+ });
224
+ })().catch(() => {
225
+ try {
226
+ diagnostic("EVENT_NOTIFICATION_FAILED");
227
+ } catch {
228
+ }
229
+ });
230
+ }
231
+ export {
232
+ billingMetadata,
233
+ billingNotice,
234
+ billingViewFromI4,
235
+ eventDefinitions,
236
+ notifyCommitted,
237
+ readableResults,
238
+ stateMetadata,
239
+ taskBillingView,
240
+ taskEventNames,
241
+ taskNotice,
242
+ taskProjection,
243
+ taskState
244
+ };
@@ -0,0 +1,16 @@
1
+ import { z } from 'vivix-studio/sdk/shared';
2
+ import { ServerContext } from 'vivix-studio/sdk/server';
3
+
4
+ declare const Config: z.ZodObject<{
5
+ role: z.ZodDefault<z.ZodEnum<{
6
+ project: "project";
7
+ coordinator: "coordinator";
8
+ }>>;
9
+ dataInstance: z.ZodDefault<z.ZodString>;
10
+ apiInstance: z.ZodDefault<z.ZodString>;
11
+ libraryInstance: z.ZodDefault<z.ZodNullable<z.ZodString>>;
12
+ }, z.core.$strict>;
13
+ declare const dependencies: (c: z.infer<typeof Config>) => string[];
14
+ declare function activate(ctx: ServerContext<z.infer<typeof Config>>): Promise<void>;
15
+
16
+ export { Config, activate as default, dependencies };