@motionharness/bridge-davinci 0.0.22 → 0.0.25
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/NOTICE +1 -1
- package/README.md +24 -14
- package/bridge-manifest.json +43 -28
- package/dist/inspector_runtime.py +4 -4
- package/dist/instance_runtime.py +1 -1
- package/dist/legacy_conversion.py +3 -5
- package/dist/resolve_rpc.py +109 -190
- package/dist/runner.mjs +699 -387
- package/package.json +2 -2
- package/resources/HotionHarness.ofx.bundle/Contents/Info.plist +1 -1
- package/resources/HotionHarness.ofx.bundle/Contents/MacOS/HotionHarness.ofx +0 -0
- package/resources/{HotionHarnessStatus.app → MotionHarnessBridge.app}/Contents/Info.plist +3 -3
- package/resources/MotionHarnessBridge.app/Contents/MacOS/MotionHarnessBridge +0 -0
- package/resources/MotionHarnessBridge.app/Contents/Resources/en.lproj/InfoPlist.strings +2 -0
- package/resources/MotionHarnessBridge.app/Contents/Resources/zh-Hans.lproj/InfoPlist.strings +2 -0
- package/resources/{HotionHarnessInstall → MotionHarnessInstall} +0 -0
- package/resources/legacy-forwarder.lua +2 -2
- package/resources/menu-entry.py +35 -21
- package/resources/sidebar-help/en.html +13 -0
- package/resources/sidebar-help/guide.css +14 -0
- package/resources/sidebar-help/index.html +10 -32
- package/resources/HotionHarnessStatus.app/Contents/MacOS/HotionHarnessStatus +0 -0
- package/resources/sidebar-help/resolve-sidebar.png +0 -0
package/dist/runner.mjs
CHANGED
|
@@ -1244,11 +1244,11 @@ var require_mtime_precision = __commonJS({
|
|
|
1244
1244
|
function probe(file2, fs, callback) {
|
|
1245
1245
|
const cachedPrecision = fs[cacheSymbol];
|
|
1246
1246
|
if (cachedPrecision) {
|
|
1247
|
-
return fs.stat(file2, (err2,
|
|
1247
|
+
return fs.stat(file2, (err2, stat8) => {
|
|
1248
1248
|
if (err2) {
|
|
1249
1249
|
return callback(err2);
|
|
1250
1250
|
}
|
|
1251
|
-
callback(null,
|
|
1251
|
+
callback(null, stat8.mtime, cachedPrecision);
|
|
1252
1252
|
});
|
|
1253
1253
|
}
|
|
1254
1254
|
const mtime = new Date(Math.ceil(Date.now() / 1e3) * 1e3 + 5);
|
|
@@ -1256,13 +1256,13 @@ var require_mtime_precision = __commonJS({
|
|
|
1256
1256
|
if (err2) {
|
|
1257
1257
|
return callback(err2);
|
|
1258
1258
|
}
|
|
1259
|
-
fs.stat(file2, (err3,
|
|
1259
|
+
fs.stat(file2, (err3, stat8) => {
|
|
1260
1260
|
if (err3) {
|
|
1261
1261
|
return callback(err3);
|
|
1262
1262
|
}
|
|
1263
|
-
const precision =
|
|
1263
|
+
const precision = stat8.mtime.getTime() % 1e3 === 0 ? "s" : "ms";
|
|
1264
1264
|
Object.defineProperty(fs, cacheSymbol, { value: precision });
|
|
1265
|
-
callback(null,
|
|
1265
|
+
callback(null, stat8.mtime, precision);
|
|
1266
1266
|
});
|
|
1267
1267
|
});
|
|
1268
1268
|
}
|
|
@@ -1316,14 +1316,14 @@ var require_lockfile = __commonJS({
|
|
|
1316
1316
|
if (options.stale <= 0) {
|
|
1317
1317
|
return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file: file2 }));
|
|
1318
1318
|
}
|
|
1319
|
-
options.fs.stat(lockfilePath, (err3,
|
|
1319
|
+
options.fs.stat(lockfilePath, (err3, stat8) => {
|
|
1320
1320
|
if (err3) {
|
|
1321
1321
|
if (err3.code === "ENOENT") {
|
|
1322
1322
|
return acquireLock(file2, { ...options, stale: 0 }, callback);
|
|
1323
1323
|
}
|
|
1324
1324
|
return callback(err3);
|
|
1325
1325
|
}
|
|
1326
|
-
if (!isLockStale(
|
|
1326
|
+
if (!isLockStale(stat8, options)) {
|
|
1327
1327
|
return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file: file2 }));
|
|
1328
1328
|
}
|
|
1329
1329
|
removeLock(file2, options, (err4) => {
|
|
@@ -1335,8 +1335,8 @@ var require_lockfile = __commonJS({
|
|
|
1335
1335
|
});
|
|
1336
1336
|
});
|
|
1337
1337
|
}
|
|
1338
|
-
function isLockStale(
|
|
1339
|
-
return
|
|
1338
|
+
function isLockStale(stat8, options) {
|
|
1339
|
+
return stat8.mtime.getTime() < Date.now() - options.stale;
|
|
1340
1340
|
}
|
|
1341
1341
|
function removeLock(file2, options, callback) {
|
|
1342
1342
|
options.fs.rmdir(getLockFile(file2, options), (err2) => {
|
|
@@ -1354,7 +1354,7 @@ var require_lockfile = __commonJS({
|
|
|
1354
1354
|
lock2.updateDelay = lock2.updateDelay || options.update;
|
|
1355
1355
|
lock2.updateTimeout = setTimeout(() => {
|
|
1356
1356
|
lock2.updateTimeout = null;
|
|
1357
|
-
options.fs.stat(lock2.lockfilePath, (err2,
|
|
1357
|
+
options.fs.stat(lock2.lockfilePath, (err2, stat8) => {
|
|
1358
1358
|
const isOverThreshold = lock2.lastUpdate + options.stale < Date.now();
|
|
1359
1359
|
if (err2) {
|
|
1360
1360
|
if (err2.code === "ENOENT" || isOverThreshold) {
|
|
@@ -1363,7 +1363,7 @@ var require_lockfile = __commonJS({
|
|
|
1363
1363
|
lock2.updateDelay = 1e3;
|
|
1364
1364
|
return updateLock(file2, options);
|
|
1365
1365
|
}
|
|
1366
|
-
const isMtimeOurs = lock2.mtime.getTime() ===
|
|
1366
|
+
const isMtimeOurs = lock2.mtime.getTime() === stat8.mtime.getTime();
|
|
1367
1367
|
if (!isMtimeOurs) {
|
|
1368
1368
|
return setLockAsCompromised(
|
|
1369
1369
|
file2,
|
|
@@ -1488,11 +1488,11 @@ var require_lockfile = __commonJS({
|
|
|
1488
1488
|
if (err2) {
|
|
1489
1489
|
return callback(err2);
|
|
1490
1490
|
}
|
|
1491
|
-
options.fs.stat(getLockFile(file3, options), (err3,
|
|
1491
|
+
options.fs.stat(getLockFile(file3, options), (err3, stat8) => {
|
|
1492
1492
|
if (err3) {
|
|
1493
1493
|
return err3.code === "ENOENT" ? callback(null, false) : callback(err3);
|
|
1494
1494
|
}
|
|
1495
|
-
return callback(null, !isLockStale(
|
|
1495
|
+
return callback(null, !isLockStale(stat8, options));
|
|
1496
1496
|
});
|
|
1497
1497
|
});
|
|
1498
1498
|
}
|
|
@@ -1538,12 +1538,12 @@ var require_adapter = __commonJS({
|
|
|
1538
1538
|
return newFs;
|
|
1539
1539
|
}
|
|
1540
1540
|
function toPromise(method) {
|
|
1541
|
-
return (...args) => new Promise((
|
|
1541
|
+
return (...args) => new Promise((resolve12, reject) => {
|
|
1542
1542
|
args.push((err2, result2) => {
|
|
1543
1543
|
if (err2) {
|
|
1544
1544
|
reject(err2);
|
|
1545
1545
|
} else {
|
|
1546
|
-
|
|
1546
|
+
resolve12(result2);
|
|
1547
1547
|
}
|
|
1548
1548
|
});
|
|
1549
1549
|
method(...args);
|
|
@@ -1620,8 +1620,8 @@ var require_proper_lockfile = __commonJS({
|
|
|
1620
1620
|
import { spawn as spawn2 } from "node:child_process";
|
|
1621
1621
|
import { closeSync, fstatSync, statSync, writeSync } from "node:fs";
|
|
1622
1622
|
import { Socket } from "node:net";
|
|
1623
|
-
import { open as open5, mkdir as mkdir9, readFile as readFile11, writeFile as writeFile2, copyFile as copyFile4, realpath as realpath6, stat as
|
|
1624
|
-
import { basename as basename5, dirname as
|
|
1623
|
+
import { open as open5, mkdir as mkdir9, readFile as readFile11, writeFile as writeFile2, copyFile as copyFile4, realpath as realpath6, stat as stat7 } from "node:fs/promises";
|
|
1624
|
+
import { basename as basename5, dirname as dirname10, join as join9, resolve as resolve11, sep as sep2 } from "node:path";
|
|
1625
1625
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
1626
1626
|
|
|
1627
1627
|
// ../../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
@@ -15476,7 +15476,7 @@ async function run(executable, args, options = {}) {
|
|
|
15476
15476
|
}
|
|
15477
15477
|
async function runBytes(executable, args, options = {}) {
|
|
15478
15478
|
if (options.signal?.aborted) throw new BridgeError("CANCELLED", "\u4EFB\u52A1\u5DF2\u53D6\u6D88\u3002", "process");
|
|
15479
|
-
return new Promise((
|
|
15479
|
+
return new Promise((resolve12, reject) => {
|
|
15480
15480
|
const child = spawn(executable, args, {
|
|
15481
15481
|
cwd: options.cwd,
|
|
15482
15482
|
shell: false,
|
|
@@ -15497,7 +15497,7 @@ async function runBytes(executable, args, options = {}) {
|
|
|
15497
15497
|
child.kill("SIGINT");
|
|
15498
15498
|
const grace = options.graceMs ?? 1e4;
|
|
15499
15499
|
termTimer = setTimeout(() => {
|
|
15500
|
-
failure = new BridgeError("PROCESS_OUTCOME_UNKNOWN", "\u5B50\u8FDB\u7A0B\u672A\u786E\u8BA4\u6B63\u5E38\u53D6\u6D88\uFF0C\u5DF2\u7EC8\u6B62\u672C\u4EFB\u52A1\u62E5\u6709\u7684\u8FDB\u7A0B\
|
|
15500
|
+
failure = new BridgeError("PROCESS_OUTCOME_UNKNOWN", "\u5B50\u8FDB\u7A0B\u672A\u786E\u8BA4\u6B63\u5E38\u53D6\u6D88\uFF0C\u5DF2\u7EC8\u6B62\u672C\u4EFB\u52A1\u62E5\u6709\u7684\u8FDB\u7A0B\uFF1BMotionHarness \u5BBF\u4E3B\u7ED3\u679C\u9700\u6838\u5BF9\u3002", "process");
|
|
15501
15501
|
child.kill("SIGTERM");
|
|
15502
15502
|
}, grace);
|
|
15503
15503
|
killTimer = setTimeout(() => child.kill("SIGKILL"), grace * 2);
|
|
@@ -15534,7 +15534,7 @@ async function runBytes(executable, args, options = {}) {
|
|
|
15534
15534
|
child.stderr.destroy();
|
|
15535
15535
|
reject(failure);
|
|
15536
15536
|
} else if (code !== 0) reject(new BridgeError("PROCESS_FAILED", `${executable} \u6267\u884C\u5931\u8D25\u3002`, "process", false, { code, signal, stderr: stderr.slice(-4e3) }));
|
|
15537
|
-
else
|
|
15537
|
+
else resolve12({ stdout: Buffer.concat(stdout), stderr });
|
|
15538
15538
|
};
|
|
15539
15539
|
child.on("exit", (code, signal) => {
|
|
15540
15540
|
exited = true;
|
|
@@ -16282,7 +16282,7 @@ function observeState(raw, cliVersion, sdkVersion, dependencyHash) {
|
|
|
16282
16282
|
const parsed = inspectSchema.safeParse(raw);
|
|
16283
16283
|
if (!parsed.success) throw new BridgeError("MH_CONTRACT_UNSUPPORTED", "mh inspect \u8FD4\u56DE\u7684\u516C\u5171\u5B57\u6BB5\u4E0D\u7B26\u5408\u5DF2\u5B9E\u73B0\u7684\u9002\u914D\u5951\u7EA6\u3002", "inspect", false, { issues: parsed.error.issues });
|
|
16284
16284
|
const data = parsed.data;
|
|
16285
|
-
assert2(data.sourceCurrent && !data.preparing && !data.error && !data.migration && !data.documentConflict && !data.lifecycle?.saveError, "BUILD_FAILED", "
|
|
16285
|
+
assert2(data.sourceCurrent && !data.preparing && !data.error && !data.migration && !data.documentConflict && !data.lifecycle?.saveError, "BUILD_FAILED", "MotionHarness \u6E90\u7801\u3001\u6784\u5EFA\u3001\u4FDD\u5B58\u6216\u8FC1\u79FB\u72B6\u6001\u5C1A\u672A\u5C31\u7EEA\u3002", { sourceCurrent: data.sourceCurrent, preparing: data.preparing, diagnostic: data.error, migration: data.migration, documentConflict: data.documentConflict, saveError: data.lifecycle?.saveError });
|
|
16286
16286
|
const { revision: _revision, ...document } = data.document;
|
|
16287
16287
|
const assets = data.sourceAssets.map((a) => ({ hash: a.$asset, kind: a.kind })).sort((a, b) => a.hash.localeCompare(b.hash));
|
|
16288
16288
|
const audioPresent = Object.values(data.document.instances).some((instance) => data.schema.components[instance.componentId]?.audio != null);
|
|
@@ -16312,7 +16312,7 @@ var MhAdapter = class {
|
|
|
16312
16312
|
return resolved;
|
|
16313
16313
|
} catch (error48) {
|
|
16314
16314
|
if (error48 instanceof BridgeError) throw error48;
|
|
16315
|
-
throw new BridgeError("SOURCE_MISSING", "
|
|
16315
|
+
throw new BridgeError("SOURCE_MISSING", "MotionHarness \u5DE5\u7A0B\u6216 package.json / pnpm-lock.yaml \u4E0D\u5B58\u5728\u3002", "inspect", false, {}, "\u6307\u5B9A\u5B8C\u6574\u7684 MotionHarness \u5DE5\u7A0B\u76EE\u5F55\uFF1B\u901A\u8FC7\u516C\u5F00 mh unpack \u6062\u590D\u5DE5\u7A0B\u3002");
|
|
16316
16316
|
}
|
|
16317
16317
|
}
|
|
16318
16318
|
async json(args, project, signal, timeoutMs) {
|
|
@@ -16321,7 +16321,7 @@ var MhAdapter = class {
|
|
|
16321
16321
|
return parseJson(result2.stdout);
|
|
16322
16322
|
} catch (error48) {
|
|
16323
16323
|
if (error48 instanceof BridgeError && String(error48.details.stderr).includes("incompatible with this CLI")) {
|
|
16324
|
-
throw new BridgeError("MH_DAEMON_VERSION_CONFLICT", "
|
|
16324
|
+
throw new BridgeError("MH_DAEMON_VERSION_CONFLICT", "MotionHarness CLI \u4E0E\u5F53\u524D\u8FD0\u884C\u7684 daemon \u7248\u672C\u4E0D\u4E00\u81F4\uFF0C\u672A\u505C\u6B62\u73B0\u6709\u4F1A\u8BDD\u3002", "mh", false, { executable: this.executable, diagnostic: error48.details.stderr }, "\u4F7F\u7528\u4E0E\u5F53\u524D\u5BBF\u4E3B\u5339\u914D\u7684\u4E3B MotionHarness CLI\uFF1B\u5982\u9700\u91CD\u542F\u5BF9\u5E94 daemon\uFF0C\u5148\u4FDD\u5B58\u5E76\u5904\u7406\u73B0\u6709\u4F1A\u8BDD\uFF0C\u6865\u63A5\u4E0D\u4F1A\u81EA\u52A8\u505C\u6B62\u5B83\u4EEC\u3002");
|
|
16325
16325
|
}
|
|
16326
16326
|
throw error48;
|
|
16327
16327
|
}
|
|
@@ -16349,7 +16349,7 @@ var MhAdapter = class {
|
|
|
16349
16349
|
for (let attempt = 0; attempt < 50; attempt++) {
|
|
16350
16350
|
const status = state;
|
|
16351
16351
|
if (!status.preparing && !status.buildsInFlight && status.sourceCurrent) break;
|
|
16352
|
-
await new Promise((
|
|
16352
|
+
await new Promise((resolve12) => setTimeout(resolve12, 100));
|
|
16353
16353
|
state = await this.json(["inspect"], project);
|
|
16354
16354
|
}
|
|
16355
16355
|
const d = doctor;
|
|
@@ -16416,7 +16416,7 @@ var MhAdapter = class {
|
|
|
16416
16416
|
async plan(path, spec, sourceDuration) {
|
|
16417
16417
|
const plan = await this.json(["render", "plan", "--json", JSON.stringify(this.renderOptions(spec, sourceDuration))], path);
|
|
16418
16418
|
const result2 = external_exports.object({ frameCount: external_exports.number().int().positive(), request: external_exports.object({ width: external_exports.number(), height: external_exports.number(), fps: external_exports.number(), start: external_exports.number(), duration: external_exports.number() }).passthrough() }).parse(plan);
|
|
16419
|
-
assert2(result2.frameCount === spec.frameCount, "OUTPUT_SPEC_MISMATCH", "
|
|
16419
|
+
assert2(result2.frameCount === spec.frameCount, "OUTPUT_SPEC_MISMATCH", "MotionHarness \u91C7\u6837\u8BA1\u5212\u5E27\u6570\u4E0E\u6865\u63A5\u8BF7\u6C42\u4E0D\u4E00\u81F4\u3002");
|
|
16420
16420
|
return result2;
|
|
16421
16421
|
}
|
|
16422
16422
|
renderOptions(spec, sourceDuration) {
|
|
@@ -16468,9 +16468,9 @@ var MhAdapter = class {
|
|
|
16468
16468
|
const result2 = external_exports.object({ id: external_exports.string(), rendered: external_exports.literal(true), saved: external_exports.literal(true), output: external_exports.string(), format: external_exports.enum(["mp4", "mov"]), progress: external_exports.object({ completed: external_exports.number(), total: external_exports.number() }) }).parse(rendered);
|
|
16469
16469
|
assert2(result2.format === (spec.format ?? "mp4"), "RENDER_RECEIPT_MISMATCH", "\u5BFC\u51FA\u6587\u4EF6\u683C\u5F0F\u4E0E\u8BF7\u6C42\u4E0D\u4E00\u81F4\u3002");
|
|
16470
16470
|
const checked = renderStatusSchema.safeParse(await this.json(["render", "status"], path));
|
|
16471
|
-
if (!checked.success) throw new BridgeError("MH_RENDER_STATUS_UNVERIFIED", "
|
|
16471
|
+
if (!checked.success) throw new BridgeError("MH_RENDER_STATUS_UNVERIFIED", "MotionHarness \u672A\u786E\u8BA4\u672C\u6B21\u6E32\u67D3\u5DF2\u5B8C\u6210\u3001\u4FDD\u5B58\u5E76\u91CA\u653E\u8D44\u6E90\u3002", "render", false, { issues: checked.error.issues }, "\u4FDD\u7559\u539F\u4EFB\u52A1\u548C\u4EA7\u7269\uFF0C\u901A\u8FC7\u516C\u5F00 mh render status \u6838\u5BF9\u72B6\u6001\uFF1B\u672A\u6838\u5B9E\u524D\u4E0D\u5C06\u6587\u4EF6\u6807\u8BB0\u4E3A\u5DF2\u9A8C\u8BC1\u7248\u672C\u3002");
|
|
16472
16472
|
const status = checked.data;
|
|
16473
|
-
assert2(status.id === result2.id && result2.output === output && result2.progress.completed === spec.frameCount && result2.progress.total === spec.frameCount, "RENDER_RECEIPT_MISMATCH", "
|
|
16473
|
+
assert2(status.id === result2.id && result2.output === output && result2.progress.completed === spec.frameCount && result2.progress.total === spec.frameCount, "RENDER_RECEIPT_MISMATCH", "MotionHarness \u6E32\u67D3\u56DE\u6267\u3001\u5B8C\u6210\u72B6\u6001\u6216\u5E27\u6570\u4E0D\u5C5E\u4E8E\u672C\u6B21\u8BF7\u6C42\u3002");
|
|
16474
16474
|
return { ...result2, status };
|
|
16475
16475
|
}
|
|
16476
16476
|
async pack(path, output) {
|
|
@@ -16546,6 +16546,10 @@ var ResolveAdapter = class {
|
|
|
16546
16546
|
return this.call("inspector", params);
|
|
16547
16547
|
}
|
|
16548
16548
|
media(scope, mediaPoolItemId) {
|
|
16549
|
+
return this.call("media_identity", { scope: scoped(scope), mediaPoolItemId });
|
|
16550
|
+
}
|
|
16551
|
+
// Only operations that inspect or change timeline instances need this scan.
|
|
16552
|
+
mediaUsages(scope, mediaPoolItemId) {
|
|
16549
16553
|
return this.call("media", { scope: scoped(scope), mediaPoolItemId });
|
|
16550
16554
|
}
|
|
16551
16555
|
findImport(scope, filePath) {
|
|
@@ -16981,29 +16985,31 @@ var Store = class {
|
|
|
16981
16985
|
};
|
|
16982
16986
|
|
|
16983
16987
|
// src/version.ts
|
|
16984
|
-
var BRIDGE_VERSION = "0.0.
|
|
16988
|
+
var BRIDGE_VERSION = "0.0.25";
|
|
16985
16989
|
|
|
16986
16990
|
// src/core/selection.ts
|
|
16987
16991
|
function selectedSource(catalog, selection) {
|
|
16988
16992
|
const unavailable = (status, message) => ({ selection, fingerprint: selection.fingerprint, canOpen: false, status, message, target: null });
|
|
16989
16993
|
if (!selection.scope || !selection.timelineId) return unavailable("no-timeline", "\u8BF7\u6253\u5F00\u5DE5\u7A0B\u4E0E\u65F6\u95F4\u7EBF\u3002");
|
|
16990
|
-
if (!selection.selectedCount) return unavailable("no-selection", "\u8BF7\u9009\u62E9\u4E00\u4E2A
|
|
16991
|
-
if (selection.selectedCount !== 1 || !selection.item) return unavailable("multiple-selection", "\u8BF7\u53EA\u9009\u62E9\u4E00\u4E2A
|
|
16994
|
+
if (!selection.selectedCount) return unavailable("no-selection", "\u8BF7\u9009\u62E9\u4E00\u4E2A MotionHarness \u7247\u6BB5\u3002");
|
|
16995
|
+
if (selection.selectedCount !== 1 || !selection.item) return unavailable("multiple-selection", "\u8BF7\u53EA\u9009\u62E9\u4E00\u4E2A MotionHarness \u7247\u6BB5\u3002");
|
|
16992
16996
|
let link2;
|
|
16993
16997
|
try {
|
|
16994
16998
|
const parsed = JSON.parse(selection.item.bridgeMetadata ?? "null");
|
|
16995
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return unavailable("not-linked", "\u6240\u9009\u7247\u6BB5\u672A\u5173\u8054
|
|
16999
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return unavailable("not-linked", "\u6240\u9009\u7247\u6BB5\u672A\u5173\u8054 MotionHarness \u5DE5\u7A0B\u3002");
|
|
16996
17000
|
link2 = parsed;
|
|
16997
17001
|
} catch {
|
|
16998
|
-
return unavailable("invalid-link", "\u7247\u6BB5\u7684
|
|
17002
|
+
return unavailable("invalid-link", "\u7247\u6BB5\u7684 MotionHarness \u5173\u8054\u4FE1\u606F\u65E0\u6548\u3002");
|
|
16999
17003
|
}
|
|
17000
|
-
if (link2.schemaVersion !== 1 || typeof link2.bindingId !== "string" || typeof link2.sourceId !== "string") return unavailable("invalid-link", "\u7247\u6BB5\u7684
|
|
17004
|
+
if (link2.schemaVersion !== 1 || typeof link2.bindingId !== "string" || typeof link2.sourceId !== "string") return unavailable("invalid-link", "\u7247\u6BB5\u7684 MotionHarness \u5173\u8054\u4FE1\u606F\u65E0\u6548\u3002");
|
|
17001
17005
|
const binding = Object.hasOwn(catalog.bindings, link2.bindingId) ? catalog.bindings[link2.bindingId] : void 0;
|
|
17002
17006
|
const source = Object.hasOwn(catalog.sources, link2.sourceId) ? catalog.sources[link2.sourceId] : void 0;
|
|
17003
17007
|
if (!binding || !source) return unavailable("unknown-workspace", "\u5F53\u524D\u6865\u63A5\u5DE5\u4F5C\u76EE\u5F55\u6CA1\u6709\u8FD9\u6BB5\u7D20\u6750\u7684\u5173\u8054\u8BB0\u5F55\u3002");
|
|
17004
17008
|
if (binding.sourceId !== source.id || binding.resolve.databaseId !== selection.scope.databaseId || binding.resolve.projectId !== selection.scope.projectId || binding.resolve.mediaPoolItemId !== selection.item.mediaPoolItemId || binding.artifactId !== link2.artifactId) return unavailable("binding-conflict", "\u7247\u6BB5\u7684\u5173\u8054\u8EAB\u4EFD\u4E0E\u8BB0\u5F55\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u68C0\u67E5\u7ED1\u5B9A\u3002");
|
|
17009
|
+
if (Object.values(catalog.bindings).filter((item) => digest(item.resolve) === digest(binding.resolve)).length !== 1)
|
|
17010
|
+
return unavailable("binding-conflict", "\u540C\u4E00\u539F\u7D20\u6750\u5B58\u5728\u591A\u4E2A\u5173\u8054\uFF0C\u8BF7\u5148\u6838\u5BF9\u5173\u8054\u8BB0\u5F55\u3002");
|
|
17005
17011
|
const target = { sourceId: source.id, bindingId: binding.id, sourceName: source.name, sourceRevision: source.revision, bindingRevision: binding.revision };
|
|
17006
|
-
return { selection, fingerprint: digest({ selection: selection.fingerprint, target }), canOpen: true, status: "linked", message: "\u5DF2\u5B9A\u4F4D\u5BF9\u5E94
|
|
17012
|
+
return { selection, fingerprint: digest({ selection: selection.fingerprint, target }), canOpen: true, status: "linked", message: "\u5DF2\u5B9A\u4F4D\u5BF9\u5E94 MotionHarness \u5DE5\u7A0B\u3002", target };
|
|
17007
17013
|
}
|
|
17008
17014
|
|
|
17009
17015
|
// src/core/legacy-conversion.ts
|
|
@@ -17391,13 +17397,15 @@ function recordBindingApplication(binding, artifact, actual, revision, mediaRela
|
|
|
17391
17397
|
});
|
|
17392
17398
|
return { bindingId: binding.id, artifactId: artifact.id, revision: binding.revision, state: binding.state, actual, applied: true };
|
|
17393
17399
|
}
|
|
17394
|
-
function
|
|
17400
|
+
function assertInstanceUsages(media) {
|
|
17395
17401
|
assert2(media.usageScanComplete && media.uses.every((i2) => i2.unsupported.length === 0), "UNSUPPORTED_TIMELINE_ITEM", "\u5F53\u524D\u7247\u6BB5\u5305\u542B\u5C1A\u672A\u9A8C\u8BC1\u7684\u5904\u7406\uFF0C\u672A\u6267\u884C\u81EA\u52A8\u66F4\u65B0\u3002", { uses: media.uses, usageScanComplete: media.usageScanComplete });
|
|
17396
17402
|
}
|
|
17397
|
-
function editUsages(media, offlineRepair = false) {
|
|
17398
|
-
return media.uses.map((item) => ({ ...item, unsupported: item.unsupported.filter((reason) => !offlineRepair || reason !== "offline-media-reference") }));
|
|
17399
|
-
}
|
|
17400
17403
|
function checkOwnership(binding, media) {
|
|
17404
|
+
assert2(
|
|
17405
|
+
media.mediaPoolItemId === binding.resolve.mediaPoolItemId && digest(media.scope) === digest({ databaseId: binding.resolve.databaseId, projectId: binding.resolve.projectId }),
|
|
17406
|
+
"VERSION_CONFLICT",
|
|
17407
|
+
"\u8BFB\u53D6\u7684\u539F\u7D20\u6750\u4E0E\u7ED1\u5B9A\u76EE\u6807\u4E0D\u540C\u3002"
|
|
17408
|
+
);
|
|
17401
17409
|
if (!binding.artifactId) return;
|
|
17402
17410
|
let link2 = {};
|
|
17403
17411
|
try {
|
|
@@ -17405,12 +17413,12 @@ function checkOwnership(binding, media) {
|
|
|
17405
17413
|
if (value && typeof value === "object" && !Array.isArray(value)) link2 = value;
|
|
17406
17414
|
} catch {
|
|
17407
17415
|
}
|
|
17408
|
-
assert2(link2.bindingId === binding.id && link2.sourceId === binding.sourceId && link2.artifactId === binding.artifactId, "VERSION_CONFLICT", "Resolve \u5173\u8054\u5143\u6570\u636E\u5DF2\u6539\u53D8\uFF0C\u672A\u8986\u76D6\u5176\u4ED6\u63A7\u5236\u7AEF\u7684\u5173\u8054\u3002");
|
|
17416
|
+
assert2(link2.schemaVersion === 1 && link2.bindingId === binding.id && link2.sourceId === binding.sourceId && link2.artifactId === binding.artifactId, "VERSION_CONFLICT", "Resolve \u5173\u8054\u5143\u6570\u636E\u5DF2\u6539\u53D8\uFF0C\u672A\u8986\u76D6\u5176\u4ED6\u63A7\u5236\u7AEF\u7684\u5173\u8054\u3002");
|
|
17409
17417
|
}
|
|
17410
17418
|
function checkObservation(obs, spec) {
|
|
17411
|
-
assert2(!obs.audioPresent, "AUDIO_UNSUPPORTED", "
|
|
17419
|
+
assert2(!obs.audioPresent, "AUDIO_UNSUPPORTED", "MotionHarness \u5DE5\u7A0B\u5305\u542B\u97F3\u9891\u7EC4\u4EF6\u6216\u89C6\u9891\u539F\u4EF6\u97F3\u8F68\uFF0C\u9996\u7248\u753B\u9762\u6865\u63A5\u4E0D\u4E22\u5F03\u8FD9\u4E9B\u58F0\u97F3\u3002");
|
|
17412
17420
|
assert2([[25, 1], [30, 1], [3e4, 1001]].some(([n, d]) => n * spec.fps.den === spec.fps.num * d), "UNSUPPORTED_FPS", "\u9996\u7248\u652F\u6301 25\u300130 \u548C 30000/1001 fps\u3002");
|
|
17413
|
-
assert2((spec.startFrame + spec.frameCount - 1) * spec.fps.den / spec.fps.num < obs.settings.duration + 1e-8, "OUTPUT_SPEC_MISMATCH", "\u6307\u5B9A\u6E90\u533A\u95F4\u8D85\u8FC7
|
|
17421
|
+
assert2((spec.startFrame + spec.frameCount - 1) * spec.fps.den / spec.fps.num < obs.settings.duration + 1e-8, "OUTPUT_SPEC_MISMATCH", "\u6307\u5B9A\u6E90\u533A\u95F4\u8D85\u8FC7 MotionHarness \u5DE5\u7A0B\u65F6\u957F\u3002");
|
|
17414
17422
|
}
|
|
17415
17423
|
function checkReplacementSpec(media, artifact) {
|
|
17416
17424
|
const properties = media.clipProperties;
|
|
@@ -17458,7 +17466,7 @@ var Bridge = class {
|
|
|
17458
17466
|
subsequentHostStability: "not-validated",
|
|
17459
17467
|
reason: "\u542B\u65E7 Fusion \u751F\u6210\u5668\u7684\u9694\u79BB\u5DE5\u7A0B\u5728\u540E\u7EED\u5207\u6362\u65F6\u95F4\u7EBF\u8BBE\u7F6E\u65F6\u51FA\u73B0\u8FC7\u5BBF\u4E3B\u65E0\u54CD\u5E94\uFF1B\u8F6C\u6362\u4EC5\u5728\u590D\u5236\u65F6\u95F4\u7EBF\u4E0A\u8FDB\u884C\u3002"
|
|
17460
17468
|
},
|
|
17461
|
-
limitations: ["\u56FA\u5B9A\u8DEF\u5F84\u66F4\u65B0\u540E\u6682\u505C\u9884\u89C8\u53EF\u80FD\u4FDD\u7559\u65E7\u5E27\uFF1B\u5B9A\u683C\u753B\u9762\u53EF\u80FD\u4ECD\u663E\u793A\u65E7\u7248\u672C\u3002", "\u4FA7\u680F\u5165\u53E3\
|
|
17469
|
+
limitations: ["\u56FA\u5B9A\u8DEF\u5F84\u66F4\u65B0\u540E\u6682\u505C\u9884\u89C8\u53EF\u80FD\u4FDD\u7559\u65E7\u5E27\uFF1B\u5B9A\u683C\u753B\u9762\u53EF\u80FD\u4ECD\u663E\u793A\u65E7\u7248\u672C\u3002", "\u4FA7\u680F\u5165\u53E3\u9700\u624B\u52A8\u9644\u52A0\uFF1B\u5DF2\u5173\u8054\u4EE3\u7406\u7684\u539F\u7D20\u6750\u6682\u4E0D\u652F\u6301\u81EA\u52A8\u66F4\u65B0\u3002", "\u65E7\u751F\u6210\u5668\u8F6C\u6362\u4E3A\u5B9E\u9A8C\u6027\u529F\u80FD\uFF0C\u540E\u7EED\u5BBF\u4E3B\u7A33\u5B9A\u6027\u5C1A\u672A\u901A\u8FC7\u9A8C\u6536\u3002"]
|
|
17462
17470
|
};
|
|
17463
17471
|
}
|
|
17464
17472
|
async bind(input) {
|
|
@@ -17491,8 +17499,10 @@ var Bridge = class {
|
|
|
17491
17499
|
const importedScope = known && (known.resolve.projectId !== request.resolve.projectId || known.resolve.databaseId !== request.resolve.databaseId);
|
|
17492
17500
|
assert2(link2.sourceId === source.id && known && (importedScope || known.resolve.mediaPoolItemId === actual.mediaPoolItemId), "BINDING_CONFLICT", "\u8BE5\u5A92\u4F53\u643A\u5E26\u5176\u4ED6\u5DE5\u4F5C\u76EE\u5F55\u6216\u5BF9\u8C61\u7684\u6865\u63A5\u8EAB\u4EFD\uFF1B\u5148\u6062\u590D\u5BF9\u5E94\u6E05\u5355\u6216\u663E\u5F0F\u5904\u7406\u8FC1\u79FB\uFF0C\u672A\u8986\u76D6\u5176\u5173\u8054\u3002");
|
|
17493
17501
|
}
|
|
17494
|
-
|
|
17495
|
-
assert2(
|
|
17502
|
+
const matches = Object.values(catalog.bindings).filter((b) => digest(b.resolve) === digest(request.resolve));
|
|
17503
|
+
assert2(matches.length <= 1, "BINDING_CONFLICT", "\u540C\u4E00\u539F\u7D20\u6750\u5B58\u5728\u591A\u4E2A\u5173\u8054\uFF0C\u672A\u731C\u6D4B\u76EE\u6807\u3002");
|
|
17504
|
+
binding = matches[0];
|
|
17505
|
+
assert2(!binding || binding.sourceId === source.id, "BINDING_CONFLICT", "\u8BE5\u5A92\u4F53\u6C60\u5BF9\u8C61\u5DF2\u5173\u8054\u5176\u4ED6 MotionHarness \u5DE5\u7A0B\u3002");
|
|
17496
17506
|
if (!binding) {
|
|
17497
17507
|
binding = { id: id("binding"), sourceId: source.id, resolve: request.resolve, revision: 1, state: "unbound", lastReadback: actual, createdAt: now() };
|
|
17498
17508
|
catalog.bindings[binding.id] = binding;
|
|
@@ -17510,10 +17520,23 @@ var Bridge = class {
|
|
|
17510
17520
|
}
|
|
17511
17521
|
async inspect(sourceId, bindingId) {
|
|
17512
17522
|
assert2(Boolean(sourceId) !== Boolean(bindingId), "INVALID_REQUEST", "\u9700\u8981\u4E14\u53EA\u80FD\u63D0\u4F9B sourceId \u6216 bindingId\u3002");
|
|
17523
|
+
if (bindingId) return this.inspectStatus(bindingId);
|
|
17524
|
+
const source = get((await this.store.read()).sources, sourceId, "\u6E90");
|
|
17525
|
+
const present = await stat3(this.store.path(source.locator)).then((info) => info.isDirectory(), () => false);
|
|
17526
|
+
return {
|
|
17527
|
+
source,
|
|
17528
|
+
current: source.observation,
|
|
17529
|
+
contentChecked: false,
|
|
17530
|
+
state: present ? "unbound" : "source-missing",
|
|
17531
|
+
...!present ? { error: { code: "SOURCE_MISSING", message: "\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\u76EE\u5F55\u3002" } } : {}
|
|
17532
|
+
};
|
|
17533
|
+
}
|
|
17534
|
+
// Export requires fresh content and full file evidence. Routine reads do not.
|
|
17535
|
+
async inspectForExport(bindingId) {
|
|
17513
17536
|
const catalog = await this.store.read();
|
|
17514
|
-
const binding =
|
|
17515
|
-
const source = get(catalog.sources,
|
|
17516
|
-
const artifact = binding
|
|
17537
|
+
const binding = get(catalog.bindings, bindingId, "\u7ED1\u5B9A");
|
|
17538
|
+
const source = get(catalog.sources, binding.sourceId, "\u6E90");
|
|
17539
|
+
const artifact = binding.artifactId ? catalog.artifacts[binding.artifactId] : void 0;
|
|
17517
17540
|
const artifactAvailable = artifact ? await fileDigest(this.store.artifactPath(artifact.relativePath)).then((hash2) => hash2 === artifact.sha256, () => false) : false;
|
|
17518
17541
|
let current;
|
|
17519
17542
|
try {
|
|
@@ -17526,67 +17549,53 @@ var Bridge = class {
|
|
|
17526
17549
|
assert2(saved.revision === source.revision && saved.locator === source.locator, "VERSION_CONFLICT", "\u68C0\u67E5\u671F\u95F4\u5DE5\u7A0B\u4F4D\u7F6E\u5DF2\u6539\u53D8\u3002");
|
|
17527
17550
|
rememberObservation(saved, current);
|
|
17528
17551
|
});
|
|
17529
|
-
const actual =
|
|
17530
|
-
let state = binding
|
|
17531
|
-
if (artifact &&
|
|
17532
|
-
else if (binding
|
|
17552
|
+
const actual = await this.host.media(binding.resolve, binding.resolve.mediaPoolItemId);
|
|
17553
|
+
let state = binding.state;
|
|
17554
|
+
if (artifact && resolve3(actual.path) !== this.store.bindingPath(binding, artifact)) state = "stale";
|
|
17555
|
+
else if (binding.appliedContentVersion && binding.appliedContentVersion !== current.contentVersion) state = "stale";
|
|
17533
17556
|
else if (artifact?.verification === "bridge-verified" && (!current.runtimeIdentity || artifact.receipt?.runtimeIdentity !== current.runtimeIdentity)) state = "stale";
|
|
17534
|
-
if (artifact && (!artifactAvailable ||
|
|
17535
|
-
if (artifact
|
|
17557
|
+
if (artifact && (!artifactAvailable || await fileDigest(this.store.bindingPath(binding, artifact)).catch(() => null) !== artifact.sha256)) state = "failed";
|
|
17558
|
+
if (artifact) {
|
|
17536
17559
|
try {
|
|
17537
|
-
|
|
17538
|
-
if (link2.bindingId !== binding.id || link2.sourceId !== source.id || link2.artifactId !== artifact.id) state = "failed";
|
|
17560
|
+
checkOwnership(binding, actual);
|
|
17539
17561
|
} catch {
|
|
17540
17562
|
state = "failed";
|
|
17541
17563
|
}
|
|
17542
|
-
if (!actual.usageScanComplete || actual.uses.some((item) => item.unsupported.some((reason) => reason !== "offline-media-reference"))) state = "unsupported";
|
|
17543
|
-
else if (actual.uses.some((item) => item.unsupported.includes("offline-media-reference")) && state !== "failed") state = "stale";
|
|
17544
17564
|
}
|
|
17545
17565
|
if (current.audioPresent) state = "unsupported";
|
|
17546
|
-
const jobs = Object.values(catalog.jobs).filter((j) => !terminalPhases.includes(j.phase) && JSON.stringify(j.request).includes(binding
|
|
17566
|
+
const jobs = Object.values(catalog.jobs).filter((j) => !terminalPhases.includes(j.phase) && JSON.stringify(j.request).includes(binding.id));
|
|
17547
17567
|
return { source, current, binding, artifact, actual, state, activeJobs: jobs, priorArtifactRemainsAvailable: artifactAvailable };
|
|
17548
17568
|
}
|
|
17549
|
-
/** Routine
|
|
17569
|
+
/** Routine status checks identity and availability, not content or timelines.
|
|
17570
|
+
* Fresh content and complete file validation happen before mutations/export. */
|
|
17550
17571
|
async inspectStatus(bindingId) {
|
|
17551
17572
|
const catalog = await this.store.read(), binding = get(catalog.bindings, bindingId, "\u7ED1\u5B9A");
|
|
17552
17573
|
const source = get(catalog.sources, binding.sourceId, "\u6E90");
|
|
17553
17574
|
const artifact = binding.artifactId ? catalog.artifacts[binding.artifactId] : void 0;
|
|
17554
|
-
const base = { source, binding, artifact };
|
|
17575
|
+
const base = { source, binding, artifact, current: source.observation, contentChecked: false };
|
|
17555
17576
|
try {
|
|
17556
|
-
const
|
|
17557
|
-
|
|
17558
|
-
|
|
17559
|
-
|
|
17560
|
-
const
|
|
17561
|
-
|
|
17562
|
-
|
|
17563
|
-
);
|
|
17564
|
-
let link2 = {};
|
|
17565
|
-
try {
|
|
17566
|
-
const value = JSON.parse(identity2.metadata?.["motionharness.bridge"] ?? "{}");
|
|
17567
|
-
if (value && typeof value === "object" && !Array.isArray(value)) link2 = value;
|
|
17568
|
-
} catch {
|
|
17569
|
-
}
|
|
17570
|
-
const associationVerified = Boolean(artifact && available && digest(identity2.scope) === digest({ databaseId: binding.resolve.databaseId, projectId: binding.resolve.projectId }) && identity2.mediaPoolItemId === binding.resolve.mediaPoolItemId && resolve3(identity2.path) === this.store.bindingPath(binding, artifact) && link2.schemaVersion === 1 && link2.bindingId === binding.id && link2.sourceId === source.id && link2.artifactId === artifact.id);
|
|
17571
|
-
let state = binding.state;
|
|
17572
|
-
if (!associationVerified) state = "failed";
|
|
17573
|
-
else if (binding.appliedContentVersion && binding.appliedContentVersion !== current.contentVersion || artifact?.verification === "bridge-verified" && (!current.runtimeIdentity || artifact.receipt?.runtimeIdentity !== current.runtimeIdentity)) state = "stale";
|
|
17574
|
-
if (!identity2.validatedHost || current.audioPresent || identity2.clipProperties?.["Proxy Media Path"]) state = "unsupported";
|
|
17577
|
+
const sourcePresent = await stat3(this.store.path(source.locator)).then((info) => info.isDirectory(), () => false);
|
|
17578
|
+
if (!sourcePresent) return { ...base, state: "source-missing", error: { code: "SOURCE_MISSING", message: "\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\uFF0C\u8BF7\u4ECE\u201C\u66F4\u591A\u2026\u201D\u91CD\u65B0\u5B9A\u4F4D\u3002" } };
|
|
17579
|
+
const identity2 = await this.host.media(binding.resolve, binding.resolve.mediaPoolItemId);
|
|
17580
|
+
checkOwnership(binding, identity2);
|
|
17581
|
+
const associationVerified = Boolean(artifact && artifact.sourceId === source.id && resolve3(identity2.path) === this.store.bindingPath(binding, artifact));
|
|
17582
|
+
assert2(associationVerified, "BINDING_CONFLICT", "\u539F\u7D20\u6750\u7684\u89C6\u9891\u8DEF\u5F84\u4E0E\u5DF2\u8BB0\u5F55\u5173\u8054\u4E0D\u4E00\u81F4\u3002");
|
|
17583
|
+
const mediaPresent = await stat3(identity2.path).then((info) => info.isFile(), () => false);
|
|
17575
17584
|
const latest = await this.store.read();
|
|
17576
17585
|
assert2(
|
|
17577
17586
|
digest(latest.bindings[binding.id]) === digest(binding) && latest.sources[source.id]?.revision === source.revision,
|
|
17578
17587
|
"VERSION_CONFLICT",
|
|
17579
17588
|
"\u6838\u5BF9\u671F\u95F4\u5173\u8054\u6216\u6E90\u4F4D\u7F6E\u5DF2\u6539\u53D8\uFF0C\u8BF7\u5237\u65B0\u72B6\u6001\u3002"
|
|
17580
17589
|
);
|
|
17590
|
+
const knownStale = binding.appliedContentVersion && source.observation && binding.appliedContentVersion !== source.observation.contentVersion;
|
|
17581
17591
|
return {
|
|
17582
17592
|
...base,
|
|
17583
|
-
|
|
17584
|
-
state,
|
|
17593
|
+
state: !mediaPresent || knownStale ? "stale" : binding.state,
|
|
17585
17594
|
actual: { associationVerified },
|
|
17586
|
-
...!
|
|
17595
|
+
...!mediaPresent ? { error: { message: "\u64AD\u653E\u89C6\u9891\u7F3A\u5931\uFF0C\u8BF7\u4ECE\u201C\u66F4\u591A\u2026\u201D\u6062\u590D\u5DF2\u5E94\u7528\u7248\u672C\u3002" } } : {}
|
|
17587
17596
|
};
|
|
17588
17597
|
} catch (error48) {
|
|
17589
|
-
return { ...base, state:
|
|
17598
|
+
return { ...base, state: "failed", actual: { associationVerified: false }, error: errorResult(error48) };
|
|
17590
17599
|
}
|
|
17591
17600
|
}
|
|
17592
17601
|
/** Prepare a fixed human-readable action. No catalog writes, tasks or media rendering. */
|
|
@@ -17636,7 +17645,6 @@ var Bridge = class {
|
|
|
17636
17645
|
const previousSettings = artifact.receipt?.before.settings;
|
|
17637
17646
|
if (previousSettings) assert2(digest(previousSettings) === digest(current.settings), "OUTPUT_SPEC_MISMATCH", "\u6E90\u65F6\u957F\u3001\u5206\u8FA8\u7387\u6216\u5E27\u7387\u5DF2\u6539\u53D8\uFF0C\u8BF7\u53D1\u9001\u4E3A\u65B0\u7D20\u6750\u3002");
|
|
17638
17647
|
const actual = await this.host.media(binding.resolve, binding.resolve.mediaPoolItemId);
|
|
17639
|
-
assertUsages(actual);
|
|
17640
17648
|
checkOwnership(binding, actual);
|
|
17641
17649
|
checkReplacementSpec(actual, artifact);
|
|
17642
17650
|
const latest = await this.store.read();
|
|
@@ -17649,9 +17657,8 @@ var Bridge = class {
|
|
|
17649
17657
|
return {
|
|
17650
17658
|
command: "update",
|
|
17651
17659
|
title: "\u786E\u8BA4\u66F4\u65B0\u5230\u8FBE\u82AC\u5947",
|
|
17652
|
-
message: "\u751F\u6210\u5E76\u66F4\u65B0\u6B64\u7D20\u6750\u7684\u5168\u90E8\u5F15\u7528\uFF0C\u4FDD\u7559\u5F53\u524D\u526A\u8F91\u3002\u786E\u8BA4\u540E\
|
|
17660
|
+
message: "\u751F\u6210\u5E76\u66F4\u65B0\u6B64\u7D20\u6750\u7684\u5168\u90E8\u5F15\u7528\uFF0C\u4FDD\u7559\u5F53\u524D\u526A\u8F91\u3002\u786E\u8BA4\u540E\u5173\u8054\u6216\u52A8\u6548\u5185\u5BB9\u53D8\u5316\u65F6\u4F1A\u505C\u6B62\u3002",
|
|
17653
17661
|
target: { projectName: actual.projectName, mediaName: String(actual.clipProperties?.["Clip Name"] ?? source.name) },
|
|
17654
|
-
usageCount: actual.uses.length,
|
|
17655
17662
|
request: {
|
|
17656
17663
|
bindingId: binding.id,
|
|
17657
17664
|
expectedRevision: binding.revision,
|
|
@@ -17674,7 +17681,7 @@ var Bridge = class {
|
|
|
17674
17681
|
await this.mh.projectPath(this.store.path(catalog.sources[result2.target.sourceId].locator));
|
|
17675
17682
|
} catch (error48) {
|
|
17676
17683
|
if (!(error48 instanceof BridgeError) || error48.code !== "SOURCE_MISSING") throw error48;
|
|
17677
|
-
return { ...result2, canOpen: false, status: "source-missing", message: "
|
|
17684
|
+
return { ...result2, canOpen: false, status: "source-missing", message: "MotionHarness \u5DE5\u7A0B\u76EE\u5F55\u4E0D\u53EF\u7528\uFF0C\u8BF7\u901A\u8FC7\u66F4\u591A\u6865\u63A5\u64CD\u4F5C\u6062\u590D\u6216\u91CD\u5B9A\u4F4D\u5DE5\u7A0B\u3002" };
|
|
17678
17685
|
}
|
|
17679
17686
|
}
|
|
17680
17687
|
return result2;
|
|
@@ -17848,9 +17855,9 @@ var Bridge = class {
|
|
|
17848
17855
|
assert2(catalog.bindings[checkpoint.bindingId]?.revision === checkpoint.expectedRevision || catalog.bindings[checkpoint.bindingId]?.revision === checkpoint.expectedRevision + 1 && catalog.bindings[checkpoint.bindingId]?.artifactId === artifact.id, "RECOVERY_CONFLICT", "\u5173\u8054\u5728\u4EFB\u52A1\u4E2D\u65AD\u540E\u5DF2\u7ECF\u6539\u53D8\u3002");
|
|
17849
17856
|
if (checkpoint.publication && action2 === "resume" && actual.metadata["motionharness.bridge"] === checkpoint.before.metadata["motionharness.bridge"]) {
|
|
17850
17857
|
assert2(
|
|
17851
|
-
actual.path === checkpoint.before.path && digest(actual.
|
|
17858
|
+
actual.path === checkpoint.before.path && digest(actual.clipProperties) === digest(checkpoint.before.clipProperties),
|
|
17852
17859
|
"RECOVERY_CONFLICT",
|
|
17853
|
-
"\u53D1\u5E03\u4E2D\u65AD\u540E\u7D20\u6750\u7684\
|
|
17860
|
+
"\u53D1\u5E03\u4E2D\u65AD\u540E\u539F\u7D20\u6750\u7684\u8DEF\u5F84\u6216\u89E3\u91CA\u5DF2\u6539\u53D8\u3002"
|
|
17854
17861
|
);
|
|
17855
17862
|
actual = await this.host.replace(
|
|
17856
17863
|
actual.scope,
|
|
@@ -17868,7 +17875,7 @@ var Bridge = class {
|
|
|
17868
17875
|
link2 = JSON.parse(encoded ?? "{}");
|
|
17869
17876
|
} catch {
|
|
17870
17877
|
}
|
|
17871
|
-
if (resolve3(actual.path) === this.store.artifactPath(checkpoint.mediaRelativePath ?? artifact.relativePath) && link2.bindingId === checkpoint.bindingId && link2.
|
|
17878
|
+
if (resolve3(actual.path) === this.store.artifactPath(checkpoint.mediaRelativePath ?? artifact.relativePath) && link2.bindingId === checkpoint.bindingId && link2.sourceId === checkpoint.sourceId && link2.artifactId === artifact.id && await fileDigest(actual.path) === artifact.sha256) {
|
|
17872
17879
|
await this.store.mutate((c) => {
|
|
17873
17880
|
const binding = get(c.bindings, checkpoint.bindingId, "\u7ED1\u5B9A");
|
|
17874
17881
|
assert2(binding.revision === checkpoint.expectedRevision || binding.revision === checkpoint.expectedRevision + 1 && binding.artifactId === artifact.id, "RECOVERY_CONFLICT", "\u672C\u5730\u7ED1\u5B9A\u5728\u4E2D\u65AD\u540E\u53D1\u751F\u5176\u4ED6\u4FEE\u6539\u3002");
|
|
@@ -17878,7 +17885,7 @@ var Bridge = class {
|
|
|
17878
17885
|
saved.results.push({ ...result2, recovered: true });
|
|
17879
17886
|
saved.progress.completed = saved.results.filter((r) => r.applied === true).length;
|
|
17880
17887
|
});
|
|
17881
|
-
} else assert2(actual.fingerprint === checkpoint.before.fingerprint || checkpoint.publication && actual.path === checkpoint.before.path && digest(actual.metadata) === digest(checkpoint.before.metadata) && digest(actual.
|
|
17888
|
+
} else assert2(actual.fingerprint === checkpoint.before.fingerprint || checkpoint.publication && actual.path === checkpoint.before.path && digest(actual.metadata) === digest(checkpoint.before.metadata) && digest(actual.clipProperties) === digest(checkpoint.before.clipProperties) && [checkpoint.publication.sha256, checkpoint.publication.previousSha256].includes(await fileDigest(actual.path)), "RECOVERY_CONFLICT", "\u5BBF\u4E3B\u7ED3\u679C\u65E2\u4E0D\u662F\u65E7\u72B6\u6001\uFF0C\u4E5F\u4E0D\u662F\u53EF\u6838\u5B9E\u7684\u65B0\u7248\u672C\u3002");
|
|
17882
17889
|
}
|
|
17883
17890
|
job = get((await this.store.read()).jobs, taskId, "\u4EFB\u52A1");
|
|
17884
17891
|
if (job.operation === "restore" || job.operation === "update" || job.operation === "apply") reconciled = job.results.some((r) => r.applied === true);
|
|
@@ -17887,7 +17894,7 @@ var Bridge = class {
|
|
|
17887
17894
|
reconciled = request.targets.every((target) => job.results.some((r) => r.bindingId === target.bindingId && r.applied === true));
|
|
17888
17895
|
for (const target of request.targets.filter((t) => !job.results.some((r) => r.bindingId === t.bindingId && r.applied === true))) {
|
|
17889
17896
|
const binding = get((await this.store.read()).bindings, target.bindingId, "\u7ED1\u5B9A"), source = get(catalog.sources, binding.sourceId, "\u6E90");
|
|
17890
|
-
assert2(!(await this.mh.renderStatus(this.store.path(source.locator))).locked, "RECOVERY_WAIT", "
|
|
17897
|
+
assert2(!(await this.mh.renderStatus(this.store.path(source.locator))).locked, "RECOVERY_WAIT", "MotionHarness \u4ECD\u6709\u6E32\u67D3\u6301\u9501\uFF0C\u8BF7\u7B49\u5F85\u8BE5\u4EFB\u52A1\u91CA\u653E\u540E\u6838\u5BF9\u3002");
|
|
17891
17898
|
}
|
|
17892
17899
|
}
|
|
17893
17900
|
} else if (job.operation === "render") {
|
|
@@ -17899,7 +17906,7 @@ var Bridge = class {
|
|
|
17899
17906
|
reconciled = true;
|
|
17900
17907
|
} else {
|
|
17901
17908
|
const source = get(catalog.sources, renderSchema.parse(job.request).sourceId, "\u6E90");
|
|
17902
|
-
assert2(!(await this.mh.renderStatus(this.store.path(source.locator))).locked, "RECOVERY_WAIT", "
|
|
17909
|
+
assert2(!(await this.mh.renderStatus(this.store.path(source.locator))).locked, "RECOVERY_WAIT", "MotionHarness \u4ECD\u6709\u6E32\u67D3\u6301\u9501\uFF0C\u8BF7\u7B49\u5F85\u6E05\u7406\u3002");
|
|
17903
17910
|
}
|
|
17904
17911
|
} else if (job.operation === "duplicate") {
|
|
17905
17912
|
const checkpoint = journal.duplicate;
|
|
@@ -17954,7 +17961,7 @@ var Bridge = class {
|
|
|
17954
17961
|
const observation = await this.mh.inspect(this.store.path(checkpoint.destination));
|
|
17955
17962
|
assert2(observation.coverage === "public-package-v1" && observation.contentVersion === checkpoint.contentVersion, "RECOVERY_CONFLICT", "\u526F\u672C\u76EE\u5F55\u4E0D\u5B8C\u6574\u6216\u5185\u5BB9\u5DF2\u6539\u53D8\uFF0C\u4FDD\u7559\u73B0\u573A\u4E14\u4E0D\u91CD\u65B0\u89E3\u5305\u3002");
|
|
17956
17963
|
await this.store.mutate((c) => {
|
|
17957
|
-
const source = c.sources[checkpoint.sourceId] ?? { id: checkpoint.sourceId, name: duplicateSchema.parse(job.request).name ?? "
|
|
17964
|
+
const source = c.sources[checkpoint.sourceId] ?? { id: checkpoint.sourceId, name: duplicateSchema.parse(job.request).name ?? "MotionHarness \u72EC\u7ACB\u526F\u672C", locator: checkpoint.destination, revision: 1, createdAt: now(), observation };
|
|
17958
17965
|
c.sources[source.id] = source;
|
|
17959
17966
|
if (!("bindingId" in duplicateSchema.parse(job.request))) get(c.jobs, taskId, "\u4EFB\u52A1").results = [{ source, originalSourceId: checkpoint.originalSourceId, independent: true, applied: true, recovered: true }];
|
|
17960
17967
|
});
|
|
@@ -18003,7 +18010,7 @@ var Bridge = class {
|
|
|
18003
18010
|
assert2(!nativeFiles.some((name) => name.startsWith(nativePrefix)), "RECOVERY_CONFLICT", "\u53D1\u73B0\u672C\u6B21\u590D\u5236\u7684\u539F\u751F\u4E8B\u52A1\u6587\u4EF6\uFF0C\u5FC5\u987B\u5148\u6838\u5BF9\u8BE5\u4E8B\u52A1\u3002");
|
|
18004
18011
|
if (instance && binding) {
|
|
18005
18012
|
assert2(binding.revision === instance.expectedRevision && binding.sourceId === checkpoint.originalSourceId, "RECOVERY_CONFLICT", "\u539F\u5173\u8054\u5728\u590D\u5236\u4E2D\u65AD\u540E\u53D1\u751F\u53D8\u5316\uFF0C\u672A\u81EA\u52A8\u7ED3\u675F\u3002");
|
|
18006
|
-
const [timeline, media] = await Promise.all([this.host.timeline(binding.resolve, instance.timelineId), this.host.
|
|
18013
|
+
const [timeline, media] = await Promise.all([this.host.timeline(binding.resolve, instance.timelineId), this.host.mediaUsages(binding.resolve, binding.resolve.mediaPoolItemId)]);
|
|
18007
18014
|
assert2(
|
|
18008
18015
|
timeline.fingerprint === instance.expectedTimelineFingerprint && media.fingerprint === instance.expectedMediaFingerprint,
|
|
18009
18016
|
"RECOVERY_CONFLICT",
|
|
@@ -18056,7 +18063,7 @@ var Bridge = class {
|
|
|
18056
18063
|
} catch (error48) {
|
|
18057
18064
|
if (entered || error48.code !== "ELOCKED") throw error48;
|
|
18058
18065
|
}
|
|
18059
|
-
await new Promise((
|
|
18066
|
+
await new Promise((resolve12) => setTimeout(resolve12, 100));
|
|
18060
18067
|
}
|
|
18061
18068
|
}
|
|
18062
18069
|
async runJob(taskId, started) {
|
|
@@ -18151,7 +18158,6 @@ var Bridge = class {
|
|
|
18151
18158
|
assert2(request.scope || !request.timelineId || request.timelineId === target.timelineId, "INVALID_REQUEST", "\u8DE8\u65F6\u95F4\u7EBF\u63D2\u5165\u9700\u8981\u540C\u65F6\u6307\u5B9A Resolve \u5DE5\u7A0B\u8EAB\u4EFD\u3002");
|
|
18152
18159
|
assert2(timelineId === target.timelineId || request.recordFrame !== void 0, "INVALID_REQUEST", "\u6307\u5B9A\u5176\u4ED6\u65F6\u95F4\u7EBF\u65F6\uFF0C\u9700\u8981\u660E\u786E\u8BE5\u65F6\u95F4\u7EBF\u7684 recordFrame\u3002");
|
|
18153
18160
|
const timeline = await this.host.timeline(scope, timelineId);
|
|
18154
|
-
assert2(timeline.validatedHost !== false, "CAPABILITY_UNAVAILABLE", "\u6B64 Resolve \u5E73\u53F0\u6216\u6784\u5EFA\u5C1A\u672A\u9A8C\u8BC1\u81EA\u52A8\u63D2\u5165\uFF0C\u672A\u5F00\u59CB\u6E32\u67D3\u3002");
|
|
18155
18161
|
const recordFrame = request.recordFrame ?? target.recordFrame;
|
|
18156
18162
|
const timelineFrames = nativeTimelineFrames(spec.frameCount, spec.fps, timeline.fps);
|
|
18157
18163
|
assert2(timeline.items.every((item) => Number.isFinite(item.startFrame) && Number.isFinite(item.endFrame) && Number.isSafeInteger(item.track)), "UNSUPPORTED_TIMELINE_ITEM", "\u65E0\u6CD5\u5B8C\u6574\u8BFB\u53D6\u8F68\u9053\u5360\u7528\u533A\u95F4\u3002");
|
|
@@ -18321,6 +18327,11 @@ var Bridge = class {
|
|
|
18321
18327
|
}
|
|
18322
18328
|
async replacePlayback(taskId, binding, artifact, before, offlineRepair) {
|
|
18323
18329
|
const catalog = await this.store.read(), previous2 = binding.artifactId ? catalog.artifacts[binding.artifactId] : void 0;
|
|
18330
|
+
assert2(artifact.sourceId === binding.sourceId && (!previous2 || previous2.sourceId === binding.sourceId), "BINDING_CONFLICT", "\u89C6\u9891\u4EA7\u7269\u4E0D\u5C5E\u4E8E\u5173\u8054\u7684\u6E90\u5DE5\u7A0B\u3002");
|
|
18331
|
+
if (previous2 && !offlineRepair) {
|
|
18332
|
+
assert2(resolve3(before.path) === this.store.bindingPath(binding, previous2), "VERSION_CONFLICT", "\u539F\u7D20\u6750\u5DF2\u88AB\u91CD\u65B0\u94FE\u63A5\uFF0C\u672A\u8986\u76D6\u5176\u4ED6\u89C6\u9891\u3002");
|
|
18333
|
+
assert2(await fileDigest(before.path).catch(() => null) === previous2.sha256, "ARTIFACT_CHANGED", "\u5F53\u524D\u64AD\u653E\u89C6\u9891\u4E0E\u5DF2\u767B\u8BB0\u4EA7\u7269\u4E0D\u540C\uFF0C\u672A\u8986\u76D6\u3002");
|
|
18334
|
+
}
|
|
18324
18335
|
const mediaRelativePath = binding.mediaRelativePath ?? this.store.stableLocator(binding.id, artifact);
|
|
18325
18336
|
const path = this.store.bindingPath({ ...binding, mediaRelativePath }, artifact);
|
|
18326
18337
|
const publication = {
|
|
@@ -18339,11 +18350,8 @@ var Bridge = class {
|
|
|
18339
18350
|
offlineRepair,
|
|
18340
18351
|
publication
|
|
18341
18352
|
);
|
|
18342
|
-
|
|
18343
|
-
|
|
18344
|
-
"APPLY_OUTCOME_UNKNOWN",
|
|
18345
|
-
"\u89C6\u9891\u66FF\u6362\u540E\u7684\u8DEF\u5F84\u6216\u526A\u8F91\u72B6\u6001\u8BFB\u56DE\u4E0D\u4E00\u81F4\u3002"
|
|
18346
|
-
);
|
|
18353
|
+
checkOwnership({ ...binding, artifactId: artifact.id }, actual);
|
|
18354
|
+
assert2(resolve3(actual.path) === path, "APPLY_OUTCOME_UNKNOWN", "\u89C6\u9891\u66FF\u6362\u540E\u7684\u539F\u7D20\u6750\u8DEF\u5F84\u8BFB\u56DE\u4E0D\u4E00\u81F4\u3002");
|
|
18347
18355
|
return actual;
|
|
18348
18356
|
}
|
|
18349
18357
|
async applyArtifact(taskId, input, restore2 = false) {
|
|
@@ -18354,11 +18362,10 @@ var Bridge = class {
|
|
|
18354
18362
|
if (binding.artifactId) assert2(sameOutputSpec(get(catalog.artifacts, binding.artifactId, "\u4EA7\u7269").spec, artifact.spec), "OUTPUT_SPEC_MISMATCH", "\u4EBA\u5DE5\u56DE\u586B\u4E0D\u80FD\u6539\u53D8\u5DF2\u5E94\u7528\u7684\u6E90\u533A\u95F4\u6216\u8F93\u51FA\u89C4\u683C\u3002");
|
|
18355
18363
|
const filePath = this.store.artifactPath(artifact.relativePath);
|
|
18356
18364
|
await this.phase(taskId, "validating");
|
|
18357
|
-
assert2(await fileDigest(filePath) === artifact.sha256, "ARTIFACT_CHANGED", "\u4EA7\u7269\u6587\u4EF6\u5DF2\u6539\u53D8\u3002");
|
|
18365
|
+
assert2(await fileDigest(filePath).catch(() => null) === artifact.sha256, "ARTIFACT_CHANGED", "\u4EA7\u7269\u6587\u4EF6\u7F3A\u5931\u6216\u5DF2\u6539\u53D8\u3002");
|
|
18358
18366
|
const before = await this.host.media(binding.resolve, binding.resolve.mediaPoolItemId);
|
|
18359
|
-
if (request.expectedMediaFingerprint) assert2(before.fingerprint === request.expectedMediaFingerprint, "VERSION_CONFLICT", "\u6240\u786E\u8BA4\u7684\u7D20\u6750\
|
|
18360
|
-
const offlineRepair = binding.artifactId === artifact.id && binding.lastReadback?.path === before.path && !await stat3(before.path).then(() => true, () => false)
|
|
18361
|
-
if (!offlineRepair) assertUsages(before);
|
|
18367
|
+
if (request.expectedMediaFingerprint) assert2(before.fingerprint === request.expectedMediaFingerprint, "VERSION_CONFLICT", "\u6240\u786E\u8BA4\u7684\u539F\u7D20\u6750\u8EAB\u4EFD\u6216\u5173\u8054\u5DF2\u7ECF\u6539\u53D8\uFF0C\u672A\u5E94\u7528\u5386\u53F2\u753B\u9762\u3002");
|
|
18368
|
+
const offlineRepair = binding.artifactId === artifact.id && binding.lastReadback?.path === before.path && !await stat3(before.path).then(() => true, () => false);
|
|
18362
18369
|
checkOwnership(binding, before);
|
|
18363
18370
|
checkReplacementSpec(before, artifact);
|
|
18364
18371
|
if (artifact.contentVersion && !restore2) {
|
|
@@ -18368,7 +18375,7 @@ var Bridge = class {
|
|
|
18368
18375
|
assert2((await this.store.read()).bindings[binding.id]?.revision === binding.revision, "VERSION_CONFLICT", "\u7ED1\u5B9A\u5728\u6821\u9A8C\u671F\u95F4\u5DF2\u6539\u53D8\u3002");
|
|
18369
18376
|
await this.store.mutate((c) => {
|
|
18370
18377
|
const job = get(c.jobs, taskId, "\u4EFB\u52A1");
|
|
18371
|
-
job.results.push({ bindingId: binding.id, artifactId: artifact.id,
|
|
18378
|
+
job.results.push({ bindingId: binding.id, artifactId: artifact.id, applied: false });
|
|
18372
18379
|
job.journal = { apply: { bindingId: binding.id, artifactId: artifact.id, sourceId: binding.sourceId, expectedRevision: binding.revision, before, offlineRepair } };
|
|
18373
18380
|
});
|
|
18374
18381
|
await this.phase(taskId, "applying");
|
|
@@ -18401,9 +18408,9 @@ var Bridge = class {
|
|
|
18401
18408
|
await this.phase(taskId, "applying");
|
|
18402
18409
|
const actual = existing ? before : await this.host.bind(binding.resolve, binding.resolve.mediaPoolItemId, wanted, before.fingerprint);
|
|
18403
18410
|
assert2(
|
|
18404
|
-
actual.metadata["motionharness.bridge"] === wanted["motionharness.bridge"] && actual.path === before.path
|
|
18411
|
+
actual.metadata["motionharness.bridge"] === wanted["motionharness.bridge"] && actual.path === before.path,
|
|
18405
18412
|
"APPLY_OUTCOME_UNKNOWN",
|
|
18406
|
-
"\u5173\u8054\u6062\u590D\u540E\u7684\
|
|
18413
|
+
"\u5173\u8054\u6062\u590D\u540E\u7684\u539F\u7D20\u6750\u8EAB\u4EFD\u8BFB\u56DE\u4E0D\u4E00\u81F4\u3002"
|
|
18407
18414
|
);
|
|
18408
18415
|
await this.finishAssociationRestore(taskId, binding.id, binding.revision, artifact, actual);
|
|
18409
18416
|
}
|
|
@@ -18443,7 +18450,7 @@ var Bridge = class {
|
|
|
18443
18450
|
assert2(
|
|
18444
18451
|
after.contentVersion === observation.contentVersion && after.runtimeIdentity === observation.runtimeIdentity && after.sessionIdentity === observation.sessionIdentity,
|
|
18445
18452
|
"VERSION_CONFLICT",
|
|
18446
|
-
"\u6E32\u67D3\u524D\u540E\u7684
|
|
18453
|
+
"\u6E32\u67D3\u524D\u540E\u7684 MotionHarness \u5185\u5BB9\u3001\u8FD0\u884C\u65F6\u6216\u4F1A\u8BDD\u4E0D\u4E00\u81F4\uFF0C\u672A\u5E94\u7528\u65B0\u7ED3\u679C\u3002"
|
|
18447
18454
|
);
|
|
18448
18455
|
await this.store.mutate((catalog) => {
|
|
18449
18456
|
const current = get(catalog.sources, sourceId, "\u6E90");
|
|
@@ -18470,7 +18477,7 @@ var Bridge = class {
|
|
|
18470
18477
|
async renderSource(taskId, input, signal) {
|
|
18471
18478
|
const request = renderSchema.parse(input), source = get((await this.store.read()).sources, request.sourceId, "\u6E90");
|
|
18472
18479
|
const observation = await this.mh.inspect(this.store.path(source.locator));
|
|
18473
|
-
assert2(observation.contentVersion === request.expectedContentVersion, "VERSION_CONFLICT", "
|
|
18480
|
+
assert2(observation.contentVersion === request.expectedContentVersion, "VERSION_CONFLICT", "MotionHarness \u5185\u5BB9\u4E0E\u8BF7\u6C42\u7684\u7248\u672C\u4E0D\u4E00\u81F4\u3002");
|
|
18474
18481
|
const artifact = await this.renderArtifact(taskId, source.id, observation, request.outputSpec, request.purpose, signal);
|
|
18475
18482
|
await this.store.mutate((c) => {
|
|
18476
18483
|
get(c.jobs, taskId, "\u4EFB\u52A1").results = [{ sourceId: source.id, artifactId: artifact.id, verification: artifact.verification, applied: false }];
|
|
@@ -18486,9 +18493,9 @@ var Bridge = class {
|
|
|
18486
18493
|
let checkpoint = (await this.job(taskId)).journal?.duplicate;
|
|
18487
18494
|
if (instance) {
|
|
18488
18495
|
assert2(originalBinding.revision === instance.expectedRevision && originalBinding.artifactId, "VERSION_CONFLICT", "\u539F\u5B9E\u4F8B\u5173\u8054\u5DF2\u6539\u53D8\u6216\u5C1A\u672A\u5E94\u7528\u89C6\u9891\u3002");
|
|
18489
|
-
const [timeline, media] = await Promise.all([this.host.timeline(originalBinding.resolve, instance.timelineId), this.host.
|
|
18496
|
+
const [timeline, media] = await Promise.all([this.host.timeline(originalBinding.resolve, instance.timelineId), this.host.mediaUsages(originalBinding.resolve, originalBinding.resolve.mediaPoolItemId)]);
|
|
18490
18497
|
assert2(timeline.fingerprint === instance.expectedTimelineFingerprint && media.fingerprint === instance.expectedMediaFingerprint, "VERSION_CONFLICT", "\u590D\u5236\u524D\u65F6\u95F4\u7EBF\u6216\u7D20\u6750\u5DF2\u6539\u53D8\u3002");
|
|
18491
|
-
|
|
18498
|
+
assertInstanceUsages(media);
|
|
18492
18499
|
checkOwnership(originalBinding, media);
|
|
18493
18500
|
const target = media.uses.find((item) => item.timelineId === instance.timelineId && item.id === instance.itemId);
|
|
18494
18501
|
assert2(target && !target.intrinsicEntry && target.kind !== "generator", "UNSUPPORTED_TIMELINE_ITEM", "\u9700\u8981\u660E\u786E\u7684\u666E\u901A\u89C6\u9891\u5B9E\u4F8B\u3002");
|
|
@@ -18632,14 +18639,13 @@ var Bridge = class {
|
|
|
18632
18639
|
const c = await this.store.read(), binding = get(c.bindings, target.bindingId, "\u7ED1\u5B9A"), source = get(c.sources, binding.sourceId, "\u6E90");
|
|
18633
18640
|
assert2(binding.revision === target.expectedRevision, "VERSION_CONFLICT", "\u7ED1\u5B9A\u7248\u672C\u5DF2\u6539\u53D8\u3002");
|
|
18634
18641
|
const obs = await this.mh.inspect(this.store.path(source.locator));
|
|
18635
|
-
assert2(obs.contentVersion === target.expectedContentVersion, "VERSION_CONFLICT", "
|
|
18642
|
+
assert2(obs.contentVersion === target.expectedContentVersion, "VERSION_CONFLICT", "MotionHarness \u5185\u5BB9\u5DF2\u6539\u53D8\u3002");
|
|
18636
18643
|
checkObservation(obs, request.outputSpec);
|
|
18637
18644
|
if (binding.artifactId) assert2(sameOutputSpec(get(c.artifacts, binding.artifactId, "\u4EA7\u7269").spec, request.outputSpec), "OUTPUT_SPEC_MISMATCH", "\u540C\u6B65\u4E0D\u80FD\u6539\u53D8\u5DF2\u5E94\u7528\u7684\u5E27\u533A\u95F4\u3001\u5C3A\u5BF8\u3001\u5E27\u7387\u6216\u989C\u8272\u89E3\u91CA\u3002");
|
|
18638
18645
|
const previousSettings = binding.artifactId ? c.artifacts[binding.artifactId]?.receipt?.before.settings : void 0;
|
|
18639
18646
|
if (previousSettings && !request.preserveSourceRange) assert2(digest(previousSettings) === digest(obs.settings), "OUTPUT_SPEC_MISMATCH", "\u6E90\u65F6\u957F\u3001\u5206\u8FA8\u7387\u6216\u5E27\u7387\u5DF2\u6539\u53D8\uFF1B\u82E5\u8981\u4FDD\u7559\u539F\u6E90\u533A\u95F4\uFF0C\u8BF7\u663E\u5F0F\u6307\u5B9A preserveSourceRange\u3002", { previousSettings, currentSettings: obs.settings });
|
|
18640
18647
|
const actual = await this.host.media(binding.resolve, binding.resolve.mediaPoolItemId);
|
|
18641
|
-
if (target.expectedMediaFingerprint) assert2(actual.fingerprint === target.expectedMediaFingerprint, "VERSION_CONFLICT", "\u786E\u8BA4\u540E\u7D20\u6750\
|
|
18642
|
-
assertUsages(actual);
|
|
18648
|
+
if (target.expectedMediaFingerprint) assert2(actual.fingerprint === target.expectedMediaFingerprint, "VERSION_CONFLICT", "\u786E\u8BA4\u540E\u539F\u7D20\u6750\u7684\u8EAB\u4EFD\u3001\u5173\u8054\u6216\u89C4\u683C\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u51C6\u5907\u3002");
|
|
18643
18649
|
checkOwnership(binding, actual);
|
|
18644
18650
|
checkReplacementSpec(actual, { spec: request.outputSpec });
|
|
18645
18651
|
}
|
|
@@ -18664,7 +18670,6 @@ var Bridge = class {
|
|
|
18664
18670
|
assert2(binding.revision === target.expectedRevision && observation.contentVersion === target.expectedContentVersion, "VERSION_CONFLICT", "\u6E90\u6216\u7ED1\u5B9A\u5728\u6392\u961F\u671F\u95F4\u5DF2\u6539\u53D8\u3002");
|
|
18665
18671
|
const before = await this.host.media(binding.resolve, binding.resolve.mediaPoolItemId);
|
|
18666
18672
|
if (target.expectedMediaFingerprint) assert2(before.fingerprint === target.expectedMediaFingerprint, "VERSION_CONFLICT", "\u51C6\u5907\u5B8C\u6210\u540E\u7D20\u6750\u72B6\u6001\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u51C6\u5907\u3002");
|
|
18667
|
-
assertUsages(before);
|
|
18668
18673
|
checkOwnership(binding, before);
|
|
18669
18674
|
const appliedArtifact = binding.artifactId ? c.artifacts[binding.artifactId] : void 0;
|
|
18670
18675
|
if (appliedArtifact && appliedArtifact.verification === "bridge-verified" && observation.runtimeIdentity && appliedArtifact.receipt?.runtimeIdentity === observation.runtimeIdentity && appliedArtifact.contentVersion === observation.contentVersion && sameOutputSpec(appliedArtifact.spec, request.outputSpec) && appliedArtifact.purpose === request.purpose && resolve3(before.path) === this.store.bindingPath(binding, appliedArtifact) && await fileDigest(before.path).then((hash2) => hash2 === appliedArtifact.sha256, () => false)) {
|
|
@@ -18683,7 +18688,6 @@ var Bridge = class {
|
|
|
18683
18688
|
assert2(latestSource.contentVersion === observation.contentVersion && latest.bindings[binding.id]?.revision === binding.revision && latest.sources[source.id]?.revision === source.revision, "VERSION_CONFLICT", "\u5E94\u7528\u524D\u5185\u5BB9\u3001\u5173\u8054\u6216\u6E90\u4F4D\u7F6E\u53D1\u751F\u53D8\u5316\u3002");
|
|
18684
18689
|
const latestMedia = await this.host.media(binding.resolve, binding.resolve.mediaPoolItemId);
|
|
18685
18690
|
assert2(latestMedia.fingerprint === before.fingerprint, "VERSION_CONFLICT", "Resolve \u5728\u6E32\u67D3\u671F\u95F4\u5DF2\u6539\u53D8\u3002");
|
|
18686
|
-
assertUsages(latestMedia);
|
|
18687
18691
|
checkReplacementSpec(latestMedia, artifact);
|
|
18688
18692
|
if (binding.artifactId === artifact.id && resolve3(latestMedia.path) === this.store.bindingPath(binding, artifact)) {
|
|
18689
18693
|
assert2(
|
|
@@ -18743,7 +18747,7 @@ var Bridge = class {
|
|
|
18743
18747
|
if (bindings.some((b) => b.bindingId === binding.id)) continue;
|
|
18744
18748
|
const fixed = binding.artifactId ? catalog.artifacts[binding.artifactId] : void 0;
|
|
18745
18749
|
if (request.manualPolicy === "allow-pinned" && fixed?.verification === "manual-pinned") {
|
|
18746
|
-
const actual = await this.host.
|
|
18750
|
+
const actual = await this.host.mediaUsages(binding.resolve, binding.resolve.mediaPoolItemId);
|
|
18747
18751
|
const valid = fixed.media.validation?.fullDecode && resolve3(actual.path) === this.store.bindingPath(binding, fixed) && await fileDigest(this.store.bindingPath(binding, fixed)).then((hash2) => hash2 === fixed.sha256, () => false);
|
|
18748
18752
|
let ownership2 = true;
|
|
18749
18753
|
try {
|
|
@@ -18755,7 +18759,7 @@ var Bridge = class {
|
|
|
18755
18759
|
bindings.push({ bindingId: binding.id, revision: binding.revision, sourceId: binding.sourceId, contentVersion: `manual-pinned:${fixed.sha256}`, artifactId: fixed.id, sha256: fixed.sha256, state: "manual-pinned" });
|
|
18756
18760
|
continue;
|
|
18757
18761
|
}
|
|
18758
|
-
const result2 = await this.
|
|
18762
|
+
const result2 = await this.inspectForExport(binding.id);
|
|
18759
18763
|
const pinnedAllowed = request.manualPolicy === "allow-pinned" && result2.state === "manual-pinned";
|
|
18760
18764
|
if (result2.state !== "ready-final" && !pinnedAllowed) blockers.push({ code: "BINDING_NOT_FINAL", bindingId: binding.id, state: result2.state, error: "error" in result2 ? result2.error : void 0 });
|
|
18761
18765
|
if (!result2.artifact || !result2.priorArtifactRemainsAvailable || !("current" in result2) || !result2.current) continue;
|
|
@@ -18816,7 +18820,7 @@ var Bridge = class {
|
|
|
18816
18820
|
await this.patchJob(taskId, { results: [{ resolveJobId: created.jobId, outputPath: output, started: true, status, applied: true }] });
|
|
18817
18821
|
if (["Complete", "Cancelled", "Failed", "Background Render Cancelled", "Remote Render Cancelled"].includes(String(status.JobStatus))) break;
|
|
18818
18822
|
if (signal.aborted) await this.host.cancelRender(receipt.request.scope, created.jobId, created.jobFingerprint);
|
|
18819
|
-
await new Promise((
|
|
18823
|
+
await new Promise((resolve12) => setTimeout(resolve12, 500));
|
|
18820
18824
|
}
|
|
18821
18825
|
if (receipt.playbackPolicy) await this.host.finishRender(receipt.request.scope, created.jobId, receipt.playbackPolicy);
|
|
18822
18826
|
assert2(status.JobStatus === "Complete", status.JobStatus === "Cancelled" ? "CANCELLED" : "RESOLVE_RENDER_FAILED", "\u6307\u5B9A Resolve \u8F93\u51FA\u4EFB\u52A1\u672A\u5B8C\u6210\u3002", { resolveJobId: created.jobId, status });
|
|
@@ -18865,7 +18869,7 @@ var Bridge = class {
|
|
|
18865
18869
|
await mkdir5(directory, { recursive: true });
|
|
18866
18870
|
const output = resolve3(directory, "source.png");
|
|
18867
18871
|
await this.mh.preview(path, time3, output);
|
|
18868
|
-
assert2((await this.mh.inspect(path)).contentVersion === before.contentVersion, "VERSION_CONFLICT", "\u622A\u56FE\u671F\u95F4
|
|
18872
|
+
assert2((await this.mh.inspect(path)).contentVersion === before.contentVersion, "VERSION_CONFLICT", "\u622A\u56FE\u671F\u95F4 MotionHarness \u5185\u5BB9\u5DF2\u6539\u53D8\u3002");
|
|
18869
18873
|
const image = await readFile4(output);
|
|
18870
18874
|
assert2(image.length <= 10 * 1024 * 1024 && image.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])), "INVALID_IMAGE", "\u68C0\u67E5\u56FE\u7247\u4E0D\u662F\u53D7\u652F\u6301\u5927\u5C0F\u7684 PNG\u3002");
|
|
18871
18875
|
return { origin: "mh-source", sourceId, contentVersion: before.contentVersion, timeSeconds: time3, filePath: output, mimeType: "image/png", data: image.toString("base64"), provesResolveComposite: false };
|
|
@@ -20542,36 +20546,298 @@ async function retireLegacyEntries(options, input) {
|
|
|
20542
20546
|
});
|
|
20543
20547
|
}
|
|
20544
20548
|
|
|
20549
|
+
// src/i18n.ts
|
|
20550
|
+
import { execFileSync } from "node:child_process";
|
|
20551
|
+
|
|
20552
|
+
// src/i18n/en.json
|
|
20553
|
+
var en_default2 = {
|
|
20554
|
+
"MotionHarness \u6865\u63A5\u7EC4\u4EF6": "MotionHarness Bridge Component",
|
|
20555
|
+
" \u526F\u672C": " Copy",
|
|
20556
|
+
"\u4E3A\u8FD9\u4E2A\u7247\u6BB5\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\u2026": "Create an independent copy for this clip\u2026",
|
|
20557
|
+
"\u4EFB\u52A1\u4E0E\u72B6\u6001\u2026": "Tasks and status\u2026",
|
|
20558
|
+
\u4EFB\u52A1\u5DF2\u53D6\u6D88: "Task cancelled",
|
|
20559
|
+
\u4EFB\u52A1\u5DF2\u5B8C\u6210: "Task completed",
|
|
20560
|
+
\u4EFB\u52A1\u5DF2\u6392\u961F: "Task queued",
|
|
20561
|
+
"\u4EFB\u52A1\u5DF2\u6392\u961F\u2026": "Task queued\u2026",
|
|
20562
|
+
"\u4FA7\u680F\u6765\u6E90\u5FEB\u7167\u65E0\u6548\u3002": "The sidebar source snapshot is invalid.",
|
|
20563
|
+
"\u4FA7\u680F\u7BA1\u7406\u5165\u53E3\u4E0D\u80FD\u6DF7\u7528\u76EE\u6807\u5FEB\u7167\u6216\u64CD\u4F5C\u53C2\u6570\u3002": "The sidebar management request cannot mix target snapshots with operation parameters.",
|
|
20564
|
+
"\u4FA7\u680F\u7BA1\u7406\u5165\u53E3\u8BF7\u6C42\u65E0\u6548\u3002": "The sidebar management request is invalid.",
|
|
20565
|
+
"\u4FA7\u680F\u7BA1\u7406\u5165\u53E3\u9700\u8981\u65B0\u7248\u6865\u63A5\u7EC4\u4EF6\uFF0C\u8BF7\u66F4\u65B0\u7EC4\u4EF6\u3002": "Update the MotionHarness Bridge Component to use sidebar management.",
|
|
20566
|
+
"\u4FA7\u680F\u9700\u8981\u652F\u6301\u6E90\u8EAB\u4EFD\u6838\u5BF9\u7684\u65B0\u7248\u6865\u63A5\u7EC4\u4EF6\u3002": "The sidebar requires a newer MotionHarness Bridge Component with source verification.",
|
|
20567
|
+
"\u4FA7\u680F\u9700\u8981\u65B0\u7248\u6865\u63A5\u7EC4\u4EF6\uFF0C\u8BF7\u5148\u66F4\u65B0\u7EC4\u4EF6\u3002\u672A\u53D1\u9001\u8BF7\u6C42\u5230\u65E7\u7248\u5165\u53E3\u3002": "Update the MotionHarness Bridge Component to use the sidebar. No request was sent to the old entry.",
|
|
20568
|
+
\u4FDD\u5B58\u72EC\u7ACB\u5DE5\u7A0B: "Save independent project",
|
|
20569
|
+
"\u4FEE\u590D\u5173\u8054\u2026": "Repair association\u2026",
|
|
20570
|
+
"\u4FEE\u590D\u5DE5\u7A0B\u5173\u8054\u2026": "Repair project association\u2026",
|
|
20571
|
+
"\u5148\u6838\u5BF9\u5DF2\u6709\u7ED3\u679C\uFF0C\u518D\u590D\u7528\u539F\u8BF7\u6C42\u4E0E\u89C6\u9891\u3002\u539F\u4EFB\u52A1\u6D89\u53CA\u7684\u5176\u4ED6\u7D20\u6750\u4E5F\u5728\u6B64\u8303\u56F4\u5185\uFF1B\u5982\u679C\u526A\u8F91\u5DF2\u53D1\u751F\u51B2\u7A81\uFF0C\u64CD\u4F5C\u4F1A\u505C\u6B62\u3002": "Existing results will be checked before reusing the original request and video. This includes other media in the original task. Editing conflicts stop the operation.",
|
|
20572
|
+
"\u5173\u8054\u6807\u8BB0\u4E3A\u6E32\u67D3\u4E2D\uFF0C\u4F46\u672A\u627E\u5230\u6D3B\u8DC3\u4EFB\u52A1\uFF0C\u8BF7\u67E5\u770B\u4EFB\u52A1\u8BE6\u60C5\u3002": "The association is marked as rendering, but no active task was found. Check task details.",
|
|
20573
|
+
"\u5173\u8054\u9700\u8981\u68C0\u67E5\uFF0C\u8BF7\u4ECE\u4FA7\u680F\u201C\u66F4\u591A\u2026\u201D\u67E5\u770B\u3002": "The association needs attention. Open More\u2026 in the sidebar.",
|
|
20574
|
+
"\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\u2026": "Create independent copy\u2026",
|
|
20575
|
+
\u5237\u65B0\u7247\u6BB5\u72B6\u6001: "Refresh clip status",
|
|
20576
|
+
\u53D6\u6D88: "Cancel",
|
|
20577
|
+
\u53D6\u6D88\u4EFB\u52A1: "Cancel task",
|
|
20578
|
+
"\u53EF\u5173\u95ED\u7A97\u53E3\uFF0C\u6309\u4E0A\u65B9\u63D0\u793A\u7EE7\u7EED\u64CD\u4F5C\u3002": "You can close this window and follow the instructions above.",
|
|
20579
|
+
"\u53EF\u7EE7\u7EED\u4F7F\u7528\u8FBE\u82AC\u5947\u3002": "You can continue using DaVinci Resolve.",
|
|
20580
|
+
"\u53EF\u7EE7\u7EED\u4F7F\u7528\u8FBE\u82AC\u5947\u3002\u5173\u95ED\u7A97\u53E3\u4E0D\u4F1A\u53D6\u6D88\u4EFB\u52A1\u3002": "You can continue using DaVinci Resolve. Closing this window keeps the task running.",
|
|
20581
|
+
"\u56FE\u6587\u6B65\u9AA4\u6682\u4E0D\u53EF\u7528\uFF0C\u8BF7\u66F4\u65B0\u6865\u63A5\u7EC4\u4EF6\u540E\u91CD\u8BD5\u3002": "The illustrated guide is unavailable. Update the MotionHarness Bridge Component and try again.",
|
|
20582
|
+
"\u5C1A\u672A\u786E\u8BA4\u6240\u9009\u5DE5\u7A0B\u7684\u7F16\u8F91\u5668\u5DF2\u6253\u5F00\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002": "The editor has not confirmed opening the selected project. Check and try again.",
|
|
20583
|
+
\u5DE5\u7A0B\u5173\u8054\u5DF2\u4FEE\u590D: "Project association repaired",
|
|
20584
|
+
"\u5DE5\u7A0B\u5DF2\u4FEE\u6539\uFF0C\u53EF\u4EE5\u66F4\u65B0\u8FBE\u82AC\u5947\u89C6\u9891\u3002": "The project has changed. You can update the video in DaVinci Resolve.",
|
|
20585
|
+
\u5DE5\u7A0B\u6253\u5F00\u8BF7\u6C42\u5DF2\u5B8C\u6210: "Project opening request completed",
|
|
20586
|
+
\u5DF2\u6253\u5F00\u7F16\u8F91\u5668: "Editor opened",
|
|
20587
|
+
"\u5F53\u524D\u4F7F\u7528\u624B\u52A8\u6307\u5B9A\u7684\u89C6\u9891\u7248\u672C\u3002": "A manually selected video version is in use.",
|
|
20588
|
+
"\u5F53\u524D\u7247\u6BB5\u6682\u4E0D\u652F\u6301\u66F4\u65B0\uFF0C\u8BF7\u67E5\u770B\u4EFB\u52A1\u8BE6\u60C5\u3002": "This clip cannot be updated yet. Check task details.",
|
|
20589
|
+
"\u6062\u590D\u5386\u53F2\u7248\u672C\u2026": "Restore previous version\u2026",
|
|
20590
|
+
\u6062\u590D\u5DF2\u5E94\u7528\u7248\u672C: "Restore applied version",
|
|
20591
|
+
"\u6062\u590D\u7248\u672C\u4F1A\u5F71\u54CD\u6B64\u7D20\u6750\u7684\u5168\u90E8\u5F15\u7528\u3002": "Restoring a version affects every use of this media.",
|
|
20592
|
+
"\u6240\u9009 MotionHarness \u7247\u6BB5": "Selected MotionHarness clip",
|
|
20593
|
+
\u6240\u9009\u7247\u6BB5: "Selected clip",
|
|
20594
|
+
"\u627E\u4E0D\u5230 MotionHarness\u3002\u8BF7\u91CD\u65B0\u5B89\u88C5\u6865\u63A5\u7EC4\u4EF6\u3002": "MotionHarness was not found. Reinstall the MotionHarness Bridge Component.",
|
|
20595
|
+
"\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\uFF0C\u8BF7\u4ECE\u4FA7\u680F\u201C\u66F4\u591A\u2026\u201D\u91CD\u65B0\u5B9A\u4F4D\u3002": "The source project was not found. Relocate it using More\u2026 in the sidebar.",
|
|
20596
|
+
"\u64CD\u4F5C\u6CA1\u6709\u5B8C\u6210\u3002\u8BF7\u8FD0\u884C\u6865\u63A5\u8BCA\u65AD\u67E5\u770B\u8BE6\u60C5\u3002": "The operation did not complete. Run bridge diagnostics for details.",
|
|
20597
|
+
"\u64CD\u4F5C\u6CA1\u6709\u5B8C\u6210\uFF0C\u8BF7\u68C0\u67E5\u6865\u63A5\u8FDE\u63A5\u3002": "The operation did not complete. Check the bridge connection.",
|
|
20598
|
+
"\u65E0\u6CD5\u4FDD\u5B58\u672C\u5730\u8BF7\u6C42\u72B6\u6001\u3002": "Unable to save the local request state.",
|
|
20599
|
+
"\u65E0\u6CD5\u521B\u5EFA\u672C\u5730\u8BF7\u6C42\u901A\u9053\u3002": "Unable to create the local request channel.",
|
|
20600
|
+
"\u65E0\u6CD5\u542F\u52A8 MotionHarness\uFF0C\u8BF7\u4FEE\u590D\u7EC4\u4EF6\u5B89\u88C5\u3002": "Unable to start MotionHarness. Repair the MotionHarness Bridge Component installation.",
|
|
20601
|
+
"\u65E0\u6CD5\u542F\u52A8 MotionHarness\uFF0C\u8BF7\u91CD\u65B0\u5B89\u88C5\u6865\u63A5\u7EC4\u4EF6\u3002": "Unable to start MotionHarness. Reinstall the MotionHarness Bridge Component.",
|
|
20602
|
+
"\u65E0\u6CD5\u6253\u5F00\u672C\u5730\u8BF7\u6C42\u72B6\u6001\u3002": "Unable to open the local request state.",
|
|
20603
|
+
"\u65E7\u5165\u53E3\u6CA1\u6709\u8FD4\u56DE\u53EF\u6838\u5BF9\u7684\u7247\u6BB5\u8EAB\u4EFD\u3002": "The legacy entry did not return a verifiable clip identity.",
|
|
20604
|
+
"\u65E7\u5165\u53E3\u7F3A\u5C11\u70B9\u51FB\u65F6\u7684\u7247\u6BB5\u8EAB\u4EFD\uFF0C\u8BF7\u4FEE\u590D\u65E7\u5165\u53E3\u8F6C\u53D1\u3002": "The legacy entry lacks the clip identity captured on click. Repair its forwarder.",
|
|
20605
|
+
"\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u76F8\u5173\u4EFB\u52A1\u72B6\u6001\uFF0C\u8BF7\u7A0D\u540E\u5237\u65B0\u7247\u6BB5\u72B6\u6001\u3002": "The related task status is temporarily unavailable. Refresh the clip status later.",
|
|
20606
|
+
"\u66F4\u591A\u2026": "More\u2026",
|
|
20607
|
+
\u66F4\u65B0\u4F1A\u5F71\u54CD\u6B64\u7D20\u6750\u5728\u5DE5\u7A0B\u4E2D\u7684\u5168\u90E8\u5F15\u7528: "Updating affects every use of this media in the project",
|
|
20608
|
+
"\u66F4\u65B0\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B\u4EFB\u52A1\u8BE6\u60C5": "Update failed. Check task details",
|
|
20609
|
+
"\u66F4\u65B0\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B\u4EFB\u52A1\u8BE6\u60C5\u3002": "Update failed. Check task details.",
|
|
20610
|
+
\u66F4\u65B0\u5B8C\u6210: "Update completed",
|
|
20611
|
+
\u66F4\u65B0\u6B64\u7D20\u6750: "Update this media",
|
|
20612
|
+
\u66F4\u65B0\u753B\u9762: "Update video",
|
|
20613
|
+
\u66F4\u65B0\u5230\u8FBE\u82AC\u5947: "Update in DaVinci Resolve",
|
|
20614
|
+
"\u66F4\u65B0\u7ED3\u679C\u5F85\u6838\u5B9E\uFF0C\u8BF7\u5148\u67E5\u770B\u4EFB\u52A1\u72B6\u6001\u3002": "The update result needs verification. Check the task status first.",
|
|
20615
|
+
"\u6700\u7EC8\u89C6\u9891\u5DF2\u5173\u8054\uFF0C\u6682\u65E0\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u3002": "The final video is linked. No task is running.",
|
|
20616
|
+
"\u672A\u6536\u5230\u53EF\u786E\u8BA4\u7684\u64CD\u4F5C\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5\u3002": "No verifiable operation was received. Refresh and try again.",
|
|
20617
|
+
"\u672A\u6536\u5230\u5B8C\u6574\u4E14\u4E00\u81F4\u7684\u7247\u6BB5\u8EAB\u4EFD\uFF0C\u8BF7\u5173\u95ED\u7A97\u53E3\u540E\u91CD\u65B0\u9009\u62E9\u7247\u6BB5\u3002": "The clip identity is incomplete or inconsistent. Close this window and select the clip again.",
|
|
20618
|
+
"\u672A\u6536\u5230\u6709\u6548\u72B6\u6001\u3002\u8BF7\u8FD0\u884C\u6865\u63A5\u8BCA\u65AD\u67E5\u770B\u8BE6\u60C5\u3002": "No valid status was received. Run bridge diagnostics for details.",
|
|
20619
|
+
"\u672A\u80FD\u56FA\u5B9A\u5F53\u524D\u9009\u62E9\u3002\u8BF7\u5173\u95ED\u6B64\u7A97\u53E3\uFF0C\u9009\u4E2D\u4E00\u4E2A\u7247\u6BB5\u540E\u91CD\u65B0\u6253\u5F00\u3002": "Unable to capture the current selection. Close this window, select one clip, and reopen it.",
|
|
20620
|
+
"\u672A\u80FD\u6253\u5F00\u56FE\u6587\u6B65\u9AA4\uFF0C\u8BF7\u4ECE Studio \u5BFC\u51FA\u533A\u67E5\u770B\u5E2E\u52A9\u3002": "Unable to open the illustrated guide. Open help in the Studio export panel.",
|
|
20621
|
+
\u67E5\u770B\u72B6\u6001: "Check status",
|
|
20622
|
+
\u6838\u5BF9\u73B0\u6709\u4EFB\u52A1\u72B6\u6001: "Check existing task status",
|
|
20623
|
+
\u6B63\u5728\u51C6\u5907\u5DE5\u7A0B: "Preparing project",
|
|
20624
|
+
"\u6B63\u5728\u51C6\u5907\u5DE5\u7A0B\u2026": "Preparing project\u2026",
|
|
20625
|
+
"\u6B63\u5728\u53D6\u6D88\u2026": "Cancelling\u2026",
|
|
20626
|
+
"\u6B63\u5728\u53D6\u6D88\u4EFB\u52A1\u2026": "Cancelling task\u2026",
|
|
20627
|
+
"\u6B63\u5728\u53D6\u6D88\u4EFB\u52A1\uFF0C\u7B49\u5F85\u786E\u8BA4\u5904\u7406\u7ED3\u679C\u2026": "Cancelling task and waiting for the result\u2026",
|
|
20628
|
+
"\u6B63\u5728\u5B9A\u4F4D\u65E7\u7247\u6BB5\u7684\u5DE5\u7A0B\u2026": "Locating the legacy clip project\u2026",
|
|
20629
|
+
"\u6B63\u5728\u6253\u5F00\u5DE5\u7A0B\u2026": "Opening project\u2026",
|
|
20630
|
+
"\u6B63\u5728\u63D0\u4EA4\u66F4\u65B0\u2026": "Submitting update\u2026",
|
|
20631
|
+
"\u6B63\u5728\u63D0\u4EA4\u8BF7\u6C42\u2026": "Submitting request\u2026",
|
|
20632
|
+
\u6B63\u5728\u66F4\u65B0\u8FBE\u82AC\u5947: "Updating DaVinci Resolve",
|
|
20633
|
+
"\u6B63\u5728\u66F4\u65B0\u8FBE\u82AC\u5947\u2026": "Updating DaVinci Resolve\u2026",
|
|
20634
|
+
"\u6B63\u5728\u6838\u5B9E\u66F4\u65B0\u7ED3\u679C\uFF0C\u8BF7\u52FF\u91CD\u590D\u66F4\u65B0": "Verifying the update result. Do not submit another update",
|
|
20635
|
+
"\u6B63\u5728\u6838\u5BF9\u5E76\u7EE7\u7EED\u539F\u4EFB\u52A1\u2026": "Checking and resuming the original task\u2026",
|
|
20636
|
+
"\u6B63\u5728\u6838\u5BF9\u6E90\u5DE5\u7A0B\u4F4D\u7F6E\u2026": "Checking source project location\u2026",
|
|
20637
|
+
"\u6B63\u5728\u6838\u5BF9\u7247\u6BB5\u4E0E\u5F71\u54CD\u8303\u56F4\u2026": "Checking clip and affected uses\u2026",
|
|
20638
|
+
"\u6B63\u5728\u6838\u5BF9\u73B0\u6709\u4EFB\u52A1\u2026": "Checking existing task\u2026",
|
|
20639
|
+
"\u6B63\u5728\u6838\u5BF9\u7D20\u6750\u5173\u8054\u2026": "Checking media association\u2026",
|
|
20640
|
+
\u6B63\u5728\u68C0\u67E5\u89C6\u9891: "Validating video",
|
|
20641
|
+
"\u6B63\u5728\u68C0\u67E5\u89C6\u9891\u2026": "Validating video\u2026",
|
|
20642
|
+
\u6B63\u5728\u6E32\u67D3\u89C6\u9891: "Rendering video",
|
|
20643
|
+
"\u6B63\u5728\u6E32\u67D3\u89C6\u9891\u2026": "Rendering video\u2026",
|
|
20644
|
+
"\u6B63\u5728\u8BFB\u53D6\u5F53\u524D\u9009\u62E9\uFF0C\u8BF7\u6838\u5BF9\u5DE5\u7A0B\u540E\u64CD\u4F5C\u2026": "Reading current selection. Check the project before continuing\u2026",
|
|
20645
|
+
"\u6B63\u5728\u8BFB\u53D6\u6240\u9009\u7247\u6BB5\u2026": "Reading selected clip\u2026",
|
|
20646
|
+
"\u6B64\u7247\u6BB5\u5C1A\u672A\u5B8C\u6210\u5173\u8054\u3002": "This clip is not fully linked yet.",
|
|
20647
|
+
"\u6CA1\u6709\u627E\u5230\u5DF2\u63D0\u4EA4\u7684\u4EFB\u52A1\u3002\u8BF7\u5237\u65B0\u7247\u6BB5\u72B6\u6001\u540E\u91CD\u8BD5\u3002": "No submitted task was found. Refresh the clip status and try again.",
|
|
20648
|
+
"\u6DFB\u52A0\u4FA7\u680F\u5165\u53E3 \xB7 \u56FE\u6587\u6B65\u9AA4": "Add sidebar entry \xB7 Illustrated guide",
|
|
20649
|
+
\u6E90\u5DE5\u7A0B\u4F4D\u7F6E\u5DF2\u66F4\u65B0: "Source project location updated",
|
|
20650
|
+
\u72B6\u6001: "Status",
|
|
20651
|
+
"\u72B6\u6001\u7A97\u53E3\u8BF7\u6C42\u65E0\u6548\u3002": "The status window request is invalid.",
|
|
20652
|
+
"\u72B6\u6001\u89C1\u63D0\u793A\u7A97\uFF1B\u66F4\u65B0\u5F71\u54CD\u5168\u90E8\u5F15\u7528": "See the status window; updates affect every use",
|
|
20653
|
+
\u72EC\u7ACB\u526F\u672C\u5DF2\u521B\u5EFA: "Independent copy created",
|
|
20654
|
+
"\u76F8\u5173\u4EFB\u52A1\u5DF2\u7ED3\u675F\uFF0C\u6240\u9009\u7247\u6BB5\u72B6\u6001\u9700\u91CD\u65B0\u8BFB\u53D6\u3002": "The related task has ended. Refresh the selected clip status.",
|
|
20655
|
+
"\u76F8\u5173\u4EFB\u52A1\u7684\u7ED3\u679C\u5F85\u6838\u5B9E\uFF0C\u8BF7\u56DE\u5230\u539F\u4EFB\u52A1\u5165\u53E3\u5904\u7406\u540E\u5237\u65B0\u3002": "The related task result needs verification. Resolve it through its original entry, then refresh.",
|
|
20656
|
+
\u76F8\u5173\u6587\u4EF6: "related file",
|
|
20657
|
+
"\u7B49\u5F85\u5DF2\u7ED3\u675F\uFF1B\u8BF7\u6C42\u53EF\u80FD\u4ECD\u5728\u540E\u53F0\u5904\u7406\uFF0C\u8BF7\u5148\u67E5\u770B\u72B6\u6001\u3002": "The wait has ended. The request may still be running in the background. Check its status first.",
|
|
20658
|
+
"\u7B49\u5F85\u8D85\u65F6\u3002\u8BF7\u6C42\u53EF\u80FD\u4ECD\u5728\u5904\u7406\uFF0C\u8BF7\u5148\u67E5\u770B\u73B0\u6709\u4EFB\u52A1\u72B6\u6001\u3002": "The request timed out and may still be running. Check the existing task status first.",
|
|
20659
|
+
"\u7EC4\u4EF6\u672A\u914D\u7F6E\u3002\u8BF7\u8FD0\u884C mh bridge davinci install \u4FEE\u590D\u3002": "The MotionHarness Bridge Component is not configured. Run mh bridge davinci install to repair it.",
|
|
20660
|
+
"\u7EC4\u4EF6\u7F3A\u5C11\u72B6\u6001\u7A97\u53E3\uFF0C\u8BF7\u4FEE\u590D MotionHarness \u6865\u63A5\u7EC4\u4EF6\u5B89\u88C5\u3002": "The status window is missing. Repair the MotionHarness Bridge Component installation.",
|
|
20661
|
+
"\u7EC4\u4EF6\u914D\u7F6E\u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002": "The component configuration path must be absolute.",
|
|
20662
|
+
\u7EE7\u7EED: "Continue",
|
|
20663
|
+
\u7EE7\u7EED\u539F\u4EFB\u52A1: "Resume original task",
|
|
20664
|
+
"\u7EE7\u7EED\u539F\u4EFB\u52A1\u2026": "Resume original task\u2026",
|
|
20665
|
+
"\u7EE7\u7EED\u539F\u4EFB\u52A1\u4E2D\u5C1A\u672A\u5B8C\u6210\u7684\u64CD\u4F5C\uFF1F": "Resume unfinished operations in the original task?",
|
|
20666
|
+
\u7EE7\u7EED\u6838\u5BF9\u6E90\u5DE5\u7A0B\u4F4D\u7F6E: "Continue checking source project location",
|
|
20667
|
+
"\u7F16\u8F91 MotionHarness \u5DE5\u7A0B": "Edit MotionHarness project",
|
|
20668
|
+
\u7F16\u8F91\u5DE5\u7A0B: "Edit project",
|
|
20669
|
+
"\u7F3A\u5C11\u8BF7\u6C42\u53C2\u6570\u3002": "Request parameters are missing.",
|
|
20670
|
+
"\u89C6\u9891\u5DF2\u51C6\u5907\uFF0C\u5C1A\u672A\u66F4\u65B0\u5230\u8FBE\u82AC\u5947\u3002": "The video is ready but has not been updated in DaVinci Resolve.",
|
|
20671
|
+
\u89C6\u9891\u5DF2\u53D1\u9001\u5230\u8FBE\u82AC\u5947: "Video sent to DaVinci Resolve",
|
|
20672
|
+
\u89C6\u9891\u5DF2\u66F4\u65B0: "Video updated",
|
|
20673
|
+
"\u89C6\u9891\u5DF2\u751F\u6210\uFF0C\u5C1A\u672A\u66F4\u65B0\u5230\u8FBE\u82AC\u5947\u3002": "The video has been generated but has not been updated in DaVinci Resolve.",
|
|
20674
|
+
"\u89C6\u9891\u7248\u672C\u5C1A\u5F85\u6838\u5B9E\uFF0C\u8BF7\u67E5\u770B\u4EFB\u52A1\u8BE6\u60C5\u3002": "The video version needs verification. Check task details.",
|
|
20675
|
+
"\u8BF7\u5728\u7BA1\u7406\u7A97\u53E3\u4E2D\u6838\u5BF9\u5DE5\u7A0B\u548C\u67E5\u770B\u72B6\u6001\u3002": "Check the project and status in the management window.",
|
|
20676
|
+
"\u8BF7\u66F4\u65B0\u6865\u63A5\u7EC4\u4EF6\u540E\u4F7F\u7528\u66F4\u591A\u64CD\u4F5C\u3002": "Update the MotionHarness Bridge Component to use more actions.",
|
|
20677
|
+
"\u8BF7\u6C42\u53D6\u6D88\uFF0C\u5E76\u6838\u5BF9\u5DF2\u7ECF\u5B8C\u6210\u7684\u7ED3\u679C\u3002": "Request cancellation and check results already completed.",
|
|
20678
|
+
"\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci doctor \u68C0\u67E5\u8FDE\u63A5\u3002": "The request failed. Run mh bridge davinci doctor to check the connection.",
|
|
20679
|
+
\u8BF7\u6C42\u5DF2\u53D7\u7406: "Request accepted",
|
|
20680
|
+
"\u8BF7\u6C42\u5DF2\u7ED3\u675F\uFF0C\u4F46\u672A\u6536\u5230\u6709\u6548\u72B6\u6001\uFF1B\u8BF7\u67E5\u770B\u8BCA\u65AD\u3002": "The request ended without a valid status. Check diagnostics.",
|
|
20681
|
+
"\u8BF7\u6C42\u6B63\u5728\u5904\u7406\u4E2D\uFF0C\u8BF7\u67E5\u770B\u5DF2\u6709\u72B6\u6001\u63D0\u793A\u3002": "The request is already running. Check the existing status window.",
|
|
20682
|
+
"\u8FBE\u82AC\u5947\u5C1A\u672A\u8FDE\u63A5\uFF0C\u8BF7\u68C0\u67E5\u8FDE\u63A5\u72B6\u6001\u3002": "DaVinci Resolve is not connected. Check the connection.",
|
|
20683
|
+
"\u8FBE\u82AC\u5947\u5DF2\u8FDE\u63A5\uFF0C\u6682\u65E0\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u3002": "DaVinci Resolve is connected. No task is running.",
|
|
20684
|
+
"\u8FBE\u82AC\u5947\u5DF2\u8FDE\u63A5\uFF0C\u672A\u627E\u5230\u6B64\u7247\u6BB5\u7684\u5173\u8054\u3002": "DaVinci Resolve is connected, but this clip has no association.",
|
|
20685
|
+
"\u8FBE\u82AC\u5947\u672A\u63D0\u4F9B\u6B64\u6548\u679C\u7684\u6E90\u89C6\u9891\u8DEF\u5F84\u3002\u8BF7\u4ECE\u5DE5\u4F5C\u533A\u83DC\u5355\u7BA1\u7406\u7247\u6BB5\u3002": "DaVinci Resolve did not provide the source video path for this effect. Manage the clip through the Workspace menu.",
|
|
20686
|
+
"\u8FBE\u82AC\u5947\u6865\u63A5\u7EC4\u4EF6\u5C1A\u672A\u5B89\u88C5\u3002": "The MotionHarness Bridge Component is not installed.",
|
|
20687
|
+
\u8FD9\u4E2A\u7247\u6BB5\u7684\u72EC\u7ACB\u526F\u672C\u5DF2\u521B\u5EFA: "An independent copy has been created for this clip",
|
|
20688
|
+
"\u8FD9\u4E2A\u7248\u672C\u7684\u89C6\u9891\u6587\u4EF6\u5DF2\u4E0D\u53EF\u7528\u3002": "The video file for this version is unavailable.",
|
|
20689
|
+
\u9009\u62E9\u4F4D\u7F6E: "Choose location",
|
|
20690
|
+
\u9009\u62E9\u5DE5\u7A0B: "Choose project",
|
|
20691
|
+
\u9009\u62E9\u79FB\u52A8\u540E\u7684\u6E90\u5DE5\u7A0B: "Choose the relocated source project",
|
|
20692
|
+
"\u91CD\u65B0\u5B9A\u4F4D\u5DE5\u7A0B\u2026": "Relocate project\u2026",
|
|
20693
|
+
"\u91CD\u65B0\u5B9A\u4F4D\u6E90\u5DE5\u7A0B\u2026": "Relocate source project\u2026",
|
|
20694
|
+
"\u9884\u89C8\u672A\u5237\u65B0\u8BF7\u64AD\u653E\uFF1B\u5B9A\u683C\u53EF\u80FD\u4FDD\u7559\u65E7\u753B\u9762\u3002": "Play to refresh the preview. Freeze frames may retain the previous image.",
|
|
20695
|
+
"\u9884\u89C8\u89C6\u9891\u5DF2\u5173\u8054\uFF0C\u6682\u65E0\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u3002": "The preview video is linked. No task is running.",
|
|
20696
|
+
"\u7F3A\u5C11 MotionHarness \u72B6\u6001\u7A97\u53E3\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install \u4FEE\u590D\u7EC4\u4EF6\u3002": "The MotionHarness Bridge Component status window is missing. Run mh bridge davinci install to repair it.",
|
|
20697
|
+
"\u627E\u4E0D\u5230 MotionHarness \u4E3B\u7A0B\u5E8F\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install \u4FEE\u590D\u7EC4\u4EF6\u3002": "The MotionHarness executable was not found. Run mh bridge davinci install to repair the bridge component.",
|
|
20698
|
+
"\u8BF7\u6253\u5F00\u65F6\u95F4\u7EBF\u5E76\u9009\u62E9\u4E00\u4E2A MotionHarness \u7247\u6BB5\u3002": "Open a timeline and select a MotionHarness clip.",
|
|
20699
|
+
"\u8BF7\u53EA\u9009\u62E9\u4E00\u4E2A MotionHarness \u89C6\u9891\u7247\u6BB5\u3002": "Select exactly one MotionHarness video clip.",
|
|
20700
|
+
"\u6240\u9009\u89C6\u9891\u672A\u5173\u8054 MotionHarness \u5DE5\u7A0B\u3002": "The selected video is not linked to a MotionHarness project.",
|
|
20701
|
+
"\u6B63\u5728\u6253\u5F00 MotionHarness \u5DE5\u7A0B\u2026": "Opening MotionHarness project\u2026",
|
|
20702
|
+
"\u6B63\u5728\u8BFB\u53D6\u6240\u9009 MotionHarness \u7247\u6BB5\u2026": "Reading selected MotionHarness clip\u2026",
|
|
20703
|
+
"\u6B63\u5728\u63D0\u4EA4 MotionHarness \u8BF7\u6C42\uFF0C\u72B6\u6001\u7A97\u53E3\u5C06\u663E\u793A\u8FDB\u5EA6\u3002": "Submitting the MotionHarness request. The status window will show progress.",
|
|
20704
|
+
"\u8FBE\u82AC\u5947\u5C1A\u672A\u8FDE\u63A5\u3002\u8BF7\u6253\u5F00\u5DE5\u7A0B\u540E\u91CD\u8BD5\u3002": "DaVinci Resolve is not connected. Open a project and try again.",
|
|
20705
|
+
"\u8FBE\u82AC\u5947\u6B63\u5728\u5BFC\u51FA\uFF0C\u8BF7\u5B8C\u6210\u540E\u91CD\u8BD5\u3002": "DaVinci Resolve is rendering. Try again when it finishes.",
|
|
20706
|
+
"\u6240\u9009\u7247\u6BB5\u6CA1\u6709\u666E\u901A\u89C6\u9891\u7D20\u6750\u3002\u8BF7\u5148\u8F6C\u6362\u65E7\u7248\u751F\u6210\u5668\u3002": "The selected clip has no ordinary video media. Convert the legacy generator first.",
|
|
20707
|
+
"\u65E0\u6CD5\u786E\u8BA4\u5F53\u524D\u5DE5\u7A0B\u4F4D\u7F6E\uFF0C\u8BF7\u68C0\u67E5\u8FBE\u82AC\u5947\u8FDE\u63A5\u3002": "Unable to verify the current project location. Check the DaVinci Resolve connection.",
|
|
20708
|
+
"\u6240\u9009\u7247\u6BB5\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u70B9\u51FB\u3002": "The selected clip changed. Click again.",
|
|
20709
|
+
"\u5F53\u524D\u5DE5\u7A0B\u4F4D\u7F6E\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u70B9\u51FB\u3002": "The current project location changed. Click again.",
|
|
20710
|
+
"\u6865\u63A5\u5B89\u88C5\u914D\u7F6E\u7F3A\u5931\u6216\u635F\u574F\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install \u4FEE\u590D\u7EC4\u4EF6\u3002": "The bridge configuration is missing or damaged. Run mh bridge davinci install to repair it.",
|
|
20711
|
+
"\u65E0\u6CD5\u8BFB\u53D6\u6240\u9009\u7247\u6BB5\uFF0C\u8BF7\u68C0\u67E5\u8FBE\u82AC\u5947\u811A\u672C\u8FDE\u63A5\u3002": "Unable to read the selected clip. Check the DaVinci Resolve scripting connection.",
|
|
20712
|
+
"\u4E0D\u80FD\u5B8C\u6574\u6838\u5BF9\u8BE5\u7D20\u6750\u7684\u4F7F\u7528\u8303\u56F4\uFF0C\u672A\u51C6\u5907\u4FEE\u6539\u3002": "The uses of this media could not be fully verified. No change was prepared.",
|
|
20713
|
+
"\u4EC5\u4E3A\u8FD9\u4E2A\u7247\u6BB5\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\uFF1F": "Create an independent copy for this clip only?",
|
|
20714
|
+
"\u4EC5\u5F71\u54CD\u9009\u5B9A\u7684\u4E00\u4E2A\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u3002": "Only the selected timeline instance is affected.",
|
|
20715
|
+
"\u4F7F\u7528\u8FD9\u4E2A\u6E90\u5DE5\u7A0B\u4F4D\u7F6E\uFF1F": "Use this source project location?",
|
|
20716
|
+
"\u4FEE\u590D\u6240\u9009\u7D20\u6750\u7684\u5173\u8054\uFF1F": "Repair the selected media association?",
|
|
20717
|
+
"\u51C6\u5907\u64CD\u4F5C\u65F6\u5173\u8054\u7248\u672C\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7247\u6BB5\u7BA1\u7406\u3002": "The association changed while preparing the operation. Reopen clip management.",
|
|
20718
|
+
"\u5355\u5B9E\u4F8B\u72EC\u7ACB\u526F\u672C\u5F53\u524D\u4EC5\u652F\u6301\u5DF2\u9A8C\u8BC1\u7684\u7D20\u6750\u548C\u65F6\u95F4\u7EBF\u5747\u4E3A 30 fps \u7684\u60C5\u51B5\u3002": "Independent instance copies currently require verified 30 fps media and a 30 fps timeline.",
|
|
20719
|
+
"\u5386\u53F2\u89C6\u9891\u4E0E\u5DF2\u8BB0\u5F55\u5185\u5BB9\u4E0D\u540C\u3002": "The historical video differs from the recorded content.",
|
|
20720
|
+
"\u539F\u5173\u8054\u767B\u8BB0\u5DF2\u7ECF\u4E0D\u53EF\u7528\u3002": "The original association record is unavailable.",
|
|
20721
|
+
"\u540C\u4E00\u5A92\u4F53\u8EAB\u4EFD\u5B58\u5728\u591A\u6761\u767B\u8BB0\uFF0C\u672A\u6309\u540D\u79F0\u6216\u5217\u8868\u987A\u5E8F\u731C\u6D4B\u3002": "Multiple records share this media identity. No target was inferred from names or list order.",
|
|
20722
|
+
"\u540C\u4E00\u6E90\u5DE5\u7A0B\u7684\u5176\u4ED6\u4EFB\u52A1\u6B63\u5728\u5904\u7406\uFF1B\u8FD9\u91CC\u4EC5\u67E5\u770B\u72B6\u6001\uFF0C\u8BF7\u4ECE\u539F\u4EFB\u52A1\u5165\u53E3\u7BA1\u7406\u3002": "Another task for this source project is running. This window only shows status. Manage the task through its original entry.",
|
|
20723
|
+
"\u540C\u4E00\u6E90\u5DE5\u7A0B\u7684\u6240\u6709\u5173\u8054\u4F7F\u7528\u65B0\u76EE\u5F55\u3002": "All associations for this source project use the new directory.",
|
|
20724
|
+
"\u5A92\u4F53\u8EAB\u4EFD\u3001\u8DEF\u5F84\u6216\u5185\u5BB9\u4E0D\u7B26\u5408\u539F\u767B\u8BB0\uFF0C\u4E0D\u80FD\u81EA\u52A8\u4FEE\u590D\u3002": "The media identity, path, or content differs from the original record. Automatic repair is unavailable.",
|
|
20725
|
+
"\u5DE5\u7A0B\u5185\u5BB9\u6307\u7EB9\u5DF2\u5339\u914D\u3002\u53EA\u4FEE\u590D\u6E90\u76EE\u5F55\u4F4D\u7F6E\uFF0C\u5F53\u524D\u8FBE\u82AC\u5947\u89C6\u9891\u4FDD\u6301\u539F\u6837\u3002": "The project content fingerprint matches. Only the source directory location will change. The current DaVinci Resolve video stays as it is.",
|
|
20726
|
+
"\u5F53\u524D\u5173\u8054\u65E0\u9700\u4FEE\u590D\uFF0C\u6216\u5DF2\u8BB0\u5F55\u7684\u89C6\u9891\u4E0D\u53EF\u7528\u3002": "The association does not need repair, or its recorded video is unavailable.",
|
|
20727
|
+
"\u5F53\u524D\u7247\u6BB5\u4E0D\u80FD\u6267\u884C\u6B64\u64CD\u4F5C\u3002": "This operation is unavailable for the current clip.",
|
|
20728
|
+
"\u5F53\u524D\u7D20\u6750\u5305\u542B\u65E0\u6CD5\u5B8C\u6574\u4FDD\u7559\u7684\u5904\u7406\u3002": "The current media includes processing that cannot be fully preserved.",
|
|
20729
|
+
"\u6062\u590D\u8FD9\u4E2A\u5DF2\u5E94\u7528\u7248\u672C\uFF1F": "Restore this applied version?",
|
|
20730
|
+
"\u6240\u9009\u5B9E\u4F8B\u4E0D\u518D\u5C5E\u4E8E\u5F53\u524D\u5A92\u4F53\u3002": "The selected instance no longer belongs to this media.",
|
|
20731
|
+
"\u6240\u9009\u5B9E\u4F8B\u7684\u5904\u7406\u4E0D\u80FD\u5B8C\u6574\u4FDD\u7559\uFF0C\u672A\u9000\u56DE\u53EA\u590D\u5236\u6E90\u5DE5\u7A0B\u3002": "The instance processing cannot be fully preserved. No source-only copy was made.",
|
|
20732
|
+
"\u6240\u9009\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u5DF2\u6539\u53D8\u3002": "The selected timeline instance has changed.",
|
|
20733
|
+
"\u6240\u9009\u7247\u6BB5\u4E0D\u662F\u53EF\u76F4\u63A5\u7BA1\u7406\u7684\u666E\u901A\u89C6\u9891\u7D20\u6750\u3002": "The selected clip is not ordinary video media that can be managed directly.",
|
|
20734
|
+
"\u6240\u9009\u7247\u6BB5\u7684\u539F\u751F\u8EAB\u4EFD\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7247\u6BB5\u7BA1\u7406\u3002": "The selected clip identity has changed. Reopen clip management.",
|
|
20735
|
+
"\u6240\u9009\u76EE\u5F55\u7684\u5185\u5BB9\u4E0E\u539F\u5DE5\u7A0B\u6307\u7EB9\u4E0D\u540C\uFF0C\u672A\u6309\u540C\u540D\u76EE\u5F55\u91CD\u65B0\u5173\u8054\u3002": "The selected directory does not match the original project fingerprint. Matching names were not used to relink it.",
|
|
20736
|
+
"\u6253\u5F00\u66F4\u591A\u64CD\u4F5C\u65F6\u5173\u8054\u5DF2\u6539\u53D8\u3002": "The association changed while opening more actions.",
|
|
20737
|
+
"\u6253\u5F00\u66F4\u591A\u64CD\u4F5C\u671F\u95F4\u5DE5\u7A0B\u5DF2\u6539\u53D8\u3002": "The project changed while opening more actions.",
|
|
20738
|
+
"\u6253\u5F00\u7BA1\u7406\u7A97\u53E3\u540E\u5173\u8054\u8EAB\u4EFD\u53D1\u751F\u53D8\u5316\uFF0C\u672A\u6539\u7528\u5176\u4ED6\u76EE\u6807\u3002": "The association identity changed after opening management. No other target was selected.",
|
|
20739
|
+
"\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\u3002\u73B0\u6709\u89C6\u9891\u4ECD\u4FDD\u7559\uFF0C\u53EF\u9009\u62E9\u201C\u91CD\u65B0\u5B9A\u4F4D\u6E90\u5DE5\u7A0B\u201D\u3002": "The source project was not found. The existing video is preserved. Choose Relocate source project.",
|
|
20740
|
+
"\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\uFF0C\u8BF7\u5148\u91CD\u65B0\u5B9A\u4F4D\u3002": "The source project was not found. Relocate it first.",
|
|
20741
|
+
"\u65B0\u4F4D\u7F6E\u5DF2\u7ECF\u5B58\u5728\uFF0C\u672A\u8986\u76D6\u73B0\u6709\u5DE5\u7A0B\u3002": "The new location already exists. The existing project was not overwritten.",
|
|
20742
|
+
"\u65E0\u6CD5\u5B8C\u6574\u6838\u5BF9\u5F53\u524D\u9009\u62E9\uFF0C\u8BF7\u4ECE\u8FBE\u82AC\u5947\u83DC\u5355\u91CD\u65B0\u6253\u5F00\u7BA1\u7406\u3002": "The current selection could not be fully verified. Reopen management from the DaVinci Resolve menu.",
|
|
20743
|
+
\u65F6\u95F4\u7EBF: "Timeline",
|
|
20744
|
+
"\u66F4\u65B0\u6216\u6062\u590D\u7248\u672C\u4F1A\u5F71\u54CD\u6B64\u7D20\u6750\u5728\u5F53\u524D\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E2D\u7684\u5168\u90E8\u5F15\u7528\u3002": "Updating or restoring a version affects every use of this media in the current DaVinci Resolve project.",
|
|
20745
|
+
"\u6B64\u4EFB\u52A1\u5F71\u54CD\u6240\u9009\u7D20\u6750\u5728\u5F53\u524D\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E2D\u7684\u5168\u90E8\u5F15\u7528\u3002": "This task affects every use of the selected media in the current DaVinci Resolve project.",
|
|
20746
|
+
"\u6B64\u5173\u8054\u5C1A\u65E0\u53EF\u66F4\u65B0\u7684\u89C6\u9891\u89C4\u683C\u3002": "This association has no video specifications available for an update.",
|
|
20747
|
+
"\u6B64\u7D20\u6750\u5DF2\u6709\u5176\u4ED6\u5173\u8054\u8EAB\u4EFD\uFF0C\u4E0D\u80FD\u8986\u76D6\u3002": "This media already has another association identity and cannot be overwritten.",
|
|
20748
|
+
"\u6B64\u7D20\u6750\u643A\u5E26\u4E0D\u540C\u7684\u5173\u8054\u8EAB\u4EFD\uFF0C\u4E0D\u80FD\u8986\u76D6\u3002": "This media carries a different association identity and cannot be overwritten.",
|
|
20749
|
+
"\u6B64\u7D20\u6750\u6CA1\u6709\u53EF\u6838\u5BF9\u7684\u672C\u673A\u5173\u8054\u3002": "This media has no verifiable local association.",
|
|
20750
|
+
"\u6CA1\u6709\u53EF\u6062\u590D\u7684\u5DF2\u5E94\u7528\u7248\u672C\uFF0C\u6216\u5386\u53F2\u89C6\u9891\u6587\u4EF6\u4E0D\u53EF\u7528\u3002": "No applied version can be restored, or the historical video file is unavailable.",
|
|
20751
|
+
"\u7247\u6BB5\u5DF2\u5173\u8054 MotionHarness\u3002\u53EF\u4EE5\u7F16\u8F91\u6E90\u5DE5\u7A0B\u6216\u66F4\u65B0\u753B\u9762\u3002": "The clip is linked to MotionHarness. You can edit the source project or update the video.",
|
|
20752
|
+
"\u72EC\u7ACB\u526F\u672C\u9700\u8981\u53EF\u5B8C\u6574\u6821\u9A8C\u7684\u516C\u5F00\u5DE5\u7A0B\u5305\u3002": "An independent copy requires a fully verifiable public project package.",
|
|
20753
|
+
"\u72EC\u7ACB\u526F\u672C\u9700\u8981\u53EF\u7528\u7684\u6E90\u5DE5\u7A0B\u4E0E\u5F53\u524D\u89C6\u9891\u3002": "An independent copy requires the source project and current video to be available.",
|
|
20754
|
+
"\u7BA1\u7406\u6B64\u7D20\u6750\u7684\u5386\u53F2\u7248\u672C\u4E0E\u5DE5\u7A0B\u5173\u8054\u3002": "Manage this media's version history and project association.",
|
|
20755
|
+
"\u7D20\u6750\u4F5C\u7528\u57DF\u5DF2\u6539\u53D8\u3002": "The media scope has changed.",
|
|
20756
|
+
"\u7F3A\u5C11\u539F\u5DE5\u7A0B\u7684\u5185\u5BB9\u6307\u7EB9\uFF0C\u4E0D\u80FD\u6309\u76EE\u5F55\u540D\u91CD\u65B0\u5173\u8054\u3002": "The original project fingerprint is missing. Directory names cannot be used to relink it.",
|
|
20757
|
+
"\u8BF7\u5148\u4FEE\u590D\u6B64\u7D20\u6750\u7684\u5173\u8054\u3002": "Repair this media association first.",
|
|
20758
|
+
"\u8BF7\u5148\u6253\u5F00\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E0E\u65F6\u95F4\u7EBF\u3002": "Open a DaVinci Resolve project and timeline first.",
|
|
20759
|
+
"\u8BF7\u5148\u6838\u5B9E\u5DF2\u6709\u4EFB\u52A1\u7684\u7ED3\u679C\u3002": "Verify the existing task result first.",
|
|
20760
|
+
"\u8BF7\u53EA\u9009\u62E9\u4E00\u4E2A\u666E\u901A\u89C6\u9891\u7247\u6BB5\u3002": "Select exactly one ordinary video clip.",
|
|
20761
|
+
"\u8BF7\u7B49\u5F85\u5F53\u524D\u4EFB\u52A1\u7ED3\u675F\u3002": "Wait for the current task to finish.",
|
|
20762
|
+
"\u8BF7\u9009\u62E9\u4E00\u4E2A\u666E\u901A\u89C6\u9891\u7247\u6BB5\u3002": "Select an ordinary video clip.",
|
|
20763
|
+
"\u8BF7\u9009\u62E9\u6B64\u5173\u8054\u4EE5\u524D\u786E\u5B9E\u5E94\u7528\u8FC7\u3001\u4E14\u89C4\u683C\u76F8\u540C\u7684\u7248\u672C\u3002": "Select a version previously applied to this association with the same specifications.",
|
|
20764
|
+
"\u8BF7\u9009\u62E9\u6E90\u5DE5\u7A0B\u76EE\u5F55\u3002": "Choose the source project directory.",
|
|
20765
|
+
"\u8BF7\u9009\u62E9\u72EC\u7ACB\u5DE5\u7A0B\u7684\u65B0\u4FDD\u5B58\u4F4D\u7F6E\u3002": "Choose a new location for the independent project.",
|
|
20766
|
+
"\u8BF7\u9009\u62E9\u8981\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\u7684\u5177\u4F53\u65F6\u95F4\u7EBF\u7247\u6BB5\u3002": "Select the specific timeline clip for the independent copy.",
|
|
20767
|
+
"\u8BFB\u53D6\u671F\u95F4\u6240\u9009\u7247\u6BB5\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7247\u6BB5\u7BA1\u7406\u3002": "The selected clip changed while reading it. Reopen clip management.",
|
|
20768
|
+
"\u9700\u8981\u5B8C\u6574\u7684\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u6216\u4FA7\u680F\u6E90\u8DEF\u5F84\u3002": "A complete timeline instance or sidebar source path is required.",
|
|
20769
|
+
"\u6B64\u4EFB\u52A1\u6D89\u53CA {0} \u4E2A\u7D20\u6750\uFF1B\u8BF7\u4ECE\u539F\u4EFB\u52A1\u5165\u53E3\u7BA1\u7406\u5B8C\u6574\u8303\u56F4\u3002": "This task includes {0} media items. Manage its full scope through the original task entry.",
|
|
20770
|
+
"{0} \xB7 \u89C6\u9891\u8F68 {1} \xB7 \u8D77\u59CB\u5E27 {2}": "{0} \xB7 Video track {1} \xB7 Start frame {2}",
|
|
20771
|
+
"\u5C06\u5F71\u54CD\u5F53\u524D\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E2D\u6B64\u7D20\u6750\u7684 {0} \u5904\u5F15\u7528\u3002": "This affects all {0} uses of this media in the current DaVinci Resolve project.",
|
|
20772
|
+
"{0}\u3002{1}\u6E90\u5DE5\u7A0B\u4FDD\u6301\u5F53\u524D\u5185\u5BB9\u3002": "{0}. {1} The source project keeps its current content.",
|
|
20773
|
+
"\u590D\u5236\u53EF\u7F16\u8F91\u5DE5\u7A0B\uFF0C\u5E76\u53EA\u6539\u53D8\u6240\u9009\u201C{0}\u201D\u7247\u6BB5\u7684\u7D20\u6750\u5173\u8054\u3002\u5176\u4ED6\u5F15\u7528\u7EE7\u7EED\u4F7F\u7528\u539F\u5DE5\u7A0B\u3002": "Copy the editable project and change the media association of the selected \u201C{0}\u201D clip only. Other uses keep the original project.",
|
|
20774
|
+
"\u5DF2\u6309\u539F\u751F\u5A92\u4F53\u8EAB\u4EFD\u548C\u89C6\u9891\u5185\u5BB9\u5339\u914D\u201C{0}\u201D\u3002\u53EA\u8865\u56DE\u5173\u8054\u5143\u6570\u636E\uFF0C\u4E0D\u91CD\u65B0\u751F\u6210\u89C6\u9891\u3002": "Matched \u201C{0}\u201D using the native media identity and video content. Only association metadata will be restored. The video will not be rendered again.",
|
|
20775
|
+
"\u6B64\u7D20\u6750\u6CA1\u6709\u53EF\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\u7684\u65F6\u95F4\u7EBF\u7247\u6BB5\u3002": "This media has no timeline clips available for an independent copy.",
|
|
20776
|
+
\u4FEE\u590D\u8FDE\u63A5: "Repair connection",
|
|
20777
|
+
"\u6865\u63A5\u914D\u7F6E\u7F3A\u5931\u6216\u635F\u574F\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install \u4FEE\u590D\u7EC4\u4EF6\u3002": "Bridge configuration is missing or damaged. Run mh bridge davinci install to repair it.",
|
|
20778
|
+
"MotionHarness \u672A\u8FDE\u63A5\uFF0C\u8BF7\u70B9\u51FB\u201C\u4FEE\u590D\u8FDE\u63A5\u201D\u3002": "MotionHarness is disconnected. Click Repair connection.",
|
|
20779
|
+
"MotionHarness \u5165\u53E3\u5C31\u7EEA\uFF1B\u66F4\u65B0\u5F71\u54CD\u5168\u90E8\u5F15\u7528": "MotionHarness is ready; updates affect all references",
|
|
20780
|
+
"\u627E\u4E0D\u5230 MotionHarness \u4E3B\u7A0B\u5E8F\u3002\u8BF7\u5B89\u88C5\u6216\u5347\u7EA7 CLI \u540E\u70B9\u51FB\u201C\u4FEE\u590D\u8FDE\u63A5\u201D\u3002": "MotionHarness could not be found. Install or upgrade the CLI, then click Repair connection.",
|
|
20781
|
+
"\u6B63\u5728\u4FEE\u590D MotionHarness \u8FDE\u63A5\u2026": "Repairing the MotionHarness connection\u2026",
|
|
20782
|
+
"MotionHarness \u8FDE\u63A5\u5DF2\u4FEE\u590D\uFF0C\u53EF\u91CD\u65B0\u70B9\u51FB\u7F16\u8F91\u6216\u66F4\u65B0\u3002": "MotionHarness connection repaired. You can click Edit or Update again.",
|
|
20783
|
+
"\u8FDE\u63A5\u5C1A\u672A\u6062\u590D\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install \u4FEE\u590D\u7EC4\u4EF6\u3002": "The connection is still unavailable. Run mh bridge davinci install to repair the component.",
|
|
20784
|
+
"CLI \u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002": "The CLI path must be absolute.",
|
|
20785
|
+
"\u6865\u63A5\u5B89\u88C5\u8BB0\u5F55\u7F3A\u5931\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install\u3002": "The bridge installation record is missing. Run mh bridge davinci install.",
|
|
20786
|
+
"\u6865\u63A5\u914D\u7F6E\u7F3A\u5931\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install\u3002": "The bridge configuration is missing. Run mh bridge davinci install.",
|
|
20787
|
+
"\u6865\u63A5\u914D\u7F6E\u5DF2\u88AB\u4FEE\u6539\uFF0C\u672A\u8986\u76D6\u3002\u8BF7\u68C0\u67E5\u914D\u7F6E\u540E\u91CD\u65B0\u5B89\u88C5\u7EC4\u4EF6\u3002": "The bridge configuration has been modified and was preserved. Check it before reinstalling the component.",
|
|
20788
|
+
"\u6865\u63A5\u5DE5\u5177\u914D\u7F6E\u5DF2\u88AB\u4FEE\u6539\uFF0C\u672A\u8986\u76D6\u3002": "The bridge tool configuration has been modified and was preserved.",
|
|
20789
|
+
\u8FDE\u63A5\u4FEE\u590D\u7ED3\u679C\u89C1\u63D0\u793A\u7A97: "See the status window for the connection repair result"
|
|
20790
|
+
};
|
|
20791
|
+
|
|
20792
|
+
// src/i18n.ts
|
|
20793
|
+
var systemLocale;
|
|
20794
|
+
function bridgeLocale(requested = process.env.MH_UI_LOCALE) {
|
|
20795
|
+
if (typeof requested === "string" && /^en(?:[-_]|$)/i.test(requested)) return "en";
|
|
20796
|
+
if (typeof requested === "string" && /^zh(?:[-_]|$)/i.test(requested)) return "zh-CN";
|
|
20797
|
+
if (systemLocale) return systemLocale;
|
|
20798
|
+
let languages = Intl.DateTimeFormat().resolvedOptions().locale;
|
|
20799
|
+
if (process.platform === "darwin") {
|
|
20800
|
+
try {
|
|
20801
|
+
languages = execFileSync("/usr/bin/defaults", ["read", "-g", "AppleLanguages"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 1e3 });
|
|
20802
|
+
} catch {
|
|
20803
|
+
}
|
|
20804
|
+
}
|
|
20805
|
+
systemLocale = languages.match(/\b(en|zh)(?:[-_]|\b)/i)?.[1]?.toLowerCase() === "en" ? "en" : "zh-CN";
|
|
20806
|
+
return systemLocale;
|
|
20807
|
+
}
|
|
20808
|
+
function bridgeText(source, locale = bridgeLocale()) {
|
|
20809
|
+
return locale === "en" ? en_default2[source] ?? source : source;
|
|
20810
|
+
}
|
|
20811
|
+
function bridgeMessage(source, values, locale = bridgeLocale()) {
|
|
20812
|
+
return bridgeText(source, locale).replace(/\{(\d+)\}/g, (token, index) => values[Number(index)] === void 0 ? token : String(values[Number(index)]));
|
|
20813
|
+
}
|
|
20814
|
+
var bridgeName = (locale = bridgeLocale()) => bridgeText("MotionHarness \u6865\u63A5\u7EC4\u4EF6", locale);
|
|
20815
|
+
var bridgeEnglishCatalog = en_default2;
|
|
20816
|
+
|
|
20545
20817
|
// src/core/entry-context.ts
|
|
20546
20818
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
20547
|
-
import { stat as
|
|
20548
|
-
import { isAbsolute as isAbsolute7, resolve as
|
|
20819
|
+
import { stat as stat5 } from "node:fs/promises";
|
|
20820
|
+
import { isAbsolute as isAbsolute7, resolve as resolve8 } from "node:path";
|
|
20549
20821
|
|
|
20550
20822
|
// src/core/ofx-entry.ts
|
|
20551
|
-
import { realpath as realpath5
|
|
20552
|
-
import { isAbsolute as isAbsolute6,
|
|
20823
|
+
import { realpath as realpath5 } from "node:fs/promises";
|
|
20824
|
+
import { isAbsolute as isAbsolute6, resolve as resolve7 } from "node:path";
|
|
20553
20825
|
var ofxSourceSchema = external_exports.strictObject({
|
|
20554
20826
|
path: external_exports.string().min(1).refine((path) => isAbsolute6(path) && !path.includes("\0"), "\u9700\u8981\u6709\u6548\u7684\u7EDD\u5BF9\u89C6\u9891\u8DEF\u5F84\u3002")
|
|
20555
20827
|
});
|
|
20556
|
-
|
|
20557
|
-
|
|
20558
|
-
|
|
20559
|
-
assert2(canonical2, code, "\u65E0\u6CD5\u6838\u5BF9\u89C6\u9891\u8DEF\u5F84\uFF0C\u672A\u8DF3\u8FC7\u4E0D\u53EF\u8BFB\u53D6\u7684\u5173\u8054\u3002\u8BF7\u4FEE\u590D\u5173\u8054\u540E\u91CD\u8BD5\u3002");
|
|
20560
|
-
return canonical2;
|
|
20561
|
-
}
|
|
20562
|
-
function verifyMetadata(metadata2, binding, artifact, allowMissing = false) {
|
|
20563
|
-
assert2(metadata2 && typeof metadata2 === "object" && !Array.isArray(metadata2), "BINDING_CONFLICT", "\u539F\u751F\u7D20\u6750\u7F3A\u5C11\u53EF\u6838\u5BF9\u7684\u5173\u8054\u4FE1\u606F\u3002");
|
|
20564
|
-
if (allowMissing && !metadata2["motionharness.bridge"]) return;
|
|
20828
|
+
var canonicalPath = (path) => realpath5(path).catch(() => resolve7(path));
|
|
20829
|
+
function verifyMetadata(metadata2, binding, artifact, allowMissing) {
|
|
20830
|
+
if (allowMissing && !metadata2?.["motionharness.bridge"]) return;
|
|
20565
20831
|
let link2;
|
|
20566
20832
|
try {
|
|
20567
|
-
const value = JSON.parse(metadata2["motionharness.bridge"] ?? "null");
|
|
20833
|
+
const value = JSON.parse(metadata2?.["motionharness.bridge"] ?? "null");
|
|
20568
20834
|
if (value && typeof value === "object" && !Array.isArray(value)) link2 = value;
|
|
20569
20835
|
} catch {
|
|
20570
20836
|
}
|
|
20571
20837
|
assert2(
|
|
20572
20838
|
link2?.schemaVersion === 1 && link2.bindingId === binding.id && link2.sourceId === binding.sourceId && link2.artifactId === artifact.id,
|
|
20573
20839
|
"BINDING_CONFLICT",
|
|
20574
|
-
"\u539F\
|
|
20840
|
+
"\u539F\u7D20\u6750\u7684\u5173\u8054\u7F3A\u5931\u6216\u4E0E\u5F53\u524D\u89C6\u9891\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u4ECE\u83DC\u5355\u6838\u5BF9\u5173\u8054\u3002"
|
|
20575
20841
|
);
|
|
20576
20842
|
}
|
|
20577
20843
|
var OfxEntry = class {
|
|
@@ -20582,91 +20848,46 @@ var OfxEntry = class {
|
|
|
20582
20848
|
store;
|
|
20583
20849
|
host;
|
|
20584
20850
|
async resolve(input, management = false) {
|
|
20585
|
-
const request = ofxSourceSchema.parse(input);
|
|
20586
|
-
const path = await canonicalPath(request.path);
|
|
20851
|
+
const request = ofxSourceSchema.parse(input), path = await canonicalPath(request.path);
|
|
20587
20852
|
const catalog = await this.store.read();
|
|
20588
|
-
const artifactsRoot = await canonicalPath(this.store.path("artifacts"));
|
|
20589
20853
|
const candidates = [];
|
|
20590
20854
|
for (const binding2 of Object.values(catalog.bindings)) {
|
|
20591
|
-
|
|
20592
|
-
|
|
20593
|
-
|
|
20594
|
-
|
|
20595
|
-
"BINDING_CONFLICT",
|
|
20596
|
-
"\u6E05\u5355\u4E2D\u5B58\u5728\u65E0\u6CD5\u6838\u5BF9\u7684\u5F53\u524D\u89C6\u9891\u5173\u8054\uFF0C\u672A\u731C\u6D4B\u4FA7\u680F\u76EE\u6807\u3002"
|
|
20597
|
-
);
|
|
20598
|
-
const currentPath = await canonicalPath(this.store.bindingPath(binding2, artifact2));
|
|
20599
|
-
const inside = relative2(artifactsRoot, currentPath);
|
|
20855
|
+
const artifact2 = binding2.artifactId ? catalog.artifacts[binding2.artifactId] : void 0;
|
|
20856
|
+
if (artifact2 && await canonicalPath(this.store.bindingPath(binding2, artifact2)) === path) candidates.push({ binding: binding2, artifact: artifact2 });
|
|
20857
|
+
}
|
|
20858
|
+
if (!candidates.length) {
|
|
20600
20859
|
assert2(
|
|
20601
|
-
|
|
20602
|
-
"
|
|
20603
|
-
"\
|
|
20860
|
+
!Object.values(catalog.artifacts).some((artifact2) => this.store.artifactPath(artifact2.relativePath) === path),
|
|
20861
|
+
"OFX_SOURCE_STALE",
|
|
20862
|
+
"\u4FA7\u680F\u4ECD\u63D0\u4F9B\u65E7\u7248\u89C6\u9891\u8DEF\u5F84\u3002\u8BF7\u4ECE\u300C\u5DE5\u4F5C\u533A \u2192 \u811A\u672C \u2192 Utility \u2192 MotionHarness \u6865\u63A5\u7EC4\u4EF6\u300D\u4E2D\u7684\u300C\u7F16\u8F91\u5DE5\u7A0B\u300D\u6216\u300C\u66F4\u65B0\u5230\u8FBE\u82AC\u5947\u300D\u7EE7\u7EED\u3002"
|
|
20604
20863
|
);
|
|
20605
|
-
if (currentPath === path) candidates.push({ binding: binding2, artifact: artifact2 });
|
|
20606
20864
|
}
|
|
20607
|
-
|
|
20608
|
-
for (const artifact2 of Object.values(catalog.artifacts)) {
|
|
20609
|
-
const historicalPath = await realpath5(this.store.artifactPath(artifact2.relativePath)).catch(() => null);
|
|
20610
|
-
assert2(
|
|
20611
|
-
historicalPath !== path,
|
|
20612
|
-
"OFX_SOURCE_STALE",
|
|
20613
|
-
"\u4FA7\u680F\u4ECD\u63D0\u4F9B\u65E7\u7248\u89C6\u9891\u8DEF\u5F84\uFF0C\u65E0\u6CD5\u786E\u8BA4\u5F53\u524D\u76EE\u6807\u3002\u8BF7\u4ECE\u300C\u5DE5\u4F5C\u533A \u2192 \u811A\u672C \u2192 Utility \u2192 Hotion Harness\u300D\u4E2D\u7684\u300C\u7F16\u8F91\u5DE5\u7A0B\u300D\u6216\u300C\u66F4\u65B0\u5230\u8FBE\u82AC\u5947\u300D\u7EE7\u7EED\u7F16\u8F91\u6216\u66F4\u65B0\u3002"
|
|
20614
|
-
);
|
|
20615
|
-
}
|
|
20616
|
-
}
|
|
20617
|
-
assert2(candidates.length === 1, "BINDING_CONFLICT", candidates.length ? "\u591A\u4E2A\u5173\u8054\u4F7F\u7528\u540C\u4E00\u89C6\u9891\uFF0C\u4FA7\u680F\u65E0\u6CD5\u786E\u5B9A\u76EE\u6807\u3002\u8BF7\u4F7F\u7528\u83DC\u5355\u7BA1\u7406\u7247\u6BB5\u3002" : "\u6B64\u89C6\u9891\u6CA1\u6709\u552F\u4E00\u7684\u5F53\u524D\u6865\u63A5\u5173\u8054\u3002\u65E7\u7248\u672C\u89C6\u9891\u4E0D\u80FD\u7528\u4E8E\u5B9A\u4F4D\u65B0\u7684\u5173\u8054\u3002");
|
|
20865
|
+
assert2(candidates.length === 1, "BINDING_CONFLICT", candidates.length ? "\u591A\u4E2A\u5173\u8054\u4F7F\u7528\u540C\u4E00\u89C6\u9891\uFF0C\u4FA7\u680F\u65E0\u6CD5\u786E\u5B9A\u76EE\u6807\u3002\u8BF7\u4F7F\u7528\u83DC\u5355\u7BA1\u7406\u7247\u6BB5\u3002" : "\u6B64\u89C6\u9891\u6CA1\u6709\u552F\u4E00\u7684\u5F53\u524D\u6865\u63A5\u5173\u8054\u3002");
|
|
20618
20866
|
const { binding, artifact } = candidates[0];
|
|
20867
|
+
assert2(artifact.sourceId === binding.sourceId, "BINDING_CONFLICT", "\u5F53\u524D\u89C6\u9891\u4E0D\u5C5E\u4E8E\u5173\u8054\u7684\u6E90\u5DE5\u7A0B\u3002");
|
|
20619
20868
|
const source = catalog.sources[binding.sourceId];
|
|
20620
|
-
assert2(source
|
|
20621
|
-
const sourcePath = management ? this.store.path(source.locator) : await canonicalPath(this.store.path(source.locator), "SOURCE_MISSING");
|
|
20622
|
-
const sourceInfo = await stat5(sourcePath).catch(() => void 0);
|
|
20623
|
-
assert2(management || sourceInfo && sourceInfo.isDirectory(), "SOURCE_MISSING", "\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\u76EE\u5F55\uFF0C\u8BF7\u4ECE\u4FA7\u680F\u201C\u66F4\u591A\u2026\u201D\u91CD\u65B0\u5B9A\u4F4D\u5DE5\u7A0B\u3002");
|
|
20624
|
-
const before = await stat5(path).catch(() => void 0);
|
|
20625
|
-
assert2(before && before.isFile() && before.size === artifact.bytes, "ARTIFACT_CHANGED", "\u5F53\u524D\u89C6\u9891\u6587\u4EF6\u7F3A\u5931\u6216\u5927\u5C0F\u4E0E\u5DF2\u767B\u8BB0\u4EA7\u7269\u4E0D\u540C\u3002");
|
|
20869
|
+
assert2(source, "SOURCE_MISSING", "\u5F53\u524D\u5173\u8054\u7684\u6E90\u5DE5\u7A0B\u767B\u8BB0\u4E0D\u5B58\u5728\u3002");
|
|
20626
20870
|
const scope = { databaseId: binding.resolve.databaseId, projectId: binding.resolve.projectId };
|
|
20627
|
-
const params = { scope, mediaPoolItemId: binding.resolve.mediaPoolItemId, path };
|
|
20628
|
-
const verifyTarget = async (target) => {
|
|
20629
|
-
assert2(target && target.unique === true && digest(target.scope) === digest(scope) && target.mediaPoolItemId === binding.resolve.mediaPoolItemId, "VERSION_CONFLICT", "\u539F\u751F\u89C6\u9891\u8EAB\u4EFD\u4E0D\u552F\u4E00\u6216\u5F53\u524D\u5DE5\u7A0B\u5DF2\u7ECF\u6539\u53D8\u3002");
|
|
20630
|
-
assert2(await canonicalPath(target.path) === path, "VERSION_CONFLICT", "\u539F\u751F\u89C6\u9891\u8DEF\u5F84\u5DF2\u7ECF\u6539\u53D8\u3002");
|
|
20631
|
-
verifyMetadata(target.metadata, binding, artifact, management);
|
|
20632
|
-
};
|
|
20633
|
-
await verifyTarget(await this.host.call("ofx_source_target", params));
|
|
20634
|
-
const media = await this.host.media(scope, binding.resolve.mediaPoolItemId);
|
|
20635
|
-
assert2(
|
|
20636
|
-
media && digest(media.scope) === digest(scope) && media.mediaPoolItemId === binding.resolve.mediaPoolItemId && media.usageScanComplete === true && typeof media.fingerprint === "string" && media.fingerprint.length > 0,
|
|
20637
|
-
"VERSION_CONFLICT",
|
|
20638
|
-
"\u65E0\u6CD5\u5B8C\u6574\u6838\u5BF9\u56FA\u5B9A\u7D20\u6750\u7684\u4F7F\u7528\u8303\u56F4\uFF0C\u672A\u66F4\u65B0\u89C6\u9891\u3002"
|
|
20639
|
-
);
|
|
20640
|
-
assert2(await canonicalPath(media.path) === path, "VERSION_CONFLICT", "\u8BFB\u53D6\u671F\u95F4\u539F\u751F\u89C6\u9891\u5DF2\u88AB\u91CD\u65B0\u94FE\u63A5\u3002");
|
|
20641
|
-
verifyMetadata(media.metadata, binding, artifact, management);
|
|
20642
|
-
await verifyTarget(await this.host.call("ofx_source_target", params));
|
|
20643
|
-
assert2(await fileDigest(path) === artifact.sha256, "ARTIFACT_CHANGED", "\u5F53\u524D\u89C6\u9891\u5185\u5BB9\u4E0E\u5DF2\u767B\u8BB0\u4EA7\u7269\u4E0D\u540C\u3002");
|
|
20644
|
-
const after = await stat5(path).catch(() => void 0);
|
|
20645
20871
|
assert2(
|
|
20646
|
-
|
|
20647
|
-
"
|
|
20648
|
-
"\
|
|
20872
|
+
Object.values(catalog.bindings).filter((item) => digest(item.resolve) === digest(binding.resolve)).length === 1,
|
|
20873
|
+
"BINDING_CONFLICT",
|
|
20874
|
+
"\u540C\u4E00\u539F\u7D20\u6750\u5B58\u5728\u591A\u4E2A\u5173\u8054\uFF0C\u672A\u731C\u6D4B\u76EE\u6807\u3002"
|
|
20649
20875
|
);
|
|
20876
|
+
const target = await this.host.call("ofx_source_target", { scope, mediaPoolItemId: binding.resolve.mediaPoolItemId, path });
|
|
20650
20877
|
assert2(
|
|
20651
|
-
|
|
20878
|
+
target?.unique === true && digest(target.scope) === digest(scope) && target.mediaPoolItemId === binding.resolve.mediaPoolItemId && typeof target.fingerprint === "string" && target.fingerprint.length > 0 && await canonicalPath(target.path) === path,
|
|
20652
20879
|
"VERSION_CONFLICT",
|
|
20653
|
-
"\
|
|
20880
|
+
"\u539F\u7D20\u6750\u7684\u8EAB\u4EFD\u6216\u89C6\u9891\u8DEF\u5F84\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u5165\u53E3\u3002"
|
|
20654
20881
|
);
|
|
20655
|
-
|
|
20656
|
-
|
|
20657
|
-
assert2(
|
|
20658
|
-
await canonicalPath(this.store.path(source.locator), "SOURCE_MISSING") === sourcePath && currentSource?.isDirectory() && currentSource.dev === sourceInfo.dev && currentSource.ino === sourceInfo.ino,
|
|
20659
|
-
"SOURCE_MISSING",
|
|
20660
|
-
"\u6838\u5BF9\u671F\u95F4\u6E90\u5DE5\u7A0B\u4F4D\u7F6E\u53D1\u751F\u53D8\u5316\u3002"
|
|
20661
|
-
);
|
|
20662
|
-
}
|
|
20663
|
-
assert2(digest(await this.store.read()) === digest(catalog), "VERSION_CONFLICT", "\u6838\u5BF9\u671F\u95F4\u6865\u63A5\u5173\u8054\u5DF2\u66F4\u65B0\uFF0C\u8BF7\u91CD\u65B0\u70B9\u51FB\u4FA7\u680F\u5165\u53E3\u3002");
|
|
20882
|
+
verifyMetadata(target.metadata, binding, artifact, management);
|
|
20883
|
+
assert2(digest((await this.store.read()).bindings[binding.id]) === digest(binding), "VERSION_CONFLICT", "\u6838\u5BF9\u671F\u95F4\u5173\u8054\u5DF2\u66F4\u65B0\uFF0C\u8BF7\u91CD\u65B0\u70B9\u51FB\u5165\u53E3\u3002");
|
|
20664
20884
|
return {
|
|
20665
20885
|
bindingId: binding.id,
|
|
20666
20886
|
sourceId: source.id,
|
|
20667
20887
|
artifactId: artifact.id,
|
|
20668
20888
|
expectedRevision: binding.revision,
|
|
20669
|
-
expectedMediaFingerprint:
|
|
20889
|
+
expectedMediaFingerprint: target.fingerprint,
|
|
20890
|
+
target
|
|
20670
20891
|
};
|
|
20671
20892
|
}
|
|
20672
20893
|
};
|
|
@@ -20683,7 +20904,7 @@ var entrySelectionSchema = external_exports.strictObject({
|
|
|
20683
20904
|
artifactId: external_exports.string().min(1).optional()
|
|
20684
20905
|
});
|
|
20685
20906
|
var entryInspectSchema = external_exports.union([
|
|
20686
|
-
external_exports.strictObject({ selection: entrySelectionSchema }),
|
|
20907
|
+
external_exports.strictObject({ selection: entrySelectionSchema, includeInstances: external_exports.literal(true).optional() }),
|
|
20687
20908
|
external_exports.strictObject({ currentSelection: external_exports.literal(true) }),
|
|
20688
20909
|
external_exports.strictObject({ ofxSource: ofxSourceSchema })
|
|
20689
20910
|
]);
|
|
@@ -20738,7 +20959,7 @@ function activeTaskScope(job, binding, selection) {
|
|
|
20738
20959
|
const instance = job.operation === "duplicate" && job.request.bindingId === binding.id && job.request.timelineId === selection.timelineId && job.request.itemId === selection.itemId;
|
|
20739
20960
|
const canControl = !multiple && Boolean(direct || singleBatch || instance);
|
|
20740
20961
|
const kind = canControl ? "selected-binding" : multiple ? "multiple-targets" : "other-targets";
|
|
20741
|
-
const message = canControl ? instance ? "\u4EC5\u5F71\u54CD\u9009\u5B9A\u7684\u4E00\u4E2A\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u3002" : "\u6B64\u4EFB\u52A1\u5F71\u54CD\u6240\u9009\u7D20\u6750\u5728\u5F53\u524D\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E2D\u7684\u5168\u90E8\u5F15\u7528\u3002" : multiple ?
|
|
20962
|
+
const message = canControl ? instance ? bridgeText("\u4EC5\u5F71\u54CD\u9009\u5B9A\u7684\u4E00\u4E2A\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u3002") : bridgeText("\u6B64\u4EFB\u52A1\u5F71\u54CD\u6240\u9009\u7D20\u6750\u5728\u5F53\u524D\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E2D\u7684\u5168\u90E8\u5F15\u7528\u3002") : multiple ? bridgeMessage("\u6B64\u4EFB\u52A1\u6D89\u53CA {0} \u4E2A\u7D20\u6750\uFF1B\u8BF7\u4ECE\u539F\u4EFB\u52A1\u5165\u53E3\u7BA1\u7406\u5B8C\u6574\u8303\u56F4\u3002", [Math.max(bindingIds.length, targets?.length ?? 0)]) : bridgeText("\u540C\u4E00\u6E90\u5DE5\u7A0B\u7684\u5176\u4ED6\u4EFB\u52A1\u6B63\u5728\u5904\u7406\uFF1B\u8FD9\u91CC\u4EC5\u67E5\u770B\u72B6\u6001\uFF0C\u8BF7\u4ECE\u539F\u4EFB\u52A1\u5165\u53E3\u7BA1\u7406\u3002");
|
|
20742
20963
|
return { kind, canControl, bindingIds, message };
|
|
20743
20964
|
}
|
|
20744
20965
|
function activeTask(catalog, binding, sourcePath) {
|
|
@@ -20746,7 +20967,7 @@ function activeTask(catalog, binding, sourcePath) {
|
|
|
20746
20967
|
if (terminalPhases.includes(job.phase) && job.phase !== "outcome-unknown") return false;
|
|
20747
20968
|
const targets = Array.isArray(job.request.targets) ? job.request.targets : [];
|
|
20748
20969
|
const replacements = job.journal?.legacy?.replacements ?? [];
|
|
20749
|
-
return job.request.bindingId === binding.id || job.request.sourceId === binding.sourceId || typeof job.request.bindingId === "string" && catalog.bindings[job.request.bindingId]?.sourceId === binding.sourceId || typeof job.request.projectPath === "string" &&
|
|
20970
|
+
return job.request.bindingId === binding.id || job.request.sourceId === binding.sourceId || typeof job.request.bindingId === "string" && catalog.bindings[job.request.bindingId]?.sourceId === binding.sourceId || typeof job.request.projectPath === "string" && resolve8(job.request.projectPath) === sourcePath || targets.some((target) => target.bindingId === binding.id || typeof target.bindingId === "string" && catalog.bindings[target.bindingId]?.sourceId === binding.sourceId) || replacements.some((item) => item.oldBindingId === binding.id || item.sourceId === binding.sourceId);
|
|
20750
20971
|
}).sort((a, b) => Number(b.phase === "outcome-unknown") - Number(a.phase === "outcome-unknown") || b.createdAt.localeCompare(a.createdAt))[0];
|
|
20751
20972
|
}
|
|
20752
20973
|
var EntryContext = class {
|
|
@@ -20759,7 +20980,7 @@ var EntryContext = class {
|
|
|
20759
20980
|
host;
|
|
20760
20981
|
mh;
|
|
20761
20982
|
async currentSelection(checking = false) {
|
|
20762
|
-
const changed = "\u8BFB\u53D6\u671F\u95F4\u6240\u9009\u7247\u6BB5\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7247\u6BB5\u7BA1\u7406\u3002";
|
|
20983
|
+
const changed = bridgeText("\u8BFB\u53D6\u671F\u95F4\u6240\u9009\u7247\u6BB5\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7247\u6BB5\u7BA1\u7406\u3002");
|
|
20763
20984
|
let raw;
|
|
20764
20985
|
try {
|
|
20765
20986
|
raw = await this.host.call("selection", { plainMediaOnly: true });
|
|
@@ -20771,23 +20992,23 @@ var EntryContext = class {
|
|
|
20771
20992
|
assert2(
|
|
20772
20993
|
response.success,
|
|
20773
20994
|
checking ? "VERSION_CONFLICT" : "CAPABILITY_UNAVAILABLE",
|
|
20774
|
-
checking ? changed : "\u65E0\u6CD5\u5B8C\u6574\u6838\u5BF9\u5F53\u524D\u9009\u62E9\uFF0C\u8BF7\u4ECE\u8FBE\u82AC\u5947\u83DC\u5355\u91CD\u65B0\u6253\u5F00\u7BA1\u7406\u3002"
|
|
20995
|
+
checking ? changed : bridgeText("\u65E0\u6CD5\u5B8C\u6574\u6838\u5BF9\u5F53\u524D\u9009\u62E9\uFF0C\u8BF7\u4ECE\u8FBE\u82AC\u5947\u83DC\u5355\u91CD\u65B0\u6253\u5F00\u7BA1\u7406\u3002")
|
|
20775
20996
|
);
|
|
20776
20997
|
const snapshot = response.data;
|
|
20777
20998
|
assert2(
|
|
20778
20999
|
snapshot.scope && snapshot.timelineId,
|
|
20779
21000
|
checking ? "VERSION_CONFLICT" : "SELECTION_UNAVAILABLE",
|
|
20780
|
-
checking ? changed : "\u8BF7\u5148\u6253\u5F00\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E0E\u65F6\u95F4\u7EBF\u3002"
|
|
21001
|
+
checking ? changed : bridgeText("\u8BF7\u5148\u6253\u5F00\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E0E\u65F6\u95F4\u7EBF\u3002")
|
|
20781
21002
|
);
|
|
20782
21003
|
assert2(
|
|
20783
21004
|
snapshot.selectedCount === 1 && snapshot.item,
|
|
20784
21005
|
checking ? "VERSION_CONFLICT" : "SELECTION_UNAVAILABLE",
|
|
20785
|
-
checking ? changed : snapshot.selectedCount === 0 ? "\u8BF7\u9009\u62E9\u4E00\u4E2A\u666E\u901A\u89C6\u9891\u7247\u6BB5\u3002" : "\u8BF7\u53EA\u9009\u62E9\u4E00\u4E2A\u666E\u901A\u89C6\u9891\u7247\u6BB5\u3002"
|
|
21006
|
+
checking ? changed : snapshot.selectedCount === 0 ? bridgeText("\u8BF7\u9009\u62E9\u4E00\u4E2A\u666E\u901A\u89C6\u9891\u7247\u6BB5\u3002") : bridgeText("\u8BF7\u53EA\u9009\u62E9\u4E00\u4E2A\u666E\u901A\u89C6\u9891\u7247\u6BB5\u3002")
|
|
20786
21007
|
);
|
|
20787
21008
|
assert2(
|
|
20788
21009
|
snapshot.item.mediaPoolItemId,
|
|
20789
21010
|
checking ? "VERSION_CONFLICT" : "UNSUPPORTED_TIMELINE_ITEM",
|
|
20790
|
-
checking ? changed : "\u6240\u9009\u7247\u6BB5\u4E0D\u662F\u53EF\u76F4\u63A5\u7BA1\u7406\u7684\u666E\u901A\u89C6\u9891\u7D20\u6750\u3002"
|
|
21011
|
+
checking ? changed : bridgeText("\u6240\u9009\u7247\u6BB5\u4E0D\u662F\u53EF\u76F4\u63A5\u7BA1\u7406\u7684\u666E\u901A\u89C6\u9891\u7D20\u6750\u3002")
|
|
20791
21012
|
);
|
|
20792
21013
|
const selection = {
|
|
20793
21014
|
scope: snapshot.scope,
|
|
@@ -20797,17 +21018,17 @@ var EntryContext = class {
|
|
|
20797
21018
|
};
|
|
20798
21019
|
return { snapshot, selection };
|
|
20799
21020
|
}
|
|
20800
|
-
async target(selection) {
|
|
20801
|
-
assert2(Boolean(selection.timelineId) === Boolean(selection.itemId) && (selection.timelineId || selection.path), "INVALID_REQUEST", "\u9700\u8981\u5B8C\u6574\u7684\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u6216\u4FA7\u680F\u6E90\u8DEF\u5F84\u3002");
|
|
20802
|
-
const native = await this.host.call("entry_target", { selection });
|
|
21021
|
+
async target(selection, resolved) {
|
|
21022
|
+
assert2(Boolean(selection.timelineId) === Boolean(selection.itemId) && (selection.timelineId || selection.path), "INVALID_REQUEST", bridgeText("\u9700\u8981\u5B8C\u6574\u7684\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u6216\u4FA7\u680F\u6E90\u8DEF\u5F84\u3002"));
|
|
21023
|
+
const native = resolved ?? await this.host.call("entry_target", { selection });
|
|
20803
21024
|
assert2(
|
|
20804
21025
|
digest(native.scope) === digest(selection.scope) && native.timelineId === selection.timelineId && native.itemId === selection.itemId && native.mediaPoolItemId === selection.mediaPoolItemId && native.metadata && typeof native.metadata === "object" && !Array.isArray(native.metadata),
|
|
20805
21026
|
"VERSION_CONFLICT",
|
|
20806
|
-
"\u6240\u9009\u7247\u6BB5\u7684\u539F\u751F\u8EAB\u4EFD\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7247\u6BB5\u7BA1\u7406\u3002"
|
|
21027
|
+
bridgeText("\u6240\u9009\u7247\u6BB5\u7684\u539F\u751F\u8EAB\u4EFD\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7247\u6BB5\u7BA1\u7406\u3002")
|
|
20807
21028
|
);
|
|
20808
21029
|
const catalog = await this.store.read();
|
|
20809
21030
|
const matches = Object.values(catalog.bindings).filter((binding2) => digest(binding2.resolve) === digest({ ...selection.scope, mediaPoolItemId: selection.mediaPoolItemId }));
|
|
20810
|
-
assert2(matches.length <= 1, "BINDING_CONFLICT", "\u540C\u4E00\u5A92\u4F53\u8EAB\u4EFD\u5B58\u5728\u591A\u6761\u767B\u8BB0\uFF0C\u672A\u6309\u540D\u79F0\u6216\u5217\u8868\u987A\u5E8F\u731C\u6D4B\u3002");
|
|
21031
|
+
assert2(matches.length <= 1, "BINDING_CONFLICT", bridgeText("\u540C\u4E00\u5A92\u4F53\u8EAB\u4EFD\u5B58\u5728\u591A\u6761\u767B\u8BB0\uFF0C\u672A\u6309\u540D\u79F0\u6216\u5217\u8868\u987A\u5E8F\u731C\u6D4B\u3002"));
|
|
20811
21032
|
const binding = matches[0];
|
|
20812
21033
|
let link2;
|
|
20813
21034
|
const encoded = native.metadata?.["motionharness.bridge"];
|
|
@@ -20820,8 +21041,8 @@ var EntryContext = class {
|
|
|
20820
21041
|
}
|
|
20821
21042
|
const conflict = Boolean(encoded && (!binding || !link2 || link2.schemaVersion !== 1 || link2.bindingId !== binding.id || link2.sourceId !== binding.sourceId || link2.artifactId !== binding.artifactId));
|
|
20822
21043
|
if (binding) {
|
|
20823
|
-
assert2((!selection.bindingId || selection.bindingId === binding.id) && (!selection.sourceId || selection.sourceId === binding.sourceId) && (!selection.artifactId || selection.artifactId === binding.artifactId), "VERSION_CONFLICT", "\u6253\u5F00\u7BA1\u7406\u7A97\u53E3\u540E\u5173\u8054\u8EAB\u4EFD\u53D1\u751F\u53D8\u5316\uFF0C\u672A\u6539\u7528\u5176\u4ED6\u76EE\u6807\u3002");
|
|
20824
|
-
} else assert2(!selection.bindingId && !selection.sourceId && !selection.artifactId, "VERSION_CONFLICT", "\u539F\u5173\u8054\u767B\u8BB0\u5DF2\u7ECF\u4E0D\u53EF\u7528\u3002");
|
|
21044
|
+
assert2((!selection.bindingId || selection.bindingId === binding.id) && (!selection.sourceId || selection.sourceId === binding.sourceId) && (!selection.artifactId || selection.artifactId === binding.artifactId), "VERSION_CONFLICT", bridgeText("\u6253\u5F00\u7BA1\u7406\u7A97\u53E3\u540E\u5173\u8054\u8EAB\u4EFD\u53D1\u751F\u53D8\u5316\uFF0C\u672A\u6539\u7528\u5176\u4ED6\u76EE\u6807\u3002"));
|
|
21045
|
+
} else assert2(!selection.bindingId && !selection.sourceId && !selection.artifactId, "VERSION_CONFLICT", bridgeText("\u539F\u5173\u8054\u767B\u8BB0\u5DF2\u7ECF\u4E0D\u53EF\u7528\u3002"));
|
|
20825
21046
|
const verified = binding ? {
|
|
20826
21047
|
...selection,
|
|
20827
21048
|
bindingId: binding.id,
|
|
@@ -20834,10 +21055,12 @@ var EntryContext = class {
|
|
|
20834
21055
|
const request = entryInspectSchema.parse(input);
|
|
20835
21056
|
const captured = "currentSelection" in request ? await this.currentSelection() : void 0;
|
|
20836
21057
|
let selection;
|
|
21058
|
+
let resolved;
|
|
20837
21059
|
if ("ofxSource" in request) {
|
|
20838
|
-
const
|
|
20839
|
-
const binding2 = (await this.store.read()).bindings[
|
|
20840
|
-
assert2(binding2 && binding2.revision ===
|
|
21060
|
+
const entry = await new OfxEntry(this.store, this.host).resolve(request.ofxSource, true);
|
|
21061
|
+
const binding2 = (await this.store.read()).bindings[entry.bindingId];
|
|
21062
|
+
assert2(binding2 && binding2.revision === entry.expectedRevision, "VERSION_CONFLICT", bridgeText("\u6253\u5F00\u66F4\u591A\u64CD\u4F5C\u65F6\u5173\u8054\u5DF2\u6539\u53D8\u3002"));
|
|
21063
|
+
resolved = { ...entry.target, name: String(entry.target.clipProperties?.["Clip Name"] ?? "") };
|
|
20841
21064
|
selection = {
|
|
20842
21065
|
scope: { databaseId: binding2.resolve.databaseId, projectId: binding2.resolve.projectId },
|
|
20843
21066
|
mediaPoolItemId: binding2.resolve.mediaPoolItemId,
|
|
@@ -20847,59 +21070,61 @@ var EntryContext = class {
|
|
|
20847
21070
|
path: request.ofxSource.path
|
|
20848
21071
|
};
|
|
20849
21072
|
} else selection = "selection" in request ? request.selection : captured.selection;
|
|
20850
|
-
const target = await this.target(selection), { binding, catalog, conflict, missingAssociation } = target;
|
|
21073
|
+
const target = await this.target(selection, resolved), { binding, catalog, conflict, missingAssociation } = target;
|
|
20851
21074
|
const source = binding ? catalog.sources[binding.sourceId] : void 0;
|
|
20852
21075
|
const artifact = binding?.artifactId ? catalog.artifacts[binding.artifactId] : void 0;
|
|
20853
|
-
const sourcePresent = source ? await
|
|
20854
|
-
const currentAvailable = artifact ? await
|
|
21076
|
+
const sourcePresent = source ? await stat5(this.store.path(source.locator)).then((info) => info.isDirectory(), () => false) : false;
|
|
21077
|
+
const currentAvailable = artifact ? await stat5(this.store.artifactPath(artifact.relativePath)).then((info) => info.isFile() && info.size === artifact.bytes, () => false) : false;
|
|
20855
21078
|
const history = [];
|
|
20856
21079
|
if (binding && artifact) {
|
|
20857
21080
|
for (const version2 of appliedHistory(catalog, binding)) {
|
|
20858
21081
|
const previous2 = catalog.artifacts[version2.artifactId];
|
|
20859
21082
|
if (previous2.id === artifact.id || !sameOutputSpec(previous2.spec, artifact.spec)) continue;
|
|
20860
|
-
const available = await
|
|
21083
|
+
const available = await stat5(this.store.artifactPath(previous2.relativePath)).then((info) => info.isFile() && info.size === previous2.bytes, () => false);
|
|
20861
21084
|
const spec = previous2.spec;
|
|
20862
21085
|
const codec2 = spec.codec === "prores-4444-xq" ? "ProRes 4444 XQ" : spec.format === "mov" ? "ProRes 4444" : "MP4";
|
|
20863
|
-
const at = new Date(version2.appliedAt).toLocaleString(
|
|
21086
|
+
const at = new Date(version2.appliedAt).toLocaleString(bridgeLocale(), { hour12: false });
|
|
20864
21087
|
history.push({ ...version2, label: `${at} \xB7 ${codec2} \xB7 ${spec.width}\xD7${spec.height}`, current: false, available });
|
|
20865
21088
|
}
|
|
20866
21089
|
}
|
|
20867
21090
|
const instances = [];
|
|
20868
|
-
|
|
20869
|
-
|
|
21091
|
+
const instancesLoaded = "includeInstances" in request && request.includeInstances === true;
|
|
21092
|
+
if (instancesLoaded && !conflict && !missingAssociation) {
|
|
21093
|
+
const media = await this.host.mediaUsages(selection.scope, selection.mediaPoolItemId);
|
|
20870
21094
|
const discovery = await this.host.call("discover", {});
|
|
20871
|
-
assert2(digest(discovery.scope) === digest(selection.scope), "VERSION_CONFLICT", "\u6253\u5F00\u66F4\u591A\u64CD\u4F5C\u671F\u95F4\u5DE5\u7A0B\u5DF2\u6539\u53D8\u3002");
|
|
21095
|
+
assert2(digest(discovery.scope) === digest(selection.scope), "VERSION_CONFLICT", bridgeText("\u6253\u5F00\u66F4\u591A\u64CD\u4F5C\u671F\u95F4\u5DE5\u7A0B\u5DF2\u6539\u53D8\u3002"));
|
|
20872
21096
|
if (media.usageScanComplete) for (const use of media.uses) instances.push({
|
|
20873
21097
|
timelineId: use.timelineId,
|
|
20874
21098
|
itemId: use.id,
|
|
20875
|
-
label:
|
|
21099
|
+
label: bridgeMessage("{0} \xB7 \u89C6\u9891\u8F68 {1} \xB7 \u8D77\u59CB\u5E27 {2}", [discovery.timelines.find((timeline) => timeline.id === use.timelineId)?.name ?? bridgeText("\u65F6\u95F4\u7EBF"), use.track, use.startFrame]),
|
|
20876
21100
|
mediaPoolItemId: use.mediaPoolItemId
|
|
20877
21101
|
});
|
|
20878
21102
|
}
|
|
20879
21103
|
const task = binding ? activeTask(catalog, binding, source ? this.store.path(source.locator) : void 0) : void 0;
|
|
20880
21104
|
const taskScope = task && binding ? activeTaskScope(task, binding, target.selection) : null;
|
|
20881
21105
|
const ready = Boolean(binding && source && !conflict && !missingAssociation), busy = Boolean(task);
|
|
20882
|
-
const blocked = conflict ? "\u6B64\u7D20\u6750\u643A\u5E26\u4E0D\u540C\u7684\u5173\u8054\u8EAB\u4EFD\uFF0C\u4E0D\u80FD\u8986\u76D6\u3002" : missingAssociation ? "\u8BF7\u5148\u4FEE\u590D\u6B64\u7D20\u6750\u7684\u5173\u8054\u3002" : !binding || !source ? "\u6B64\u7D20\u6750\u6CA1\u6709\u53EF\u6838\u5BF9\u7684\u672C\u673A\u5173\u8054\u3002" : task?.phase === "outcome-unknown" ? "\u8BF7\u5148\u6838\u5B9E\u5DF2\u6709\u4EFB\u52A1\u7684\u7ED3\u679C\u3002" : busy ? "\u8BF7\u7B49\u5F85\u5F53\u524D\u4EFB\u52A1\u7ED3\u675F\u3002" : "";
|
|
21106
|
+
const blocked = conflict ? bridgeText("\u6B64\u7D20\u6750\u643A\u5E26\u4E0D\u540C\u7684\u5173\u8054\u8EAB\u4EFD\uFF0C\u4E0D\u80FD\u8986\u76D6\u3002") : missingAssociation ? bridgeText("\u8BF7\u5148\u4FEE\u590D\u6B64\u7D20\u6750\u7684\u5173\u8054\u3002") : !binding || !source ? bridgeText("\u6B64\u7D20\u6750\u6CA1\u6709\u53EF\u6838\u5BF9\u7684\u672C\u673A\u5173\u8054\u3002") : task?.phase === "outcome-unknown" ? bridgeText("\u8BF7\u5148\u6838\u5B9E\u5DF2\u6709\u4EFB\u52A1\u7684\u7ED3\u679C\u3002") : busy ? bridgeText("\u8BF7\u7B49\u5F85\u5F53\u524D\u4EFB\u52A1\u7ED3\u675F\u3002") : "";
|
|
20883
21107
|
const status = conflict ? "association-conflict" : !binding || !source ? "unlinked" : task?.phase === "outcome-unknown" ? "outcome-unknown" : busy ? "busy" : missingAssociation ? "association-missing" : !sourcePresent ? "source-missing" : "linked";
|
|
20884
|
-
const message = blocked || (!sourcePresent ? "\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\u3002\u73B0\u6709\u89C6\u9891\u4ECD\u4FDD\u7559\uFF0C\u53EF\u9009\u62E9\u201C\u91CD\u65B0\u5B9A\u4F4D\u6E90\u5DE5\u7A0B\u201D\u3002" : selection.path ? "\u7BA1\u7406\u6B64\u7D20\u6750\u7684\u5386\u53F2\u7248\u672C\u4E0E\u5DE5\u7A0B\u5173\u8054\u3002" : "\u7247\u6BB5\u5DF2\u5173\u8054
|
|
21108
|
+
const message = blocked || (!sourcePresent ? bridgeText("\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\u3002\u73B0\u6709\u89C6\u9891\u4ECD\u4FDD\u7559\uFF0C\u53EF\u9009\u62E9\u201C\u91CD\u65B0\u5B9A\u4F4D\u6E90\u5DE5\u7A0B\u201D\u3002") : selection.path ? bridgeText("\u7BA1\u7406\u6B64\u7D20\u6750\u7684\u5386\u53F2\u7248\u672C\u4E0E\u5DE5\u7A0B\u5173\u8054\u3002") : bridgeText("\u7247\u6BB5\u5DF2\u5173\u8054 MotionHarness\u3002\u53EF\u4EE5\u7F16\u8F91\u6E90\u5DE5\u7A0B\u6216\u66F4\u65B0\u753B\u9762\u3002"));
|
|
20885
21109
|
const location = [target.native.projectName, target.native.timelineName].filter((value) => typeof value === "string" && value.trim().length > 0).join(" / ");
|
|
20886
|
-
const scopeMessage = taskScope?.message ?? "\u66F4\u65B0\u6216\u6062\u590D\u7248\u672C\u4F1A\u5F71\u54CD\u6B64\u7D20\u6750\u5728\u5F53\u524D\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E2D\u7684\u5168\u90E8\u5F15\u7528\u3002";
|
|
21110
|
+
const scopeMessage = taskScope?.message ?? bridgeText("\u66F4\u65B0\u6216\u6062\u590D\u7248\u672C\u4F1A\u5F71\u54CD\u6B64\u7D20\u6750\u5728\u5F53\u524D\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E2D\u7684\u5168\u90E8\u5F15\u7528\u3002");
|
|
20887
21111
|
const context = {
|
|
20888
21112
|
selection: target.selection,
|
|
20889
|
-
title: source?.name ?? target.native.name ?? "
|
|
21113
|
+
title: source?.name ?? target.native.name ?? "MotionHarness",
|
|
20890
21114
|
status,
|
|
20891
21115
|
message,
|
|
20892
21116
|
sourceDirectory: source && !conflict ? this.store.path(source.locator) : void 0,
|
|
20893
21117
|
scopeLabel: location ? `${location} \xB7 ${scopeMessage}` : scopeMessage,
|
|
20894
21118
|
history,
|
|
20895
21119
|
instances,
|
|
21120
|
+
instancesLoaded,
|
|
20896
21121
|
actions: {
|
|
20897
|
-
edit: action(ready && sourcePresent, blocked || "\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\uFF0C\u8BF7\u5148\u91CD\u65B0\u5B9A\u4F4D\u3002"),
|
|
20898
|
-
update: action(ready && sourcePresent && Boolean(artifact) && !busy, blocked || (!sourcePresent ? "\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\uFF0C\u8BF7\u5148\u91CD\u65B0\u5B9A\u4F4D\u3002" : "\u6B64\u5173\u8054\u5C1A\u65E0\u53EF\u66F4\u65B0\u7684\u89C6\u9891\u89C4\u683C\u3002")),
|
|
20899
|
-
restore: action(ready && history.some((item) => item.available) && !busy, blocked || "\u6CA1\u6709\u53EF\u6062\u590D\u7684\u5DF2\u5E94\u7528\u7248\u672C\uFF0C\u6216\u5386\u53F2\u89C6\u9891\u6587\u4EF6\u4E0D\u53EF\u7528\u3002"),
|
|
20900
|
-
duplicate: action(ready && sourcePresent && currentAvailable && !busy && Boolean(selection.itemId || instances.length), blocked || "\u72EC\u7ACB\u526F\u672C\u9700\u8981\u53EF\u7528\u7684\u6E90\u5DE5\u7A0B\u4E0E\u5F53\u524D\u89C6\u9891\u3002"),
|
|
20901
|
-
relink: action(Boolean(binding && source?.observation?.contentVersion && !conflict && !busy), blocked || "\u7F3A\u5C11\u539F\u5DE5\u7A0B\u7684\u5185\u5BB9\u6307\u7EB9\uFF0C\u4E0D\u80FD\u6309\u76EE\u5F55\u540D\u91CD\u65B0\u5173\u8054\u3002"),
|
|
20902
|
-
repairAssociation: action(Boolean(binding && missingAssociation && artifact && currentAvailable && !conflict && !busy), blocked || "\u5F53\u524D\u5173\u8054\u65E0\u9700\u4FEE\u590D\uFF0C\u6216\u5DF2\u8BB0\u5F55\u7684\u89C6\u9891\u4E0D\u53EF\u7528\u3002")
|
|
21122
|
+
edit: action(ready && sourcePresent, blocked || bridgeText("\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\uFF0C\u8BF7\u5148\u91CD\u65B0\u5B9A\u4F4D\u3002")),
|
|
21123
|
+
update: action(ready && sourcePresent && Boolean(artifact) && !busy, blocked || (!sourcePresent ? bridgeText("\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\uFF0C\u8BF7\u5148\u91CD\u65B0\u5B9A\u4F4D\u3002") : bridgeText("\u6B64\u5173\u8054\u5C1A\u65E0\u53EF\u66F4\u65B0\u7684\u89C6\u9891\u89C4\u683C\u3002"))),
|
|
21124
|
+
restore: action(ready && history.some((item) => item.available) && !busy, blocked || bridgeText("\u6CA1\u6709\u53EF\u6062\u590D\u7684\u5DF2\u5E94\u7528\u7248\u672C\uFF0C\u6216\u5386\u53F2\u89C6\u9891\u6587\u4EF6\u4E0D\u53EF\u7528\u3002")),
|
|
21125
|
+
duplicate: action(ready && sourcePresent && currentAvailable && !busy && Boolean(selection.itemId || selection.path && (!instancesLoaded || instances.length)), blocked || bridgeText("\u72EC\u7ACB\u526F\u672C\u9700\u8981\u53EF\u7528\u7684\u6E90\u5DE5\u7A0B\u4E0E\u5F53\u524D\u89C6\u9891\u3002")),
|
|
21126
|
+
relink: action(Boolean(binding && source?.observation?.contentVersion && !conflict && !busy), blocked || bridgeText("\u7F3A\u5C11\u539F\u5DE5\u7A0B\u7684\u5185\u5BB9\u6307\u7EB9\uFF0C\u4E0D\u80FD\u6309\u76EE\u5F55\u540D\u91CD\u65B0\u5173\u8054\u3002")),
|
|
21127
|
+
repairAssociation: action(Boolean(binding && missingAssociation && artifact && currentAvailable && !conflict && !busy), blocked || bridgeText("\u5F53\u524D\u5173\u8054\u65E0\u9700\u4FEE\u590D\uFF0C\u6216\u5DF2\u8BB0\u5F55\u7684\u89C6\u9891\u4E0D\u53EF\u7528\u3002"))
|
|
20903
21128
|
},
|
|
20904
21129
|
activeTask: task ? { ...task, taskId: task.id } : null,
|
|
20905
21130
|
activeTaskScope: taskScope
|
|
@@ -20909,7 +21134,7 @@ var EntryContext = class {
|
|
|
20909
21134
|
assert2(
|
|
20910
21135
|
current.snapshot.fingerprint === captured.snapshot.fingerprint && digest(current.selection) === digest(captured.selection) && digest(current.snapshot) === digest(captured.snapshot),
|
|
20911
21136
|
"VERSION_CONFLICT",
|
|
20912
|
-
"\u8BFB\u53D6\u671F\u95F4\u6240\u9009\u7247\u6BB5\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7247\u6BB5\u7BA1\u7406\u3002"
|
|
21137
|
+
bridgeText("\u8BFB\u53D6\u671F\u95F4\u6240\u9009\u7247\u6BB5\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7247\u6BB5\u7BA1\u7406\u3002")
|
|
20913
21138
|
);
|
|
20914
21139
|
}
|
|
20915
21140
|
return context;
|
|
@@ -20917,23 +21142,23 @@ var EntryContext = class {
|
|
|
20917
21142
|
async prepare(input) {
|
|
20918
21143
|
const request = entryPrepareSchema.parse(input), context = await this.inspect({ selection: request.selection });
|
|
20919
21144
|
const key = request.operation === "repair-association" ? "repairAssociation" : request.operation;
|
|
20920
|
-
assert2(context.actions[key].enabled, "ENTRY_ACTION_UNAVAILABLE", context.actions[key].reason ?? "\u5F53\u524D\u7247\u6BB5\u4E0D\u80FD\u6267\u884C\u6B64\u64CD\u4F5C\u3002");
|
|
21145
|
+
assert2(context.actions[key].enabled, "ENTRY_ACTION_UNAVAILABLE", context.actions[key].reason ?? bridgeText("\u5F53\u524D\u7247\u6BB5\u4E0D\u80FD\u6267\u884C\u6B64\u64CD\u4F5C\u3002"));
|
|
20921
21146
|
const catalog = await this.store.read(), binding = catalog.bindings[context.selection.bindingId];
|
|
20922
21147
|
const source = binding ? catalog.sources[binding.sourceId] : void 0;
|
|
20923
21148
|
const selection = context.selection, idempotencyKey = randomUUID6();
|
|
20924
21149
|
assert2(
|
|
20925
21150
|
binding && source && binding.sourceId === selection.sourceId && binding.artifactId === selection.artifactId && digest(binding.resolve) === digest({ ...selection.scope, mediaPoolItemId: selection.mediaPoolItemId }),
|
|
20926
21151
|
"VERSION_CONFLICT",
|
|
20927
|
-
"\u51C6\u5907\u64CD\u4F5C\u65F6\u5173\u8054\u7248\u672C\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7247\u6BB5\u7BA1\u7406\u3002"
|
|
21152
|
+
bridgeText("\u51C6\u5907\u64CD\u4F5C\u65F6\u5173\u8054\u7248\u672C\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7247\u6BB5\u7BA1\u7406\u3002")
|
|
20928
21153
|
);
|
|
20929
21154
|
if (request.operation === "relink") {
|
|
20930
|
-
assert2(request.projectPath && isAbsolute7(request.projectPath) && source.observation?.contentVersion, "INVALID_REQUEST", "\u8BF7\u9009\u62E9\u6E90\u5DE5\u7A0B\u76EE\u5F55\u3002");
|
|
20931
|
-
const projectPath = await this.mh.projectPath(
|
|
20932
|
-
assert2(observation.contentVersion === source.observation.contentVersion, "VERSION_CONFLICT", "\u6240\u9009\u76EE\u5F55\u7684\u5185\u5BB9\u4E0E\u539F\u5DE5\u7A0B\u6307\u7EB9\u4E0D\u540C\uFF0C\u672A\u6309\u540C\u540D\u76EE\u5F55\u91CD\u65B0\u5173\u8054\u3002");
|
|
21155
|
+
assert2(request.projectPath && isAbsolute7(request.projectPath) && source.observation?.contentVersion, "INVALID_REQUEST", bridgeText("\u8BF7\u9009\u62E9\u6E90\u5DE5\u7A0B\u76EE\u5F55\u3002"));
|
|
21156
|
+
const projectPath = await this.mh.projectPath(resolve8(request.projectPath)), observation = await this.mh.inspect(projectPath);
|
|
21157
|
+
assert2(observation.contentVersion === source.observation.contentVersion, "VERSION_CONFLICT", bridgeText("\u6240\u9009\u76EE\u5F55\u7684\u5185\u5BB9\u4E0E\u539F\u5DE5\u7A0B\u6307\u7EB9\u4E0D\u540C\uFF0C\u672A\u6309\u540C\u540D\u76EE\u5F55\u91CD\u65B0\u5173\u8054\u3002"));
|
|
20933
21158
|
return {
|
|
20934
|
-
title: "\u4F7F\u7528\u8FD9\u4E2A\u6E90\u5DE5\u7A0B\u4F4D\u7F6E\uFF1F",
|
|
20935
|
-
message: "\u5DE5\u7A0B\u5185\u5BB9\u6307\u7EB9\u5DF2\u5339\u914D\u3002\u53EA\u4FEE\u590D\u6E90\u76EE\u5F55\u4F4D\u7F6E\uFF0C\u5F53\u524D\u8FBE\u82AC\u5947\u89C6\u9891\u4FDD\u6301\u539F\u6837\u3002",
|
|
20936
|
-
scopeLabel: "\u540C\u4E00\u6E90\u5DE5\u7A0B\u7684\u6240\u6709\u5173\u8054\u4F7F\u7528\u65B0\u76EE\u5F55\u3002",
|
|
21159
|
+
title: bridgeText("\u4F7F\u7528\u8FD9\u4E2A\u6E90\u5DE5\u7A0B\u4F4D\u7F6E\uFF1F"),
|
|
21160
|
+
message: bridgeText("\u5DE5\u7A0B\u5185\u5BB9\u6307\u7EB9\u5DF2\u5339\u914D\u3002\u53EA\u4FEE\u590D\u6E90\u76EE\u5F55\u4F4D\u7F6E\uFF0C\u5F53\u524D\u8FBE\u82AC\u5947\u89C6\u9891\u4FDD\u6301\u539F\u6837\u3002"),
|
|
21161
|
+
scopeLabel: bridgeText("\u540C\u4E00\u6E90\u5DE5\u7A0B\u7684\u6240\u6709\u5173\u8054\u4F7F\u7528\u65B0\u76EE\u5F55\u3002"),
|
|
20937
21162
|
command: "relink",
|
|
20938
21163
|
request: {
|
|
20939
21164
|
sourceId: source.id,
|
|
@@ -20945,33 +21170,31 @@ var EntryContext = class {
|
|
|
20945
21170
|
}
|
|
20946
21171
|
};
|
|
20947
21172
|
}
|
|
20948
|
-
|
|
21173
|
+
if (request.operation === "duplicate") assert2(selection.timelineId && selection.itemId, "INVALID_REQUEST", bridgeText("\u8BF7\u9009\u62E9\u8981\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\u7684\u5177\u4F53\u65F6\u95F4\u7EBF\u7247\u6BB5\u3002"));
|
|
21174
|
+
const media = request.operation === "duplicate" ? await this.host.mediaUsages(selection.scope, selection.mediaPoolItemId) : await this.host.media(selection.scope, selection.mediaPoolItemId);
|
|
20949
21175
|
assert2(
|
|
20950
21176
|
digest(media.scope) === digest(selection.scope) && media.mediaPoolItemId === selection.mediaPoolItemId,
|
|
20951
21177
|
"VERSION_CONFLICT",
|
|
20952
|
-
"\u7D20\u6750\u4F5C\u7528\u57DF\u5DF2\u6539\u53D8\u3002"
|
|
21178
|
+
bridgeText("\u7D20\u6750\u4F5C\u7528\u57DF\u5DF2\u6539\u53D8\u3002")
|
|
20953
21179
|
);
|
|
20954
|
-
assert2(media.usageScanComplete, "UNSUPPORTED_TIMELINE_ITEM", "\u4E0D\u80FD\u5B8C\u6574\u6838\u5BF9\u8BE5\u7D20\u6750\u7684\u4F7F\u7528\u8303\u56F4\uFF0C\u672A\u51C6\u5907\u4FEE\u6539\u3002");
|
|
20955
21180
|
const target = selection.itemId ? media.uses.filter((item) => item.timelineId === selection.timelineId && item.id === selection.itemId) : [];
|
|
20956
|
-
|
|
20957
|
-
const
|
|
20958
|
-
|
|
20959
|
-
if (timeline) assert2(timeline.items.some((item) => item.id === selection.itemId && item.mediaPoolItemId === selection.mediaPoolItemId), "VERSION_CONFLICT", "\u6240\u9009\u5B9E\u4F8B\u4E0D\u518D\u5C5E\u4E8E\u5F53\u524D\u5A92\u4F53\u3002");
|
|
21181
|
+
const scopeLabel = bridgeText("\u66F4\u65B0\u6216\u6062\u590D\u7248\u672C\u4F1A\u5F71\u54CD\u6B64\u7D20\u6750\u5728\u5F53\u524D\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E2D\u7684\u5168\u90E8\u5F15\u7528\u3002");
|
|
21182
|
+
const timeline = request.operation === "duplicate" && selection.timelineId ? await this.host.timeline(selection.scope, selection.timelineId) : void 0;
|
|
21183
|
+
if (timeline) assert2(timeline.items.some((item) => item.id === selection.itemId && item.mediaPoolItemId === selection.mediaPoolItemId), "VERSION_CONFLICT", bridgeText("\u6240\u9009\u5B9E\u4F8B\u4E0D\u518D\u5C5E\u4E8E\u5F53\u524D\u5A92\u4F53\u3002"));
|
|
20960
21184
|
const guard = { expectedMediaFingerprint: media.fingerprint, ...timeline ? { expectedTimelineFingerprint: timeline.fingerprint } : {} };
|
|
20961
21185
|
const fixedSelection = { ...selection, ...guard };
|
|
20962
21186
|
if (request.operation === "restore") {
|
|
20963
21187
|
assert2(
|
|
20964
21188
|
request.artifactId && context.history.some((version3) => version3.artifactId === request.artifactId && version3.available),
|
|
20965
21189
|
"INVALID_REQUEST",
|
|
20966
|
-
"\u8BF7\u9009\u62E9\u6B64\u5173\u8054\u4EE5\u524D\u786E\u5B9E\u5E94\u7528\u8FC7\u3001\u4E14\u89C4\u683C\u76F8\u540C\u7684\u7248\u672C\u3002"
|
|
21190
|
+
bridgeText("\u8BF7\u9009\u62E9\u6B64\u5173\u8054\u4EE5\u524D\u786E\u5B9E\u5E94\u7528\u8FC7\u3001\u4E14\u89C4\u683C\u76F8\u540C\u7684\u7248\u672C\u3002")
|
|
20967
21191
|
);
|
|
20968
|
-
assert2(media.uses.every((item) => !item.unsupported.length), "UNSUPPORTED_TIMELINE_ITEM", "\u5F53\u524D\u7D20\u6750\u5305\u542B\u65E0\u6CD5\u5B8C\u6574\u4FDD\u7559\u7684\u5904\u7406\u3002");
|
|
20969
21192
|
const artifact2 = catalog.artifacts[request.artifactId];
|
|
20970
|
-
assert2(await fileDigest(this.store.artifactPath(artifact2.relativePath)) === artifact2.sha256, "ARTIFACT_CHANGED", "\u5386\u53F2\u89C6\u9891\u4E0E\u5DF2\u8BB0\u5F55\u5185\u5BB9\u4E0D\u540C\u3002");
|
|
21193
|
+
assert2(await fileDigest(this.store.artifactPath(artifact2.relativePath)) === artifact2.sha256, "ARTIFACT_CHANGED", bridgeText("\u5386\u53F2\u89C6\u9891\u4E0E\u5DF2\u8BB0\u5F55\u5185\u5BB9\u4E0D\u540C\u3002"));
|
|
20971
21194
|
const version2 = context.history.find((value) => value.artifactId === artifact2.id);
|
|
20972
21195
|
return {
|
|
20973
|
-
title: "\u6062\u590D\u8FD9\u4E2A\u5DF2\u5E94\u7528\u7248\u672C\uFF1F",
|
|
20974
|
-
message:
|
|
21196
|
+
title: bridgeText("\u6062\u590D\u8FD9\u4E2A\u5DF2\u5E94\u7528\u7248\u672C\uFF1F"),
|
|
21197
|
+
message: bridgeMessage("{0}\u3002{1}\u6E90\u5DE5\u7A0B\u4FDD\u6301\u5F53\u524D\u5185\u5BB9\u3002", [version2.label, scopeLabel]),
|
|
20975
21198
|
scopeLabel,
|
|
20976
21199
|
command: "restore",
|
|
20977
21200
|
request: {
|
|
@@ -20985,31 +21208,36 @@ var EntryContext = class {
|
|
|
20985
21208
|
};
|
|
20986
21209
|
}
|
|
20987
21210
|
if (request.operation === "duplicate") {
|
|
20988
|
-
assert2(
|
|
20989
|
-
|
|
20990
|
-
|
|
21211
|
+
assert2(
|
|
21212
|
+
media.usageScanComplete && target.length === 1 && target[0].mediaPoolItemId === selection.mediaPoolItemId,
|
|
21213
|
+
"UNSUPPORTED_TIMELINE_ITEM",
|
|
21214
|
+
bridgeText("\u4E0D\u80FD\u5B8C\u6574\u6838\u5BF9\u8BE5\u7D20\u6750\u7684\u4F7F\u7528\u8303\u56F4\uFF0C\u672A\u51C6\u5907\u4FEE\u6539\u3002")
|
|
21215
|
+
);
|
|
21216
|
+
assert2(timeline && selection.timelineId && selection.itemId, "INVALID_REQUEST", bridgeText("\u8BF7\u9009\u62E9\u8981\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\u7684\u5177\u4F53\u65F6\u95F4\u7EBF\u7247\u6BB5\u3002"));
|
|
21217
|
+
assert2(request.projectPath && isAbsolute7(request.projectPath), "INVALID_REQUEST", bridgeText("\u8BF7\u9009\u62E9\u72EC\u7ACB\u5DE5\u7A0B\u7684\u65B0\u4FDD\u5B58\u4F4D\u7F6E\u3002"));
|
|
21218
|
+
assert2(!await stat5(request.projectPath).then(() => true, () => false), "TARGET_OCCUPIED", bridgeText("\u65B0\u4F4D\u7F6E\u5DF2\u7ECF\u5B58\u5728\uFF0C\u672A\u8986\u76D6\u73B0\u6709\u5DE5\u7A0B\u3002"));
|
|
20991
21219
|
const observation = await this.mh.inspect(this.store.path(source.locator));
|
|
20992
|
-
assert2(observation.coverage === "public-package-v1", "CAPABILITY_UNAVAILABLE", "\u72EC\u7ACB\u526F\u672C\u9700\u8981\u53EF\u5B8C\u6574\u6821\u9A8C\u7684\u516C\u5F00\u5DE5\u7A0B\u5305\u3002");
|
|
21220
|
+
assert2(observation.coverage === "public-package-v1", "CAPABILITY_UNAVAILABLE", bridgeText("\u72EC\u7ACB\u526F\u672C\u9700\u8981\u53EF\u5B8C\u6574\u6821\u9A8C\u7684\u516C\u5F00\u5DE5\u7A0B\u5305\u3002"));
|
|
20993
21221
|
const artifact2 = binding.artifactId ? catalog.artifacts[binding.artifactId] : void 0;
|
|
20994
21222
|
assert2(
|
|
20995
21223
|
artifact2 && artifact2.spec.fps.num === 30 * artifact2.spec.fps.den && timeline.fps.num === 30 * timeline.fps.den,
|
|
20996
21224
|
"CAPABILITY_UNAVAILABLE",
|
|
20997
|
-
"\u5355\u5B9E\u4F8B\u72EC\u7ACB\u526F\u672C\u5F53\u524D\u4EC5\u652F\u6301\u5DF2\u9A8C\u8BC1\u7684\u7D20\u6750\u548C\u65F6\u95F4\u7EBF\u5747\u4E3A 30 fps \u7684\u60C5\u51B5\u3002"
|
|
21225
|
+
bridgeText("\u5355\u5B9E\u4F8B\u72EC\u7ACB\u526F\u672C\u5F53\u524D\u4EC5\u652F\u6301\u5DF2\u9A8C\u8BC1\u7684\u7D20\u6750\u548C\u65F6\u95F4\u7EBF\u5747\u4E3A 30 fps \u7684\u60C5\u51B5\u3002")
|
|
20998
21226
|
);
|
|
20999
21227
|
assert2(
|
|
21000
21228
|
media.uses.every((item) => !item.unsupported.length) && !target[0].intrinsicEntry && target[0].kind === "video",
|
|
21001
21229
|
"UNSUPPORTED_TIMELINE_ITEM",
|
|
21002
|
-
"\u6240\u9009\u5B9E\u4F8B\u7684\u5904\u7406\u4E0D\u80FD\u5B8C\u6574\u4FDD\u7559\uFF0C\u672A\u9000\u56DE\u53EA\u590D\u5236\u6E90\u5DE5\u7A0B\u3002"
|
|
21230
|
+
bridgeText("\u6240\u9009\u5B9E\u4F8B\u7684\u5904\u7406\u4E0D\u80FD\u5B8C\u6574\u4FDD\u7559\uFF0C\u672A\u9000\u56DE\u53EA\u590D\u5236\u6E90\u5DE5\u7A0B\u3002")
|
|
21003
21231
|
);
|
|
21004
21232
|
return {
|
|
21005
|
-
title: "\u4EC5\u4E3A\u8FD9\u4E2A\u7247\u6BB5\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\uFF1F",
|
|
21006
|
-
message:
|
|
21007
|
-
scopeLabel: "\u4EC5\u5F71\u54CD\u9009\u5B9A\u7684\u4E00\u4E2A\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u3002",
|
|
21233
|
+
title: bridgeText("\u4EC5\u4E3A\u8FD9\u4E2A\u7247\u6BB5\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\uFF1F"),
|
|
21234
|
+
message: bridgeMessage("\u590D\u5236\u53EF\u7F16\u8F91\u5DE5\u7A0B\uFF0C\u5E76\u53EA\u6539\u53D8\u6240\u9009\u201C{0}\u201D\u7247\u6BB5\u7684\u7D20\u6750\u5173\u8054\u3002\u5176\u4ED6\u5F15\u7528\u7EE7\u7EED\u4F7F\u7528\u539F\u5DE5\u7A0B\u3002", [context.title]),
|
|
21235
|
+
scopeLabel: bridgeText("\u4EC5\u5F71\u54CD\u9009\u5B9A\u7684\u4E00\u4E2A\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u3002"),
|
|
21008
21236
|
command: "duplicate",
|
|
21009
21237
|
request: {
|
|
21010
21238
|
bindingId: binding.id,
|
|
21011
21239
|
sourceId: source.id,
|
|
21012
|
-
projectPath:
|
|
21240
|
+
projectPath: resolve8(request.projectPath),
|
|
21013
21241
|
expectedContentVersion: observation.contentVersion,
|
|
21014
21242
|
expectedRevision: binding.revision,
|
|
21015
21243
|
timelineId: selection.timelineId,
|
|
@@ -21021,11 +21249,11 @@ var EntryContext = class {
|
|
|
21021
21249
|
};
|
|
21022
21250
|
}
|
|
21023
21251
|
const artifact = binding.artifactId ? catalog.artifacts[binding.artifactId] : void 0;
|
|
21024
|
-
assert2(!media.metadata["motionharness.bridge"], "BINDING_CONFLICT", "\u6B64\u7D20\u6750\u5DF2\u6709\u5176\u4ED6\u5173\u8054\u8EAB\u4EFD\uFF0C\u4E0D\u80FD\u8986\u76D6\u3002");
|
|
21025
|
-
assert2(artifact &&
|
|
21252
|
+
assert2(!media.metadata["motionharness.bridge"], "BINDING_CONFLICT", bridgeText("\u6B64\u7D20\u6750\u5DF2\u6709\u5176\u4ED6\u5173\u8054\u8EAB\u4EFD\uFF0C\u4E0D\u80FD\u8986\u76D6\u3002"));
|
|
21253
|
+
assert2(artifact && resolve8(media.path) === this.store.bindingPath(binding, artifact) && await fileDigest(media.path).catch(() => null) === artifact.sha256, "RECOVERY_CONFLICT", bridgeText("\u5A92\u4F53\u8EAB\u4EFD\u3001\u8DEF\u5F84\u6216\u5185\u5BB9\u4E0D\u7B26\u5408\u539F\u767B\u8BB0\uFF0C\u4E0D\u80FD\u81EA\u52A8\u4FEE\u590D\u3002"));
|
|
21026
21254
|
return {
|
|
21027
|
-
title: "\u4FEE\u590D\u6240\u9009\u7D20\u6750\u7684\u5173\u8054\uFF1F",
|
|
21028
|
-
message:
|
|
21255
|
+
title: bridgeText("\u4FEE\u590D\u6240\u9009\u7D20\u6750\u7684\u5173\u8054\uFF1F"),
|
|
21256
|
+
message: bridgeMessage("\u5DF2\u6309\u539F\u751F\u5A92\u4F53\u8EAB\u4EFD\u548C\u89C6\u9891\u5185\u5BB9\u5339\u914D\u201C{0}\u201D\u3002\u53EA\u8865\u56DE\u5173\u8054\u5143\u6570\u636E\uFF0C\u4E0D\u91CD\u65B0\u751F\u6210\u89C6\u9891\u3002", [context.title]),
|
|
21029
21257
|
scopeLabel,
|
|
21030
21258
|
command: "restore",
|
|
21031
21259
|
request: {
|
|
@@ -21042,20 +21270,67 @@ var EntryContext = class {
|
|
|
21042
21270
|
|
|
21043
21271
|
// src/native-install.ts
|
|
21044
21272
|
import { homedir as homedir3 } from "node:os";
|
|
21045
|
-
import { basename as basename4, delimiter as delimiter3, dirname as
|
|
21046
|
-
import { access as access3, mkdir as mkdir8, readFile as
|
|
21273
|
+
import { basename as basename4, delimiter as delimiter3, dirname as dirname9, isAbsolute as isAbsolute8, join as join8, resolve as resolve10 } from "node:path";
|
|
21274
|
+
import { access as access3, mkdir as mkdir8, readFile as readFile10, writeFile, rename as rename6, rm as rm7, rmdir, readdir as readdir2, stat as stat6, lstat as lstat5 } from "node:fs/promises";
|
|
21047
21275
|
import { constants as constants6 } from "node:fs";
|
|
21048
21276
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
21049
21277
|
|
|
21278
|
+
// src/sidebar-guide.ts
|
|
21279
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
21280
|
+
import { dirname as dirname7, join as join6 } from "node:path";
|
|
21281
|
+
var sidebarHint = {
|
|
21282
|
+
optional: true,
|
|
21283
|
+
title: "\u6DFB\u52A0\u4FA7\u680F\u7F16\u8F91\u5165\u53E3\uFF08\u53EF\u9009\uFF09",
|
|
21284
|
+
message: "\u7D20\u6750\u5DF2\u53D1\u9001\u5E76\u5173\u8054\u5DE5\u7A0B\u3002\u60F3\u4ECE\u8FBE\u82AC\u5947\u4FA7\u680F\u76F4\u63A5\u7F16\u8F91\uFF0C\u53EF\u6DFB\u52A0 MotionHarness \u6865\u63A5\u7EC4\u4EF6\u3002",
|
|
21285
|
+
steps: [
|
|
21286
|
+
"\u5728\u8FBE\u82AC\u5947\u300C\u526A\u8F91\u300D\u9875\u6253\u5F00\u5DE6\u4E0A\u89D2\u300C\u7279\u6548\u5E93\u300D\uFF08\u9B54\u68D2\u56FE\u6807\uFF09\u3002",
|
|
21287
|
+
"\u70B9\u51FB\u653E\u5927\u955C\uFF0C\u641C\u7D22 MotionHarness \u6865\u63A5\u7EC4\u4EF6\uFF0C\u5C06 Open FX \u4E2D\u7684\u540C\u540D\u6548\u679C\u62D6\u5230\u76EE\u6807\u52A8\u6548\u7247\u6BB5\u3002",
|
|
21288
|
+
"\u9009\u4E2D\u7247\u6BB5\uFF0C\u5728\u300C\u68C0\u67E5\u5668 \u2192 \u7279\u6548 \u2192 Open FX\u300D\u4E2D\u70B9\u51FB\u300C\u7F16\u8F91 MotionHarness \u5DE5\u7A0B\u300D\u3002"
|
|
21289
|
+
],
|
|
21290
|
+
shortcut: "\u4E5F\u53EF\u5148\u9009\u4E2D\u7247\u6BB5\uFF0C\u6309 Shift + Space \u641C\u7D22\u5E76\u6DFB\u52A0\u3002",
|
|
21291
|
+
alternative: "\u4E0D\u6DFB\u52A0\u4E5F\u80FD\u4ECE\u300C\u5DE5\u4F5C\u533A \u2192 \u811A\u672C \u2192 Utility \u2192 MotionHarness \u6865\u63A5\u7EC4\u4EF6 \u2192 \u7F16\u8F91\u5DE5\u7A0B\u300D\u6253\u5F00\u3002",
|
|
21292
|
+
guideCommand: "mh bridge davinci sidebar-guide"
|
|
21293
|
+
};
|
|
21294
|
+
function sidebarHintForLocale(locale = bridgeLocale()) {
|
|
21295
|
+
if (locale !== "en") return sidebarHint;
|
|
21296
|
+
return {
|
|
21297
|
+
...sidebarHint,
|
|
21298
|
+
title: "Add sidebar entry (optional)",
|
|
21299
|
+
message: `The media is linked to its source project. Add the ${bridgeName(locale)} to edit from the DaVinci Resolve sidebar.`,
|
|
21300
|
+
steps: [
|
|
21301
|
+
"On the Edit page in DaVinci Resolve, open the Effects Library (magic wand icon).",
|
|
21302
|
+
"Search for MotionHarness Bridge Component and drag the Open FX effect onto the target clip.",
|
|
21303
|
+
"Select the clip and click Edit MotionHarness project under Inspector \u2192 Effects \u2192 Open FX."
|
|
21304
|
+
],
|
|
21305
|
+
shortcut: "You can also select the clip, press Shift + Space, then search and add the effect.",
|
|
21306
|
+
alternative: "You can also open the project from Workspace \u2192 Scripts \u2192 Utility \u2192 MotionHarness Bridge Component \u2192 Edit project."
|
|
21307
|
+
};
|
|
21308
|
+
}
|
|
21309
|
+
async function readSidebarGuideDocument(guidePath) {
|
|
21310
|
+
const html = await readFile9(guidePath, "utf8");
|
|
21311
|
+
const link2 = '<link rel="stylesheet" href="guide.css">';
|
|
21312
|
+
if (!html.includes(link2)) return html;
|
|
21313
|
+
const css = await readFile9(join6(dirname7(guidePath), "guide.css"), "utf8");
|
|
21314
|
+
return html.replace(link2, () => `<style>
|
|
21315
|
+
${css}</style>`);
|
|
21316
|
+
}
|
|
21317
|
+
async function readSidebarGuide(componentRoot, inline = false, locale = bridgeLocale()) {
|
|
21318
|
+
const directory = join6(componentRoot, "resources/sidebar-help");
|
|
21319
|
+
const guidePath = join6(directory, locale === "en" ? "en.html" : "index.html");
|
|
21320
|
+
const hint = sidebarHintForLocale(locale);
|
|
21321
|
+
if (!inline) return { ...hint, guidePath };
|
|
21322
|
+
return { ...hint, html: await readSidebarGuideDocument(guidePath) };
|
|
21323
|
+
}
|
|
21324
|
+
|
|
21050
21325
|
// src/native-permissions.ts
|
|
21051
21326
|
import { access as access2, lstat as lstat4 } from "node:fs/promises";
|
|
21052
21327
|
import { constants as constants5 } from "node:fs";
|
|
21053
|
-
import { dirname as
|
|
21328
|
+
import { dirname as dirname8, join as join7, resolve as resolve9 } from "node:path";
|
|
21054
21329
|
var systemPluginRoot = "/Library/OFX/Plugins";
|
|
21055
21330
|
async function prepareOfxPermissions(componentRoot, pluginRoot, directories) {
|
|
21056
21331
|
let writable = true;
|
|
21057
21332
|
for (const directory of new Set(directories)) {
|
|
21058
|
-
let current =
|
|
21333
|
+
let current = resolve9(directory);
|
|
21059
21334
|
while (true) {
|
|
21060
21335
|
const info2 = await lstat4(current).catch((error48) => {
|
|
21061
21336
|
if (error48.code === "ENOENT") return null;
|
|
@@ -21070,18 +21345,18 @@ async function prepareOfxPermissions(componentRoot, pluginRoot, directories) {
|
|
|
21070
21345
|
}
|
|
21071
21346
|
break;
|
|
21072
21347
|
}
|
|
21073
|
-
const parent =
|
|
21348
|
+
const parent = dirname8(current);
|
|
21074
21349
|
assert2(parent !== current, "INSTALL_CONFLICT", "\u627E\u4E0D\u5230 OFX \u5B89\u88C5\u76EE\u5F55\u7684\u7236\u76EE\u5F55\u3002");
|
|
21075
21350
|
current = parent;
|
|
21076
21351
|
}
|
|
21077
|
-
for (let ancestor =
|
|
21352
|
+
for (let ancestor = dirname8(current); ancestor !== dirname8(ancestor); ancestor = dirname8(ancestor)) {
|
|
21078
21353
|
const info2 = await lstat4(ancestor);
|
|
21079
21354
|
assert2(info2.isDirectory() && !info2.isSymbolicLink(), "INSTALL_CONFLICT", "OFX \u5B89\u88C5\u8DEF\u5F84\u5305\u542B\u7B26\u53F7\u94FE\u63A5\u3002", { path: ancestor });
|
|
21080
21355
|
}
|
|
21081
21356
|
}
|
|
21082
21357
|
if (writable) return { authorized: false };
|
|
21083
21358
|
const uid = process.getuid?.(), gid = process.getgid?.();
|
|
21084
|
-
if (process.platform !== "darwin" ||
|
|
21359
|
+
if (process.platform !== "darwin" || resolve9(pluginRoot) !== systemPluginRoot || !uid || gid === void 0) {
|
|
21085
21360
|
throw new BridgeError(
|
|
21086
21361
|
"OFX_PERMISSION_REQUIRED",
|
|
21087
21362
|
"OFX \u76EE\u5F55\u4E0D\u53EF\u5199\uFF0C\u672A\u5B89\u88C5\u6216\u5347\u7EA7\u4EFB\u4F55\u5165\u53E3\u6587\u4EF6\u3002",
|
|
@@ -21091,7 +21366,7 @@ async function prepareOfxPermissions(componentRoot, pluginRoot, directories) {
|
|
|
21091
21366
|
"\u4FEE\u590D\u81EA\u5B9A\u4E49 OFX \u76EE\u5F55\u6743\u9650\u540E\u91CD\u65B0\u8FD0\u884C mh bridge davinci install\uFF1B\u4E0D\u8981\u4EE5 root \u8FD0\u884C\u6574\u4E2A CLI\u3002"
|
|
21092
21367
|
);
|
|
21093
21368
|
}
|
|
21094
|
-
const helper =
|
|
21369
|
+
const helper = join7(componentRoot, "resources/MotionHarnessInstall");
|
|
21095
21370
|
const info = await lstat4(helper);
|
|
21096
21371
|
assert2(info.isFile() && !info.isSymbolicLink(), "INSTALL_CONFLICT", "OFX \u6743\u9650\u52A9\u624B\u5FC5\u987B\u662F\u7ECF\u8FC7\u7EC4\u4EF6\u6821\u9A8C\u7684\u666E\u901A\u53EF\u6267\u884C\u6587\u4EF6\u3002");
|
|
21097
21372
|
await access2(helper, constants5.X_OK);
|
|
@@ -21117,27 +21392,27 @@ end timeout`;
|
|
|
21117
21392
|
}
|
|
21118
21393
|
|
|
21119
21394
|
// src/native-install.ts
|
|
21120
|
-
var statusAppName = "
|
|
21121
|
-
var statusAppBinary =
|
|
21122
|
-
var recordPath = (root) =>
|
|
21395
|
+
var statusAppName = "MotionHarnessBridge.app";
|
|
21396
|
+
var statusAppBinary = join8("Contents", "MacOS", "MotionHarnessBridge");
|
|
21397
|
+
var recordPath = (root) => join8(root, "native-install.json");
|
|
21123
21398
|
async function previous(root) {
|
|
21124
|
-
return
|
|
21399
|
+
return readFile10(recordPath(root), "utf8").then(JSON.parse).catch((error48) => {
|
|
21125
21400
|
if (error48.code !== "ENOENT") throw error48;
|
|
21126
21401
|
return { version: 1, files: [], entry: { automaticAttachment: false, ofx: "unavailable" } };
|
|
21127
21402
|
});
|
|
21128
21403
|
}
|
|
21129
21404
|
async function nativeStatus(configRoot) {
|
|
21130
21405
|
const manifest = await previous(configRoot);
|
|
21131
|
-
const matches = async (file2) => Boolean(file2 && await fileDigest(file2.path).then(async (actual) => actual === file2.sha256 && (process.platform === "win32" || file2.mode === void 0 || ((await
|
|
21132
|
-
const helperPath = manifest.statusExecutable ??
|
|
21133
|
-
const applicationRoot =
|
|
21134
|
-
const application = helperPath ===
|
|
21406
|
+
const matches = async (file2) => Boolean(file2 && await fileDigest(file2.path).then(async (actual) => actual === file2.sha256 && (process.platform === "win32" || file2.mode === void 0 || ((await stat6(file2.path)).mode & 511) === file2.mode), () => false));
|
|
21407
|
+
const helperPath = manifest.statusExecutable ?? join8(configRoot, "bin/HotionHarnessStatus");
|
|
21408
|
+
const applicationRoot = join8(configRoot, "bin", statusAppName);
|
|
21409
|
+
const application = helperPath === join8(applicationRoot, statusAppBinary);
|
|
21135
21410
|
const helper = manifest.files.find((file2) => file2.path === helperPath);
|
|
21136
21411
|
const applicationFiles = application ? manifest.files.filter((file2) => file2.path.startsWith(applicationRoot + "/")) : [];
|
|
21137
|
-
const applicationComplete = !application || applicationFiles.some((file2) => file2.path ===
|
|
21412
|
+
const applicationComplete = !application || applicationFiles.some((file2) => file2.path === join8(applicationRoot, "Contents/Info.plist")) && (await Promise.all(applicationFiles.map(matches))).every(Boolean);
|
|
21138
21413
|
const helperInstalled = manifest.entry.statusHelper === "installed" && await matches(helper) && applicationComplete;
|
|
21139
|
-
const names = ["\u7F16\u8F91\u5DE5\u7A0B.py", "\u66F4\u65B0\u5230\u8FBE\u82AC\u5947.py"];
|
|
21140
|
-
const menusInstalled = helperInstalled && (await Promise.all(names.map((
|
|
21414
|
+
const names = [["\u7F16\u8F91\u5DE5\u7A0B.py", "Edit project.py"], ["\u66F4\u65B0\u5230\u8FBE\u82AC\u5947.py", "Update in DaVinci Resolve.py"]];
|
|
21415
|
+
const menusInstalled = helperInstalled && (await Promise.all(names.map(async (alternatives) => (await Promise.all(manifest.files.filter((file2) => alternatives.includes(basename4(file2.path))).map(matches))).some(Boolean)))).every(Boolean);
|
|
21141
21416
|
const pluginFiles = manifest.files.filter((file2) => file2.path.split(/[\\/]/).includes("HotionHarness.ofx.bundle"));
|
|
21142
21417
|
const pluginInstalled = manifest.entry.ofx === "manual-attachment" && pluginFiles.length > 0 && (await Promise.all(pluginFiles.map(matches))).every(Boolean);
|
|
21143
21418
|
return {
|
|
@@ -21150,7 +21425,7 @@ async function nativeStatus(configRoot) {
|
|
|
21150
21425
|
};
|
|
21151
21426
|
}
|
|
21152
21427
|
async function publish(path, bytes, mode = 384) {
|
|
21153
|
-
await mkdir8(
|
|
21428
|
+
await mkdir8(dirname9(path), { recursive: true });
|
|
21154
21429
|
const pending = `${path}.${randomUUID7()}.pending`;
|
|
21155
21430
|
try {
|
|
21156
21431
|
await writeFile(pending, bytes, { flag: "wx", mode });
|
|
@@ -21160,25 +21435,66 @@ async function publish(path, bytes, mode = 384) {
|
|
|
21160
21435
|
}
|
|
21161
21436
|
}
|
|
21162
21437
|
async function toolPath(command) {
|
|
21163
|
-
const candidates = isAbsolute8(command) ? [command] : (process.env.PATH ?? "").split(delimiter3).filter(Boolean).map((directory) =>
|
|
21438
|
+
const candidates = isAbsolute8(command) ? [command] : (process.env.PATH ?? "").split(delimiter3).filter(Boolean).map((directory) => resolve10(directory, command));
|
|
21164
21439
|
for (const candidate of candidates) {
|
|
21165
21440
|
try {
|
|
21166
21441
|
await access3(candidate, constants6.X_OK);
|
|
21167
|
-
if ((await
|
|
21442
|
+
if ((await stat6(candidate)).isFile()) return candidate;
|
|
21168
21443
|
} catch {
|
|
21169
21444
|
}
|
|
21170
21445
|
}
|
|
21171
21446
|
return void 0;
|
|
21172
21447
|
}
|
|
21448
|
+
async function cliLauncher(cliPath) {
|
|
21449
|
+
const packageJson = process.env.MH_NPM_PACKAGE_JSON;
|
|
21450
|
+
if (!packageJson || !isAbsolute8(packageJson)) return void 0;
|
|
21451
|
+
const pkg = JSON.parse(await readFile10(packageJson, "utf8"));
|
|
21452
|
+
if (pkg.name !== "@motionharness/cli" || typeof pkg.bin?.mh !== "string") return void 0;
|
|
21453
|
+
const script = resolve10(dirname9(packageJson), pkg.bin.mh);
|
|
21454
|
+
if (!script.startsWith(dirname9(packageJson) + "/") || !(await stat6(script)).isFile()) return void 0;
|
|
21455
|
+
assert2(isAbsolute8(cliPath), "INSTALL_CONFLICT", "CLI \u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002");
|
|
21456
|
+
return { executable: process.execPath, script };
|
|
21457
|
+
}
|
|
21458
|
+
async function repairNativeConnection(options) {
|
|
21459
|
+
await finishNativeInstall(options.configRoot);
|
|
21460
|
+
const record2 = await readNativeFile(recordPath(options.configRoot));
|
|
21461
|
+
assert2(record2, "INSTALL_MISSING", "\u6865\u63A5\u5B89\u88C5\u8BB0\u5F55\u7F3A\u5931\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install\u3002");
|
|
21462
|
+
const manifest = JSON.parse(record2.bytes.toString("utf8"));
|
|
21463
|
+
assert2(manifest.nativeConfig, "INSTALL_MISSING", "\u6865\u63A5\u914D\u7F6E\u7F3A\u5931\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install\u3002");
|
|
21464
|
+
const config2 = await readNativeFile(manifest.nativeConfig);
|
|
21465
|
+
assert2(config2, "INSTALL_MISSING", "\u6865\u63A5\u914D\u7F6E\u7F3A\u5931\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install\u3002");
|
|
21466
|
+
const saved = manifest.files.find((file2) => file2.path === manifest.nativeConfig);
|
|
21467
|
+
assert2(
|
|
21468
|
+
saved?.sha256 === "sha256:" + config2.sha256 && (saved.mode === void 0 || saved.mode === config2.mode),
|
|
21469
|
+
"INSTALL_CONFLICT",
|
|
21470
|
+
"\u6865\u63A5\u914D\u7F6E\u5DF2\u88AB\u4FEE\u6539\uFF0C\u672A\u8986\u76D6\u3002\u8BF7\u68C0\u67E5\u914D\u7F6E\u540E\u91CD\u65B0\u5B89\u88C5\u7EC4\u4EF6\u3002"
|
|
21471
|
+
);
|
|
21472
|
+
const value = JSON.parse(config2.bytes.toString("utf8"));
|
|
21473
|
+
const launcher = await cliLauncher(options.cliPath);
|
|
21474
|
+
const tools = { ...value.tools, node: process.execPath };
|
|
21475
|
+
const toolDirectories = [...new Set(Object.values(tools).filter((path) => typeof path === "string" && isAbsolute8(path)).map(dirname9))];
|
|
21476
|
+
const bytes = JSON.stringify({ ...value, cliPath: options.cliPath, ...launcher ? { cliLauncher: launcher } : {}, tools, toolDirectories }, null, 2) + "\n";
|
|
21477
|
+
const toolchainPath = join8(options.configRoot, "toolchain.json");
|
|
21478
|
+
const toolchain = await readNativeFile(toolchainPath), savedTools = manifest.files.find((file2) => file2.path === toolchainPath);
|
|
21479
|
+
assert2(toolchain && savedTools?.sha256 === "sha256:" + toolchain.sha256 && (savedTools.mode === void 0 || savedTools.mode === toolchain.mode), "INSTALL_CONFLICT", "\u6865\u63A5\u5DE5\u5177\u914D\u7F6E\u5DF2\u88AB\u4FEE\u6539\uFF0C\u672A\u8986\u76D6\u3002");
|
|
21480
|
+
const changes = [
|
|
21481
|
+
{ path: manifest.nativeConfig, bytes, mode: config2.mode, expectedBefore: nativeFileState(config2) },
|
|
21482
|
+
{ path: toolchainPath, bytes: JSON.stringify({ schemaVersion: 1, tools, toolDirectories }, null, 2) + "\n", mode: toolchain.mode, expectedBefore: nativeFileState(toolchain) }
|
|
21483
|
+
];
|
|
21484
|
+
for (const change of changes) manifest.files = manifest.files.map((file2) => file2.path === change.path ? { ...file2, sha256: "sha256:" + sha256(change.bytes), mode: change.mode } : file2);
|
|
21485
|
+
changes.push({ path: recordPath(options.configRoot), bytes: JSON.stringify(manifest), mode: record2.mode, expectedBefore: nativeFileState(record2) });
|
|
21486
|
+
await publishNativeFiles(options.configRoot, changes);
|
|
21487
|
+
return { repaired: true, restartResolveRequired: false };
|
|
21488
|
+
}
|
|
21173
21489
|
async function bundleFiles(source, destination, executable) {
|
|
21174
21490
|
const files = [];
|
|
21175
21491
|
for (const item of await readdir2(source, { withFileTypes: true })) {
|
|
21176
|
-
const path =
|
|
21492
|
+
const path = join8(source, item.name), output = join8(destination, item.name);
|
|
21177
21493
|
assert2(!item.isSymbolicLink(), "INSTALL_CONFLICT", "\u539F\u751F\u5B89\u88C5\u8D44\u6E90\u4E0D\u80FD\u5305\u542B\u7B26\u53F7\u94FE\u63A5\u3002");
|
|
21178
21494
|
if (item.isDirectory()) files.push(...await bundleFiles(path, output, executable));
|
|
21179
21495
|
else {
|
|
21180
21496
|
assert2(item.isFile(), "INSTALL_CONFLICT", "\u539F\u751F\u5B89\u88C5\u8D44\u6E90\u53EA\u80FD\u5305\u542B\u666E\u901A\u6587\u4EF6\u3002");
|
|
21181
|
-
files.push({ path: output, bytes: await
|
|
21497
|
+
files.push({ path: output, bytes: await readFile10(path), mode: output === executable || (await stat6(path)).mode & 73 ? 493 : 420 });
|
|
21182
21498
|
}
|
|
21183
21499
|
}
|
|
21184
21500
|
return files;
|
|
@@ -21187,19 +21503,20 @@ async function installNative(options) {
|
|
|
21187
21503
|
assert2(!options.requireComplete || process.platform === "darwin", "PLATFORM_UNSUPPORTED", "\u5305\u542B\u83DC\u5355\u3001\u5C0F\u7A97\u53E3\u4E0E OFX \u7684\u6865\u63A5\u5B89\u88C5\u76EE\u524D\u53EA\u652F\u6301 macOS\u3002");
|
|
21188
21504
|
assert2(!options.requireComplete || process.getuid?.() !== 0, "INSTALL_AS_USER", "\u8BF7\u4EE5\u666E\u901A\u7528\u6237\u8FD0\u884C mh bridge davinci install\uFF1B\u9700\u8981\u7CFB\u7EDF\u6743\u9650\u65F6\u4F1A\u5355\u72EC\u8BF7\u6C42\u6388\u6743\u3002");
|
|
21189
21505
|
await finishNativeInstall(options.configRoot);
|
|
21190
|
-
const previousRecord = await
|
|
21506
|
+
const previousRecord = await readFile10(recordPath(options.configRoot)).catch((error48) => {
|
|
21191
21507
|
if (error48.code === "ENOENT") return null;
|
|
21192
21508
|
throw error48;
|
|
21193
21509
|
});
|
|
21194
21510
|
const old = previousRecord ? JSON.parse(previousRecord.toString("utf8")) : { version: 1, files: [], entry: { automaticAttachment: false, ofx: "unavailable" } };
|
|
21195
21511
|
const oldByPath = new Map(old.files.map((file2) => [file2.path, file2]));
|
|
21196
|
-
const expectedRecord = previousRecord ? { sha256: sha256(previousRecord), mode: (await
|
|
21512
|
+
const expectedRecord = previousRecord ? { sha256: sha256(previousRecord), mode: (await stat6(recordPath(options.configRoot))).mode & 511 } : null;
|
|
21197
21513
|
const validated = /* @__PURE__ */ new Map();
|
|
21198
|
-
const
|
|
21199
|
-
const
|
|
21200
|
-
const
|
|
21201
|
-
const
|
|
21202
|
-
const
|
|
21514
|
+
const locale = bridgeLocale(), label = bridgeName(locale);
|
|
21515
|
+
const scriptsRoot = process.env.MH_DAVINCI_SCRIPTS_DIR ?? (process.platform === "darwin" ? join8(homedir3(), "Library/Application Support/Blackmagic Design/DaVinci Resolve/Fusion/Scripts/Utility", label) : process.platform === "win32" ? join8(process.env.APPDATA ?? homedir3(), "Blackmagic Design/DaVinci Resolve/Support/Fusion/Scripts/Utility", label) : join8(homedir3(), ".local/share/DaVinciResolve/Fusion/Scripts/Utility", label));
|
|
21516
|
+
const nativeConfig = process.env.MH_DAVINCI_NATIVE_CONFIG ?? (process.platform === "darwin" ? join8(homedir3(), "Library/Application Support/Hotion Harness/bridge/davinci/native-entry.json") : join8(options.configRoot, "native-entry.json"));
|
|
21517
|
+
const template = await readFile10(join8(options.componentRoot, "resources/menu-entry.py"), "utf8");
|
|
21518
|
+
const helper = join8(options.componentRoot, "resources/HotionHarnessStatus");
|
|
21519
|
+
const application = join8(options.componentRoot, "resources", statusAppName);
|
|
21203
21520
|
const resourceInfo = async (path) => process.platform === "darwin" ? lstat5(path).catch((error48) => {
|
|
21204
21521
|
if (error48.code === "ENOENT") return null;
|
|
21205
21522
|
throw error48;
|
|
@@ -21208,63 +21525,69 @@ async function installNative(options) {
|
|
|
21208
21525
|
assert2(!applicationInfo || applicationInfo.isDirectory(), "INSTALL_CONFLICT", "\u72B6\u6001\u7A97\u53E3\u5E94\u7528\u5FC5\u987B\u662F\u666E\u901A\u76EE\u5F55\u3002");
|
|
21209
21526
|
const helperInfo = applicationInfo ? null : await resourceInfo(helper);
|
|
21210
21527
|
assert2(!helperInfo || helperInfo.isFile(), "INSTALL_CONFLICT", "\u72B6\u6001\u7A97\u53E3\u8D44\u6E90\u5FC5\u987B\u662F\u666E\u901A\u53EF\u6267\u884C\u6587\u4EF6\u3002");
|
|
21211
|
-
const statusExecutable = applicationInfo ?
|
|
21528
|
+
const statusExecutable = applicationInfo ? join8(options.configRoot, "bin", statusAppName, statusAppBinary) : helperInfo ? join8(options.configRoot, "bin/HotionHarnessStatus") : void 0;
|
|
21212
21529
|
const tools = {
|
|
21213
21530
|
node: process.execPath,
|
|
21214
21531
|
pnpm: await toolPath(process.platform === "win32" ? "pnpm.cmd" : "pnpm"),
|
|
21215
21532
|
ffmpeg: await toolPath(process.env.MH_FFMPEG ?? "ffmpeg"),
|
|
21216
21533
|
ffprobe: await toolPath(process.env.MH_FFPROBE ?? "ffprobe")
|
|
21217
21534
|
};
|
|
21218
|
-
const toolDirectories = [...new Set(Object.values(tools).filter((path) => Boolean(path)).map(
|
|
21535
|
+
const toolDirectories = [...new Set(Object.values(tools).filter((path) => Boolean(path)).map(dirname9))];
|
|
21219
21536
|
const toolchain = { schemaVersion: 1, tools, toolDirectories };
|
|
21220
21537
|
const desired = [];
|
|
21221
|
-
const
|
|
21222
|
-
|
|
21223
|
-
const
|
|
21538
|
+
const translationsPath = join8(options.configRoot, "i18n/en.json");
|
|
21539
|
+
desired.push({ path: translationsPath, bytes: JSON.stringify(bridgeEnglishCatalog), mode: 420 });
|
|
21540
|
+
const guideNames = ["index.html", "en.html"];
|
|
21541
|
+
const guideDirectory = join8(options.componentRoot, "resources/sidebar-help");
|
|
21542
|
+
const guideAvailable = (await Promise.all(guideNames.map((name) => lstat5(join8(guideDirectory, name)).then((info) => info.isFile(), (error48) => {
|
|
21224
21543
|
if (error48.code === "ENOENT") return false;
|
|
21225
21544
|
throw error48;
|
|
21226
21545
|
})))).every(Boolean);
|
|
21227
|
-
const sidebarGuidePath = guideAvailable ?
|
|
21546
|
+
const sidebarGuidePath = guideAvailable ? join8(options.configRoot, "help/sidebar", locale === "en" ? "en.html" : "index.html") : void 0;
|
|
21228
21547
|
if (guideAvailable) for (const name of guideNames) desired.push({
|
|
21229
|
-
path:
|
|
21230
|
-
bytes: await
|
|
21548
|
+
path: join8(options.configRoot, "help/sidebar", name),
|
|
21549
|
+
bytes: await readSidebarGuideDocument(join8(guideDirectory, name)),
|
|
21231
21550
|
mode: 420
|
|
21232
21551
|
});
|
|
21233
21552
|
if (applicationInfo) {
|
|
21234
|
-
desired.push(...await bundleFiles(application,
|
|
21553
|
+
desired.push(...await bundleFiles(application, join8(options.configRoot, "bin", statusAppName), statusExecutable));
|
|
21235
21554
|
assert2(
|
|
21236
|
-
desired.some((file2) => file2.path === statusExecutable) && desired.some((file2) => file2.path ===
|
|
21555
|
+
desired.some((file2) => file2.path === statusExecutable) && desired.some((file2) => file2.path === join8(options.configRoot, "bin", statusAppName, "Contents/Info.plist")),
|
|
21237
21556
|
"INSTALL_CONFLICT",
|
|
21238
21557
|
"\u72B6\u6001\u7A97\u53E3\u5E94\u7528\u7F3A\u5C11\u53EF\u6267\u884C\u6587\u4EF6\u6216 Info.plist\u3002"
|
|
21239
21558
|
);
|
|
21240
|
-
} else if (statusExecutable) desired.push({ path: statusExecutable, bytes: await
|
|
21241
|
-
desired.push({ path:
|
|
21559
|
+
} else if (statusExecutable) desired.push({ path: statusExecutable, bytes: await readFile10(helper), mode: 493 });
|
|
21560
|
+
desired.push({ path: join8(options.configRoot, "toolchain.json"), bytes: JSON.stringify(toolchain, null, 2) + "\n", mode: 384 });
|
|
21561
|
+
const launcher = await cliLauncher(options.cliPath);
|
|
21242
21562
|
desired.push({ path: nativeConfig, bytes: JSON.stringify({
|
|
21243
21563
|
schemaVersion: 1,
|
|
21244
21564
|
ofxSourceProtocol: 1,
|
|
21245
21565
|
ofxManagementProtocol: 1,
|
|
21246
21566
|
ofxSelectionReviewProtocol: 1,
|
|
21247
21567
|
cliPath: options.cliPath,
|
|
21568
|
+
...launcher ? { cliLauncher: launcher } : {},
|
|
21248
21569
|
workspace: options.workspace,
|
|
21249
|
-
bridgeDirectory:
|
|
21570
|
+
bridgeDirectory: dirname9(options.configRoot),
|
|
21250
21571
|
tools,
|
|
21251
21572
|
toolDirectories,
|
|
21573
|
+
locale,
|
|
21574
|
+
translationsPath,
|
|
21252
21575
|
...sidebarGuidePath ? { sidebarGuidePath } : {},
|
|
21253
21576
|
...statusExecutable ? { statusExecutable } : {}
|
|
21254
21577
|
}, null, 2) + "\n", mode: 384 });
|
|
21255
|
-
for (const [
|
|
21256
|
-
desired.push({ path:
|
|
21578
|
+
for (const [label2, action2] of statusExecutable ? [["\u7F16\u8F91\u5DE5\u7A0B", "edit"], ["\u66F4\u65B0\u5230\u8FBE\u82AC\u5947", "update"]] : []) {
|
|
21579
|
+
desired.push({ path: join8(scriptsRoot, `${bridgeText(label2, locale)}.py`), bytes: template.replaceAll("__HOTION_ACTION_JSON__", JSON.stringify(action2)).replaceAll("__HOTION_CONFIG_PATH_JSON__", JSON.stringify(nativeConfig)).replaceAll("__HOTION_STATUS_PATH_JSON__", JSON.stringify(statusExecutable)), mode: 384 });
|
|
21257
21580
|
}
|
|
21258
21581
|
const registeredForwarder = await prepareRegisteredForwarder(options, old, statusExecutable, nativeConfig);
|
|
21259
21582
|
if (registeredForwarder) desired.push(registeredForwarder.file);
|
|
21260
|
-
const bundle =
|
|
21583
|
+
const bundle = join8(options.componentRoot, "resources", "HotionHarness.ofx.bundle");
|
|
21261
21584
|
const bundleInfo = process.platform === "darwin" ? await lstat5(bundle).catch((error48) => {
|
|
21262
21585
|
if (error48.code === "ENOENT") return null;
|
|
21263
21586
|
throw error48;
|
|
21264
21587
|
}) : null;
|
|
21265
21588
|
assert2(!bundleInfo || bundleInfo.isDirectory(), "INSTALL_CONFLICT", "OFX \u5B89\u88C5\u8D44\u6E90\u5FC5\u987B\u662F\u666E\u901A\u76EE\u5F55\u3002");
|
|
21266
21589
|
const pluginRoot = process.env.MH_DAVINCI_OFX_DIR ?? (process.platform === "darwin" ? "/Library/OFX/Plugins" : void 0);
|
|
21267
|
-
const pluginFiles = bundleInfo && pluginRoot ? await bundleFiles(bundle,
|
|
21590
|
+
const pluginFiles = bundleInfo && pluginRoot ? await bundleFiles(bundle, join8(pluginRoot, "HotionHarness.ofx.bundle")) : [];
|
|
21268
21591
|
if (options.requireComplete) {
|
|
21269
21592
|
assert2(
|
|
21270
21593
|
applicationInfo && pluginFiles.some((file2) => file2.path.endsWith("/Contents/MacOS/HotionHarness.ofx")) && pluginFiles.some((file2) => file2.path.endsWith("/Contents/Info.plist")),
|
|
@@ -21291,12 +21614,12 @@ async function installNative(options) {
|
|
|
21291
21614
|
const recorded = oldByPath.get(file2.path), expected = "sha256:" + sha256(file2.bytes);
|
|
21292
21615
|
assert2(existing === recorded?.sha256 || existing === expected, "INSTALL_CONFLICT", "\u5B89\u88C5\u8DEF\u5F84\u5305\u542B\u975E\u672C\u7EC4\u4EF6\u6587\u4EF6\u6216\u7528\u6237\u4FEE\u6539\uFF0C\u672A\u8986\u76D6\u3002", { path: file2.path });
|
|
21293
21616
|
if (process.platform !== "win32" && recorded?.mode !== void 0) assert2(
|
|
21294
|
-
((await
|
|
21617
|
+
((await stat6(file2.path)).mode & 511) === recorded.mode,
|
|
21295
21618
|
"INSTALL_CONFLICT",
|
|
21296
21619
|
"\u7528\u6237\u4FEE\u6539\u4E86\u5B89\u88C5\u6587\u4EF6\u6743\u9650\uFF0C\u672A\u8986\u76D6\u3002",
|
|
21297
21620
|
{ path: file2.path }
|
|
21298
21621
|
);
|
|
21299
|
-
validated.set(file2.path, { sha256: existing.slice("sha256:".length), mode: (await
|
|
21622
|
+
validated.set(file2.path, { sha256: existing.slice("sha256:".length), mode: (await stat6(file2.path)).mode & 511 });
|
|
21300
21623
|
}
|
|
21301
21624
|
};
|
|
21302
21625
|
await validate(desired);
|
|
@@ -21306,7 +21629,7 @@ async function installNative(options) {
|
|
|
21306
21629
|
} catch (error48) {
|
|
21307
21630
|
if (!["EACCES", "EPERM"].includes(error48.code ?? "")) throw error48;
|
|
21308
21631
|
}
|
|
21309
|
-
await prepareOfxPermissions(options.componentRoot, pluginRoot, pluginFiles.map((file2) =>
|
|
21632
|
+
await prepareOfxPermissions(options.componentRoot, pluginRoot, pluginFiles.map((file2) => dirname9(file2.path)));
|
|
21310
21633
|
}
|
|
21311
21634
|
let pluginAccessible = true;
|
|
21312
21635
|
try {
|
|
@@ -21335,11 +21658,11 @@ async function installNative(options) {
|
|
|
21335
21658
|
owned.delete(file2.path);
|
|
21336
21659
|
continue;
|
|
21337
21660
|
}
|
|
21338
|
-
if (actual !== file2.sha256 || process.platform !== "win32" && file2.mode !== void 0 && ((await
|
|
21661
|
+
if (actual !== file2.sha256 || process.platform !== "win32" && file2.mode !== void 0 && ((await stat6(file2.path)).mode & 511) !== file2.mode) {
|
|
21339
21662
|
retained.push(file2.path);
|
|
21340
21663
|
continue;
|
|
21341
21664
|
}
|
|
21342
|
-
changes.push({ path: file2.path, bytes: null, expectedBefore: { sha256: actual.slice("sha256:".length), mode: (await
|
|
21665
|
+
changes.push({ path: file2.path, bytes: null, expectedBefore: { sha256: actual.slice("sha256:".length), mode: (await stat6(file2.path)).mode & 511 } });
|
|
21343
21666
|
owned.delete(file2.path);
|
|
21344
21667
|
removed.push(file2.path);
|
|
21345
21668
|
}
|
|
@@ -21360,12 +21683,19 @@ async function installNative(options) {
|
|
|
21360
21683
|
if (options.requireComplete) throw error48;
|
|
21361
21684
|
const failure = error48;
|
|
21362
21685
|
const within = (child, parent) => child === parent || child.startsWith(parent + "/");
|
|
21363
|
-
const failedPath = typeof failure.path === "string" ?
|
|
21364
|
-
const pluginPath = pluginRoot ?
|
|
21365
|
-
const optionalPath = failedPath && pluginPath && (within(failedPath, pluginPath) || within(pluginPath, failedPath) && !desired.some((file2) => within(
|
|
21686
|
+
const failedPath = typeof failure.path === "string" ? resolve10(failure.path) : void 0;
|
|
21687
|
+
const pluginPath = pluginRoot ? resolve10(pluginRoot) : void 0;
|
|
21688
|
+
const optionalPath = failedPath && pluginPath && (within(failedPath, pluginPath) || within(pluginPath, failedPath) && !desired.some((file2) => within(resolve10(file2.path), failedPath)));
|
|
21366
21689
|
if (!pluginAccessible || !["EACCES", "EPERM", "EROFS"].includes(failure.code ?? "") || !optionalPath) throw error48;
|
|
21367
21690
|
await apply(false);
|
|
21368
21691
|
}
|
|
21692
|
+
const retiredGroups = ["Hotion Harness", "Motion Harness", "Motion Harness \u6865\u63A5\u7EC4\u4EF6", "Motion Harness Bridge Component", "MotionHarness", "MotionHarness \u6865\u63A5\u7EC4\u4EF6", "MotionHarness Bridge Component"];
|
|
21693
|
+
for (const directory of new Set(removed.map(dirname9))) {
|
|
21694
|
+
if (directory === scriptsRoot || !retiredGroups.includes(basename4(directory)) || basename4(dirname9(directory)) !== "Utility") continue;
|
|
21695
|
+
await rmdir(directory).catch((error48) => {
|
|
21696
|
+
if (!["ENOENT", "ENOTEMPTY", "EEXIST", "EACCES", "EPERM"].includes(error48.code)) throw error48;
|
|
21697
|
+
});
|
|
21698
|
+
}
|
|
21369
21699
|
return {
|
|
21370
21700
|
installed: true,
|
|
21371
21701
|
complete: Boolean(statusExecutable && pluginFiles.length && entry.ofx === "manual-attachment"),
|
|
@@ -21387,7 +21717,7 @@ async function uninstallNative({ configRoot }) {
|
|
|
21387
21717
|
throw error48;
|
|
21388
21718
|
});
|
|
21389
21719
|
if (!actual) continue;
|
|
21390
|
-
if (actual !== file2.sha256 || process.platform !== "win32" && file2.mode !== void 0 && ((await
|
|
21720
|
+
if (actual !== file2.sha256 || process.platform !== "win32" && file2.mode !== void 0 && ((await stat6(file2.path)).mode & 511) !== file2.mode) {
|
|
21391
21721
|
retained.push(file2);
|
|
21392
21722
|
continue;
|
|
21393
21723
|
}
|
|
@@ -21398,42 +21728,17 @@ async function uninstallNative({ configRoot }) {
|
|
|
21398
21728
|
return { installed: false, removed, retained: retained.map((file2) => file2.path), associationsPreserved: true, legacyForwarder };
|
|
21399
21729
|
}
|
|
21400
21730
|
|
|
21401
|
-
// src/sidebar-guide.ts
|
|
21402
|
-
import { readFile as readFile10 } from "node:fs/promises";
|
|
21403
|
-
import { join as join8 } from "node:path";
|
|
21404
|
-
var sidebarHint = {
|
|
21405
|
-
optional: true,
|
|
21406
|
-
title: "\u6DFB\u52A0\u4FA7\u680F\u7F16\u8F91\u5165\u53E3\uFF08\u53EF\u9009\uFF09",
|
|
21407
|
-
message: "\u7D20\u6750\u5DF2\u53D1\u9001\u5E76\u5173\u8054\u5DE5\u7A0B\u3002\u60F3\u4ECE\u8FBE\u82AC\u5947\u4FA7\u680F\u76F4\u63A5\u7F16\u8F91\uFF0C\u53EF\u6DFB\u52A0 Hotion Harness \u6548\u679C\u3002",
|
|
21408
|
-
steps: [
|
|
21409
|
-
"\u5728\u8FBE\u82AC\u5947\u300C\u526A\u8F91\u300D\u9875\u6253\u5F00\u5DE6\u4E0A\u89D2\u300C\u7279\u6548\u5E93\u300D\uFF08\u9B54\u68D2\u56FE\u6807\uFF09\u3002",
|
|
21410
|
-
"\u70B9\u51FB\u653E\u5927\u955C\uFF0C\u641C\u7D22 Hotion Harness\uFF0C\u5C06 Open FX \u4E2D\u7684\u540C\u540D\u6548\u679C\u62D6\u5230\u76EE\u6807\u52A8\u6548\u7247\u6BB5\u3002",
|
|
21411
|
-
"\u9009\u4E2D\u7247\u6BB5\uFF0C\u5728\u300C\u68C0\u67E5\u5668 \u2192 \u7279\u6548 \u2192 Open FX\u300D\u4E2D\u70B9\u51FB\u300C\u7F16\u8F91 Hotion Harness \u5DE5\u7A0B\u300D\u3002"
|
|
21412
|
-
],
|
|
21413
|
-
shortcut: "\u4E5F\u53EF\u5148\u9009\u4E2D\u7247\u6BB5\uFF0C\u6309 Shift + Space \u641C\u7D22\u5E76\u6DFB\u52A0\u3002",
|
|
21414
|
-
alternative: "\u4E0D\u6DFB\u52A0\u4E5F\u80FD\u4ECE\u300C\u5DE5\u4F5C\u533A \u2192 \u811A\u672C \u2192 Utility \u2192 Hotion Harness \u2192 \u7F16\u8F91\u5DE5\u7A0B\u300D\u6253\u5F00\u3002",
|
|
21415
|
-
guideCommand: "mh bridge davinci sidebar-guide"
|
|
21416
|
-
};
|
|
21417
|
-
async function readSidebarGuide(componentRoot, inline = false) {
|
|
21418
|
-
const directory = join8(componentRoot, "resources/sidebar-help");
|
|
21419
|
-
const guidePath = join8(directory, "index.html"), screenshotPath = join8(directory, "resolve-sidebar.png");
|
|
21420
|
-
if (!inline) return { ...sidebarHint, guidePath, screenshotPath };
|
|
21421
|
-
const html = await readFile10(guidePath, "utf8");
|
|
21422
|
-
const image = (await readFile10(screenshotPath)).toString("base64");
|
|
21423
|
-
return { ...sidebarHint, html: html.replaceAll('src="resolve-sidebar.png"', `src="data:image/png;base64,${image}"`) };
|
|
21424
|
-
}
|
|
21425
|
-
|
|
21426
21731
|
// src/runner.ts
|
|
21427
21732
|
var taskView = (job) => ({
|
|
21428
21733
|
...job,
|
|
21429
21734
|
taskId: job.id,
|
|
21430
21735
|
message: job.error?.message ?? job.progress.stage,
|
|
21431
|
-
...job.operation === "send" && job.phase === "completed" && job.results.some((result2) => result2.applied === true && result2.bindingId) ? { sidebarHint } : {}
|
|
21736
|
+
...job.operation === "send" && job.phase === "completed" && job.results.some((result2) => result2.applied === true && result2.bindingId) ? { sidebarHint: sidebarHintForLocale() } : {}
|
|
21432
21737
|
});
|
|
21433
21738
|
var jobOperations = { send: "send", update: "update", insert: "insert", render: "render", adopt: "adopt", apply: "apply", restore: "restore", duplicate: "duplicate", sync: "sync", "legacy-convert": "legacy-convert" };
|
|
21434
21739
|
function assertJobScope(bridge, catalog, job, projectPath, readOnly = false) {
|
|
21435
21740
|
if (!projectPath) return;
|
|
21436
|
-
const path =
|
|
21741
|
+
const path = resolve11(projectPath);
|
|
21437
21742
|
const sourceIds = new Set(Object.values(catalog.sources).filter((source) => bridge.store.path(source.locator) === path).map((source) => source.id));
|
|
21438
21743
|
const bindingIds = new Set(Object.values(catalog.bindings).filter((binding) => sourceIds.has(binding.sourceId)).map((binding) => binding.id));
|
|
21439
21744
|
const targets = Array.isArray(job.request.targets) ? job.request.targets : [];
|
|
@@ -21503,14 +21808,14 @@ async function launchWorker(bridge, taskId, request) {
|
|
|
21503
21808
|
shell: false,
|
|
21504
21809
|
env: process.env
|
|
21505
21810
|
});
|
|
21506
|
-
const cleaned = child.exitCode !== null || child.signalCode !== null ? Promise.resolve(child.signalCode === null) : new Promise((
|
|
21507
|
-
child.once("exit", (_code, signal) =>
|
|
21508
|
-
child.once("error", () =>
|
|
21811
|
+
const cleaned = child.exitCode !== null || child.signalCode !== null ? Promise.resolve(child.signalCode === null) : new Promise((resolve12) => {
|
|
21812
|
+
child.once("exit", (_code, signal) => resolve12(signal === null));
|
|
21813
|
+
child.once("error", () => resolve12(child.pid === void 0));
|
|
21509
21814
|
});
|
|
21510
21815
|
const readiness = child.stdio[4];
|
|
21511
21816
|
try {
|
|
21512
21817
|
assert2(readiness, "WORKER_LEASE_REQUIRED", "\u540E\u53F0\u76D1\u7763\u8FDB\u7A0B\u7F3A\u5C11\u542F\u52A8\u786E\u8BA4\u901A\u9053\u3002");
|
|
21513
|
-
await new Promise((
|
|
21818
|
+
await new Promise((resolve12, reject) => {
|
|
21514
21819
|
let text = "", settled = false;
|
|
21515
21820
|
const finish = (error48) => {
|
|
21516
21821
|
if (settled) return;
|
|
@@ -21521,7 +21826,7 @@ async function launchWorker(bridge, taskId, request) {
|
|
|
21521
21826
|
readiness.off("end", ended);
|
|
21522
21827
|
readiness.off("error", failed);
|
|
21523
21828
|
if (error48) reject(error48);
|
|
21524
|
-
else
|
|
21829
|
+
else resolve12();
|
|
21525
21830
|
};
|
|
21526
21831
|
const failed = (error48) => finish(error48);
|
|
21527
21832
|
const ended = () => finish(new BridgeError("WORKER_START_FAILED", "\u540E\u53F0 worker \u672A\u786E\u8BA4\u9886\u53D6\u4EFB\u52A1\uFF1B\u8BF7\u67E5\u8BE2\u539F taskId\uFF0C\u672A\u91CD\u590D\u521B\u5EFA\u4EFB\u52A1\u3002"));
|
|
@@ -21546,8 +21851,8 @@ async function launchWorker(bridge, taskId, request) {
|
|
|
21546
21851
|
} catch (error48) {
|
|
21547
21852
|
if (child.exitCode === null && child.signalCode === null) child.kill("SIGTERM");
|
|
21548
21853
|
let cleanupTimer;
|
|
21549
|
-
const cleanupObserved = await Promise.race([cleaned, new Promise((
|
|
21550
|
-
cleanupTimer = setTimeout(() =>
|
|
21854
|
+
const cleanupObserved = await Promise.race([cleaned, new Promise((resolve12) => {
|
|
21855
|
+
cleanupTimer = setTimeout(() => resolve12(false), 3e3);
|
|
21551
21856
|
})]);
|
|
21552
21857
|
clearTimeout(cleanupTimer);
|
|
21553
21858
|
if (cleanupObserved) await recordWorkerStartFailure(bridge, taskId, error48);
|
|
@@ -21589,7 +21894,7 @@ async function execute(request) {
|
|
|
21589
21894
|
}
|
|
21590
21895
|
if (requestedOperation === "send") {
|
|
21591
21896
|
payload2.projectPath ??= request.projectPath;
|
|
21592
|
-
if (typeof payload2.projectPath === "string") payload2.projectPath =
|
|
21897
|
+
if (typeof payload2.projectPath === "string") payload2.projectPath = resolve11(payload2.projectPath);
|
|
21593
21898
|
}
|
|
21594
21899
|
if (requestedOperation === "update" && !payload2.bindingId) payload2.bindingId = catalog.jobs[String(receipt.result.taskId)]?.request.bindingId;
|
|
21595
21900
|
return replayTask(bridge, request, catalog, requestedOperation, payload2, selectionHash);
|
|
@@ -21648,9 +21953,9 @@ async function execute(request) {
|
|
|
21648
21953
|
if (selection.expectedMediaFingerprint) assert2(
|
|
21649
21954
|
(await bridge.host.media(selection.scope, selection.mediaPoolItemId)).fingerprint === selection.expectedMediaFingerprint,
|
|
21650
21955
|
"VERSION_CONFLICT",
|
|
21651
|
-
"\u786E\u8BA4\u540E\u7684\u7D20\u6750\
|
|
21956
|
+
"\u786E\u8BA4\u540E\u7684\u539F\u7D20\u6750\u8EAB\u4EFD\u6216\u5173\u8054\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6838\u5BF9\u3002"
|
|
21652
21957
|
);
|
|
21653
|
-
if (selection.expectedTimelineFingerprint) {
|
|
21958
|
+
if (request.operation === "duplicate" && selection.expectedTimelineFingerprint) {
|
|
21654
21959
|
assert2(selection.timelineId, "INVALID_REQUEST", "\u65F6\u95F4\u7EBF\u6307\u7EB9\u7F3A\u5C11\u5BF9\u5E94\u5B9E\u4F8B\u3002");
|
|
21655
21960
|
assert2(
|
|
21656
21961
|
(await bridge.host.timeline(selection.scope, selection.timelineId)).fingerprint === selection.expectedTimelineFingerprint,
|
|
@@ -21674,7 +21979,7 @@ async function execute(request) {
|
|
|
21674
21979
|
assert2(await realpath6(bridge.store.path(catalog.sources[binding.sourceId].locator)) === requestedProject, "VERSION_CONFLICT", "\u5173\u8054\u4E0D\u5C5E\u4E8E\u5F53\u524D Studio \u5DE5\u7A0B\u3002");
|
|
21675
21980
|
}
|
|
21676
21981
|
if (request.operation === "install-complete") return finishNativeInstall(request.configRoot);
|
|
21677
|
-
if (request.operation === "sidebar-guide") return readSidebarGuide(request.componentRoot, input.inline === true);
|
|
21982
|
+
if (request.operation === "sidebar-guide") return readSidebarGuide(request.componentRoot, input.inline === true, bridgeLocale(input.locale));
|
|
21678
21983
|
if (request.operation === "install") {
|
|
21679
21984
|
assert2(!Object.values((await bridge.store.read()).jobs).some((job) => !terminalPhases.includes(job.phase)), "TASK_BUSY", "\u6865\u63A5\u4ECD\u6709\u4EFB\u52A1\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5B8C\u6210\u6216\u53D6\u6D88\u540E\u4FEE\u590D\u5B89\u88C5\u3002");
|
|
21680
21985
|
return installNative({ cliPath: request.cliPath, componentRoot: request.componentRoot, configRoot: request.configRoot, workspace: request.workspace, requireComplete: true, activationToken: typeof input.activationToken === "string" ? input.activationToken : void 0 });
|
|
@@ -21689,10 +21994,17 @@ async function execute(request) {
|
|
|
21689
21994
|
assert2(Object.hasOwn(schemas, name), "INVALID_REQUEST", "\u672A\u77E5\u4FEE\u6539\u64CD\u4F5C\u3002", { operations: Object.keys(schemas) });
|
|
21690
21995
|
return { operation: name, cli: `mh bridge davinci ${name.startsWith("legacy-retire-") ? name.replaceAll("-", " ") : name.replace(/^(legacy|entry|action)-/, "$1 ")} --json <JSON>`, requestSchema: external_exports.toJSONSchema(schemas[name], { io: "input" }) };
|
|
21691
21996
|
}
|
|
21692
|
-
if (request.operation === "doctor")
|
|
21997
|
+
if (request.operation === "doctor") {
|
|
21998
|
+
if (input.repairConnection === true) {
|
|
21999
|
+
const connection = await repairNativeConnection(request);
|
|
22000
|
+
const native = await bridge.host.call("connection");
|
|
22001
|
+
return { ...connection, ...native };
|
|
22002
|
+
}
|
|
22003
|
+
return bridge.capabilities();
|
|
22004
|
+
}
|
|
21693
22005
|
if (request.operation === "status") {
|
|
21694
22006
|
const catalog = await bridge.store.read();
|
|
21695
|
-
const projectPath = request.projectPath ? await realpath6(request.projectPath).catch(() =>
|
|
22007
|
+
const projectPath = request.projectPath ? await realpath6(request.projectPath).catch(() => resolve11(request.projectPath)) : void 0;
|
|
21696
22008
|
const sources = Object.values(catalog.sources).filter((source) => !projectPath || bridge.store.path(source.locator) === projectPath);
|
|
21697
22009
|
const sourceIds = new Set(sources.map((source) => source.id));
|
|
21698
22010
|
const bindings = Object.values(catalog.bindings).filter((binding) => sourceIds.has(binding.sourceId)).map((binding) => {
|
|
@@ -21711,7 +22023,7 @@ async function execute(request) {
|
|
|
21711
22023
|
state: binding.state,
|
|
21712
22024
|
name,
|
|
21713
22025
|
outputSpec: spec,
|
|
21714
|
-
lastKnownUsageCount: binding.lastReadback?.uses.length
|
|
22026
|
+
lastKnownUsageCount: binding.lastReadback?.usageScanComplete ? binding.lastReadback.uses.length : null
|
|
21715
22027
|
};
|
|
21716
22028
|
});
|
|
21717
22029
|
const tasks = Object.values(catalog.jobs).filter((job) => {
|
|
@@ -21809,18 +22121,18 @@ async function execute(request) {
|
|
|
21809
22121
|
const key = digest(sourceId).slice(7), marker = bridge.store.path(`.scratch/editor-${key}.json`);
|
|
21810
22122
|
return bridge.store.withLock(`editor-${key}`, async () => {
|
|
21811
22123
|
if (bindingId) {
|
|
21812
|
-
await mkdir9(
|
|
22124
|
+
await mkdir9(dirname10(marker), { recursive: true });
|
|
21813
22125
|
await writeFile2(bridge.store.path(`.scratch/edit-context-${key}.json`), JSON.stringify({ bindingId, nonce: randomUUID8(), at: Date.now() }), { mode: 384 });
|
|
21814
22126
|
}
|
|
21815
22127
|
const previous2 = await readFile11(marker, "utf8").then(JSON.parse).catch(() => null);
|
|
21816
22128
|
if (previous2?.at && Date.now() - previous2.at < 1500) return { opened: true, reused: true, sourceId };
|
|
21817
22129
|
await bridge.openStudio(sourceId);
|
|
21818
|
-
await mkdir9(
|
|
22130
|
+
await mkdir9(dirname10(marker), { recursive: true });
|
|
21819
22131
|
await writeFile2(marker, JSON.stringify({ at: Date.now() }), { mode: 384 });
|
|
21820
22132
|
return { opened: true, sourceId };
|
|
21821
22133
|
});
|
|
21822
22134
|
}
|
|
21823
|
-
if (request.operation === "entry-restore") throw new BridgeError("CAPABILITY_UNAVAILABLE", "\u8FBE\u82AC\u5947\u516C\u5F00\u63A5\u53E3\u5C1A\u4E0D\u652F\u6301\u81EA\u52A8\u91CD\u65B0\u9644\u52A0\u4FA7\u680F\u5165\u53E3\u3002\u5DE5\u7A0B\u5173\u8054\u4ECD\u4FDD\u7559\uFF0C\u53EF\u4ECE\u300C\u5DE5\u4F5C\u533A \u2192 \u811A\u672C \u2192 Utility \u2192
|
|
22135
|
+
if (request.operation === "entry-restore") throw new BridgeError("CAPABILITY_UNAVAILABLE", "\u8FBE\u82AC\u5947\u516C\u5F00\u63A5\u53E3\u5C1A\u4E0D\u652F\u6301\u81EA\u52A8\u91CD\u65B0\u9644\u52A0\u4FA7\u680F\u5165\u53E3\u3002\u5DE5\u7A0B\u5173\u8054\u4ECD\u4FDD\u7559\uFF0C\u53EF\u4ECE\u300C\u5DE5\u4F5C\u533A \u2192 \u811A\u672C \u2192 Utility \u2192 MotionHarness \u6865\u63A5\u7EC4\u4EF6\u300D\u7F16\u8F91\u6216\u66F4\u65B0\u3002", "entry", false, { automaticAttachment: false }, "\u4F7F\u7528\u56FA\u5B9A\u811A\u672C\u83DC\u5355\u7EE7\u7EED\u7F16\u8F91\u3002\u5B9E\u9A8C\u4FA7\u680F\u53EA\u53EF\u5728\u5BBF\u4E3B\u63D0\u4F9B\u6709\u6548\u6E90\u8DEF\u5F84\u5E76\u5B8C\u6210\u4E25\u683C\u8EAB\u4EFD\u6838\u5BF9\u65F6\u5904\u7406\u8BF7\u6C42\uFF0C\u81EA\u52A8\u9644\u52A0\u4ECD\u672A\u5F00\u653E\u3002");
|
|
21824
22136
|
if (request.operation === "relink") return bridge.relink(input);
|
|
21825
22137
|
if (request.operation === "recover") {
|
|
21826
22138
|
const checked = reconcileSchema.parse(input);
|
|
@@ -21839,7 +22151,7 @@ async function execute(request) {
|
|
|
21839
22151
|
const payload = { ...input };
|
|
21840
22152
|
if (operation === "send") {
|
|
21841
22153
|
payload.projectPath ??= request.projectPath;
|
|
21842
|
-
if (typeof payload.projectPath === "string") payload.projectPath =
|
|
22154
|
+
if (typeof payload.projectPath === "string") payload.projectPath = resolve11(payload.projectPath);
|
|
21843
22155
|
}
|
|
21844
22156
|
if (operation === "update" && !payload.bindingId) {
|
|
21845
22157
|
const selected = await bridge.selectedSource();
|
|
@@ -21864,7 +22176,7 @@ async function execute(request) {
|
|
|
21864
22176
|
...Array.isArray(value.targets) ? value.targets.map((target) => catalog.bindings[target.bindingId]?.sourceId) : []
|
|
21865
22177
|
].filter((value2) => Boolean(value2)));
|
|
21866
22178
|
return /* @__PURE__ */ new Set([
|
|
21867
|
-
...typeof value.projectPath === "string" ? [
|
|
22179
|
+
...typeof value.projectPath === "string" ? [resolve11(value.projectPath)] : [],
|
|
21868
22180
|
...[...sourceIds].map((sourceId) => catalog.sources[sourceId] ? bridge.store.path(catalog.sources[sourceId].locator) : `source:${sourceId}`)
|
|
21869
22181
|
]);
|
|
21870
22182
|
};
|
|
@@ -21917,14 +22229,14 @@ function assertMigrationReady(blockers, old) {
|
|
|
21917
22229
|
);
|
|
21918
22230
|
}
|
|
21919
22231
|
async function proposedWorkspaceRoot(path) {
|
|
21920
|
-
let existing =
|
|
22232
|
+
let existing = resolve11(path);
|
|
21921
22233
|
const suffix = [];
|
|
21922
22234
|
for (; ; ) {
|
|
21923
22235
|
try {
|
|
21924
|
-
return
|
|
22236
|
+
return resolve11(await realpath6(existing), ...suffix);
|
|
21925
22237
|
} catch (error48) {
|
|
21926
22238
|
if (error48.code !== "ENOENT") throw error48;
|
|
21927
|
-
const parent =
|
|
22239
|
+
const parent = dirname10(existing);
|
|
21928
22240
|
if (parent === existing) throw error48;
|
|
21929
22241
|
suffix.unshift(basename5(existing));
|
|
21930
22242
|
existing = parent;
|
|
@@ -21932,7 +22244,7 @@ async function proposedWorkspaceRoot(path) {
|
|
|
21932
22244
|
}
|
|
21933
22245
|
}
|
|
21934
22246
|
function assertSeparateMigrationRoots(oldRoot, targetRoot) {
|
|
21935
|
-
const prefix = (root) => root.endsWith(
|
|
22247
|
+
const prefix = (root) => root.endsWith(sep2) ? root : root + sep2;
|
|
21936
22248
|
assert2(
|
|
21937
22249
|
targetRoot !== oldRoot && !targetRoot.startsWith(prefix(oldRoot)) && !oldRoot.startsWith(prefix(targetRoot)),
|
|
21938
22250
|
"INVALID_REQUEST",
|
|
@@ -21970,7 +22282,7 @@ async function withLegacyMigrationLocks(old, action2) {
|
|
|
21970
22282
|
function legacyMcpGate() {
|
|
21971
22283
|
const inspect = async (root) => {
|
|
21972
22284
|
const old = new Store(root);
|
|
21973
|
-
const locks = await
|
|
22285
|
+
const locks = await stat7(old.path("locks"));
|
|
21974
22286
|
assert2(locks.isDirectory(), "LEGACY_LOCKS_MISSING", "\u65E7\u76EE\u5F55\u7F3A\u5C11\u534F\u4F5C\u9501\u76EE\u5F55\uFF0C\u672A\u9000\u5F79\u914D\u7F6E\u3002");
|
|
21975
22287
|
const snapshot = await migrationSnapshot(old);
|
|
21976
22288
|
assertMigrationReady(migrationTaskBlockers(snapshot.catalog), old);
|
|
@@ -21995,7 +22307,7 @@ async function migrate(bridge, input) {
|
|
|
21995
22307
|
assertSeparateMigrationRoots(old.root, targetRoot);
|
|
21996
22308
|
const snapshot = await migrationSnapshot(old), catalog = snapshot.catalog;
|
|
21997
22309
|
const blockers = migrationTaskBlockers(catalog);
|
|
21998
|
-
const locksDirectory = await
|
|
22310
|
+
const locksDirectory = await stat7(old.path("locks")).catch((error48) => {
|
|
21999
22311
|
if (error48.code === "ENOENT") return void 0;
|
|
22000
22312
|
throw error48;
|
|
22001
22313
|
});
|
|
@@ -22065,14 +22377,14 @@ async function migrate(bridge, input) {
|
|
|
22065
22377
|
const source = old.artifactPath(artifact.relativePath);
|
|
22066
22378
|
assert2(await fileDigest(source) === artifact.sha256, "ARTIFACT_CHANGED", "\u65E7\u7248\u4E0D\u53EF\u53D8\u4EA7\u7269\u6821\u9A8C\u5931\u8D25\uFF0C\u539F\u6587\u4EF6\u672A\u6539\u53D8\u3002");
|
|
22067
22379
|
const destination = bridge.store.artifactPath(artifact.relativePath);
|
|
22068
|
-
await mkdir9(
|
|
22380
|
+
await mkdir9(dirname10(destination), { recursive: true });
|
|
22069
22381
|
try {
|
|
22070
22382
|
await copyFile4(source, destination, 1);
|
|
22071
22383
|
} catch (error48) {
|
|
22072
22384
|
if (error48.code !== "EEXIST" || await fileDigest(destination) !== artifact.sha256) throw error48;
|
|
22073
22385
|
}
|
|
22074
22386
|
assert2(
|
|
22075
|
-
(await
|
|
22387
|
+
(await stat7(destination)).size === artifact.bytes && await fileDigest(destination) === artifact.sha256,
|
|
22076
22388
|
"ARTIFACT_CHANGED",
|
|
22077
22389
|
"\u8FC1\u79FB\u526F\u672C\u6821\u9A8C\u5931\u8D25\u3002"
|
|
22078
22390
|
);
|
|
@@ -22145,7 +22457,7 @@ if (process.argv[2] === "--worker") {
|
|
|
22145
22457
|
} finally {
|
|
22146
22458
|
supervisor?.write(Buffer.from([0]));
|
|
22147
22459
|
}
|
|
22148
|
-
} else if (process.argv[1] &&
|
|
22460
|
+
} else if (process.argv[1] && resolve11(process.argv[1]) === fileURLToPath2(import.meta.url)) {
|
|
22149
22461
|
try {
|
|
22150
22462
|
let text = "";
|
|
22151
22463
|
for await (const chunk of process.stdin) {
|