@lumenkey/cli 0.3.0 → 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.
Files changed (184) hide show
  1. package/README.md +51 -2
  2. package/dist/cli/copied.js +86 -85
  3. package/dist/cli/index.js +56 -44
  4. package/dist/cli/render.js +5 -1
  5. package/dist/core/asset-stream.d.ts +16 -0
  6. package/dist/core/asset-stream.js +64 -0
  7. package/dist/core/atomic-config-file.js +8 -7
  8. package/dist/core/chinese-messages.d.ts +4 -0
  9. package/dist/core/chinese-messages.js +907 -0
  10. package/dist/core/chinese-script.d.ts +7 -0
  11. package/dist/core/chinese-script.js +28 -0
  12. package/dist/core/client.js +2 -1
  13. package/dist/core/config-dir.js +2 -1
  14. package/dist/core/config.js +7 -6
  15. package/dist/core/download-root.d.ts +5 -0
  16. package/dist/core/download-root.js +64 -0
  17. package/dist/core/download.js +15 -12
  18. package/dist/core/generation-input.js +3 -2
  19. package/dist/core/generation.d.ts +8 -1
  20. package/dist/core/generation.js +13 -10
  21. package/dist/core/job-display.js +7 -6
  22. package/dist/core/locale.d.ts +2 -0
  23. package/dist/core/locale.js +172 -142
  24. package/dist/core/outcome.d.ts +6 -0
  25. package/dist/core/outcome.js +17 -4
  26. package/dist/core/output-path.d.ts +3 -1
  27. package/dist/core/output-path.js +5 -2
  28. package/dist/core/params.js +26 -25
  29. package/dist/core/profiles.js +5 -4
  30. package/dist/core/set-values.d.ts +0 -1
  31. package/dist/core/set-values.js +7 -7
  32. package/dist/core/submission-journal.js +43 -17
  33. package/dist/core/version.js +2 -3
  34. package/dist/mcp/server.js +30 -29
  35. package/dist/studio/asset-integrity-hash.d.ts +28 -0
  36. package/dist/studio/asset-integrity-hash.js +93 -0
  37. package/dist/studio/asset-integrity-queue.d.ts +24 -0
  38. package/dist/studio/asset-integrity-queue.js +94 -0
  39. package/dist/studio/asset-store.d.ts +52 -0
  40. package/dist/studio/asset-store.js +352 -0
  41. package/dist/studio/canvas/LICENSES.txt +1590 -0
  42. package/dist/studio/canvas/dependencies.json +862 -0
  43. package/dist/studio/canvas/director-source-manifest.json +47 -0
  44. package/dist/studio/canvas/editor.css +239 -0
  45. package/dist/studio/canvas/editor.js +4613 -0
  46. package/dist/studio/canvas/integration-source-manifest.json +384 -0
  47. package/dist/studio/canvas/source-manifest.json +240 -0
  48. package/dist/studio/canvas-store.d.ts +1254 -0
  49. package/dist/studio/canvas-store.js +205 -0
  50. package/dist/studio/capture-placement.d.ts +11 -0
  51. package/dist/studio/capture-placement.js +85 -0
  52. package/dist/studio/cloud-contract.d.ts +128 -0
  53. package/dist/studio/cloud-contract.js +229 -0
  54. package/dist/studio/cloud-service.d.ts +178 -0
  55. package/dist/studio/cloud-service.js +202 -0
  56. package/dist/studio/director-captures.d.ts +59 -0
  57. package/dist/studio/director-captures.js +141 -0
  58. package/dist/studio/director-contract.d.ts +1489 -0
  59. package/dist/studio/director-contract.js +288 -0
  60. package/dist/studio/director-png.d.ts +6 -0
  61. package/dist/studio/director-png.js +41 -0
  62. package/dist/studio/director-relations.d.ts +40 -0
  63. package/dist/studio/director-relations.js +103 -0
  64. package/dist/studio/document-authority.d.ts +7 -0
  65. package/dist/studio/document-authority.js +50 -0
  66. package/dist/studio/draft-store.d.ts +95 -0
  67. package/dist/studio/draft-store.js +100 -0
  68. package/dist/studio/errors.d.ts +85 -0
  69. package/dist/studio/errors.js +94 -0
  70. package/dist/studio/launch.d.ts +5 -0
  71. package/dist/studio/launch.js +31 -0
  72. package/dist/studio/media.d.ts +9 -0
  73. package/dist/studio/media.js +50 -0
  74. package/dist/studio/output-save-contract.d.ts +1321 -0
  75. package/dist/studio/output-save-contract.js +26 -0
  76. package/dist/studio/output-save-journal.d.ts +971 -0
  77. package/dist/studio/output-save-journal.js +287 -0
  78. package/dist/studio/output-save-recovery.d.ts +18 -0
  79. package/dist/studio/output-save-recovery.js +161 -0
  80. package/dist/studio/output-save-service.d.ts +436 -0
  81. package/dist/studio/output-save-service.js +251 -0
  82. package/dist/studio/output-save-worker.d.ts +40 -0
  83. package/dist/studio/output-save-worker.js +360 -0
  84. package/dist/studio/paths.d.ts +6 -0
  85. package/dist/studio/paths.js +68 -0
  86. package/dist/studio/run-journal.d.ts +993 -0
  87. package/dist/studio/run-journal.js +125 -0
  88. package/dist/studio/server.d.ts +17 -0
  89. package/dist/studio/server.js +440 -0
  90. package/dist/studio/session.d.ts +6 -0
  91. package/dist/studio/session.js +26 -0
  92. package/dist/studio/shell.d.ts +3 -0
  93. package/dist/studio/shell.js +23 -0
  94. package/dist/studio/style.d.ts +2 -0
  95. package/dist/studio/style.js +29 -0
  96. package/dist/studio/types.d.ts +26 -0
  97. package/dist/studio/types.js +2 -0
  98. package/dist/studio/web/app.d.ts +2 -0
  99. package/dist/studio/web/app.js +662 -0
  100. package/dist/studio/web/asset-controller.d.ts +37 -0
  101. package/dist/studio/web/asset-controller.js +191 -0
  102. package/dist/studio/web/asset-model.d.ts +29 -0
  103. package/dist/studio/web/asset-model.js +51 -0
  104. package/dist/studio/web/controller.d.ts +113 -0
  105. package/dist/studio/web/controller.js +401 -0
  106. package/dist/studio/web/messages.d.ts +2 -0
  107. package/dist/studio/web/messages.js +74 -0
  108. package/dist/studio/web/model.d.ts +75 -0
  109. package/dist/studio/web/model.js +182 -0
  110. package/dist/studio/web/save-controller.d.ts +85 -0
  111. package/dist/studio/web/save-controller.js +495 -0
  112. package/dist/studio/web/save-model.d.ts +63 -0
  113. package/dist/studio/web/save-model.js +64 -0
  114. package/dist/studio/web/save-queue.d.ts +7 -0
  115. package/dist/studio/web/save-queue.js +62 -0
  116. package/dist/studio/web/save-view.d.ts +9 -0
  117. package/dist/studio/web/save-view.js +19 -0
  118. package/dist/studio/writer-lock.d.ts +5 -0
  119. package/dist/studio/writer-lock.js +88 -0
  120. package/package.json +11 -5
  121. package/dist/cli/copied.d.ts.map +0 -1
  122. package/dist/cli/copied.js.map +0 -1
  123. package/dist/cli/index.d.ts.map +0 -1
  124. package/dist/cli/index.js.map +0 -1
  125. package/dist/cli/render.d.ts.map +0 -1
  126. package/dist/cli/render.js.map +0 -1
  127. package/dist/core/atomic-config-file.d.ts.map +0 -1
  128. package/dist/core/atomic-config-file.js.map +0 -1
  129. package/dist/core/chat.d.ts.map +0 -1
  130. package/dist/core/chat.js.map +0 -1
  131. package/dist/core/client.d.ts.map +0 -1
  132. package/dist/core/client.js.map +0 -1
  133. package/dist/core/config-dir.d.ts.map +0 -1
  134. package/dist/core/config-dir.js.map +0 -1
  135. package/dist/core/config-error.d.ts.map +0 -1
  136. package/dist/core/config-error.js.map +0 -1
  137. package/dist/core/config.d.ts.map +0 -1
  138. package/dist/core/config.js.map +0 -1
  139. package/dist/core/credit-cap.d.ts.map +0 -1
  140. package/dist/core/credit-cap.js.map +0 -1
  141. package/dist/core/download.d.ts.map +0 -1
  142. package/dist/core/download.js.map +0 -1
  143. package/dist/core/error-result.d.ts.map +0 -1
  144. package/dist/core/error-result.js.map +0 -1
  145. package/dist/core/explain.d.ts.map +0 -1
  146. package/dist/core/explain.js.map +0 -1
  147. package/dist/core/generation-input.d.ts.map +0 -1
  148. package/dist/core/generation-input.js.map +0 -1
  149. package/dist/core/generation-result.d.ts.map +0 -1
  150. package/dist/core/generation-result.js.map +0 -1
  151. package/dist/core/generation.d.ts.map +0 -1
  152. package/dist/core/generation.js.map +0 -1
  153. package/dist/core/job-display.d.ts.map +0 -1
  154. package/dist/core/job-display.js.map +0 -1
  155. package/dist/core/locale.d.ts.map +0 -1
  156. package/dist/core/locale.js.map +0 -1
  157. package/dist/core/origin.d.ts.map +0 -1
  158. package/dist/core/origin.js.map +0 -1
  159. package/dist/core/outcome.d.ts.map +0 -1
  160. package/dist/core/outcome.js.map +0 -1
  161. package/dist/core/output-path.d.ts.map +0 -1
  162. package/dist/core/output-path.js.map +0 -1
  163. package/dist/core/params.d.ts.map +0 -1
  164. package/dist/core/params.js.map +0 -1
  165. package/dist/core/poller.d.ts.map +0 -1
  166. package/dist/core/poller.js.map +0 -1
  167. package/dist/core/profiles.d.ts.map +0 -1
  168. package/dist/core/profiles.js.map +0 -1
  169. package/dist/core/set-values.d.ts.map +0 -1
  170. package/dist/core/set-values.js.map +0 -1
  171. package/dist/core/submission-journal.d.ts.map +0 -1
  172. package/dist/core/submission-journal.js.map +0 -1
  173. package/dist/core/types.d.ts.map +0 -1
  174. package/dist/core/types.js.map +0 -1
  175. package/dist/core/version.d.ts.map +0 -1
  176. package/dist/core/version.js.map +0 -1
  177. package/dist/core/wait.d.ts.map +0 -1
  178. package/dist/core/wait.js.map +0 -1
  179. package/dist/index.d.ts.map +0 -1
  180. package/dist/index.js.map +0 -1
  181. package/dist/mcp/render.d.ts.map +0 -1
  182. package/dist/mcp/render.js.map +0 -1
  183. package/dist/mcp/server.d.ts.map +0 -1
  184. package/dist/mcp/server.js.map +0 -1
