@lumenkey/cli 0.3.1 → 0.4.0-rc.1
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/README.md +36 -2
- package/dist/cli/copied.js +86 -85
- package/dist/cli/index.js +56 -44
- package/dist/cli/render.js +3 -2
- package/dist/core/asset-stream.d.ts +16 -0
- package/dist/core/asset-stream.js +64 -0
- package/dist/core/atomic-config-file.js +8 -7
- package/dist/core/chinese-messages.d.ts +4 -0
- package/dist/core/chinese-messages.js +907 -0
- package/dist/core/chinese-script.d.ts +7 -0
- package/dist/core/chinese-script.js +28 -0
- package/dist/core/client.js +2 -1
- package/dist/core/config-dir.js +2 -1
- package/dist/core/config.js +7 -6
- package/dist/core/download-root.d.ts +5 -0
- package/dist/core/download-root.js +64 -0
- package/dist/core/download.js +15 -12
- package/dist/core/generation-input.js +3 -2
- package/dist/core/generation.d.ts +8 -1
- package/dist/core/generation.js +13 -10
- package/dist/core/job-display.js +7 -6
- package/dist/core/locale.js +163 -148
- package/dist/core/outcome.js +6 -4
- package/dist/core/output-path.d.ts +3 -1
- package/dist/core/output-path.js +5 -2
- package/dist/core/params.js +26 -25
- package/dist/core/profiles.js +5 -4
- package/dist/core/set-values.d.ts +0 -1
- package/dist/core/set-values.js +7 -7
- package/dist/core/submission-journal.js +31 -16
- package/dist/core/version.js +2 -3
- package/dist/mcp/server.js +30 -29
- package/dist/studio/asset-integrity-hash.d.ts +28 -0
- package/dist/studio/asset-integrity-hash.js +93 -0
- package/dist/studio/asset-integrity-queue.d.ts +24 -0
- package/dist/studio/asset-integrity-queue.js +94 -0
- package/dist/studio/asset-store.d.ts +52 -0
- package/dist/studio/asset-store.js +352 -0
- package/dist/studio/canvas/LICENSES.txt +1590 -0
- package/dist/studio/canvas/dependencies.json +862 -0
- package/dist/studio/canvas/director-source-manifest.json +47 -0
- package/dist/studio/canvas/editor.css +239 -0
- package/dist/studio/canvas/editor.js +4613 -0
- package/dist/studio/canvas/integration-source-manifest.json +384 -0
- package/dist/studio/canvas/source-manifest.json +240 -0
- package/dist/studio/canvas-store.d.ts +1254 -0
- package/dist/studio/canvas-store.js +205 -0
- package/dist/studio/capture-placement.d.ts +11 -0
- package/dist/studio/capture-placement.js +85 -0
- package/dist/studio/cloud-contract.d.ts +128 -0
- package/dist/studio/cloud-contract.js +229 -0
- package/dist/studio/cloud-service.d.ts +178 -0
- package/dist/studio/cloud-service.js +202 -0
- package/dist/studio/director-captures.d.ts +59 -0
- package/dist/studio/director-captures.js +141 -0
- package/dist/studio/director-contract.d.ts +1489 -0
- package/dist/studio/director-contract.js +288 -0
- package/dist/studio/director-png.d.ts +6 -0
- package/dist/studio/director-png.js +41 -0
- package/dist/studio/director-relations.d.ts +40 -0
- package/dist/studio/director-relations.js +103 -0
- package/dist/studio/document-authority.d.ts +7 -0
- package/dist/studio/document-authority.js +50 -0
- package/dist/studio/draft-store.d.ts +95 -0
- package/dist/studio/draft-store.js +100 -0
- package/dist/studio/errors.d.ts +85 -0
- package/dist/studio/errors.js +94 -0
- package/dist/studio/launch.d.ts +5 -0
- package/dist/studio/launch.js +31 -0
- package/dist/studio/media.d.ts +9 -0
- package/dist/studio/media.js +50 -0
- package/dist/studio/output-save-contract.d.ts +1321 -0
- package/dist/studio/output-save-contract.js +26 -0
- package/dist/studio/output-save-journal.d.ts +971 -0
- package/dist/studio/output-save-journal.js +287 -0
- package/dist/studio/output-save-recovery.d.ts +18 -0
- package/dist/studio/output-save-recovery.js +161 -0
- package/dist/studio/output-save-service.d.ts +436 -0
- package/dist/studio/output-save-service.js +251 -0
- package/dist/studio/output-save-worker.d.ts +40 -0
- package/dist/studio/output-save-worker.js +360 -0
- package/dist/studio/paths.d.ts +6 -0
- package/dist/studio/paths.js +68 -0
- package/dist/studio/run-journal.d.ts +993 -0
- package/dist/studio/run-journal.js +125 -0
- package/dist/studio/server.d.ts +17 -0
- package/dist/studio/server.js +440 -0
- package/dist/studio/session.d.ts +6 -0
- package/dist/studio/session.js +26 -0
- package/dist/studio/shell.d.ts +3 -0
- package/dist/studio/shell.js +23 -0
- package/dist/studio/style.d.ts +2 -0
- package/dist/studio/style.js +29 -0
- package/dist/studio/types.d.ts +26 -0
- package/dist/studio/types.js +2 -0
- package/dist/studio/web/app.d.ts +2 -0
- package/dist/studio/web/app.js +662 -0
- package/dist/studio/web/asset-controller.d.ts +37 -0
- package/dist/studio/web/asset-controller.js +191 -0
- package/dist/studio/web/asset-model.d.ts +29 -0
- package/dist/studio/web/asset-model.js +51 -0
- package/dist/studio/web/controller.d.ts +113 -0
- package/dist/studio/web/controller.js +401 -0
- package/dist/studio/web/messages.d.ts +2 -0
- package/dist/studio/web/messages.js +74 -0
- package/dist/studio/web/model.d.ts +75 -0
- package/dist/studio/web/model.js +182 -0
- package/dist/studio/web/save-controller.d.ts +85 -0
- package/dist/studio/web/save-controller.js +495 -0
- package/dist/studio/web/save-model.d.ts +63 -0
- package/dist/studio/web/save-model.js +64 -0
- package/dist/studio/web/save-queue.d.ts +7 -0
- package/dist/studio/web/save-queue.js +62 -0
- package/dist/studio/web/save-view.d.ts +9 -0
- package/dist/studio/web/save-view.js +19 -0
- package/dist/studio/writer-lock.d.ts +5 -0
- package/dist/studio/writer-lock.js +88 -0
- package/package.json +11 -5
- package/dist/cli/copied.d.ts.map +0 -1
- package/dist/cli/copied.js.map +0 -1
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/render.d.ts.map +0 -1
- package/dist/cli/render.js.map +0 -1
- package/dist/core/atomic-config-file.d.ts.map +0 -1
- package/dist/core/atomic-config-file.js.map +0 -1
- package/dist/core/chat.d.ts.map +0 -1
- package/dist/core/chat.js.map +0 -1
- package/dist/core/client.d.ts.map +0 -1
- package/dist/core/client.js.map +0 -1
- package/dist/core/config-dir.d.ts.map +0 -1
- package/dist/core/config-dir.js.map +0 -1
- package/dist/core/config-error.d.ts.map +0 -1
- package/dist/core/config-error.js.map +0 -1
- package/dist/core/config.d.ts.map +0 -1
- package/dist/core/config.js.map +0 -1
- package/dist/core/credit-cap.d.ts.map +0 -1
- package/dist/core/credit-cap.js.map +0 -1
- package/dist/core/download.d.ts.map +0 -1
- package/dist/core/download.js.map +0 -1
- package/dist/core/error-result.d.ts.map +0 -1
- package/dist/core/error-result.js.map +0 -1
- package/dist/core/explain.d.ts.map +0 -1
- package/dist/core/explain.js.map +0 -1
- package/dist/core/generation-input.d.ts.map +0 -1
- package/dist/core/generation-input.js.map +0 -1
- package/dist/core/generation-result.d.ts.map +0 -1
- package/dist/core/generation-result.js.map +0 -1
- package/dist/core/generation.d.ts.map +0 -1
- package/dist/core/generation.js.map +0 -1
- package/dist/core/job-display.d.ts.map +0 -1
- package/dist/core/job-display.js.map +0 -1
- package/dist/core/locale.d.ts.map +0 -1
- package/dist/core/locale.js.map +0 -1
- package/dist/core/origin.d.ts.map +0 -1
- package/dist/core/origin.js.map +0 -1
- package/dist/core/outcome.d.ts.map +0 -1
- package/dist/core/outcome.js.map +0 -1
- package/dist/core/output-path.d.ts.map +0 -1
- package/dist/core/output-path.js.map +0 -1
- package/dist/core/params.d.ts.map +0 -1
- package/dist/core/params.js.map +0 -1
- package/dist/core/poller.d.ts.map +0 -1
- package/dist/core/poller.js.map +0 -1
- package/dist/core/profiles.d.ts.map +0 -1
- package/dist/core/profiles.js.map +0 -1
- package/dist/core/set-values.d.ts.map +0 -1
- package/dist/core/set-values.js.map +0 -1
- package/dist/core/submission-journal.d.ts.map +0 -1
- package/dist/core/submission-journal.js.map +0 -1
- package/dist/core/types.d.ts.map +0 -1
- package/dist/core/types.js.map +0 -1
- package/dist/core/version.d.ts.map +0 -1
- package/dist/core/version.js.map +0 -1
- package/dist/core/wait.d.ts.map +0 -1
- package/dist/core/wait.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/mcp/render.d.ts.map +0 -1
- package/dist/mcp/render.js.map +0 -1
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js.map +0 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type StudioApi, type Resource } from './controller.js';
|
|
2
|
+
import { createSaveQueue } from './save-queue.js';
|
|
3
|
+
import { type LocalAsset } from './asset-model.js';
|
|
4
|
+
interface Clock {
|
|
5
|
+
now(): number;
|
|
6
|
+
setTimeout(fn: () => void, ms: number): unknown;
|
|
7
|
+
clearTimeout(handle: unknown): void;
|
|
8
|
+
}
|
|
9
|
+
type Observation = Resource<LocalAsset> & {
|
|
10
|
+
notice?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function createAssetController(options: {
|
|
13
|
+
api: StudioApi;
|
|
14
|
+
queue?: ReturnType<typeof createSaveQueue>;
|
|
15
|
+
clock?: Clock;
|
|
16
|
+
onChange?: () => void;
|
|
17
|
+
}): {
|
|
18
|
+
state: Record<string, Observation>;
|
|
19
|
+
read: (id: string, opts?: {
|
|
20
|
+
manual?: boolean;
|
|
21
|
+
automatic?: boolean;
|
|
22
|
+
lazy?: boolean;
|
|
23
|
+
}) => Promise<void>;
|
|
24
|
+
markVisible: (id: string, on: boolean) => void;
|
|
25
|
+
setPageVisible: (value: boolean) => void;
|
|
26
|
+
beginList: () => {
|
|
27
|
+
serial: number;
|
|
28
|
+
inFlight: Set<string>;
|
|
29
|
+
};
|
|
30
|
+
rememberList: (assets: LocalAsset[], ticket: ReturnType<() => {
|
|
31
|
+
serial: number;
|
|
32
|
+
inFlight: Set<string>;
|
|
33
|
+
}>) => void;
|
|
34
|
+
dispose: () => void;
|
|
35
|
+
};
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=asset-controller.d.ts.map
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { uiError } from './controller.js';
|
|
2
|
+
import { createSaveQueue } from './save-queue.js';
|
|
3
|
+
import { pendingDelay, backoffDelay } from './save-model.js';
|
|
4
|
+
import { parseAssetMetadata } from './asset-model.js';
|
|
5
|
+
export function createAssetController(options) {
|
|
6
|
+
const state = {}, queue = options.queue ?? createSaveQueue(), clock = options.clock ?? { now: Date.now, setTimeout: (fn, ms) => setTimeout(fn, ms), clearTimeout: (h) => clearTimeout(h) };
|
|
7
|
+
const follows = new Map(), visible = new Set(), lazy = new Set(), tickets = new Map();
|
|
8
|
+
let epoch = 0, serial = 0, pageVisible = true, timer;
|
|
9
|
+
const paused = Symbol('paused'), expired = Symbol('expired'), capped = Symbol('follow-limit'), emit = () => options.onChange?.();
|
|
10
|
+
const context = (id) => {
|
|
11
|
+
let f = follows.get(id);
|
|
12
|
+
if (!f) {
|
|
13
|
+
f = { count: 0, failures: 0 };
|
|
14
|
+
follows.set(id, f);
|
|
15
|
+
}
|
|
16
|
+
return f;
|
|
17
|
+
};
|
|
18
|
+
const key = (id) => `asset:${epoch}:${id}`;
|
|
19
|
+
function stopTimer() {
|
|
20
|
+
if (timer !== undefined)
|
|
21
|
+
clock.clearTimeout(timer);
|
|
22
|
+
timer = undefined;
|
|
23
|
+
}
|
|
24
|
+
function expire(id, f) {
|
|
25
|
+
if (f.start === undefined || clock.now() < f.start + 120000)
|
|
26
|
+
return false;
|
|
27
|
+
f.next = undefined;
|
|
28
|
+
if (state[id])
|
|
29
|
+
state[id].notice = f.failures ? '暂不可核对 · 核对文件状态' : '核验尚未完成 · 核对文件状态';
|
|
30
|
+
queue.cancel(key(id), expired);
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
function arm() {
|
|
34
|
+
stopTimer();
|
|
35
|
+
if (!pageVisible)
|
|
36
|
+
return;
|
|
37
|
+
const due = [];
|
|
38
|
+
for (const [id, f] of follows) {
|
|
39
|
+
if (expire(id, f))
|
|
40
|
+
continue;
|
|
41
|
+
if (f.busy) {
|
|
42
|
+
if (f.start !== undefined)
|
|
43
|
+
due.push(f.start + 120000);
|
|
44
|
+
}
|
|
45
|
+
else if (f.next !== undefined)
|
|
46
|
+
due.push(f.start === undefined ? f.next : Math.min(f.next, f.start + 120000));
|
|
47
|
+
}
|
|
48
|
+
if (due.length)
|
|
49
|
+
timer = clock.setTimeout(tick, Math.max(0, Math.min(...due) - clock.now()));
|
|
50
|
+
}
|
|
51
|
+
function tick() {
|
|
52
|
+
timer = undefined;
|
|
53
|
+
if (!pageVisible)
|
|
54
|
+
return;
|
|
55
|
+
for (const [id, f] of follows)
|
|
56
|
+
if (!expire(id, f) && !f.busy && f.next !== undefined && f.next <= clock.now())
|
|
57
|
+
void read(id, { automatic: true });
|
|
58
|
+
arm();
|
|
59
|
+
emit();
|
|
60
|
+
}
|
|
61
|
+
function beginList() {
|
|
62
|
+
return { serial: ++serial, inFlight: new Set([...follows].filter(([, f]) => f.busy).map(([id]) => id)) };
|
|
63
|
+
}
|
|
64
|
+
function rememberList(assets, ticket) {
|
|
65
|
+
for (const a of assets) {
|
|
66
|
+
if (ticket.inFlight.has(a.assetId) || (tickets.get(a.assetId) ?? 0) > ticket.serial)
|
|
67
|
+
continue;
|
|
68
|
+
tickets.set(a.assetId, ticket.serial);
|
|
69
|
+
state[a.assetId] = { status: 'ready', value: a };
|
|
70
|
+
if (a.integrity?.integrityCheck === 'IDLE') {
|
|
71
|
+
const f = context(a.assetId);
|
|
72
|
+
f.start = undefined;
|
|
73
|
+
f.next = undefined;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
arm();
|
|
77
|
+
emit();
|
|
78
|
+
}
|
|
79
|
+
function read(id, opts = {}) {
|
|
80
|
+
const f = context(id);
|
|
81
|
+
if (f.busy)
|
|
82
|
+
return f.busy;
|
|
83
|
+
const before = state[id];
|
|
84
|
+
if (!before?.value)
|
|
85
|
+
return Promise.resolve();
|
|
86
|
+
const started = epoch, oldNext = f.next, ticket = ++serial;
|
|
87
|
+
f.next = undefined;
|
|
88
|
+
if (opts.manual) {
|
|
89
|
+
f.start = undefined;
|
|
90
|
+
f.count = 0;
|
|
91
|
+
f.failures = 0;
|
|
92
|
+
}
|
|
93
|
+
tickets.set(id, ticket);
|
|
94
|
+
const loading = { ...before, status: 'loading' };
|
|
95
|
+
state[id] = loading;
|
|
96
|
+
emit();
|
|
97
|
+
const pending = (async () => {
|
|
98
|
+
try {
|
|
99
|
+
const reply = await queue.run(key(id), opts.manual ? 1 : 2, () => {
|
|
100
|
+
if (started !== epoch || !pageVisible || opts.lazy && !visible.has(id))
|
|
101
|
+
return Promise.resolve(paused);
|
|
102
|
+
if (expire(id, f))
|
|
103
|
+
return Promise.resolve(expired);
|
|
104
|
+
if (opts.automatic && f.start !== undefined && f.count >= 13)
|
|
105
|
+
return Promise.resolve(capped);
|
|
106
|
+
if (opts.lazy)
|
|
107
|
+
lazy.add(id);
|
|
108
|
+
if (opts.automatic)
|
|
109
|
+
f.count++;
|
|
110
|
+
return options.api(`assets/${id}`);
|
|
111
|
+
});
|
|
112
|
+
if (started !== epoch)
|
|
113
|
+
return;
|
|
114
|
+
if (reply === paused || reply === expired || reply === capped) {
|
|
115
|
+
if (reply === paused)
|
|
116
|
+
f.next = oldNext;
|
|
117
|
+
if (reply === capped)
|
|
118
|
+
f.next = f.start + 120000;
|
|
119
|
+
if (state[id] === loading)
|
|
120
|
+
state[id] = { ...before, ...(state[id].notice ? { notice: state[id].notice } : {}) };
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const asset = parseAssetMetadata(reply, id);
|
|
124
|
+
if ((tickets.get(id) ?? 0) > ticket)
|
|
125
|
+
return;
|
|
126
|
+
state[id] = { status: 'ready', value: asset };
|
|
127
|
+
f.failures = 0;
|
|
128
|
+
if (asset.integrity.integrityCheck === 'PENDING') {
|
|
129
|
+
f.start ??= clock.now();
|
|
130
|
+
if (!expire(id, f))
|
|
131
|
+
f.next = f.count < 13 ? clock.now() + pendingDelay(f.count) : f.start + 120000;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
f.start = undefined;
|
|
135
|
+
f.next = undefined;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
if (started !== epoch)
|
|
140
|
+
return;
|
|
141
|
+
state[id] = { ...state[id], status: 'error', error: uiError(error), notice: '文件状态尚未确认 · 核对文件状态' };
|
|
142
|
+
const status = error?.status ?? uiError(error).httpStatus;
|
|
143
|
+
const transient = status === 503 || status === undefined && (!(error?.code) || uiError(error).code === 'STUDIO_REQUEST_FAILED');
|
|
144
|
+
if (transient && f.start !== undefined && !expire(id, f))
|
|
145
|
+
f.next = clock.now() + backoffDelay(f.failures++);
|
|
146
|
+
else
|
|
147
|
+
f.next = undefined;
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
if (started === epoch) {
|
|
151
|
+
f.busy = undefined;
|
|
152
|
+
arm();
|
|
153
|
+
emit();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
})();
|
|
157
|
+
f.busy = pending;
|
|
158
|
+
return pending;
|
|
159
|
+
}
|
|
160
|
+
function markVisible(id, on) {
|
|
161
|
+
if (on)
|
|
162
|
+
visible.add(id);
|
|
163
|
+
else
|
|
164
|
+
visible.delete(id);
|
|
165
|
+
if (pageVisible && on && !lazy.has(id) && state[id]?.value)
|
|
166
|
+
void read(id, { lazy: true });
|
|
167
|
+
}
|
|
168
|
+
function setPageVisible(value) {
|
|
169
|
+
pageVisible = value;
|
|
170
|
+
if (value)
|
|
171
|
+
for (const id of visible)
|
|
172
|
+
if (!lazy.has(id) && state[id]?.value)
|
|
173
|
+
void read(id, { lazy: true });
|
|
174
|
+
arm();
|
|
175
|
+
emit();
|
|
176
|
+
}
|
|
177
|
+
function dispose() {
|
|
178
|
+
epoch++;
|
|
179
|
+
queue.reset('asset:');
|
|
180
|
+
stopTimer();
|
|
181
|
+
follows.clear();
|
|
182
|
+
visible.clear();
|
|
183
|
+
lazy.clear();
|
|
184
|
+
tickets.clear();
|
|
185
|
+
for (const id of Object.keys(state))
|
|
186
|
+
delete state[id];
|
|
187
|
+
emit();
|
|
188
|
+
}
|
|
189
|
+
return { state, read, markVisible, setPageVisible, beginList, rememberList, dispose };
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=asset-controller.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface AssetIntegrity {
|
|
2
|
+
file: 'NOT_CHECKED' | 'ABSENT' | 'PARTIAL' | 'VERIFIED' | 'MISSING' | 'MODIFIED' | 'UNSAFE' | 'UNKNOWN';
|
|
3
|
+
checkedAt: string | null;
|
|
4
|
+
integrityCheck: 'IDLE' | 'PENDING';
|
|
5
|
+
}
|
|
6
|
+
export interface LocalAsset {
|
|
7
|
+
assetId: string;
|
|
8
|
+
displayName: string;
|
|
9
|
+
mediaType: string;
|
|
10
|
+
byteLength: number;
|
|
11
|
+
integrity?: AssetIntegrity;
|
|
12
|
+
}
|
|
13
|
+
export interface ObservedAsset extends LocalAsset {
|
|
14
|
+
integrity: AssetIntegrity;
|
|
15
|
+
}
|
|
16
|
+
/** A fresh local list receipt, shared with Canvas C1. Loading/error values remain stale, not new receipts. */
|
|
17
|
+
export declare function parseLocalAssetReceipt(resource: unknown): {
|
|
18
|
+
assets: LocalAsset[];
|
|
19
|
+
recoveryIssues: unknown[];
|
|
20
|
+
} | undefined;
|
|
21
|
+
export declare function assetFileLink(asset: LocalAsset): {
|
|
22
|
+
canOpen: boolean;
|
|
23
|
+
reason: string;
|
|
24
|
+
};
|
|
25
|
+
export declare function parseAssetMetadata(value: unknown, assetId: string): ObservedAsset;
|
|
26
|
+
export declare function assetPresentation(asset: LocalAsset, observationFailed?: boolean): {
|
|
27
|
+
status: string;
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=asset-model.d.ts.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { isId, isRecord, invalidSaveResponse } from './save-model.js';
|
|
2
|
+
/** A fresh local list receipt, shared with Canvas C1. Loading/error values remain stale, not new receipts. */
|
|
3
|
+
export function parseLocalAssetReceipt(resource) {
|
|
4
|
+
if (!isRecord(resource) || resource.status !== 'ready')
|
|
5
|
+
return undefined;
|
|
6
|
+
const value = resource.value;
|
|
7
|
+
if (!isRecord(value) || !Array.isArray(value.assets) || !Array.isArray(value.recoveryIssues))
|
|
8
|
+
return invalidSaveResponse();
|
|
9
|
+
for (const asset of value.assets) {
|
|
10
|
+
if (!isRecord(asset) || !isId(asset.assetId) || typeof asset.displayName !== 'string' || typeof asset.mediaType !== 'string' ||
|
|
11
|
+
!Number.isSafeInteger(asset.byteLength) || asset.byteLength < 1)
|
|
12
|
+
return invalidSaveResponse();
|
|
13
|
+
}
|
|
14
|
+
if (new Set(value.assets.map(asset => asset.assetId)).size !== value.assets.length)
|
|
15
|
+
return invalidSaveResponse();
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
export function assetFileLink(asset) {
|
|
19
|
+
switch (asset.integrity?.file) {
|
|
20
|
+
case 'MISSING':
|
|
21
|
+
return { canOpen: false, reason: '文件已缺失,无法打开本机文件。' };
|
|
22
|
+
case 'UNSAFE':
|
|
23
|
+
return { canOpen: false, reason: '文件安全状态异常,暂不能打开本机文件。' };
|
|
24
|
+
case 'MODIFIED':
|
|
25
|
+
return { canOpen: true, reason: '文件已被修改,当前内容可能与原素材不同。' };
|
|
26
|
+
default:
|
|
27
|
+
return { canOpen: true, reason: '' };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function parseAssetMetadata(value, assetId) {
|
|
31
|
+
if (!isRecord(value) || !(value.scope === null || isRecord(value.scope) && (value.scope.rootId === null || isId(value.scope.rootId)) && isId(value.scope.connectionId)) || !isRecord(value.asset))
|
|
32
|
+
return invalidSaveResponse();
|
|
33
|
+
const a = value.asset, fact = a.integrity;
|
|
34
|
+
if (a.assetId !== assetId || !isId(a.assetId) || typeof a.displayName !== 'string' || typeof a.mediaType !== 'string' || typeof a.byteLength !== 'number' || !Number.isSafeInteger(a.byteLength) || a.byteLength < 1 || !isRecord(fact) ||
|
|
35
|
+
!['NOT_CHECKED', 'ABSENT', 'PARTIAL', 'VERIFIED', 'MISSING', 'MODIFIED', 'UNSAFE', 'UNKNOWN'].includes(fact.file) || !['IDLE', 'PENDING'].includes(fact.integrityCheck) || !(fact.checkedAt === null || typeof fact.checkedAt === 'string' && Number.isFinite(Date.parse(fact.checkedAt))) || fact.file === 'VERIFIED' && !fact.checkedAt || fact.integrityCheck === 'PENDING' && fact.file !== 'NOT_CHECKED')
|
|
36
|
+
return invalidSaveResponse();
|
|
37
|
+
return a;
|
|
38
|
+
}
|
|
39
|
+
export function assetPresentation(asset, observationFailed = false) {
|
|
40
|
+
if (observationFailed)
|
|
41
|
+
return { status: '文件状态尚未确认' };
|
|
42
|
+
const fact = asset.integrity;
|
|
43
|
+
if (!fact)
|
|
44
|
+
return { status: '文件状态尚未读取' };
|
|
45
|
+
if (fact.integrityCheck === 'PENDING')
|
|
46
|
+
return { status: '正在核对文件' };
|
|
47
|
+
if (fact.file === 'VERIFIED' && fact.checkedAt)
|
|
48
|
+
return { status: '本机文件 · 当前已核验' };
|
|
49
|
+
return { status: { NOT_CHECKED: '文件尚未核验', MISSING: '文件现已缺失', MODIFIED: '文件现已变更', UNSAFE: '文件安全状态异常', UNKNOWN: '文件状态未确认', ABSENT: '文件不存在', PARTIAL: '文件不完整', VERIFIED: '文件状态未确认' }[fact.file] };
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=asset-model.js.map
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { type MediaModel, type Mode, type PublicRun, type PublicFailure } from './model.js';
|
|
2
|
+
import { type SaveState } from './save-controller.js';
|
|
3
|
+
import { createAssetController } from './asset-controller.js';
|
|
4
|
+
import { type LocalAsset } from './asset-model.js';
|
|
5
|
+
export interface Resource<T> {
|
|
6
|
+
status: 'idle' | 'loading' | 'ready' | 'error';
|
|
7
|
+
value?: T;
|
|
8
|
+
error?: UiError;
|
|
9
|
+
}
|
|
10
|
+
export type UiError = Omit<PublicFailure, 'type'> & {
|
|
11
|
+
type?: string;
|
|
12
|
+
};
|
|
13
|
+
interface Draft {
|
|
14
|
+
modelId: string;
|
|
15
|
+
fields: Record<string, string>;
|
|
16
|
+
savedAt?: string;
|
|
17
|
+
}
|
|
18
|
+
interface Drafts {
|
|
19
|
+
revision: number;
|
|
20
|
+
drafts: Partial<Record<Mode, Draft>>;
|
|
21
|
+
}
|
|
22
|
+
export interface Session {
|
|
23
|
+
storage: {
|
|
24
|
+
configured: boolean;
|
|
25
|
+
outputDir?: string;
|
|
26
|
+
};
|
|
27
|
+
cloud: {
|
|
28
|
+
connected: boolean;
|
|
29
|
+
gateway?: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export type Asset = LocalAsset;
|
|
33
|
+
export interface State {
|
|
34
|
+
local: Resource<Session>;
|
|
35
|
+
catalog: Resource<MediaModel[]>;
|
|
36
|
+
balance: Resource<{
|
|
37
|
+
availableCredits: number;
|
|
38
|
+
reservedCredits: number;
|
|
39
|
+
}>;
|
|
40
|
+
runs: Resource<PublicRun[]>;
|
|
41
|
+
assets: Resource<{
|
|
42
|
+
assets: Asset[];
|
|
43
|
+
recoveryIssues: unknown[];
|
|
44
|
+
}>;
|
|
45
|
+
drafts: Resource<Drafts>;
|
|
46
|
+
mode: Mode;
|
|
47
|
+
edits: Record<Mode, Draft>;
|
|
48
|
+
dirty: Record<Mode, boolean>;
|
|
49
|
+
connected: boolean;
|
|
50
|
+
gateway?: string;
|
|
51
|
+
connecting: boolean;
|
|
52
|
+
quoteBusy: boolean;
|
|
53
|
+
submitBusy: boolean;
|
|
54
|
+
saving: boolean;
|
|
55
|
+
refreshing: boolean;
|
|
56
|
+
quote?: PublicRun;
|
|
57
|
+
error?: UiError;
|
|
58
|
+
notice: string;
|
|
59
|
+
sessionExpired: boolean;
|
|
60
|
+
saves: SaveState;
|
|
61
|
+
assetChecks: ReturnType<typeof createAssetController>['state'];
|
|
62
|
+
}
|
|
63
|
+
export type StudioApi = (route: string, body?: unknown) => Promise<any>;
|
|
64
|
+
export declare function createLocalApi(fetcher?: typeof fetch, onUnauthorized?: () => void): StudioApi & {
|
|
65
|
+
request: typeof fetch;
|
|
66
|
+
};
|
|
67
|
+
export declare function uiError(error: unknown): UiError;
|
|
68
|
+
export declare function createStudioController(options: {
|
|
69
|
+
api: StudioApi;
|
|
70
|
+
onChange?: (state: State) => void;
|
|
71
|
+
uuid?: () => string;
|
|
72
|
+
now?: () => number;
|
|
73
|
+
}): {
|
|
74
|
+
state: State;
|
|
75
|
+
expireSession: () => void;
|
|
76
|
+
readOutputs: (runId: string, retry?: boolean) => Promise<void>;
|
|
77
|
+
saveOutput: (runId: string, outputId: string) => Promise<void>;
|
|
78
|
+
checkOutput: (runId: string, outputId: string) => Promise<void>;
|
|
79
|
+
readSave: (id: string, readOptions?: {
|
|
80
|
+
manual?: boolean;
|
|
81
|
+
automatic?: boolean;
|
|
82
|
+
lazy?: boolean;
|
|
83
|
+
}) => Promise<void>;
|
|
84
|
+
retrySave: (id: string) => Promise<void>;
|
|
85
|
+
markSaveVisible: (id: string, onScreen: boolean) => void;
|
|
86
|
+
readAsset: (id: string, opts?: {
|
|
87
|
+
manual?: boolean;
|
|
88
|
+
automatic?: boolean;
|
|
89
|
+
lazy?: boolean;
|
|
90
|
+
}) => Promise<void>;
|
|
91
|
+
markAssetVisible: (id: string, on: boolean) => void;
|
|
92
|
+
setSavePageVisible(value: boolean): void;
|
|
93
|
+
disposeSaves(): void;
|
|
94
|
+
bindSaves(): Promise<void>;
|
|
95
|
+
init(): Promise<void>;
|
|
96
|
+
setMode(mode: Mode): void;
|
|
97
|
+
selectModel(id: string): void;
|
|
98
|
+
setField(key: string, value: string): void;
|
|
99
|
+
saveDraft(): Promise<void>;
|
|
100
|
+
rereadDrafts(): Promise<void>;
|
|
101
|
+
connect(): Promise<void>;
|
|
102
|
+
disconnect(): Promise<void>;
|
|
103
|
+
refreshCloud: () => Promise<void>;
|
|
104
|
+
quote(): Promise<void>;
|
|
105
|
+
confirm(): Promise<void>;
|
|
106
|
+
refreshRun(id: string): Promise<void>;
|
|
107
|
+
refreshAssets: (options?: {
|
|
108
|
+
afterWrite?: boolean;
|
|
109
|
+
}) => Promise<void>;
|
|
110
|
+
reportError: (error: unknown) => void;
|
|
111
|
+
};
|
|
112
|
+
export {};
|
|
113
|
+
//# sourceMappingURL=controller.d.ts.map
|