@@ -0,0 +1,182 @@
1
+ // Browser-safe contract: no Node imports and no credentials.
2
+ import { messageForCode } from './messages.js';
3
+ // Source (read-only r13 zh-CN): F:/光钥/_admin-manual-approval-20261007-cn-frontend/workbench-suno-audio-r13-20261016/candidate/src/i18n/locales/zh-CN.json
4
+ // SHA256 b5f9ce939088eab3. Field names only; no fallback/unspecified or audio-only Suno keys.
5
+ const fieldLabels = Object.freeze({
6
+ 'playground.fields.prompt': '提示词',
7
+ 'playground.fields.image_size': '图像尺寸',
8
+ 'playground.fields.num_images': '图像数量',
9
+ 'playground.fields.duration': '时长',
10
+ 'playground.fields.aspect_ratio': '画面比例',
11
+ 'playground.fields.size': '自定义尺寸(宽 × 高)',
12
+ 'playground.fields.prompt_extend': '扩展提示词',
13
+ 'playground.fields.resolution': '清晰度',
14
+ 'playground.fields.generate_audio': '生成音频',
15
+ 'playground.fields.source': '源图像',
16
+ 'playground.fields.outputs': '输出数量',
17
+ 'playground.fields.seed': '种子',
18
+ 'playground.fields.count': '数量',
19
+ 'playground.fields.containsRealPerson': '包含真人',
20
+ });
21
+ const displayControls = new Set(['upload', 'select', 'textarea', 'checkbox', 'number', 'text']);
22
+ export function modelsFor(models, mode) { return models.filter(m => m.type === mode || m.capabilities?.includes(mode)); }
23
+ const dangerous = (key) => ['__proto__', 'constructor', 'prototype'].includes(key);
24
+ function safe(value, depth = 0) {
25
+ if (depth > 20)
26
+ return false;
27
+ if (value === null || typeof value === 'string' || typeof value === 'boolean')
28
+ return true;
29
+ if (typeof value === 'number')
30
+ return Number.isFinite(value);
31
+ if (Array.isArray(value))
32
+ return value.every(v => safe(v, depth + 1));
33
+ return !!value && typeof value === 'object' && Object.entries(value).every(([k, v]) => !dangerous(k) && safe(v, depth + 1));
34
+ }
35
+ const encode = (value) => typeof value === 'string' ? value : JSON.stringify(value);
36
+ const record = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
37
+ const schemaTypes = new Set(['string', 'number', 'integer', 'boolean', 'object', 'array', 'null']);
38
+ const validType = (value) => typeof value === 'string' && schemaTypes.has(value);
39
+ const catalogInvalid = () => { throw Object.assign(new Error('模型目录字段不符合表单契约;当前编辑已保留。'), { code: 'STUDIO_CATALOG_RESPONSE_INVALID' }); };
40
+ export function validateModels(value) {
41
+ if (!Array.isArray(value) || value.length > 10000)
42
+ return catalogInvalid();
43
+ const ids = new Set();
44
+ for (const model of value) {
45
+ if (!record(model) || typeof model.id !== 'string' || !model.id || ids.has(model.id) || !safe(model))
46
+ return catalogInvalid();
47
+ ids.add(model.id);
48
+ if ((model.type !== undefined && typeof model.type !== 'string') || (model.capabilities !== undefined && (!Array.isArray(model.capabilities) || !model.capabilities.every(v => typeof v === 'string'))))
49
+ return catalogInvalid();
50
+ const schema = model.inputSchema;
51
+ if (!record(schema) || !record(schema.properties) || (schema.required !== undefined && (!Array.isArray(schema.required) || !schema.required.every(v => typeof v === 'string'))))
52
+ return catalogInvalid();
53
+ for (const [key, spec] of Object.entries(schema.properties)) {
54
+ if (dangerous(key) || !record(spec) || (spec.title !== undefined && typeof spec.title !== 'string') || (spec.enum !== undefined && (!Array.isArray(spec.enum) || !spec.enum.length || new Set(spec.enum.map(v => JSON.stringify(v))).size !== spec.enum.length)))
55
+ return catalogInvalid();
56
+ if (spec.type !== undefined && !validType(spec.type) && !(Array.isArray(spec.type) && spec.type.length > 0 && spec.type.every(validType) && new Set(spec.type).size === spec.type.length))
57
+ return catalogInvalid();
58
+ }
59
+ }
60
+ return value;
61
+ }
62
+ export function describeFields(model) {
63
+ validateModels([model]);
64
+ const schema = model.inputSchema, candidate = schema['x-lumenkey-ui'];
65
+ const ui = record(candidate) && candidate.version === 1 && (candidate.mode === 'image' || candidate.mode === 'video')
66
+ && Array.isArray(candidate.core) && candidate.core.every((key) => typeof key === 'string')
67
+ && Array.isArray(candidate.advanced) && candidate.advanced.every((key) => typeof key === 'string')
68
+ ? { core: candidate.core, advanced: candidate.advanced } : undefined;
69
+ const core = new Set(ui?.core), advanced = new Set(ui?.advanced);
70
+ const keys = ui ? [...new Set([...ui.core, ...ui.advanced, ...Object.keys(schema.properties)])].filter(key => Object.hasOwn(schema.properties, key)) : Object.keys(schema.properties);
71
+ return keys.map(key => {
72
+ const spec = schema.properties[key];
73
+ const type = spec.type;
74
+ const values = Array.isArray(spec.enum) ? spec.enum : undefined;
75
+ const control = spec['x-lumenkey-control'], knownControl = typeof control === 'string' && displayControls.has(control);
76
+ const unlisted = !!ui && !core.has(key) && !advanced.has(key);
77
+ const labelKey = spec['x-lumenkey-label-key'];
78
+ const labelKnown = !unlisted && (control === undefined || knownControl) && typeof labelKey === 'string' && Object.hasOwn(fieldLabels, labelKey);
79
+ const field = { key, title: labelKnown ? fieldLabels[labelKey] : key, labelKnown, spec, required: schema.required?.includes(key) ?? false,
80
+ kind: values ? 'enum' : type === 'string' ? 'text' : type === 'integer' || type === 'number' ? 'number' : type === 'boolean' ? 'boolean' : 'json',
81
+ ...(values ? { options: values.map(v => ({ value: JSON.stringify(v), label: v === '' ? '空字符串(显式值)' : encode(v) + (values.filter(other => encode(other) === encode(v)).length > 1 ? `(${typeof v})` : '') })) } : {}),
82
+ ...(Object.hasOwn(spec, 'default') ? { defaultHint: encode(spec.default) } : {}), };
83
+ if (ui)
84
+ field.placement = unlisted ? 'advanced' : !knownControl ? fieldPlacement(field) : core.has(key) ? control === 'textarea' || control === 'upload' ? 'input' : 'common' : 'advanced';
85
+ return field;
86
+ });
87
+ }
88
+ export function parseFields(model, fields) {
89
+ const specs = new Map(describeFields(model).map(f => [f.key, f]));
90
+ const input = {};
91
+ for (const [key, raw] of Object.entries(fields)) {
92
+ if (raw === '')
93
+ continue;
94
+ const f = specs.get(key);
95
+ const fail = () => { throw Object.assign(new Error(`请检查参数 ${key} 的格式。`), { code: 'STUDIO_INPUT_INVALID' }); };
96
+ if (!f || dangerous(key))
97
+ fail();
98
+ let value;
99
+ if (f.kind === 'text')
100
+ value = raw;
101
+ else if (f.kind === 'enum') {
102
+ const matches = f.spec.enum.filter(v => JSON.stringify(v) === raw);
103
+ if (matches.length !== 1)
104
+ fail();
105
+ value = matches[0];
106
+ }
107
+ else if (f.kind === 'number') {
108
+ if (!/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(raw))
109
+ fail();
110
+ value = Number(raw);
111
+ if (!Number.isFinite(value) || (f.spec.type === 'integer' && !Number.isSafeInteger(value)))
112
+ fail();
113
+ }
114
+ else if (f.kind === 'boolean') {
115
+ if (!['true', 'false'].includes(raw))
116
+ fail();
117
+ value = raw === 'true';
118
+ }
119
+ else {
120
+ try {
121
+ value = JSON.parse(raw);
122
+ }
123
+ catch {
124
+ fail();
125
+ }
126
+ }
127
+ if (!safe(value))
128
+ fail();
129
+ input[key] = value;
130
+ }
131
+ return input;
132
+ }
133
+ export function runLabel(run) {
134
+ if (run.state === 'SUBMISSION_REJECTED')
135
+ return '提交被拒';
136
+ if (run.state === 'SUBMISSION_UNKNOWN' || run.state === 'SUBMITTING')
137
+ return run.job ? '任务已建立 · 状态待核对' : '提交结果待确认';
138
+ if (run.job?.error)
139
+ return '任务失败 / 返回错误';
140
+ if (run.job?.status === 'succeeded')
141
+ return run.job.outputs.length ? '云端完成' : '未取得可用输出';
142
+ if (run.job && ['failed', 'rejected', 'cancelled', 'expired'].includes(run.job.status))
143
+ return `任务失败或结束 · ${run.job.status}`;
144
+ if (run.job)
145
+ return `云端处理中 · ${run.job.status}`;
146
+ return run.state === 'QUOTED' ? '已报价 · 未提交' : '状态待核对';
147
+ }
148
+ export function runDiagnosticText(run) {
149
+ const diagnostic = run.failure ?? run.job?.error;
150
+ if (diagnostic)
151
+ return `${messageForCode(diagnostic.code, diagnostic.message || '请核对平台记录。')} (${diagnostic.code})`;
152
+ if (run.lastErrorCode)
153
+ return `${run.state === 'SUBMISSION_REJECTED' ? '本次提交被拒,请核对原因后重新报价。' : '请核对任务状态,不要重复提交。'} (${run.lastErrorCode})`;
154
+ }
155
+ export function runRecoveryText(run) {
156
+ // Studio's journal is not CLI/MCP pending storage; no replay command/window exists.
157
+ if (!run.job && ['SUBMISSION_UNKNOWN', 'SUBMITTING'].includes(run.state))
158
+ return '请到平台核对任务与账单记录;当前页面不能确认这次提交结果,请勿重复提交。';
159
+ }
160
+ export function safeOutputUrl(value) {
161
+ try {
162
+ const u = new URL(value);
163
+ if (['http:', 'https:'].includes(u.protocol) && !u.username && !u.password)
164
+ return u.href;
165
+ }
166
+ catch { /* reject */ }
167
+ }
168
+ // Frozen v1 display metadata wins; absent/unknown metadata falls back by schema type.
169
+ export function fieldPlacement(field) {
170
+ return field.placement ?? (field.kind === 'json' ? 'advanced' : field.kind === 'text' ? 'input' : 'common');
171
+ }
172
+ export function fieldDisplayLabel(field) {
173
+ return field.title + (field.required ? ' *' : '');
174
+ }
175
+ export function compactLocation(path) {
176
+ if (path.length <= 42)
177
+ return path;
178
+ const separator = path.includes('\\') ? '\\' : '/', parts = path.split(/[\\/]+/).filter(Boolean);
179
+ const root = /^[A-Za-z]:/.exec(path)?.[0] ?? (path.startsWith('/') ? '' : parts.shift() ?? '');
180
+ return root + separator + '…' + separator + parts.slice(-2).join(separator);
181
+ }
182
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1,85 @@
1
+ import { uiError, type Resource, type StudioApi } from './controller.js';
2
+ import { type SaveReceipt } from './save-model.js';
3
+ import { createSaveQueue } from './save-queue.js';
4
+ export interface SaveScope {
5
+ rootId: string | null;
6
+ connectionId: string;
7
+ }
8
+ export interface SaveBinding {
9
+ scope: SaveScope;
10
+ root: {
11
+ absolutePath: string;
12
+ } | null;
13
+ code: 'SAVE_OUTPUT_ROOT_REQUIRED' | null;
14
+ }
15
+ export type IdentityReason = 'LEGACY_AWAITING_FRESH_GET' | 'JOB_UNAVAILABLE' | 'NO_VERIFIABLE_OUTPUTS' | 'IDENTITY_CONFLICT';
16
+ export interface OutputView {
17
+ localOutputId: string | null;
18
+ runId: string;
19
+ jobId: string;
20
+ gatewayAssetId: string | null;
21
+ outputIndex: number | null;
22
+ displayOrdinal: number;
23
+ outputType: 'image' | 'video' | 'audio' | null;
24
+ mediaType: string | null;
25
+ identity: {
26
+ status: 'VERIFIED' | 'UNVERIFIED';
27
+ reason: IdentityReason | null;
28
+ };
29
+ acceptance: 'ACCEPTED' | 'NEVER_ACCEPTED' | 'UNKNOWN';
30
+ saveAllowed: boolean;
31
+ saveBlockedCode: string | null;
32
+ saveOperationId: string | null;
33
+ save: SaveReceipt | null;
34
+ }
35
+ export interface OutputList {
36
+ scope: SaveScope;
37
+ revision: number;
38
+ items: OutputView[];
39
+ }
40
+ export interface SaveState {
41
+ binding: Resource<SaveBinding>;
42
+ outputs: Record<string, Resource<OutputList>>;
43
+ operations: Record<string, Resource<SaveReceipt> & {
44
+ notice?: string;
45
+ }>;
46
+ targets: Record<string, {
47
+ status: 'idle' | 'submitting' | 'unknown' | 'known';
48
+ operationId?: string;
49
+ checking?: boolean;
50
+ error?: ReturnType<typeof uiError>;
51
+ }>;
52
+ }
53
+ export declare function parseBinding(value: unknown): SaveBinding;
54
+ export declare function parseOutputs(value: unknown, scope: SaveScope, runId: string): OutputList;
55
+ interface SaveClock {
56
+ now(): number;
57
+ setTimeout(fn: () => void, ms: number): unknown;
58
+ clearTimeout(handle: unknown): void;
59
+ }
60
+ export declare function createSaveController(options: {
61
+ api: StudioApi;
62
+ onChange?: () => void;
63
+ uuid?: () => string;
64
+ clock?: SaveClock;
65
+ queue?: ReturnType<typeof createSaveQueue>;
66
+ }): {
67
+ state: SaveState;
68
+ invalidate: () => void;
69
+ bind: () => Promise<void>;
70
+ readOutputs: (runId: string, retry?: boolean) => Promise<void>;
71
+ rememberReceipt: (next: SaveReceipt) => SaveReceipt;
72
+ readOperation: (id: string, readOptions?: {
73
+ manual?: boolean;
74
+ automatic?: boolean;
75
+ lazy?: boolean;
76
+ }) => Promise<void>;
77
+ checkOutput: (runId: string, outputId: string) => Promise<void>;
78
+ saveOutput: (runId: string, outputId: string) => Promise<void>;
79
+ retryOperation: (id: string) => Promise<void>;
80
+ markVisible: (id: string, onScreen: boolean) => void;
81
+ setPageVisible: (value: boolean) => void;
82
+ dispose: () => void;
83
+ };
84
+ export {};
85
+ //# sourceMappingURL=save-controller.d.ts.map