@motionharness/bridge-davinci 0.0.22 → 0.0.23

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/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, stat9) => {
1247
+ return fs.stat(file2, (err2, stat8) => {
1248
1248
  if (err2) {
1249
1249
  return callback(err2);
1250
1250
  }
1251
- callback(null, stat9.mtime, cachedPrecision);
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, stat9) => {
1259
+ fs.stat(file2, (err3, stat8) => {
1260
1260
  if (err3) {
1261
1261
  return callback(err3);
1262
1262
  }
1263
- const precision = stat9.mtime.getTime() % 1e3 === 0 ? "s" : "ms";
1263
+ const precision = stat8.mtime.getTime() % 1e3 === 0 ? "s" : "ms";
1264
1264
  Object.defineProperty(fs, cacheSymbol, { value: precision });
1265
- callback(null, stat9.mtime, precision);
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, stat9) => {
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(stat9, options)) {
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(stat9, options) {
1339
- return stat9.mtime.getTime() < Date.now() - options.stale;
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, stat9) => {
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() === stat9.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, stat9) => {
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(stat9, options));
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((resolve11, reject) => {
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
- resolve11(result2);
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 stat8 } from "node:fs/promises";
1624
- import { basename as basename5, dirname as dirname9, join as join9, resolve as resolve10, sep as sep3 } from "node:path";
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 dirname9, 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((resolve11, reject) => {
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\uFF1BHotion Harness \u5BBF\u4E3B\u7ED3\u679C\u9700\u6838\u5BF9\u3002", "process");
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\uFF1BMotion Harness \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 resolve11({ stdout: Buffer.concat(stdout), stderr });
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", "Hotion Harness \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 });
16285
+ assert2(data.sourceCurrent && !data.preparing && !data.error && !data.migration && !data.documentConflict && !data.lifecycle?.saveError, "BUILD_FAILED", "Motion Harness \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", "Hotion Harness \u5DE5\u7A0B\u6216 package.json / pnpm-lock.yaml \u4E0D\u5B58\u5728\u3002", "inspect", false, {}, "\u6307\u5B9A\u5B8C\u6574\u7684 Hotion Harness \u5DE5\u7A0B\u76EE\u5F55\uFF1B\u901A\u8FC7\u516C\u5F00 mh unpack \u6062\u590D\u5DE5\u7A0B\u3002");
16315
+ throw new BridgeError("SOURCE_MISSING", "Motion Harness \u5DE5\u7A0B\u6216 package.json / pnpm-lock.yaml \u4E0D\u5B58\u5728\u3002", "inspect", false, {}, "\u6307\u5B9A\u5B8C\u6574\u7684 Motion Harness \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", "Hotion Harness 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 Hotion Harness 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");
16324
+ throw new BridgeError("MH_DAEMON_VERSION_CONFLICT", "Motion Harness 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 Motion Harness 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((resolve11) => setTimeout(resolve11, 100));
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", "Hotion Harness \u91C7\u6837\u8BA1\u5212\u5E27\u6570\u4E0E\u6865\u63A5\u8BF7\u6C42\u4E0D\u4E00\u81F4\u3002");
16419
+ assert2(result2.frameCount === spec.frameCount, "OUTPUT_SPEC_MISMATCH", "Motion Harness \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", "Hotion Harness \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");
16471
+ if (!checked.success) throw new BridgeError("MH_RENDER_STATUS_UNVERIFIED", "Motion Harness \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", "Hotion Harness \u6E32\u67D3\u56DE\u6267\u3001\u5B8C\u6210\u72B6\u6001\u6216\u5E27\u6570\u4E0D\u5C5E\u4E8E\u672C\u6B21\u8BF7\u6C42\u3002");
16473
+ assert2(status.id === result2.id && result2.output === output && result2.progress.completed === spec.frameCount && result2.progress.total === spec.frameCount, "RENDER_RECEIPT_MISMATCH", "Motion Harness \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.22";
16988
+ var BRIDGE_VERSION = "0.0.23";
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 Hotion Harness \u7247\u6BB5\u3002");
16991
- if (selection.selectedCount !== 1 || !selection.item) return unavailable("multiple-selection", "\u8BF7\u53EA\u9009\u62E9\u4E00\u4E2A Hotion Harness \u7247\u6BB5\u3002");
16994
+ if (!selection.selectedCount) return unavailable("no-selection", "\u8BF7\u9009\u62E9\u4E00\u4E2A Motion Harness \u7247\u6BB5\u3002");
16995
+ if (selection.selectedCount !== 1 || !selection.item) return unavailable("multiple-selection", "\u8BF7\u53EA\u9009\u62E9\u4E00\u4E2A Motion Harness \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 Hotion Harness \u5DE5\u7A0B\u3002");
16999
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return unavailable("not-linked", "\u6240\u9009\u7247\u6BB5\u672A\u5173\u8054 Motion Harness \u5DE5\u7A0B\u3002");
16996
17000
  link2 = parsed;
16997
17001
  } catch {
16998
- return unavailable("invalid-link", "\u7247\u6BB5\u7684 Hotion Harness \u5173\u8054\u4FE1\u606F\u65E0\u6548\u3002");
17002
+ return unavailable("invalid-link", "\u7247\u6BB5\u7684 Motion Harness \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 Hotion Harness \u5173\u8054\u4FE1\u606F\u65E0\u6548\u3002");
17004
+ if (link2.schemaVersion !== 1 || typeof link2.bindingId !== "string" || typeof link2.sourceId !== "string") return unavailable("invalid-link", "\u7247\u6BB5\u7684 Motion Harness \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 Hotion Harness \u5DE5\u7A0B\u3002", target };
17012
+ return { selection, fingerprint: digest({ selection: selection.fingerprint, target }), canOpen: true, status: "linked", message: "\u5DF2\u5B9A\u4F4D\u5BF9\u5E94 Motion Harness \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 assertUsages(media) {
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", "Hotion Harness \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");
17419
+ assert2(!obs.audioPresent, "AUDIO_UNSUPPORTED", "Motion Harness \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 Hotion Harness \u5DE5\u7A0B\u65F6\u957F\u3002");
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 Motion Harness \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\u81EA\u52A8\u9644\u52A0\u5C1A\u4E0D\u53EF\u7528\uFF1B\u5DF2\u5173\u8054\u4EE3\u7406\u3001\u672A\u77E5\u65F6\u95F4\u6620\u5C04\u548C\u672A\u9A8C\u8BC1\u6548\u679C\u4FDD\u6301\u963B\u6B62\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"]
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
- binding = Object.values(catalog.bindings).find((b) => digest(b.resolve) === digest(request.resolve));
17495
- assert2(!binding || binding.sourceId === source.id, "BINDING_CONFLICT", "\u8BE5\u5A92\u4F53\u6C60\u5BF9\u8C61\u5DF2\u5173\u8054\u5176\u4ED6 Hotion Harness \u5DE5\u7A0B\u3002");
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 Motion Harness \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 = bindingId ? get(catalog.bindings, bindingId, "\u7ED1\u5B9A") : void 0;
17515
- const source = get(catalog.sources, sourceId ?? binding.sourceId, "\u6E90");
17516
- const artifact = binding?.artifactId ? catalog.artifacts[binding.artifactId] : void 0;
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 = binding ? await this.host.media(binding.resolve, binding.resolve.mediaPoolItemId) : void 0;
17530
- let state = binding?.state ?? "unbound";
17531
- if (artifact && actual && resolve3(actual.path) !== this.store.bindingPath(binding, artifact)) state = "stale";
17532
- else if (binding?.appliedContentVersion && binding.appliedContentVersion !== current.contentVersion) state = "stale";
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 || binding && await fileDigest(this.store.bindingPath(binding, artifact)).catch(() => null) !== artifact.sha256)) state = "failed";
17535
- if (artifact && actual) {
17557
+ if (artifact && (!artifactAvailable || await fileDigest(this.store.bindingPath(binding, artifact)).catch(() => null) !== artifact.sha256)) state = "failed";
17558
+ if (artifact) {
17536
17559
  try {
17537
- const link2 = JSON.parse(actual.metadata["motionharness.bridge"] ?? "{}");
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?.id ?? source.id));
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 panel state reads never scan timelines, export OTIO or select a UI page. */
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 [current, available] = await Promise.all([
17557
- this.mh.inspect(this.store.path(source.locator)),
17558
- artifact ? fileDigest(this.store.bindingPath(binding, artifact)).then((value) => value === artifact.sha256, () => false) : Promise.resolve(false)
17559
- ]);
17560
- const identity2 = await this.host.call(
17561
- "media_identity",
17562
- { scope: { databaseId: binding.resolve.databaseId, projectId: binding.resolve.projectId }, mediaPoolItemId: binding.resolve.mediaPoolItemId }
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
- current,
17584
- state,
17593
+ state: !mediaPresent || knownStale ? "stale" : binding.state,
17585
17594
  actual: { associationVerified },
17586
- ...!associationVerified ? { error: { message: "\u5F53\u524D\u89C6\u9891\u4E0E\u5DF2\u8BB0\u5F55\u5173\u8054\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u68C0\u67E5\u5173\u8054\u6216\u91CD\u65B0\u66F4\u65B0\u3002" } } : {}
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: error48.code === "SOURCE_MISSING" ? "source-missing" : "failed", error: errorResult(error48) };
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\u5F15\u7528\u8303\u56F4\u6216\u52A8\u6548\u5185\u5BB9\u53D8\u5316\u65F6\u4F1A\u505C\u6B62\u3002",
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: "Hotion Harness \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" };
17684
+ return { ...result2, canOpen: false, status: "source-missing", message: "Motion Harness \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.uses) === digest(checkpoint.before.uses) && digest(actual.clipProperties) === digest(checkpoint.before.clipProperties) && digest(actual.playbackPolicy) === digest(checkpoint.before.playbackPolicy),
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\u526A\u8F91\u3001\u89E3\u91CA\u6216\u64AD\u653E\u8BBE\u7F6E\u5DF2\u6539\u53D8\u3002"
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.artifactId === artifact.id && digest(editUsages(actual, checkpoint.offlineRepair)) === digest(editUsages(checkpoint.before, checkpoint.offlineRepair)) && await fileDigest(actual.path) === artifact.sha256) {
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.uses) === digest(checkpoint.before.uses) && digest(actual.clipProperties) === digest(checkpoint.before.clipProperties) && digest(actual.playbackPolicy) === digest(checkpoint.before.playbackPolicy) && [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");
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", "Hotion Harness \u4ECD\u6709\u6E32\u67D3\u6301\u9501\uFF0C\u8BF7\u7B49\u5F85\u8BE5\u4EFB\u52A1\u91CA\u653E\u540E\u6838\u5BF9\u3002");
17897
+ assert2(!(await this.mh.renderStatus(this.store.path(source.locator))).locked, "RECOVERY_WAIT", "Motion Harness \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", "Hotion Harness \u4ECD\u6709\u6E32\u67D3\u6301\u9501\uFF0C\u8BF7\u7B49\u5F85\u6E05\u7406\u3002");
17909
+ assert2(!(await this.mh.renderStatus(this.store.path(source.locator))).locked, "RECOVERY_WAIT", "Motion Harness \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 ?? "Hotion Harness \u72EC\u7ACB\u526F\u672C", locator: checkpoint.destination, revision: 1, createdAt: now(), observation };
17964
+ const source = c.sources[checkpoint.sourceId] ?? { id: checkpoint.sourceId, name: duplicateSchema.parse(job.request).name ?? "Motion Harness \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.media(binding.resolve, binding.resolve.mediaPoolItemId)]);
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((resolve11) => setTimeout(resolve11, 100));
18066
+ await new Promise((resolve12) => setTimeout(resolve12, 100));
18060
18067
  }
18061
18068
  }
18062
18069
  async runJob(taskId, started) {
@@ -18321,6 +18328,11 @@ var Bridge = class {
18321
18328
  }
18322
18329
  async replacePlayback(taskId, binding, artifact, before, offlineRepair) {
18323
18330
  const catalog = await this.store.read(), previous2 = binding.artifactId ? catalog.artifacts[binding.artifactId] : void 0;
18331
+ 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");
18332
+ if (previous2 && !offlineRepair) {
18333
+ 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");
18334
+ 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");
18335
+ }
18324
18336
  const mediaRelativePath = binding.mediaRelativePath ?? this.store.stableLocator(binding.id, artifact);
18325
18337
  const path = this.store.bindingPath({ ...binding, mediaRelativePath }, artifact);
18326
18338
  const publication = {
@@ -18339,11 +18351,8 @@ var Bridge = class {
18339
18351
  offlineRepair,
18340
18352
  publication
18341
18353
  );
18342
- assert2(
18343
- resolve3(actual.path) === path && digest(editUsages(actual, Boolean(offlineRepair))) === digest(editUsages(before, Boolean(offlineRepair))),
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
- );
18354
+ checkOwnership({ ...binding, artifactId: artifact.id }, actual);
18355
+ 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
18356
  return actual;
18348
18357
  }
18349
18358
  async applyArtifact(taskId, input, restore2 = false) {
@@ -18354,11 +18363,10 @@ var Bridge = class {
18354
18363
  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
18364
  const filePath = this.store.artifactPath(artifact.relativePath);
18356
18365
  await this.phase(taskId, "validating");
18357
- assert2(await fileDigest(filePath) === artifact.sha256, "ARTIFACT_CHANGED", "\u4EA7\u7269\u6587\u4EF6\u5DF2\u6539\u53D8\u3002");
18366
+ assert2(await fileDigest(filePath).catch(() => null) === artifact.sha256, "ARTIFACT_CHANGED", "\u4EA7\u7269\u6587\u4EF6\u7F3A\u5931\u6216\u5DF2\u6539\u53D8\u3002");
18358
18367
  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\u5F15\u7528\u6216\u526A\u8F91\u72B6\u6001\u5DF2\u7ECF\u6539\u53D8\uFF0C\u672A\u5E94\u7528\u5386\u53F2\u753B\u9762\u3002");
18360
- const offlineRepair = binding.artifactId === artifact.id && binding.lastReadback?.path === before.path && !await stat3(before.path).then(() => true, () => false) && before.usageScanComplete && before.uses.every((item) => item.unsupported.every((reason) => reason === "offline-media-reference"));
18361
- if (!offlineRepair) assertUsages(before);
18368
+ 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");
18369
+ const offlineRepair = binding.artifactId === artifact.id && binding.lastReadback?.path === before.path && !await stat3(before.path).then(() => true, () => false);
18362
18370
  checkOwnership(binding, before);
18363
18371
  checkReplacementSpec(before, artifact);
18364
18372
  if (artifact.contentVersion && !restore2) {
@@ -18368,7 +18376,7 @@ var Bridge = class {
18368
18376
  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
18377
  await this.store.mutate((c) => {
18370
18378
  const job = get(c.jobs, taskId, "\u4EFB\u52A1");
18371
- job.results.push({ bindingId: binding.id, artifactId: artifact.id, affectedUses: before.uses, applied: false });
18379
+ job.results.push({ bindingId: binding.id, artifactId: artifact.id, applied: false });
18372
18380
  job.journal = { apply: { bindingId: binding.id, artifactId: artifact.id, sourceId: binding.sourceId, expectedRevision: binding.revision, before, offlineRepair } };
18373
18381
  });
18374
18382
  await this.phase(taskId, "applying");
@@ -18401,9 +18409,9 @@ var Bridge = class {
18401
18409
  await this.phase(taskId, "applying");
18402
18410
  const actual = existing ? before : await this.host.bind(binding.resolve, binding.resolve.mediaPoolItemId, wanted, before.fingerprint);
18403
18411
  assert2(
18404
- actual.metadata["motionharness.bridge"] === wanted["motionharness.bridge"] && actual.path === before.path && digest(actual.uses) === digest(before.uses),
18412
+ actual.metadata["motionharness.bridge"] === wanted["motionharness.bridge"] && actual.path === before.path,
18405
18413
  "APPLY_OUTCOME_UNKNOWN",
18406
- "\u5173\u8054\u6062\u590D\u540E\u7684\u8EAB\u4EFD\u6216\u526A\u8F91\u8BFB\u56DE\u4E0D\u4E00\u81F4\u3002"
18414
+ "\u5173\u8054\u6062\u590D\u540E\u7684\u539F\u7D20\u6750\u8EAB\u4EFD\u8BFB\u56DE\u4E0D\u4E00\u81F4\u3002"
18407
18415
  );
18408
18416
  await this.finishAssociationRestore(taskId, binding.id, binding.revision, artifact, actual);
18409
18417
  }
@@ -18443,7 +18451,7 @@ var Bridge = class {
18443
18451
  assert2(
18444
18452
  after.contentVersion === observation.contentVersion && after.runtimeIdentity === observation.runtimeIdentity && after.sessionIdentity === observation.sessionIdentity,
18445
18453
  "VERSION_CONFLICT",
18446
- "\u6E32\u67D3\u524D\u540E\u7684 Hotion Harness \u5185\u5BB9\u3001\u8FD0\u884C\u65F6\u6216\u4F1A\u8BDD\u4E0D\u4E00\u81F4\uFF0C\u672A\u5E94\u7528\u65B0\u7ED3\u679C\u3002"
18454
+ "\u6E32\u67D3\u524D\u540E\u7684 Motion Harness \u5185\u5BB9\u3001\u8FD0\u884C\u65F6\u6216\u4F1A\u8BDD\u4E0D\u4E00\u81F4\uFF0C\u672A\u5E94\u7528\u65B0\u7ED3\u679C\u3002"
18447
18455
  );
18448
18456
  await this.store.mutate((catalog) => {
18449
18457
  const current = get(catalog.sources, sourceId, "\u6E90");
@@ -18470,7 +18478,7 @@ var Bridge = class {
18470
18478
  async renderSource(taskId, input, signal) {
18471
18479
  const request = renderSchema.parse(input), source = get((await this.store.read()).sources, request.sourceId, "\u6E90");
18472
18480
  const observation = await this.mh.inspect(this.store.path(source.locator));
18473
- assert2(observation.contentVersion === request.expectedContentVersion, "VERSION_CONFLICT", "Hotion Harness \u5185\u5BB9\u4E0E\u8BF7\u6C42\u7684\u7248\u672C\u4E0D\u4E00\u81F4\u3002");
18481
+ assert2(observation.contentVersion === request.expectedContentVersion, "VERSION_CONFLICT", "Motion Harness \u5185\u5BB9\u4E0E\u8BF7\u6C42\u7684\u7248\u672C\u4E0D\u4E00\u81F4\u3002");
18474
18482
  const artifact = await this.renderArtifact(taskId, source.id, observation, request.outputSpec, request.purpose, signal);
18475
18483
  await this.store.mutate((c) => {
18476
18484
  get(c.jobs, taskId, "\u4EFB\u52A1").results = [{ sourceId: source.id, artifactId: artifact.id, verification: artifact.verification, applied: false }];
@@ -18486,9 +18494,9 @@ var Bridge = class {
18486
18494
  let checkpoint = (await this.job(taskId)).journal?.duplicate;
18487
18495
  if (instance) {
18488
18496
  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.media(originalBinding.resolve, originalBinding.resolve.mediaPoolItemId)]);
18497
+ const [timeline, media] = await Promise.all([this.host.timeline(originalBinding.resolve, instance.timelineId), this.host.mediaUsages(originalBinding.resolve, originalBinding.resolve.mediaPoolItemId)]);
18490
18498
  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
- assertUsages(media);
18499
+ assertInstanceUsages(media);
18492
18500
  checkOwnership(originalBinding, media);
18493
18501
  const target = media.uses.find((item) => item.timelineId === instance.timelineId && item.id === instance.itemId);
18494
18502
  assert2(target && !target.intrinsicEntry && target.kind !== "generator", "UNSUPPORTED_TIMELINE_ITEM", "\u9700\u8981\u660E\u786E\u7684\u666E\u901A\u89C6\u9891\u5B9E\u4F8B\u3002");
@@ -18632,14 +18640,13 @@ var Bridge = class {
18632
18640
  const c = await this.store.read(), binding = get(c.bindings, target.bindingId, "\u7ED1\u5B9A"), source = get(c.sources, binding.sourceId, "\u6E90");
18633
18641
  assert2(binding.revision === target.expectedRevision, "VERSION_CONFLICT", "\u7ED1\u5B9A\u7248\u672C\u5DF2\u6539\u53D8\u3002");
18634
18642
  const obs = await this.mh.inspect(this.store.path(source.locator));
18635
- assert2(obs.contentVersion === target.expectedContentVersion, "VERSION_CONFLICT", "Hotion Harness \u5185\u5BB9\u5DF2\u6539\u53D8\u3002");
18643
+ assert2(obs.contentVersion === target.expectedContentVersion, "VERSION_CONFLICT", "Motion Harness \u5185\u5BB9\u5DF2\u6539\u53D8\u3002");
18636
18644
  checkObservation(obs, request.outputSpec);
18637
18645
  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
18646
  const previousSettings = binding.artifactId ? c.artifacts[binding.artifactId]?.receipt?.before.settings : void 0;
18639
18647
  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
18648
  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\u5F15\u7528\u6216\u526A\u8F91\u72B6\u6001\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u51C6\u5907\u3002");
18642
- assertUsages(actual);
18649
+ 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
18650
  checkOwnership(binding, actual);
18644
18651
  checkReplacementSpec(actual, { spec: request.outputSpec });
18645
18652
  }
@@ -18664,7 +18671,6 @@ var Bridge = class {
18664
18671
  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
18672
  const before = await this.host.media(binding.resolve, binding.resolve.mediaPoolItemId);
18666
18673
  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
18674
  checkOwnership(binding, before);
18669
18675
  const appliedArtifact = binding.artifactId ? c.artifacts[binding.artifactId] : void 0;
18670
18676
  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 +18689,6 @@ var Bridge = class {
18683
18689
  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
18690
  const latestMedia = await this.host.media(binding.resolve, binding.resolve.mediaPoolItemId);
18685
18691
  assert2(latestMedia.fingerprint === before.fingerprint, "VERSION_CONFLICT", "Resolve \u5728\u6E32\u67D3\u671F\u95F4\u5DF2\u6539\u53D8\u3002");
18686
- assertUsages(latestMedia);
18687
18692
  checkReplacementSpec(latestMedia, artifact);
18688
18693
  if (binding.artifactId === artifact.id && resolve3(latestMedia.path) === this.store.bindingPath(binding, artifact)) {
18689
18694
  assert2(
@@ -18743,7 +18748,7 @@ var Bridge = class {
18743
18748
  if (bindings.some((b) => b.bindingId === binding.id)) continue;
18744
18749
  const fixed = binding.artifactId ? catalog.artifacts[binding.artifactId] : void 0;
18745
18750
  if (request.manualPolicy === "allow-pinned" && fixed?.verification === "manual-pinned") {
18746
- const actual = await this.host.media(binding.resolve, binding.resolve.mediaPoolItemId);
18751
+ const actual = await this.host.mediaUsages(binding.resolve, binding.resolve.mediaPoolItemId);
18747
18752
  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
18753
  let ownership2 = true;
18749
18754
  try {
@@ -18755,7 +18760,7 @@ var Bridge = class {
18755
18760
  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
18761
  continue;
18757
18762
  }
18758
- const result2 = await this.inspect(void 0, binding.id);
18763
+ const result2 = await this.inspectForExport(binding.id);
18759
18764
  const pinnedAllowed = request.manualPolicy === "allow-pinned" && result2.state === "manual-pinned";
18760
18765
  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
18766
  if (!result2.artifact || !result2.priorArtifactRemainsAvailable || !("current" in result2) || !result2.current) continue;
@@ -18816,7 +18821,7 @@ var Bridge = class {
18816
18821
  await this.patchJob(taskId, { results: [{ resolveJobId: created.jobId, outputPath: output, started: true, status, applied: true }] });
18817
18822
  if (["Complete", "Cancelled", "Failed", "Background Render Cancelled", "Remote Render Cancelled"].includes(String(status.JobStatus))) break;
18818
18823
  if (signal.aborted) await this.host.cancelRender(receipt.request.scope, created.jobId, created.jobFingerprint);
18819
- await new Promise((resolve11) => setTimeout(resolve11, 500));
18824
+ await new Promise((resolve12) => setTimeout(resolve12, 500));
18820
18825
  }
18821
18826
  if (receipt.playbackPolicy) await this.host.finishRender(receipt.request.scope, created.jobId, receipt.playbackPolicy);
18822
18827
  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 +18870,7 @@ var Bridge = class {
18865
18870
  await mkdir5(directory, { recursive: true });
18866
18871
  const output = resolve3(directory, "source.png");
18867
18872
  await this.mh.preview(path, time3, output);
18868
- assert2((await this.mh.inspect(path)).contentVersion === before.contentVersion, "VERSION_CONFLICT", "\u622A\u56FE\u671F\u95F4 Hotion Harness \u5185\u5BB9\u5DF2\u6539\u53D8\u3002");
18873
+ assert2((await this.mh.inspect(path)).contentVersion === before.contentVersion, "VERSION_CONFLICT", "\u622A\u56FE\u671F\u95F4 Motion Harness \u5185\u5BB9\u5DF2\u6539\u53D8\u3002");
18869
18874
  const image = await readFile4(output);
18870
18875
  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
18876
  return { origin: "mh-source", sourceId, contentVersion: before.contentVersion, timeSeconds: time3, filePath: output, mimeType: "image/png", data: image.toString("base64"), provesResolveComposite: false };
@@ -20542,36 +20547,298 @@ async function retireLegacyEntries(options, input) {
20542
20547
  });
20543
20548
  }
20544
20549
 
20550
+ // src/i18n.ts
20551
+ import { execFileSync } from "node:child_process";
20552
+
20553
+ // src/i18n/en.json
20554
+ var en_default2 = {
20555
+ "Motion Harness \u6865\u63A5\u7EC4\u4EF6": "Motion Harness Bridge Component",
20556
+ " \u526F\u672C": " Copy",
20557
+ "\u4E3A\u8FD9\u4E2A\u7247\u6BB5\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\u2026": "Create an independent copy for this clip\u2026",
20558
+ "\u4EFB\u52A1\u4E0E\u72B6\u6001\u2026": "Tasks and status\u2026",
20559
+ \u4EFB\u52A1\u5DF2\u53D6\u6D88: "Task cancelled",
20560
+ \u4EFB\u52A1\u5DF2\u5B8C\u6210: "Task completed",
20561
+ \u4EFB\u52A1\u5DF2\u6392\u961F: "Task queued",
20562
+ "\u4EFB\u52A1\u5DF2\u6392\u961F\u2026": "Task queued\u2026",
20563
+ "\u4FA7\u680F\u6765\u6E90\u5FEB\u7167\u65E0\u6548\u3002": "The sidebar source snapshot is invalid.",
20564
+ "\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.",
20565
+ "\u4FA7\u680F\u7BA1\u7406\u5165\u53E3\u8BF7\u6C42\u65E0\u6548\u3002": "The sidebar management request is invalid.",
20566
+ "\u4FA7\u680F\u7BA1\u7406\u5165\u53E3\u9700\u8981\u65B0\u7248\u6865\u63A5\u7EC4\u4EF6\uFF0C\u8BF7\u66F4\u65B0\u7EC4\u4EF6\u3002": "Update the Motion Harness Bridge Component to use sidebar management.",
20567
+ "\u4FA7\u680F\u9700\u8981\u652F\u6301\u6E90\u8EAB\u4EFD\u6838\u5BF9\u7684\u65B0\u7248\u6865\u63A5\u7EC4\u4EF6\u3002": "The sidebar requires a newer Motion Harness Bridge Component with source verification.",
20568
+ "\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 Motion Harness Bridge Component to use the sidebar. No request was sent to the old entry.",
20569
+ \u4FDD\u5B58\u72EC\u7ACB\u5DE5\u7A0B: "Save independent project",
20570
+ "\u4FEE\u590D\u5173\u8054\u2026": "Repair association\u2026",
20571
+ "\u4FEE\u590D\u5DE5\u7A0B\u5173\u8054\u2026": "Repair project association\u2026",
20572
+ "\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.",
20573
+ "\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.",
20574
+ "\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.",
20575
+ "\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\u2026": "Create independent copy\u2026",
20576
+ \u5237\u65B0\u7247\u6BB5\u72B6\u6001: "Refresh clip status",
20577
+ \u53D6\u6D88: "Cancel",
20578
+ \u53D6\u6D88\u4EFB\u52A1: "Cancel task",
20579
+ "\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.",
20580
+ "\u53EF\u7EE7\u7EED\u4F7F\u7528\u8FBE\u82AC\u5947\u3002": "You can continue using DaVinci Resolve.",
20581
+ "\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.",
20582
+ "\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 Motion Harness Bridge Component and try again.",
20583
+ "\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.",
20584
+ \u5DE5\u7A0B\u5173\u8054\u5DF2\u4FEE\u590D: "Project association repaired",
20585
+ "\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.",
20586
+ \u5DE5\u7A0B\u6253\u5F00\u8BF7\u6C42\u5DF2\u5B8C\u6210: "Project opening request completed",
20587
+ \u5DF2\u6253\u5F00\u7F16\u8F91\u5668: "Editor opened",
20588
+ "\u5F53\u524D\u4F7F\u7528\u624B\u52A8\u6307\u5B9A\u7684\u89C6\u9891\u7248\u672C\u3002": "A manually selected video version is in use.",
20589
+ "\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.",
20590
+ "\u6062\u590D\u5386\u53F2\u7248\u672C\u2026": "Restore previous version\u2026",
20591
+ \u6062\u590D\u5DF2\u5E94\u7528\u7248\u672C: "Restore applied version",
20592
+ "\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.",
20593
+ "\u6240\u9009 Motion Harness \u7247\u6BB5": "Selected Motion Harness clip",
20594
+ \u6240\u9009\u7247\u6BB5: "Selected clip",
20595
+ "\u627E\u4E0D\u5230 Motion Harness\u3002\u8BF7\u91CD\u65B0\u5B89\u88C5\u6865\u63A5\u7EC4\u4EF6\u3002": "Motion Harness was not found. Reinstall the Motion Harness Bridge Component.",
20596
+ "\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.",
20597
+ "\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.",
20598
+ "\u64CD\u4F5C\u6CA1\u6709\u5B8C\u6210\uFF0C\u8BF7\u68C0\u67E5\u6865\u63A5\u8FDE\u63A5\u3002": "The operation did not complete. Check the bridge connection.",
20599
+ "\u65E0\u6CD5\u4FDD\u5B58\u672C\u5730\u8BF7\u6C42\u72B6\u6001\u3002": "Unable to save the local request state.",
20600
+ "\u65E0\u6CD5\u521B\u5EFA\u672C\u5730\u8BF7\u6C42\u901A\u9053\u3002": "Unable to create the local request channel.",
20601
+ "\u65E0\u6CD5\u542F\u52A8 Motion Harness\uFF0C\u8BF7\u4FEE\u590D\u7EC4\u4EF6\u5B89\u88C5\u3002": "Unable to start Motion Harness. Repair the Motion Harness Bridge Component installation.",
20602
+ "\u65E0\u6CD5\u542F\u52A8 Motion Harness\uFF0C\u8BF7\u91CD\u65B0\u5B89\u88C5\u6865\u63A5\u7EC4\u4EF6\u3002": "Unable to start Motion Harness. Reinstall the Motion Harness Bridge Component.",
20603
+ "\u65E0\u6CD5\u6253\u5F00\u672C\u5730\u8BF7\u6C42\u72B6\u6001\u3002": "Unable to open the local request state.",
20604
+ "\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.",
20605
+ "\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.",
20606
+ "\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.",
20607
+ "\u66F4\u591A\u2026": "More\u2026",
20608
+ \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",
20609
+ "\u66F4\u65B0\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B\u4EFB\u52A1\u8BE6\u60C5": "Update failed. Check task details",
20610
+ "\u66F4\u65B0\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B\u4EFB\u52A1\u8BE6\u60C5\u3002": "Update failed. Check task details.",
20611
+ \u66F4\u65B0\u5B8C\u6210: "Update completed",
20612
+ \u66F4\u65B0\u6B64\u7D20\u6750: "Update this media",
20613
+ \u66F4\u65B0\u753B\u9762: "Update video",
20614
+ \u66F4\u65B0\u5230\u8FBE\u82AC\u5947: "Update in DaVinci Resolve",
20615
+ "\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.",
20616
+ "\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.",
20617
+ "\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.",
20618
+ "\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.",
20619
+ "\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.",
20620
+ "\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.",
20621
+ "\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.",
20622
+ \u67E5\u770B\u72B6\u6001: "Check status",
20623
+ \u6838\u5BF9\u73B0\u6709\u4EFB\u52A1\u72B6\u6001: "Check existing task status",
20624
+ \u6B63\u5728\u51C6\u5907\u5DE5\u7A0B: "Preparing project",
20625
+ "\u6B63\u5728\u51C6\u5907\u5DE5\u7A0B\u2026": "Preparing project\u2026",
20626
+ "\u6B63\u5728\u53D6\u6D88\u2026": "Cancelling\u2026",
20627
+ "\u6B63\u5728\u53D6\u6D88\u4EFB\u52A1\u2026": "Cancelling task\u2026",
20628
+ "\u6B63\u5728\u53D6\u6D88\u4EFB\u52A1\uFF0C\u7B49\u5F85\u786E\u8BA4\u5904\u7406\u7ED3\u679C\u2026": "Cancelling task and waiting for the result\u2026",
20629
+ "\u6B63\u5728\u5B9A\u4F4D\u65E7\u7247\u6BB5\u7684\u5DE5\u7A0B\u2026": "Locating the legacy clip project\u2026",
20630
+ "\u6B63\u5728\u6253\u5F00\u5DE5\u7A0B\u2026": "Opening project\u2026",
20631
+ "\u6B63\u5728\u63D0\u4EA4\u66F4\u65B0\u2026": "Submitting update\u2026",
20632
+ "\u6B63\u5728\u63D0\u4EA4\u8BF7\u6C42\u2026": "Submitting request\u2026",
20633
+ \u6B63\u5728\u66F4\u65B0\u8FBE\u82AC\u5947: "Updating DaVinci Resolve",
20634
+ "\u6B63\u5728\u66F4\u65B0\u8FBE\u82AC\u5947\u2026": "Updating DaVinci Resolve\u2026",
20635
+ "\u6B63\u5728\u6838\u5B9E\u66F4\u65B0\u7ED3\u679C\uFF0C\u8BF7\u52FF\u91CD\u590D\u66F4\u65B0": "Verifying the update result. Do not submit another update",
20636
+ "\u6B63\u5728\u6838\u5BF9\u5E76\u7EE7\u7EED\u539F\u4EFB\u52A1\u2026": "Checking and resuming the original task\u2026",
20637
+ "\u6B63\u5728\u6838\u5BF9\u6E90\u5DE5\u7A0B\u4F4D\u7F6E\u2026": "Checking source project location\u2026",
20638
+ "\u6B63\u5728\u6838\u5BF9\u7247\u6BB5\u4E0E\u5F71\u54CD\u8303\u56F4\u2026": "Checking clip and affected uses\u2026",
20639
+ "\u6B63\u5728\u6838\u5BF9\u73B0\u6709\u4EFB\u52A1\u2026": "Checking existing task\u2026",
20640
+ "\u6B63\u5728\u6838\u5BF9\u7D20\u6750\u5173\u8054\u2026": "Checking media association\u2026",
20641
+ \u6B63\u5728\u68C0\u67E5\u89C6\u9891: "Validating video",
20642
+ "\u6B63\u5728\u68C0\u67E5\u89C6\u9891\u2026": "Validating video\u2026",
20643
+ \u6B63\u5728\u6E32\u67D3\u89C6\u9891: "Rendering video",
20644
+ "\u6B63\u5728\u6E32\u67D3\u89C6\u9891\u2026": "Rendering video\u2026",
20645
+ "\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",
20646
+ "\u6B63\u5728\u8BFB\u53D6\u6240\u9009\u7247\u6BB5\u2026": "Reading selected clip\u2026",
20647
+ "\u6B64\u7247\u6BB5\u5C1A\u672A\u5B8C\u6210\u5173\u8054\u3002": "This clip is not fully linked yet.",
20648
+ "\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.",
20649
+ "\u6DFB\u52A0\u4FA7\u680F\u5165\u53E3 \xB7 \u56FE\u6587\u6B65\u9AA4": "Add sidebar entry \xB7 Illustrated guide",
20650
+ \u6E90\u5DE5\u7A0B\u4F4D\u7F6E\u5DF2\u66F4\u65B0: "Source project location updated",
20651
+ \u72B6\u6001: "Status",
20652
+ "\u72B6\u6001\u7A97\u53E3\u8BF7\u6C42\u65E0\u6548\u3002": "The status window request is invalid.",
20653
+ "\u72B6\u6001\u89C1\u63D0\u793A\u7A97\uFF1B\u66F4\u65B0\u5F71\u54CD\u5168\u90E8\u5F15\u7528": "See the status window; updates affect every use",
20654
+ \u72EC\u7ACB\u526F\u672C\u5DF2\u521B\u5EFA: "Independent copy created",
20655
+ "\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.",
20656
+ "\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.",
20657
+ \u76F8\u5173\u6587\u4EF6: "related file",
20658
+ "\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.",
20659
+ "\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.",
20660
+ "\u7EC4\u4EF6\u672A\u914D\u7F6E\u3002\u8BF7\u8FD0\u884C mh bridge davinci install \u4FEE\u590D\u3002": "The Motion Harness Bridge Component is not configured. Run mh bridge davinci install to repair it.",
20661
+ "\u7EC4\u4EF6\u7F3A\u5C11\u72B6\u6001\u7A97\u53E3\uFF0C\u8BF7\u4FEE\u590D Motion Harness \u6865\u63A5\u7EC4\u4EF6\u5B89\u88C5\u3002": "The status window is missing. Repair the Motion Harness Bridge Component installation.",
20662
+ "\u7EC4\u4EF6\u914D\u7F6E\u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002": "The component configuration path must be absolute.",
20663
+ \u7EE7\u7EED: "Continue",
20664
+ \u7EE7\u7EED\u539F\u4EFB\u52A1: "Resume original task",
20665
+ "\u7EE7\u7EED\u539F\u4EFB\u52A1\u2026": "Resume original task\u2026",
20666
+ "\u7EE7\u7EED\u539F\u4EFB\u52A1\u4E2D\u5C1A\u672A\u5B8C\u6210\u7684\u64CD\u4F5C\uFF1F": "Resume unfinished operations in the original task?",
20667
+ \u7EE7\u7EED\u6838\u5BF9\u6E90\u5DE5\u7A0B\u4F4D\u7F6E: "Continue checking source project location",
20668
+ "\u7F16\u8F91 Motion Harness \u5DE5\u7A0B": "Edit Motion Harness project",
20669
+ \u7F16\u8F91\u5DE5\u7A0B: "Edit project",
20670
+ "\u7F3A\u5C11\u8BF7\u6C42\u53C2\u6570\u3002": "Request parameters are missing.",
20671
+ "\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.",
20672
+ \u89C6\u9891\u5DF2\u53D1\u9001\u5230\u8FBE\u82AC\u5947: "Video sent to DaVinci Resolve",
20673
+ \u89C6\u9891\u5DF2\u66F4\u65B0: "Video updated",
20674
+ "\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.",
20675
+ "\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.",
20676
+ "\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.",
20677
+ "\u8BF7\u66F4\u65B0\u6865\u63A5\u7EC4\u4EF6\u540E\u4F7F\u7528\u66F4\u591A\u64CD\u4F5C\u3002": "Update the Motion Harness Bridge Component to use more actions.",
20678
+ "\u8BF7\u6C42\u53D6\u6D88\uFF0C\u5E76\u6838\u5BF9\u5DF2\u7ECF\u5B8C\u6210\u7684\u7ED3\u679C\u3002": "Request cancellation and check results already completed.",
20679
+ "\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.",
20680
+ \u8BF7\u6C42\u5DF2\u53D7\u7406: "Request accepted",
20681
+ "\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.",
20682
+ "\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.",
20683
+ "\u8FBE\u82AC\u5947\u5C1A\u672A\u8FDE\u63A5\uFF0C\u8BF7\u68C0\u67E5\u8FDE\u63A5\u72B6\u6001\u3002": "DaVinci Resolve is not connected. Check the connection.",
20684
+ "\u8FBE\u82AC\u5947\u5DF2\u8FDE\u63A5\uFF0C\u6682\u65E0\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u3002": "DaVinci Resolve is connected. No task is running.",
20685
+ "\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.",
20686
+ "\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.",
20687
+ "\u8FBE\u82AC\u5947\u6865\u63A5\u7EC4\u4EF6\u5C1A\u672A\u5B89\u88C5\u3002": "The Motion Harness Bridge Component is not installed.",
20688
+ \u8FD9\u4E2A\u7247\u6BB5\u7684\u72EC\u7ACB\u526F\u672C\u5DF2\u521B\u5EFA: "An independent copy has been created for this clip",
20689
+ "\u8FD9\u4E2A\u7248\u672C\u7684\u89C6\u9891\u6587\u4EF6\u5DF2\u4E0D\u53EF\u7528\u3002": "The video file for this version is unavailable.",
20690
+ \u9009\u62E9\u4F4D\u7F6E: "Choose location",
20691
+ \u9009\u62E9\u5DE5\u7A0B: "Choose project",
20692
+ \u9009\u62E9\u79FB\u52A8\u540E\u7684\u6E90\u5DE5\u7A0B: "Choose the relocated source project",
20693
+ "\u91CD\u65B0\u5B9A\u4F4D\u5DE5\u7A0B\u2026": "Relocate project\u2026",
20694
+ "\u91CD\u65B0\u5B9A\u4F4D\u6E90\u5DE5\u7A0B\u2026": "Relocate source project\u2026",
20695
+ "\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.",
20696
+ "\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.",
20697
+ "\u7F3A\u5C11 Motion Harness \u72B6\u6001\u7A97\u53E3\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install \u4FEE\u590D\u7EC4\u4EF6\u3002": "The Motion Harness Bridge Component status window is missing. Run mh bridge davinci install to repair it.",
20698
+ "\u627E\u4E0D\u5230 Motion Harness \u4E3B\u7A0B\u5E8F\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install \u4FEE\u590D\u7EC4\u4EF6\u3002": "The Motion Harness executable was not found. Run mh bridge davinci install to repair the bridge component.",
20699
+ "\u8BF7\u6253\u5F00\u65F6\u95F4\u7EBF\u5E76\u9009\u62E9\u4E00\u4E2A Motion Harness \u7247\u6BB5\u3002": "Open a timeline and select a Motion Harness clip.",
20700
+ "\u8BF7\u53EA\u9009\u62E9\u4E00\u4E2A Motion Harness \u89C6\u9891\u7247\u6BB5\u3002": "Select exactly one Motion Harness video clip.",
20701
+ "\u6240\u9009\u89C6\u9891\u672A\u5173\u8054 Motion Harness \u5DE5\u7A0B\u3002": "The selected video is not linked to a Motion Harness project.",
20702
+ "\u6B63\u5728\u6253\u5F00 Motion Harness \u5DE5\u7A0B\u2026": "Opening Motion Harness project\u2026",
20703
+ "\u6B63\u5728\u8BFB\u53D6\u6240\u9009 Motion Harness \u7247\u6BB5\u2026": "Reading selected Motion Harness clip\u2026",
20704
+ "\u6B63\u5728\u63D0\u4EA4 Motion Harness \u8BF7\u6C42\uFF0C\u72B6\u6001\u7A97\u53E3\u5C06\u663E\u793A\u8FDB\u5EA6\u3002": "Submitting the Motion Harness request. The status window will show progress.",
20705
+ "\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.",
20706
+ "\u8FBE\u82AC\u5947\u6B63\u5728\u5BFC\u51FA\uFF0C\u8BF7\u5B8C\u6210\u540E\u91CD\u8BD5\u3002": "DaVinci Resolve is rendering. Try again when it finishes.",
20707
+ "\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.",
20708
+ "\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.",
20709
+ "\u6240\u9009\u7247\u6BB5\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u70B9\u51FB\u3002": "The selected clip changed. Click again.",
20710
+ "\u5F53\u524D\u5DE5\u7A0B\u4F4D\u7F6E\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u70B9\u51FB\u3002": "The current project location changed. Click again.",
20711
+ "\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.",
20712
+ "\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.",
20713
+ "\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.",
20714
+ "\u4EC5\u4E3A\u8FD9\u4E2A\u7247\u6BB5\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\uFF1F": "Create an independent copy for this clip only?",
20715
+ "\u4EC5\u5F71\u54CD\u9009\u5B9A\u7684\u4E00\u4E2A\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u3002": "Only the selected timeline instance is affected.",
20716
+ "\u4F7F\u7528\u8FD9\u4E2A\u6E90\u5DE5\u7A0B\u4F4D\u7F6E\uFF1F": "Use this source project location?",
20717
+ "\u4FEE\u590D\u6240\u9009\u7D20\u6750\u7684\u5173\u8054\uFF1F": "Repair the selected media association?",
20718
+ "\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.",
20719
+ "\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.",
20720
+ "\u5386\u53F2\u89C6\u9891\u4E0E\u5DF2\u8BB0\u5F55\u5185\u5BB9\u4E0D\u540C\u3002": "The historical video differs from the recorded content.",
20721
+ "\u539F\u5173\u8054\u767B\u8BB0\u5DF2\u7ECF\u4E0D\u53EF\u7528\u3002": "The original association record is unavailable.",
20722
+ "\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.",
20723
+ "\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.",
20724
+ "\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.",
20725
+ "\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.",
20726
+ "\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.",
20727
+ "\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.",
20728
+ "\u5F53\u524D\u7247\u6BB5\u4E0D\u80FD\u6267\u884C\u6B64\u64CD\u4F5C\u3002": "This operation is unavailable for the current clip.",
20729
+ "\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.",
20730
+ "\u6062\u590D\u8FD9\u4E2A\u5DF2\u5E94\u7528\u7248\u672C\uFF1F": "Restore this applied version?",
20731
+ "\u6240\u9009\u5B9E\u4F8B\u4E0D\u518D\u5C5E\u4E8E\u5F53\u524D\u5A92\u4F53\u3002": "The selected instance no longer belongs to this media.",
20732
+ "\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.",
20733
+ "\u6240\u9009\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u5DF2\u6539\u53D8\u3002": "The selected timeline instance has changed.",
20734
+ "\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.",
20735
+ "\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.",
20736
+ "\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.",
20737
+ "\u6253\u5F00\u66F4\u591A\u64CD\u4F5C\u65F6\u5173\u8054\u5DF2\u6539\u53D8\u3002": "The association changed while opening more actions.",
20738
+ "\u6253\u5F00\u66F4\u591A\u64CD\u4F5C\u671F\u95F4\u5DE5\u7A0B\u5DF2\u6539\u53D8\u3002": "The project changed while opening more actions.",
20739
+ "\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.",
20740
+ "\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.",
20741
+ "\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\uFF0C\u8BF7\u5148\u91CD\u65B0\u5B9A\u4F4D\u3002": "The source project was not found. Relocate it first.",
20742
+ "\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.",
20743
+ "\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.",
20744
+ \u65F6\u95F4\u7EBF: "Timeline",
20745
+ "\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.",
20746
+ "\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.",
20747
+ "\u6B64\u5173\u8054\u5C1A\u65E0\u53EF\u66F4\u65B0\u7684\u89C6\u9891\u89C4\u683C\u3002": "This association has no video specifications available for an update.",
20748
+ "\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.",
20749
+ "\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.",
20750
+ "\u6B64\u7D20\u6750\u6CA1\u6709\u53EF\u6838\u5BF9\u7684\u672C\u673A\u5173\u8054\u3002": "This media has no verifiable local association.",
20751
+ "\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.",
20752
+ "\u7247\u6BB5\u5DF2\u5173\u8054 Motion Harness\u3002\u53EF\u4EE5\u7F16\u8F91\u6E90\u5DE5\u7A0B\u6216\u66F4\u65B0\u753B\u9762\u3002": "The clip is linked to Motion Harness. You can edit the source project or update the video.",
20753
+ "\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.",
20754
+ "\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.",
20755
+ "\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.",
20756
+ "\u7D20\u6750\u4F5C\u7528\u57DF\u5DF2\u6539\u53D8\u3002": "The media scope has changed.",
20757
+ "\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.",
20758
+ "\u8BF7\u5148\u4FEE\u590D\u6B64\u7D20\u6750\u7684\u5173\u8054\u3002": "Repair this media association first.",
20759
+ "\u8BF7\u5148\u6253\u5F00\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E0E\u65F6\u95F4\u7EBF\u3002": "Open a DaVinci Resolve project and timeline first.",
20760
+ "\u8BF7\u5148\u6838\u5B9E\u5DF2\u6709\u4EFB\u52A1\u7684\u7ED3\u679C\u3002": "Verify the existing task result first.",
20761
+ "\u8BF7\u53EA\u9009\u62E9\u4E00\u4E2A\u666E\u901A\u89C6\u9891\u7247\u6BB5\u3002": "Select exactly one ordinary video clip.",
20762
+ "\u8BF7\u7B49\u5F85\u5F53\u524D\u4EFB\u52A1\u7ED3\u675F\u3002": "Wait for the current task to finish.",
20763
+ "\u8BF7\u9009\u62E9\u4E00\u4E2A\u666E\u901A\u89C6\u9891\u7247\u6BB5\u3002": "Select an ordinary video clip.",
20764
+ "\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.",
20765
+ "\u8BF7\u9009\u62E9\u6E90\u5DE5\u7A0B\u76EE\u5F55\u3002": "Choose the source project directory.",
20766
+ "\u8BF7\u9009\u62E9\u72EC\u7ACB\u5DE5\u7A0B\u7684\u65B0\u4FDD\u5B58\u4F4D\u7F6E\u3002": "Choose a new location for the independent project.",
20767
+ "\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.",
20768
+ "\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.",
20769
+ "\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.",
20770
+ "\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.",
20771
+ "{0} \xB7 \u89C6\u9891\u8F68 {1} \xB7 \u8D77\u59CB\u5E27 {2}": "{0} \xB7 Video track {1} \xB7 Start frame {2}",
20772
+ "\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.",
20773
+ "{0}\u3002{1}\u6E90\u5DE5\u7A0B\u4FDD\u6301\u5F53\u524D\u5185\u5BB9\u3002": "{0}. {1} The source project keeps its current content.",
20774
+ "\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.",
20775
+ "\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.",
20776
+ "\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.",
20777
+ \u4FEE\u590D\u8FDE\u63A5: "Repair connection",
20778
+ "\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.",
20779
+ "MH \u672A\u8FDE\u63A5\uFF0C\u8BF7\u70B9\u51FB\u201C\u4FEE\u590D\u8FDE\u63A5\u201D\u3002": "MH is disconnected. Click Repair connection.",
20780
+ "MH \u5165\u53E3\u5C31\u7EEA\uFF1B\u66F4\u65B0\u5F71\u54CD\u5168\u90E8\u5F15\u7528": "MH is ready; updates affect all references",
20781
+ "\u627E\u4E0D\u5230 MH \u4E3B\u7A0B\u5E8F\u3002\u8BF7\u5B89\u88C5\u6216\u5347\u7EA7 CLI \u540E\u70B9\u51FB\u201C\u4FEE\u590D\u8FDE\u63A5\u201D\u3002": "MH could not be found. Install or upgrade the CLI, then click Repair connection.",
20782
+ "\u6B63\u5728\u4FEE\u590D MH \u8FDE\u63A5\u2026": "Repairing the MH connection\u2026",
20783
+ "MH \u8FDE\u63A5\u5DF2\u4FEE\u590D\uFF0C\u53EF\u91CD\u65B0\u70B9\u51FB\u7F16\u8F91\u6216\u66F4\u65B0\u3002": "MH connection repaired. You can click Edit or Update again.",
20784
+ "\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.",
20785
+ "CLI \u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002": "The CLI path must be absolute.",
20786
+ "\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.",
20787
+ "\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.",
20788
+ "\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.",
20789
+ "\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.",
20790
+ \u8FDE\u63A5\u4FEE\u590D\u7ED3\u679C\u89C1\u63D0\u793A\u7A97: "See the status window for the connection repair result"
20791
+ };
20792
+
20793
+ // src/i18n.ts
20794
+ var systemLocale;
20795
+ function bridgeLocale(requested = process.env.MH_UI_LOCALE) {
20796
+ if (typeof requested === "string" && /^en(?:[-_]|$)/i.test(requested)) return "en";
20797
+ if (typeof requested === "string" && /^zh(?:[-_]|$)/i.test(requested)) return "zh-CN";
20798
+ if (systemLocale) return systemLocale;
20799
+ let languages = Intl.DateTimeFormat().resolvedOptions().locale;
20800
+ if (process.platform === "darwin") {
20801
+ try {
20802
+ languages = execFileSync("/usr/bin/defaults", ["read", "-g", "AppleLanguages"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 1e3 });
20803
+ } catch {
20804
+ }
20805
+ }
20806
+ systemLocale = languages.match(/\b(en|zh)(?:[-_]|\b)/i)?.[1]?.toLowerCase() === "en" ? "en" : "zh-CN";
20807
+ return systemLocale;
20808
+ }
20809
+ function bridgeText(source, locale = bridgeLocale()) {
20810
+ return locale === "en" ? en_default2[source] ?? source : source;
20811
+ }
20812
+ function bridgeMessage(source, values, locale = bridgeLocale()) {
20813
+ return bridgeText(source, locale).replace(/\{(\d+)\}/g, (token, index) => values[Number(index)] === void 0 ? token : String(values[Number(index)]));
20814
+ }
20815
+ var bridgeName = (locale = bridgeLocale()) => bridgeText("Motion Harness \u6865\u63A5\u7EC4\u4EF6", locale);
20816
+ var bridgeEnglishCatalog = en_default2;
20817
+
20545
20818
  // src/core/entry-context.ts
20546
20819
  import { randomUUID as randomUUID6 } from "node:crypto";
20547
- import { stat as stat6 } from "node:fs/promises";
20548
- import { isAbsolute as isAbsolute7, resolve as resolve7 } from "node:path";
20820
+ import { stat as stat5 } from "node:fs/promises";
20821
+ import { isAbsolute as isAbsolute7, resolve as resolve8 } from "node:path";
20549
20822
 
20550
20823
  // src/core/ofx-entry.ts
20551
- import { realpath as realpath5, stat as stat5 } from "node:fs/promises";
20552
- import { isAbsolute as isAbsolute6, relative as relative2, sep as sep2 } from "node:path";
20824
+ import { realpath as realpath5 } from "node:fs/promises";
20825
+ import { isAbsolute as isAbsolute6, resolve as resolve7 } from "node:path";
20553
20826
  var ofxSourceSchema = external_exports.strictObject({
20554
20827
  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
20828
  });
20556
- async function canonicalPath(path, code = "BINDING_CONFLICT") {
20557
- assert2(typeof path === "string" && isAbsolute6(path) && !path.includes("\0"), code, "\u65E0\u6CD5\u6838\u5BF9\u89C6\u9891\u7684\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u8BF7\u4F7F\u7528\u83DC\u5355\u7BA1\u7406\u7247\u6BB5\u3002");
20558
- const canonical2 = await realpath5(path).catch(() => void 0);
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;
20829
+ var canonicalPath = (path) => realpath5(path).catch(() => resolve7(path));
20830
+ function verifyMetadata(metadata2, binding, artifact, allowMissing) {
20831
+ if (allowMissing && !metadata2?.["motionharness.bridge"]) return;
20565
20832
  let link2;
20566
20833
  try {
20567
- const value = JSON.parse(metadata2["motionharness.bridge"] ?? "null");
20834
+ const value = JSON.parse(metadata2?.["motionharness.bridge"] ?? "null");
20568
20835
  if (value && typeof value === "object" && !Array.isArray(value)) link2 = value;
20569
20836
  } catch {
20570
20837
  }
20571
20838
  assert2(
20572
20839
  link2?.schemaVersion === 1 && link2.bindingId === binding.id && link2.sourceId === binding.sourceId && link2.artifactId === artifact.id,
20573
20840
  "BINDING_CONFLICT",
20574
- "\u539F\u751F\u7D20\u6750\u7684\u5173\u8054\u4E0E\u5F53\u524D\u89C6\u9891\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u4ECE\u83DC\u5355\u6838\u5BF9\u5173\u8054\u3002"
20841
+ "\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
20842
  );
20576
20843
  }
20577
20844
  var OfxEntry = class {
@@ -20582,91 +20849,46 @@ var OfxEntry = class {
20582
20849
  store;
20583
20850
  host;
20584
20851
  async resolve(input, management = false) {
20585
- const request = ofxSourceSchema.parse(input);
20586
- const path = await canonicalPath(request.path);
20852
+ const request = ofxSourceSchema.parse(input), path = await canonicalPath(request.path);
20587
20853
  const catalog = await this.store.read();
20588
- const artifactsRoot = await canonicalPath(this.store.path("artifacts"));
20589
20854
  const candidates = [];
20590
20855
  for (const binding2 of Object.values(catalog.bindings)) {
20591
- if (!binding2.artifactId) continue;
20592
- const artifact2 = catalog.artifacts[binding2.artifactId];
20593
- assert2(
20594
- artifact2 && artifact2.id === binding2.artifactId && artifact2.sourceId === binding2.sourceId,
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);
20856
+ const artifact2 = binding2.artifactId ? catalog.artifacts[binding2.artifactId] : void 0;
20857
+ if (artifact2 && await canonicalPath(this.store.bindingPath(binding2, artifact2)) === path) candidates.push({ binding: binding2, artifact: artifact2 });
20858
+ }
20859
+ if (!candidates.length) {
20600
20860
  assert2(
20601
- inside && !isAbsolute6(inside) && inside !== ".." && !inside.startsWith(`..${sep2}`),
20602
- "BINDING_CONFLICT",
20603
- "\u5F53\u524D\u89C6\u9891\u5B9E\u9645\u4F4D\u7F6E\u4E0D\u5728\u6865\u63A5\u4EA7\u7269\u76EE\u5F55\u5185\uFF0C\u672A\u4F7F\u7528\u6B64\u4FA7\u680F\u5165\u53E3\u3002"
20861
+ !Object.values(catalog.artifacts).some((artifact2) => this.store.artifactPath(artifact2.relativePath) === path),
20862
+ "OFX_SOURCE_STALE",
20863
+ "\u4FA7\u680F\u4ECD\u63D0\u4F9B\u65E7\u7248\u89C6\u9891\u8DEF\u5F84\u3002\u8BF7\u4ECE\u300C\u5DE5\u4F5C\u533A \u2192 \u811A\u672C \u2192 Utility \u2192 Motion Harness \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
20864
  );
20605
- if (currentPath === path) candidates.push({ binding: binding2, artifact: artifact2 });
20606
- }
20607
- if (candidates.length === 0) {
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
20865
  }
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");
20866
+ 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
20867
  const { binding, artifact } = candidates[0];
20868
+ assert2(artifact.sourceId === binding.sourceId, "BINDING_CONFLICT", "\u5F53\u524D\u89C6\u9891\u4E0D\u5C5E\u4E8E\u5173\u8054\u7684\u6E90\u5DE5\u7A0B\u3002");
20619
20869
  const source = catalog.sources[binding.sourceId];
20620
- assert2(source && source.id === binding.sourceId, "SOURCE_MISSING", "\u5F53\u524D\u5173\u8054\u7684\u6E90\u5DE5\u7A0B\u767B\u8BB0\u4E0D\u5B58\u5728\u3002");
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");
20870
+ assert2(source, "SOURCE_MISSING", "\u5F53\u524D\u5173\u8054\u7684\u6E90\u5DE5\u7A0B\u767B\u8BB0\u4E0D\u5B58\u5728\u3002");
20626
20871
  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
20872
  assert2(
20646
- after?.isFile() && after.size === before.size && after.dev === before.dev && after.ino === before.ino && after.mtimeMs === before.mtimeMs && after.ctimeMs === before.ctimeMs,
20647
- "ARTIFACT_CHANGED",
20648
- "\u6838\u5BF9\u671F\u95F4\u89C6\u9891\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u4FA7\u680F\u5165\u53E3\u3002"
20873
+ Object.values(catalog.bindings).filter((item) => digest(item.resolve) === digest(binding.resolve)).length === 1,
20874
+ "BINDING_CONFLICT",
20875
+ "\u540C\u4E00\u539F\u7D20\u6750\u5B58\u5728\u591A\u4E2A\u5173\u8054\uFF0C\u672A\u731C\u6D4B\u76EE\u6807\u3002"
20649
20876
  );
20877
+ const target = await this.host.call("ofx_source_target", { scope, mediaPoolItemId: binding.resolve.mediaPoolItemId, path });
20650
20878
  assert2(
20651
- await canonicalPath(request.path) === path && await canonicalPath(this.store.bindingPath(binding, artifact)) === path,
20879
+ 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
20880
  "VERSION_CONFLICT",
20653
- "\u6838\u5BF9\u671F\u95F4\u89C6\u9891\u8DEF\u5F84\u53D1\u751F\u53D8\u5316\u3002"
20881
+ "\u539F\u7D20\u6750\u7684\u8EAB\u4EFD\u6216\u89C6\u9891\u8DEF\u5F84\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u5165\u53E3\u3002"
20654
20882
  );
20655
- if (!management) {
20656
- const currentSource = await stat5(sourcePath).catch(() => void 0);
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");
20883
+ verifyMetadata(target.metadata, binding, artifact, management);
20884
+ 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
20885
  return {
20665
20886
  bindingId: binding.id,
20666
20887
  sourceId: source.id,
20667
20888
  artifactId: artifact.id,
20668
20889
  expectedRevision: binding.revision,
20669
- expectedMediaFingerprint: media.fingerprint
20890
+ expectedMediaFingerprint: target.fingerprint,
20891
+ target
20670
20892
  };
20671
20893
  }
20672
20894
  };
@@ -20683,7 +20905,7 @@ var entrySelectionSchema = external_exports.strictObject({
20683
20905
  artifactId: external_exports.string().min(1).optional()
20684
20906
  });
20685
20907
  var entryInspectSchema = external_exports.union([
20686
- external_exports.strictObject({ selection: entrySelectionSchema }),
20908
+ external_exports.strictObject({ selection: entrySelectionSchema, includeInstances: external_exports.literal(true).optional() }),
20687
20909
  external_exports.strictObject({ currentSelection: external_exports.literal(true) }),
20688
20910
  external_exports.strictObject({ ofxSource: ofxSourceSchema })
20689
20911
  ]);
@@ -20738,7 +20960,7 @@ function activeTaskScope(job, binding, selection) {
20738
20960
  const instance = job.operation === "duplicate" && job.request.bindingId === binding.id && job.request.timelineId === selection.timelineId && job.request.itemId === selection.itemId;
20739
20961
  const canControl = !multiple && Boolean(direct || singleBatch || instance);
20740
20962
  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 ? `\u6B64\u4EFB\u52A1\u6D89\u53CA ${Math.max(bindingIds.length, targets?.length ?? 0)} \u4E2A\u7D20\u6750\uFF1B\u8BF7\u4ECE\u539F\u4EFB\u52A1\u5165\u53E3\u7BA1\u7406\u5B8C\u6574\u8303\u56F4\u3002` : "\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";
20963
+ 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
20964
  return { kind, canControl, bindingIds, message };
20743
20965
  }
20744
20966
  function activeTask(catalog, binding, sourcePath) {
@@ -20746,7 +20968,7 @@ function activeTask(catalog, binding, sourcePath) {
20746
20968
  if (terminalPhases.includes(job.phase) && job.phase !== "outcome-unknown") return false;
20747
20969
  const targets = Array.isArray(job.request.targets) ? job.request.targets : [];
20748
20970
  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" && resolve7(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);
20971
+ 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
20972
  }).sort((a, b) => Number(b.phase === "outcome-unknown") - Number(a.phase === "outcome-unknown") || b.createdAt.localeCompare(a.createdAt))[0];
20751
20973
  }
20752
20974
  var EntryContext = class {
@@ -20759,7 +20981,7 @@ var EntryContext = class {
20759
20981
  host;
20760
20982
  mh;
20761
20983
  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";
20984
+ 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
20985
  let raw;
20764
20986
  try {
20765
20987
  raw = await this.host.call("selection", { plainMediaOnly: true });
@@ -20771,23 +20993,23 @@ var EntryContext = class {
20771
20993
  assert2(
20772
20994
  response.success,
20773
20995
  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"
20996
+ 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
20997
  );
20776
20998
  const snapshot = response.data;
20777
20999
  assert2(
20778
21000
  snapshot.scope && snapshot.timelineId,
20779
21001
  checking ? "VERSION_CONFLICT" : "SELECTION_UNAVAILABLE",
20780
- checking ? changed : "\u8BF7\u5148\u6253\u5F00\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E0E\u65F6\u95F4\u7EBF\u3002"
21002
+ checking ? changed : bridgeText("\u8BF7\u5148\u6253\u5F00\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E0E\u65F6\u95F4\u7EBF\u3002")
20781
21003
  );
20782
21004
  assert2(
20783
21005
  snapshot.selectedCount === 1 && snapshot.item,
20784
21006
  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"
21007
+ 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
21008
  );
20787
21009
  assert2(
20788
21010
  snapshot.item.mediaPoolItemId,
20789
21011
  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"
21012
+ checking ? changed : bridgeText("\u6240\u9009\u7247\u6BB5\u4E0D\u662F\u53EF\u76F4\u63A5\u7BA1\u7406\u7684\u666E\u901A\u89C6\u9891\u7D20\u6750\u3002")
20791
21013
  );
20792
21014
  const selection = {
20793
21015
  scope: snapshot.scope,
@@ -20797,17 +21019,17 @@ var EntryContext = class {
20797
21019
  };
20798
21020
  return { snapshot, selection };
20799
21021
  }
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 });
21022
+ async target(selection, resolved) {
21023
+ 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"));
21024
+ const native = resolved ?? await this.host.call("entry_target", { selection });
20803
21025
  assert2(
20804
21026
  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
21027
  "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"
21028
+ 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
21029
  );
20808
21030
  const catalog = await this.store.read();
20809
21031
  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");
21032
+ 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
21033
  const binding = matches[0];
20812
21034
  let link2;
20813
21035
  const encoded = native.metadata?.["motionharness.bridge"];
@@ -20820,8 +21042,8 @@ var EntryContext = class {
20820
21042
  }
20821
21043
  const conflict = Boolean(encoded && (!binding || !link2 || link2.schemaVersion !== 1 || link2.bindingId !== binding.id || link2.sourceId !== binding.sourceId || link2.artifactId !== binding.artifactId));
20822
21044
  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");
21045
+ 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"));
21046
+ } else assert2(!selection.bindingId && !selection.sourceId && !selection.artifactId, "VERSION_CONFLICT", bridgeText("\u539F\u5173\u8054\u767B\u8BB0\u5DF2\u7ECF\u4E0D\u53EF\u7528\u3002"));
20825
21047
  const verified = binding ? {
20826
21048
  ...selection,
20827
21049
  bindingId: binding.id,
@@ -20834,10 +21056,12 @@ var EntryContext = class {
20834
21056
  const request = entryInspectSchema.parse(input);
20835
21057
  const captured = "currentSelection" in request ? await this.currentSelection() : void 0;
20836
21058
  let selection;
21059
+ let resolved;
20837
21060
  if ("ofxSource" in request) {
20838
- const resolved = await new OfxEntry(this.store, this.host).resolve(request.ofxSource, true);
20839
- const binding2 = (await this.store.read()).bindings[resolved.bindingId];
20840
- assert2(binding2 && binding2.revision === resolved.expectedRevision, "VERSION_CONFLICT", "\u6253\u5F00\u66F4\u591A\u64CD\u4F5C\u65F6\u5173\u8054\u5DF2\u6539\u53D8\u3002");
21061
+ const entry = await new OfxEntry(this.store, this.host).resolve(request.ofxSource, true);
21062
+ const binding2 = (await this.store.read()).bindings[entry.bindingId];
21063
+ assert2(binding2 && binding2.revision === entry.expectedRevision, "VERSION_CONFLICT", bridgeText("\u6253\u5F00\u66F4\u591A\u64CD\u4F5C\u65F6\u5173\u8054\u5DF2\u6539\u53D8\u3002"));
21064
+ resolved = { ...entry.target, name: String(entry.target.clipProperties?.["Clip Name"] ?? "") };
20841
21065
  selection = {
20842
21066
  scope: { databaseId: binding2.resolve.databaseId, projectId: binding2.resolve.projectId },
20843
21067
  mediaPoolItemId: binding2.resolve.mediaPoolItemId,
@@ -20847,59 +21071,61 @@ var EntryContext = class {
20847
21071
  path: request.ofxSource.path
20848
21072
  };
20849
21073
  } else selection = "selection" in request ? request.selection : captured.selection;
20850
- const target = await this.target(selection), { binding, catalog, conflict, missingAssociation } = target;
21074
+ const target = await this.target(selection, resolved), { binding, catalog, conflict, missingAssociation } = target;
20851
21075
  const source = binding ? catalog.sources[binding.sourceId] : void 0;
20852
21076
  const artifact = binding?.artifactId ? catalog.artifacts[binding.artifactId] : void 0;
20853
- const sourcePresent = source ? await stat6(this.store.path(source.locator)).then((info) => info.isDirectory(), () => false) : false;
20854
- const currentAvailable = artifact ? await stat6(this.store.artifactPath(artifact.relativePath)).then((info) => info.isFile() && info.size === artifact.bytes, () => false) : false;
21077
+ const sourcePresent = source ? await stat5(this.store.path(source.locator)).then((info) => info.isDirectory(), () => false) : false;
21078
+ const currentAvailable = artifact ? await stat5(this.store.artifactPath(artifact.relativePath)).then((info) => info.isFile() && info.size === artifact.bytes, () => false) : false;
20855
21079
  const history = [];
20856
21080
  if (binding && artifact) {
20857
21081
  for (const version2 of appliedHistory(catalog, binding)) {
20858
21082
  const previous2 = catalog.artifacts[version2.artifactId];
20859
21083
  if (previous2.id === artifact.id || !sameOutputSpec(previous2.spec, artifact.spec)) continue;
20860
- const available = await stat6(this.store.artifactPath(previous2.relativePath)).then((info) => info.isFile() && info.size === previous2.bytes, () => false);
21084
+ const available = await stat5(this.store.artifactPath(previous2.relativePath)).then((info) => info.isFile() && info.size === previous2.bytes, () => false);
20861
21085
  const spec = previous2.spec;
20862
21086
  const codec2 = spec.codec === "prores-4444-xq" ? "ProRes 4444 XQ" : spec.format === "mov" ? "ProRes 4444" : "MP4";
20863
- const at = new Date(version2.appliedAt).toLocaleString("zh-CN", { hour12: false });
21087
+ const at = new Date(version2.appliedAt).toLocaleString(bridgeLocale(), { hour12: false });
20864
21088
  history.push({ ...version2, label: `${at} \xB7 ${codec2} \xB7 ${spec.width}\xD7${spec.height}`, current: false, available });
20865
21089
  }
20866
21090
  }
20867
21091
  const instances = [];
20868
- if (selection.path && !conflict) {
20869
- const media = await this.host.media(selection.scope, selection.mediaPoolItemId);
21092
+ const instancesLoaded = "includeInstances" in request && request.includeInstances === true;
21093
+ if (instancesLoaded && !conflict && !missingAssociation) {
21094
+ const media = await this.host.mediaUsages(selection.scope, selection.mediaPoolItemId);
20870
21095
  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");
21096
+ 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
21097
  if (media.usageScanComplete) for (const use of media.uses) instances.push({
20873
21098
  timelineId: use.timelineId,
20874
21099
  itemId: use.id,
20875
- label: `${discovery.timelines.find((timeline) => timeline.id === use.timelineId)?.name ?? "\u65F6\u95F4\u7EBF"} \xB7 \u89C6\u9891\u8F68 ${use.track} \xB7 \u8D77\u59CB\u5E27 ${use.startFrame}`,
21100
+ 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
21101
  mediaPoolItemId: use.mediaPoolItemId
20877
21102
  });
20878
21103
  }
20879
21104
  const task = binding ? activeTask(catalog, binding, source ? this.store.path(source.locator) : void 0) : void 0;
20880
21105
  const taskScope = task && binding ? activeTaskScope(task, binding, target.selection) : null;
20881
21106
  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" : "";
21107
+ 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
21108
  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 Hotion Harness\u3002\u53EF\u4EE5\u7F16\u8F91\u6E90\u5DE5\u7A0B\u6216\u66F4\u65B0\u753B\u9762\u3002");
21109
+ 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 Motion Harness\u3002\u53EF\u4EE5\u7F16\u8F91\u6E90\u5DE5\u7A0B\u6216\u66F4\u65B0\u753B\u9762\u3002"));
20885
21110
  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";
21111
+ 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
21112
  const context = {
20888
21113
  selection: target.selection,
20889
- title: source?.name ?? target.native.name ?? "Hotion Harness",
21114
+ title: source?.name ?? target.native.name ?? "Motion Harness",
20890
21115
  status,
20891
21116
  message,
20892
21117
  sourceDirectory: source && !conflict ? this.store.path(source.locator) : void 0,
20893
21118
  scopeLabel: location ? `${location} \xB7 ${scopeMessage}` : scopeMessage,
20894
21119
  history,
20895
21120
  instances,
21121
+ instancesLoaded,
20896
21122
  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")
21123
+ edit: action(ready && sourcePresent, blocked || bridgeText("\u627E\u4E0D\u5230\u6E90\u5DE5\u7A0B\uFF0C\u8BF7\u5148\u91CD\u65B0\u5B9A\u4F4D\u3002")),
21124
+ 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"))),
21125
+ 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")),
21126
+ 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")),
21127
+ 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")),
21128
+ 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
21129
  },
20904
21130
  activeTask: task ? { ...task, taskId: task.id } : null,
20905
21131
  activeTaskScope: taskScope
@@ -20909,7 +21135,7 @@ var EntryContext = class {
20909
21135
  assert2(
20910
21136
  current.snapshot.fingerprint === captured.snapshot.fingerprint && digest(current.selection) === digest(captured.selection) && digest(current.snapshot) === digest(captured.snapshot),
20911
21137
  "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"
21138
+ bridgeText("\u8BFB\u53D6\u671F\u95F4\u6240\u9009\u7247\u6BB5\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7247\u6BB5\u7BA1\u7406\u3002")
20913
21139
  );
20914
21140
  }
20915
21141
  return context;
@@ -20917,23 +21143,23 @@ var EntryContext = class {
20917
21143
  async prepare(input) {
20918
21144
  const request = entryPrepareSchema.parse(input), context = await this.inspect({ selection: request.selection });
20919
21145
  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");
21146
+ 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
21147
  const catalog = await this.store.read(), binding = catalog.bindings[context.selection.bindingId];
20922
21148
  const source = binding ? catalog.sources[binding.sourceId] : void 0;
20923
21149
  const selection = context.selection, idempotencyKey = randomUUID6();
20924
21150
  assert2(
20925
21151
  binding && source && binding.sourceId === selection.sourceId && binding.artifactId === selection.artifactId && digest(binding.resolve) === digest({ ...selection.scope, mediaPoolItemId: selection.mediaPoolItemId }),
20926
21152
  "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"
21153
+ 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
21154
  );
20929
21155
  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(resolve7(request.projectPath)), observation = await this.mh.inspect(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");
21156
+ assert2(request.projectPath && isAbsolute7(request.projectPath) && source.observation?.contentVersion, "INVALID_REQUEST", bridgeText("\u8BF7\u9009\u62E9\u6E90\u5DE5\u7A0B\u76EE\u5F55\u3002"));
21157
+ const projectPath = await this.mh.projectPath(resolve8(request.projectPath)), observation = await this.mh.inspect(projectPath);
21158
+ 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
21159
  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",
21160
+ title: bridgeText("\u4F7F\u7528\u8FD9\u4E2A\u6E90\u5DE5\u7A0B\u4F4D\u7F6E\uFF1F"),
21161
+ 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"),
21162
+ scopeLabel: bridgeText("\u540C\u4E00\u6E90\u5DE5\u7A0B\u7684\u6240\u6709\u5173\u8054\u4F7F\u7528\u65B0\u76EE\u5F55\u3002"),
20937
21163
  command: "relink",
20938
21164
  request: {
20939
21165
  sourceId: source.id,
@@ -20945,33 +21171,31 @@ var EntryContext = class {
20945
21171
  }
20946
21172
  };
20947
21173
  }
20948
- const media = await this.host.media(selection.scope, selection.mediaPoolItemId);
21174
+ 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"));
21175
+ const media = request.operation === "duplicate" ? await this.host.mediaUsages(selection.scope, selection.mediaPoolItemId) : await this.host.media(selection.scope, selection.mediaPoolItemId);
20949
21176
  assert2(
20950
21177
  digest(media.scope) === digest(selection.scope) && media.mediaPoolItemId === selection.mediaPoolItemId,
20951
21178
  "VERSION_CONFLICT",
20952
- "\u7D20\u6750\u4F5C\u7528\u57DF\u5DF2\u6539\u53D8\u3002"
21179
+ bridgeText("\u7D20\u6750\u4F5C\u7528\u57DF\u5DF2\u6539\u53D8\u3002")
20953
21180
  );
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
21181
  const target = selection.itemId ? media.uses.filter((item) => item.timelineId === selection.timelineId && item.id === selection.itemId) : [];
20956
- if (selection.itemId) assert2(target.length === 1 && target[0].mediaPoolItemId === selection.mediaPoolItemId, "VERSION_CONFLICT", "\u6240\u9009\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u5DF2\u6539\u53D8\u3002");
20957
- const scopeLabel = `\u5C06\u5F71\u54CD\u5F53\u524D\u8FBE\u82AC\u5947\u5DE5\u7A0B\u4E2D\u6B64\u7D20\u6750\u7684 ${media.uses.length} \u5904\u5F15\u7528\u3002`;
20958
- const timeline = selection.timelineId ? await this.host.timeline(selection.scope, selection.timelineId) : void 0;
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");
21182
+ 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");
21183
+ const timeline = request.operation === "duplicate" && selection.timelineId ? await this.host.timeline(selection.scope, selection.timelineId) : void 0;
21184
+ 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
21185
  const guard = { expectedMediaFingerprint: media.fingerprint, ...timeline ? { expectedTimelineFingerprint: timeline.fingerprint } : {} };
20961
21186
  const fixedSelection = { ...selection, ...guard };
20962
21187
  if (request.operation === "restore") {
20963
21188
  assert2(
20964
21189
  request.artifactId && context.history.some((version3) => version3.artifactId === request.artifactId && version3.available),
20965
21190
  "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"
21191
+ 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
21192
  );
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
21193
  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");
21194
+ 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
21195
  const version2 = context.history.find((value) => value.artifactId === artifact2.id);
20972
21196
  return {
20973
- title: "\u6062\u590D\u8FD9\u4E2A\u5DF2\u5E94\u7528\u7248\u672C\uFF1F",
20974
- message: `${version2.label}\u3002${scopeLabel}\u6E90\u5DE5\u7A0B\u4FDD\u6301\u5F53\u524D\u5185\u5BB9\u3002`,
21197
+ title: bridgeText("\u6062\u590D\u8FD9\u4E2A\u5DF2\u5E94\u7528\u7248\u672C\uFF1F"),
21198
+ message: bridgeMessage("{0}\u3002{1}\u6E90\u5DE5\u7A0B\u4FDD\u6301\u5F53\u524D\u5185\u5BB9\u3002", [version2.label, scopeLabel]),
20975
21199
  scopeLabel,
20976
21200
  command: "restore",
20977
21201
  request: {
@@ -20985,31 +21209,36 @@ var EntryContext = class {
20985
21209
  };
20986
21210
  }
20987
21211
  if (request.operation === "duplicate") {
20988
- assert2(timeline && selection.timelineId && selection.itemId, "INVALID_REQUEST", "\u8BF7\u9009\u62E9\u8981\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\u7684\u5177\u4F53\u65F6\u95F4\u7EBF\u7247\u6BB5\u3002");
20989
- assert2(request.projectPath && isAbsolute7(request.projectPath), "INVALID_REQUEST", "\u8BF7\u9009\u62E9\u72EC\u7ACB\u5DE5\u7A0B\u7684\u65B0\u4FDD\u5B58\u4F4D\u7F6E\u3002");
20990
- assert2(!await stat6(request.projectPath).then(() => true, () => false), "TARGET_OCCUPIED", "\u65B0\u4F4D\u7F6E\u5DF2\u7ECF\u5B58\u5728\uFF0C\u672A\u8986\u76D6\u73B0\u6709\u5DE5\u7A0B\u3002");
21212
+ assert2(
21213
+ media.usageScanComplete && target.length === 1 && target[0].mediaPoolItemId === selection.mediaPoolItemId,
21214
+ "UNSUPPORTED_TIMELINE_ITEM",
21215
+ bridgeText("\u4E0D\u80FD\u5B8C\u6574\u6838\u5BF9\u8BE5\u7D20\u6750\u7684\u4F7F\u7528\u8303\u56F4\uFF0C\u672A\u51C6\u5907\u4FEE\u6539\u3002")
21216
+ );
21217
+ 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"));
21218
+ assert2(request.projectPath && isAbsolute7(request.projectPath), "INVALID_REQUEST", bridgeText("\u8BF7\u9009\u62E9\u72EC\u7ACB\u5DE5\u7A0B\u7684\u65B0\u4FDD\u5B58\u4F4D\u7F6E\u3002"));
21219
+ 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
21220
  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");
21221
+ 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
21222
  const artifact2 = binding.artifactId ? catalog.artifacts[binding.artifactId] : void 0;
20994
21223
  assert2(
20995
21224
  artifact2 && artifact2.spec.fps.num === 30 * artifact2.spec.fps.den && timeline.fps.num === 30 * timeline.fps.den,
20996
21225
  "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"
21226
+ 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
21227
  );
20999
21228
  assert2(
21000
21229
  media.uses.every((item) => !item.unsupported.length) && !target[0].intrinsicEntry && target[0].kind === "video",
21001
21230
  "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"
21231
+ 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
21232
  );
21004
21233
  return {
21005
- title: "\u4EC5\u4E3A\u8FD9\u4E2A\u7247\u6BB5\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\uFF1F",
21006
- message: `\u590D\u5236\u53EF\u7F16\u8F91\u5DE5\u7A0B\uFF0C\u5E76\u53EA\u6539\u53D8\u6240\u9009\u201C${context.title}\u201D\u7247\u6BB5\u7684\u7D20\u6750\u5173\u8054\u3002\u5176\u4ED6\u5F15\u7528\u7EE7\u7EED\u4F7F\u7528\u539F\u5DE5\u7A0B\u3002`,
21007
- scopeLabel: "\u4EC5\u5F71\u54CD\u9009\u5B9A\u7684\u4E00\u4E2A\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u3002",
21234
+ title: bridgeText("\u4EC5\u4E3A\u8FD9\u4E2A\u7247\u6BB5\u521B\u5EFA\u72EC\u7ACB\u526F\u672C\uFF1F"),
21235
+ 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]),
21236
+ scopeLabel: bridgeText("\u4EC5\u5F71\u54CD\u9009\u5B9A\u7684\u4E00\u4E2A\u65F6\u95F4\u7EBF\u5B9E\u4F8B\u3002"),
21008
21237
  command: "duplicate",
21009
21238
  request: {
21010
21239
  bindingId: binding.id,
21011
21240
  sourceId: source.id,
21012
- projectPath: resolve7(request.projectPath),
21241
+ projectPath: resolve8(request.projectPath),
21013
21242
  expectedContentVersion: observation.contentVersion,
21014
21243
  expectedRevision: binding.revision,
21015
21244
  timelineId: selection.timelineId,
@@ -21021,11 +21250,11 @@ var EntryContext = class {
21021
21250
  };
21022
21251
  }
21023
21252
  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 && resolve7(media.path) === this.store.bindingPath(binding, artifact) && await fileDigest(media.path).catch(() => null) === artifact.sha256, "RECOVERY_CONFLICT", "\u5A92\u4F53\u8EAB\u4EFD\u3001\u8DEF\u5F84\u6216\u5185\u5BB9\u4E0D\u7B26\u5408\u539F\u767B\u8BB0\uFF0C\u4E0D\u80FD\u81EA\u52A8\u4FEE\u590D\u3002");
21253
+ 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"));
21254
+ 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
21255
  return {
21027
- title: "\u4FEE\u590D\u6240\u9009\u7D20\u6750\u7684\u5173\u8054\uFF1F",
21028
- message: `\u5DF2\u6309\u539F\u751F\u5A92\u4F53\u8EAB\u4EFD\u548C\u89C6\u9891\u5185\u5BB9\u5339\u914D\u201C${context.title}\u201D\u3002\u53EA\u8865\u56DE\u5173\u8054\u5143\u6570\u636E\uFF0C\u4E0D\u91CD\u65B0\u751F\u6210\u89C6\u9891\u3002`,
21256
+ title: bridgeText("\u4FEE\u590D\u6240\u9009\u7D20\u6750\u7684\u5173\u8054\uFF1F"),
21257
+ 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
21258
  scopeLabel,
21030
21259
  command: "restore",
21031
21260
  request: {
@@ -21042,20 +21271,20 @@ var EntryContext = class {
21042
21271
 
21043
21272
  // src/native-install.ts
21044
21273
  import { homedir as homedir3 } from "node:os";
21045
- import { basename as basename4, delimiter as delimiter3, dirname as dirname8, isAbsolute as isAbsolute8, join as join7, resolve as resolve9 } from "node:path";
21046
- import { access as access3, mkdir as mkdir8, readFile as readFile9, writeFile, rename as rename6, rm as rm7, readdir as readdir2, stat as stat7, lstat as lstat5 } from "node:fs/promises";
21274
+ import { basename as basename4, delimiter as delimiter3, dirname as dirname8, isAbsolute as isAbsolute8, join as join7, resolve as resolve10 } from "node:path";
21275
+ import { access as access3, mkdir as mkdir8, readFile as readFile9, writeFile, rename as rename6, rm as rm7, rmdir, readdir as readdir2, stat as stat6, lstat as lstat5 } from "node:fs/promises";
21047
21276
  import { constants as constants6 } from "node:fs";
21048
21277
  import { randomUUID as randomUUID7 } from "node:crypto";
21049
21278
 
21050
21279
  // src/native-permissions.ts
21051
21280
  import { access as access2, lstat as lstat4 } from "node:fs/promises";
21052
21281
  import { constants as constants5 } from "node:fs";
21053
- import { dirname as dirname7, join as join6, resolve as resolve8 } from "node:path";
21282
+ import { dirname as dirname7, join as join6, resolve as resolve9 } from "node:path";
21054
21283
  var systemPluginRoot = "/Library/OFX/Plugins";
21055
21284
  async function prepareOfxPermissions(componentRoot, pluginRoot, directories) {
21056
21285
  let writable = true;
21057
21286
  for (const directory of new Set(directories)) {
21058
- let current = resolve8(directory);
21287
+ let current = resolve9(directory);
21059
21288
  while (true) {
21060
21289
  const info2 = await lstat4(current).catch((error48) => {
21061
21290
  if (error48.code === "ENOENT") return null;
@@ -21081,7 +21310,7 @@ async function prepareOfxPermissions(componentRoot, pluginRoot, directories) {
21081
21310
  }
21082
21311
  if (writable) return { authorized: false };
21083
21312
  const uid = process.getuid?.(), gid = process.getgid?.();
21084
- if (process.platform !== "darwin" || resolve8(pluginRoot) !== systemPluginRoot || !uid || gid === void 0) {
21313
+ if (process.platform !== "darwin" || resolve9(pluginRoot) !== systemPluginRoot || !uid || gid === void 0) {
21085
21314
  throw new BridgeError(
21086
21315
  "OFX_PERMISSION_REQUIRED",
21087
21316
  "OFX \u76EE\u5F55\u4E0D\u53EF\u5199\uFF0C\u672A\u5B89\u88C5\u6216\u5347\u7EA7\u4EFB\u4F55\u5165\u53E3\u6587\u4EF6\u3002",
@@ -21128,7 +21357,7 @@ async function previous(root) {
21128
21357
  }
21129
21358
  async function nativeStatus(configRoot) {
21130
21359
  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 stat7(file2.path)).mode & 511) === file2.mode), () => false));
21360
+ 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));
21132
21361
  const helperPath = manifest.statusExecutable ?? join7(configRoot, "bin/HotionHarnessStatus");
21133
21362
  const applicationRoot = join7(configRoot, "bin", statusAppName);
21134
21363
  const application = helperPath === join7(applicationRoot, statusAppBinary);
@@ -21136,8 +21365,8 @@ async function nativeStatus(configRoot) {
21136
21365
  const applicationFiles = application ? manifest.files.filter((file2) => file2.path.startsWith(applicationRoot + "/")) : [];
21137
21366
  const applicationComplete = !application || applicationFiles.some((file2) => file2.path === join7(applicationRoot, "Contents/Info.plist")) && (await Promise.all(applicationFiles.map(matches))).every(Boolean);
21138
21367
  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((name) => matches(manifest.files.find((file2) => basename4(file2.path) === name))))).every(Boolean);
21368
+ const names = [["\u7F16\u8F91\u5DE5\u7A0B.py", "Edit project.py"], ["\u66F4\u65B0\u5230\u8FBE\u82AC\u5947.py", "Update in DaVinci Resolve.py"]];
21369
+ 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
21370
  const pluginFiles = manifest.files.filter((file2) => file2.path.split(/[\\/]/).includes("HotionHarness.ofx.bundle"));
21142
21371
  const pluginInstalled = manifest.entry.ofx === "manual-attachment" && pluginFiles.length > 0 && (await Promise.all(pluginFiles.map(matches))).every(Boolean);
21143
21372
  return {
@@ -21160,16 +21389,57 @@ async function publish(path, bytes, mode = 384) {
21160
21389
  }
21161
21390
  }
21162
21391
  async function toolPath(command) {
21163
- const candidates = isAbsolute8(command) ? [command] : (process.env.PATH ?? "").split(delimiter3).filter(Boolean).map((directory) => resolve9(directory, command));
21392
+ const candidates = isAbsolute8(command) ? [command] : (process.env.PATH ?? "").split(delimiter3).filter(Boolean).map((directory) => resolve10(directory, command));
21164
21393
  for (const candidate of candidates) {
21165
21394
  try {
21166
21395
  await access3(candidate, constants6.X_OK);
21167
- if ((await stat7(candidate)).isFile()) return candidate;
21396
+ if ((await stat6(candidate)).isFile()) return candidate;
21168
21397
  } catch {
21169
21398
  }
21170
21399
  }
21171
21400
  return void 0;
21172
21401
  }
21402
+ async function cliLauncher(cliPath) {
21403
+ const packageJson = process.env.MH_NPM_PACKAGE_JSON;
21404
+ if (!packageJson || !isAbsolute8(packageJson)) return void 0;
21405
+ const pkg = JSON.parse(await readFile9(packageJson, "utf8"));
21406
+ if (pkg.name !== "@motionharness/cli" || typeof pkg.bin?.mh !== "string") return void 0;
21407
+ const script = resolve10(dirname8(packageJson), pkg.bin.mh);
21408
+ if (!script.startsWith(dirname8(packageJson) + "/") || !(await stat6(script)).isFile()) return void 0;
21409
+ assert2(isAbsolute8(cliPath), "INSTALL_CONFLICT", "CLI \u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002");
21410
+ return { executable: process.execPath, script };
21411
+ }
21412
+ async function repairNativeConnection(options) {
21413
+ await finishNativeInstall(options.configRoot);
21414
+ const record2 = await readNativeFile(recordPath(options.configRoot));
21415
+ assert2(record2, "INSTALL_MISSING", "\u6865\u63A5\u5B89\u88C5\u8BB0\u5F55\u7F3A\u5931\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install\u3002");
21416
+ const manifest = JSON.parse(record2.bytes.toString("utf8"));
21417
+ assert2(manifest.nativeConfig, "INSTALL_MISSING", "\u6865\u63A5\u914D\u7F6E\u7F3A\u5931\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install\u3002");
21418
+ const config2 = await readNativeFile(manifest.nativeConfig);
21419
+ assert2(config2, "INSTALL_MISSING", "\u6865\u63A5\u914D\u7F6E\u7F3A\u5931\uFF0C\u8BF7\u8FD0\u884C mh bridge davinci install\u3002");
21420
+ const saved = manifest.files.find((file2) => file2.path === manifest.nativeConfig);
21421
+ assert2(
21422
+ saved?.sha256 === "sha256:" + config2.sha256 && (saved.mode === void 0 || saved.mode === config2.mode),
21423
+ "INSTALL_CONFLICT",
21424
+ "\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"
21425
+ );
21426
+ const value = JSON.parse(config2.bytes.toString("utf8"));
21427
+ const launcher = await cliLauncher(options.cliPath);
21428
+ const tools = { ...value.tools, node: process.execPath };
21429
+ const toolDirectories = [...new Set(Object.values(tools).filter((path) => typeof path === "string" && isAbsolute8(path)).map(dirname8))];
21430
+ const bytes = JSON.stringify({ ...value, cliPath: options.cliPath, ...launcher ? { cliLauncher: launcher } : {}, tools, toolDirectories }, null, 2) + "\n";
21431
+ const toolchainPath = join7(options.configRoot, "toolchain.json");
21432
+ const toolchain = await readNativeFile(toolchainPath), savedTools = manifest.files.find((file2) => file2.path === toolchainPath);
21433
+ 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");
21434
+ const changes = [
21435
+ { path: manifest.nativeConfig, bytes, mode: config2.mode, expectedBefore: nativeFileState(config2) },
21436
+ { path: toolchainPath, bytes: JSON.stringify({ schemaVersion: 1, tools, toolDirectories }, null, 2) + "\n", mode: toolchain.mode, expectedBefore: nativeFileState(toolchain) }
21437
+ ];
21438
+ 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);
21439
+ changes.push({ path: recordPath(options.configRoot), bytes: JSON.stringify(manifest), mode: record2.mode, expectedBefore: nativeFileState(record2) });
21440
+ await publishNativeFiles(options.configRoot, changes);
21441
+ return { repaired: true, restartResolveRequired: false };
21442
+ }
21173
21443
  async function bundleFiles(source, destination, executable) {
21174
21444
  const files = [];
21175
21445
  for (const item of await readdir2(source, { withFileTypes: true })) {
@@ -21178,7 +21448,7 @@ async function bundleFiles(source, destination, executable) {
21178
21448
  if (item.isDirectory()) files.push(...await bundleFiles(path, output, executable));
21179
21449
  else {
21180
21450
  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 readFile9(path), mode: output === executable || (await stat7(path)).mode & 73 ? 493 : 420 });
21451
+ files.push({ path: output, bytes: await readFile9(path), mode: output === executable || (await stat6(path)).mode & 73 ? 493 : 420 });
21182
21452
  }
21183
21453
  }
21184
21454
  return files;
@@ -21193,9 +21463,10 @@ async function installNative(options) {
21193
21463
  });
21194
21464
  const old = previousRecord ? JSON.parse(previousRecord.toString("utf8")) : { version: 1, files: [], entry: { automaticAttachment: false, ofx: "unavailable" } };
21195
21465
  const oldByPath = new Map(old.files.map((file2) => [file2.path, file2]));
21196
- const expectedRecord = previousRecord ? { sha256: sha256(previousRecord), mode: (await stat7(recordPath(options.configRoot))).mode & 511 } : null;
21466
+ const expectedRecord = previousRecord ? { sha256: sha256(previousRecord), mode: (await stat6(recordPath(options.configRoot))).mode & 511 } : null;
21197
21467
  const validated = /* @__PURE__ */ new Map();
21198
- const scriptsRoot = process.env.MH_DAVINCI_SCRIPTS_DIR ?? (process.platform === "darwin" ? join7(homedir3(), "Library/Application Support/Blackmagic Design/DaVinci Resolve/Fusion/Scripts/Utility/Hotion Harness") : process.platform === "win32" ? join7(process.env.APPDATA ?? homedir3(), "Blackmagic Design/DaVinci Resolve/Support/Fusion/Scripts/Utility/Hotion Harness") : join7(homedir3(), ".local/share/DaVinciResolve/Fusion/Scripts/Utility/Hotion Harness"));
21468
+ const locale = bridgeLocale(), label = bridgeName(locale);
21469
+ const scriptsRoot = process.env.MH_DAVINCI_SCRIPTS_DIR ?? (process.platform === "darwin" ? join7(homedir3(), "Library/Application Support/Blackmagic Design/DaVinci Resolve/Fusion/Scripts/Utility", label) : process.platform === "win32" ? join7(process.env.APPDATA ?? homedir3(), "Blackmagic Design/DaVinci Resolve/Support/Fusion/Scripts/Utility", label) : join7(homedir3(), ".local/share/DaVinciResolve/Fusion/Scripts/Utility", label));
21199
21470
  const nativeConfig = process.env.MH_DAVINCI_NATIVE_CONFIG ?? (process.platform === "darwin" ? join7(homedir3(), "Library/Application Support/Hotion Harness/bridge/davinci/native-entry.json") : join7(options.configRoot, "native-entry.json"));
21200
21471
  const template = await readFile9(join7(options.componentRoot, "resources/menu-entry.py"), "utf8");
21201
21472
  const helper = join7(options.componentRoot, "resources/HotionHarnessStatus");
@@ -21218,13 +21489,15 @@ async function installNative(options) {
21218
21489
  const toolDirectories = [...new Set(Object.values(tools).filter((path) => Boolean(path)).map(dirname8))];
21219
21490
  const toolchain = { schemaVersion: 1, tools, toolDirectories };
21220
21491
  const desired = [];
21221
- const guideNames = ["index.html", "resolve-sidebar.png"];
21492
+ const translationsPath = join7(options.configRoot, "i18n/en.json");
21493
+ desired.push({ path: translationsPath, bytes: JSON.stringify(bridgeEnglishCatalog), mode: 420 });
21494
+ const guideNames = ["index.html", "en.html"];
21222
21495
  const guideDirectory = join7(options.componentRoot, "resources/sidebar-help");
21223
21496
  const guideAvailable = (await Promise.all(guideNames.map((name) => lstat5(join7(guideDirectory, name)).then((info) => info.isFile(), (error48) => {
21224
21497
  if (error48.code === "ENOENT") return false;
21225
21498
  throw error48;
21226
21499
  })))).every(Boolean);
21227
- const sidebarGuidePath = guideAvailable ? join7(options.configRoot, "help/sidebar/index.html") : void 0;
21500
+ const sidebarGuidePath = guideAvailable ? join7(options.configRoot, "help/sidebar", locale === "en" ? "en.html" : "index.html") : void 0;
21228
21501
  if (guideAvailable) for (const name of guideNames) desired.push({
21229
21502
  path: join7(options.configRoot, "help/sidebar", name),
21230
21503
  bytes: await readFile9(join7(guideDirectory, name)),
@@ -21239,21 +21512,25 @@ async function installNative(options) {
21239
21512
  );
21240
21513
  } else if (statusExecutable) desired.push({ path: statusExecutable, bytes: await readFile9(helper), mode: 493 });
21241
21514
  desired.push({ path: join7(options.configRoot, "toolchain.json"), bytes: JSON.stringify(toolchain, null, 2) + "\n", mode: 384 });
21515
+ const launcher = await cliLauncher(options.cliPath);
21242
21516
  desired.push({ path: nativeConfig, bytes: JSON.stringify({
21243
21517
  schemaVersion: 1,
21244
21518
  ofxSourceProtocol: 1,
21245
21519
  ofxManagementProtocol: 1,
21246
21520
  ofxSelectionReviewProtocol: 1,
21247
21521
  cliPath: options.cliPath,
21522
+ ...launcher ? { cliLauncher: launcher } : {},
21248
21523
  workspace: options.workspace,
21249
21524
  bridgeDirectory: dirname8(options.configRoot),
21250
21525
  tools,
21251
21526
  toolDirectories,
21527
+ locale,
21528
+ translationsPath,
21252
21529
  ...sidebarGuidePath ? { sidebarGuidePath } : {},
21253
21530
  ...statusExecutable ? { statusExecutable } : {}
21254
21531
  }, null, 2) + "\n", mode: 384 });
21255
- for (const [label, action2] of statusExecutable ? [["\u7F16\u8F91\u5DE5\u7A0B", "edit"], ["\u66F4\u65B0\u5230\u8FBE\u82AC\u5947", "update"]] : []) {
21256
- desired.push({ path: join7(scriptsRoot, `${label}.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 });
21532
+ for (const [label2, action2] of statusExecutable ? [["\u7F16\u8F91\u5DE5\u7A0B", "edit"], ["\u66F4\u65B0\u5230\u8FBE\u82AC\u5947", "update"]] : []) {
21533
+ desired.push({ path: join7(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
21534
  }
21258
21535
  const registeredForwarder = await prepareRegisteredForwarder(options, old, statusExecutable, nativeConfig);
21259
21536
  if (registeredForwarder) desired.push(registeredForwarder.file);
@@ -21291,12 +21568,12 @@ async function installNative(options) {
21291
21568
  const recorded = oldByPath.get(file2.path), expected = "sha256:" + sha256(file2.bytes);
21292
21569
  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
21570
  if (process.platform !== "win32" && recorded?.mode !== void 0) assert2(
21294
- ((await stat7(file2.path)).mode & 511) === recorded.mode,
21571
+ ((await stat6(file2.path)).mode & 511) === recorded.mode,
21295
21572
  "INSTALL_CONFLICT",
21296
21573
  "\u7528\u6237\u4FEE\u6539\u4E86\u5B89\u88C5\u6587\u4EF6\u6743\u9650\uFF0C\u672A\u8986\u76D6\u3002",
21297
21574
  { path: file2.path }
21298
21575
  );
21299
- validated.set(file2.path, { sha256: existing.slice("sha256:".length), mode: (await stat7(file2.path)).mode & 511 });
21576
+ validated.set(file2.path, { sha256: existing.slice("sha256:".length), mode: (await stat6(file2.path)).mode & 511 });
21300
21577
  }
21301
21578
  };
21302
21579
  await validate(desired);
@@ -21335,11 +21612,11 @@ async function installNative(options) {
21335
21612
  owned.delete(file2.path);
21336
21613
  continue;
21337
21614
  }
21338
- if (actual !== file2.sha256 || process.platform !== "win32" && file2.mode !== void 0 && ((await stat7(file2.path)).mode & 511) !== file2.mode) {
21615
+ if (actual !== file2.sha256 || process.platform !== "win32" && file2.mode !== void 0 && ((await stat6(file2.path)).mode & 511) !== file2.mode) {
21339
21616
  retained.push(file2.path);
21340
21617
  continue;
21341
21618
  }
21342
- changes.push({ path: file2.path, bytes: null, expectedBefore: { sha256: actual.slice("sha256:".length), mode: (await stat7(file2.path)).mode & 511 } });
21619
+ changes.push({ path: file2.path, bytes: null, expectedBefore: { sha256: actual.slice("sha256:".length), mode: (await stat6(file2.path)).mode & 511 } });
21343
21620
  owned.delete(file2.path);
21344
21621
  removed.push(file2.path);
21345
21622
  }
@@ -21360,12 +21637,19 @@ async function installNative(options) {
21360
21637
  if (options.requireComplete) throw error48;
21361
21638
  const failure = error48;
21362
21639
  const within = (child, parent) => child === parent || child.startsWith(parent + "/");
21363
- const failedPath = typeof failure.path === "string" ? resolve9(failure.path) : void 0;
21364
- const pluginPath = pluginRoot ? resolve9(pluginRoot) : void 0;
21365
- const optionalPath = failedPath && pluginPath && (within(failedPath, pluginPath) || within(pluginPath, failedPath) && !desired.some((file2) => within(resolve9(file2.path), failedPath)));
21640
+ const failedPath = typeof failure.path === "string" ? resolve10(failure.path) : void 0;
21641
+ const pluginPath = pluginRoot ? resolve10(pluginRoot) : void 0;
21642
+ const optionalPath = failedPath && pluginPath && (within(failedPath, pluginPath) || within(pluginPath, failedPath) && !desired.some((file2) => within(resolve10(file2.path), failedPath)));
21366
21643
  if (!pluginAccessible || !["EACCES", "EPERM", "EROFS"].includes(failure.code ?? "") || !optionalPath) throw error48;
21367
21644
  await apply(false);
21368
21645
  }
21646
+ const retiredGroups = ["Hotion Harness", "Motion Harness", "Motion Harness \u6865\u63A5\u7EC4\u4EF6", "Motion Harness Bridge Component"];
21647
+ for (const directory of new Set(removed.map(dirname8))) {
21648
+ if (directory === scriptsRoot || !retiredGroups.includes(basename4(directory)) || basename4(dirname8(directory)) !== "Utility") continue;
21649
+ await rmdir(directory).catch((error48) => {
21650
+ if (!["ENOENT", "ENOTEMPTY", "EEXIST", "EACCES", "EPERM"].includes(error48.code)) throw error48;
21651
+ });
21652
+ }
21369
21653
  return {
21370
21654
  installed: true,
21371
21655
  complete: Boolean(statusExecutable && pluginFiles.length && entry.ofx === "manual-attachment"),
@@ -21387,7 +21671,7 @@ async function uninstallNative({ configRoot }) {
21387
21671
  throw error48;
21388
21672
  });
21389
21673
  if (!actual) continue;
21390
- if (actual !== file2.sha256 || process.platform !== "win32" && file2.mode !== void 0 && ((await stat7(file2.path)).mode & 511) !== file2.mode) {
21674
+ if (actual !== file2.sha256 || process.platform !== "win32" && file2.mode !== void 0 && ((await stat6(file2.path)).mode & 511) !== file2.mode) {
21391
21675
  retained.push(file2);
21392
21676
  continue;
21393
21677
  }
@@ -21404,23 +21688,38 @@ import { join as join8 } from "node:path";
21404
21688
  var sidebarHint = {
21405
21689
  optional: true,
21406
21690
  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",
21691
+ 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 Motion Harness \u6865\u63A5\u7EC4\u4EF6\u3002",
21408
21692
  steps: [
21409
21693
  "\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"
21694
+ "\u70B9\u51FB\u653E\u5927\u955C\uFF0C\u641C\u7D22 Motion Harness \u6865\u63A5\u7EC4\u4EF6\uFF0C\u5C06 Open FX \u4E2D\u7684\u540C\u540D\u6548\u679C\u62D6\u5230\u76EE\u6807\u52A8\u6548\u7247\u6BB5\u3002",
21695
+ "\u9009\u4E2D\u7247\u6BB5\uFF0C\u5728\u300C\u68C0\u67E5\u5668 \u2192 \u7279\u6548 \u2192 Open FX\u300D\u4E2D\u70B9\u51FB\u300C\u7F16\u8F91 Motion Harness \u5DE5\u7A0B\u300D\u3002"
21412
21696
  ],
21413
21697
  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",
21698
+ alternative: "\u4E0D\u6DFB\u52A0\u4E5F\u80FD\u4ECE\u300C\u5DE5\u4F5C\u533A \u2192 \u811A\u672C \u2192 Utility \u2192 Motion Harness \u6865\u63A5\u7EC4\u4EF6 \u2192 \u7F16\u8F91\u5DE5\u7A0B\u300D\u6253\u5F00\u3002",
21415
21699
  guideCommand: "mh bridge davinci sidebar-guide"
21416
21700
  };
21417
- async function readSidebarGuide(componentRoot, inline = false) {
21701
+ function sidebarHintForLocale(locale = bridgeLocale()) {
21702
+ if (locale !== "en") return sidebarHint;
21703
+ return {
21704
+ ...sidebarHint,
21705
+ title: "Add sidebar entry (optional)",
21706
+ message: `The media is linked to its source project. Add the ${bridgeName(locale)} to edit from the DaVinci Resolve sidebar.`,
21707
+ steps: [
21708
+ "On the Edit page in DaVinci Resolve, open the Effects Library (magic wand icon).",
21709
+ "Search for Motion Harness Bridge Component and drag the Open FX effect onto the target clip.",
21710
+ "Select the clip and click Edit Motion Harness project under Inspector \u2192 Effects \u2192 Open FX."
21711
+ ],
21712
+ shortcut: "You can also select the clip, press Shift + Space, then search and add the effect.",
21713
+ alternative: "You can also open the project from Workspace \u2192 Scripts \u2192 Utility \u2192 Motion Harness Bridge Component \u2192 Edit project."
21714
+ };
21715
+ }
21716
+ async function readSidebarGuide(componentRoot, inline = false, locale = bridgeLocale()) {
21418
21717
  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 };
21718
+ const guidePath = join8(directory, locale === "en" ? "en.html" : "index.html");
21719
+ const hint = sidebarHintForLocale(locale);
21720
+ if (!inline) return { ...hint, guidePath };
21421
21721
  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}"`) };
21722
+ return { ...hint, html };
21424
21723
  }
21425
21724
 
21426
21725
  // src/runner.ts
@@ -21428,12 +21727,12 @@ var taskView = (job) => ({
21428
21727
  ...job,
21429
21728
  taskId: job.id,
21430
21729
  message: job.error?.message ?? job.progress.stage,
21431
- ...job.operation === "send" && job.phase === "completed" && job.results.some((result2) => result2.applied === true && result2.bindingId) ? { sidebarHint } : {}
21730
+ ...job.operation === "send" && job.phase === "completed" && job.results.some((result2) => result2.applied === true && result2.bindingId) ? { sidebarHint: sidebarHintForLocale() } : {}
21432
21731
  });
21433
21732
  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
21733
  function assertJobScope(bridge, catalog, job, projectPath, readOnly = false) {
21435
21734
  if (!projectPath) return;
21436
- const path = resolve10(projectPath);
21735
+ const path = resolve11(projectPath);
21437
21736
  const sourceIds = new Set(Object.values(catalog.sources).filter((source) => bridge.store.path(source.locator) === path).map((source) => source.id));
21438
21737
  const bindingIds = new Set(Object.values(catalog.bindings).filter((binding) => sourceIds.has(binding.sourceId)).map((binding) => binding.id));
21439
21738
  const targets = Array.isArray(job.request.targets) ? job.request.targets : [];
@@ -21503,14 +21802,14 @@ async function launchWorker(bridge, taskId, request) {
21503
21802
  shell: false,
21504
21803
  env: process.env
21505
21804
  });
21506
- const cleaned = child.exitCode !== null || child.signalCode !== null ? Promise.resolve(child.signalCode === null) : new Promise((resolve11) => {
21507
- child.once("exit", (_code, signal) => resolve11(signal === null));
21508
- child.once("error", () => resolve11(child.pid === void 0));
21805
+ const cleaned = child.exitCode !== null || child.signalCode !== null ? Promise.resolve(child.signalCode === null) : new Promise((resolve12) => {
21806
+ child.once("exit", (_code, signal) => resolve12(signal === null));
21807
+ child.once("error", () => resolve12(child.pid === void 0));
21509
21808
  });
21510
21809
  const readiness = child.stdio[4];
21511
21810
  try {
21512
21811
  assert2(readiness, "WORKER_LEASE_REQUIRED", "\u540E\u53F0\u76D1\u7763\u8FDB\u7A0B\u7F3A\u5C11\u542F\u52A8\u786E\u8BA4\u901A\u9053\u3002");
21513
- await new Promise((resolve11, reject) => {
21812
+ await new Promise((resolve12, reject) => {
21514
21813
  let text = "", settled = false;
21515
21814
  const finish = (error48) => {
21516
21815
  if (settled) return;
@@ -21521,7 +21820,7 @@ async function launchWorker(bridge, taskId, request) {
21521
21820
  readiness.off("end", ended);
21522
21821
  readiness.off("error", failed);
21523
21822
  if (error48) reject(error48);
21524
- else resolve11();
21823
+ else resolve12();
21525
21824
  };
21526
21825
  const failed = (error48) => finish(error48);
21527
21826
  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 +21845,8 @@ async function launchWorker(bridge, taskId, request) {
21546
21845
  } catch (error48) {
21547
21846
  if (child.exitCode === null && child.signalCode === null) child.kill("SIGTERM");
21548
21847
  let cleanupTimer;
21549
- const cleanupObserved = await Promise.race([cleaned, new Promise((resolve11) => {
21550
- cleanupTimer = setTimeout(() => resolve11(false), 3e3);
21848
+ const cleanupObserved = await Promise.race([cleaned, new Promise((resolve12) => {
21849
+ cleanupTimer = setTimeout(() => resolve12(false), 3e3);
21551
21850
  })]);
21552
21851
  clearTimeout(cleanupTimer);
21553
21852
  if (cleanupObserved) await recordWorkerStartFailure(bridge, taskId, error48);
@@ -21589,7 +21888,7 @@ async function execute(request) {
21589
21888
  }
21590
21889
  if (requestedOperation === "send") {
21591
21890
  payload2.projectPath ??= request.projectPath;
21592
- if (typeof payload2.projectPath === "string") payload2.projectPath = resolve10(payload2.projectPath);
21891
+ if (typeof payload2.projectPath === "string") payload2.projectPath = resolve11(payload2.projectPath);
21593
21892
  }
21594
21893
  if (requestedOperation === "update" && !payload2.bindingId) payload2.bindingId = catalog.jobs[String(receipt.result.taskId)]?.request.bindingId;
21595
21894
  return replayTask(bridge, request, catalog, requestedOperation, payload2, selectionHash);
@@ -21648,9 +21947,9 @@ async function execute(request) {
21648
21947
  if (selection.expectedMediaFingerprint) assert2(
21649
21948
  (await bridge.host.media(selection.scope, selection.mediaPoolItemId)).fingerprint === selection.expectedMediaFingerprint,
21650
21949
  "VERSION_CONFLICT",
21651
- "\u786E\u8BA4\u540E\u7684\u7D20\u6750\u4F7F\u7528\u8303\u56F4\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6838\u5BF9\u3002"
21950
+ "\u786E\u8BA4\u540E\u7684\u539F\u7D20\u6750\u8EAB\u4EFD\u6216\u5173\u8054\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6838\u5BF9\u3002"
21652
21951
  );
21653
- if (selection.expectedTimelineFingerprint) {
21952
+ if (request.operation === "duplicate" && selection.expectedTimelineFingerprint) {
21654
21953
  assert2(selection.timelineId, "INVALID_REQUEST", "\u65F6\u95F4\u7EBF\u6307\u7EB9\u7F3A\u5C11\u5BF9\u5E94\u5B9E\u4F8B\u3002");
21655
21954
  assert2(
21656
21955
  (await bridge.host.timeline(selection.scope, selection.timelineId)).fingerprint === selection.expectedTimelineFingerprint,
@@ -21674,7 +21973,7 @@ async function execute(request) {
21674
21973
  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
21974
  }
21676
21975
  if (request.operation === "install-complete") return finishNativeInstall(request.configRoot);
21677
- if (request.operation === "sidebar-guide") return readSidebarGuide(request.componentRoot, input.inline === true);
21976
+ if (request.operation === "sidebar-guide") return readSidebarGuide(request.componentRoot, input.inline === true, bridgeLocale(input.locale));
21678
21977
  if (request.operation === "install") {
21679
21978
  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
21979
  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 +21988,17 @@ async function execute(request) {
21689
21988
  assert2(Object.hasOwn(schemas, name), "INVALID_REQUEST", "\u672A\u77E5\u4FEE\u6539\u64CD\u4F5C\u3002", { operations: Object.keys(schemas) });
21690
21989
  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
21990
  }
21692
- if (request.operation === "doctor") return bridge.capabilities();
21991
+ if (request.operation === "doctor") {
21992
+ if (input.repairConnection === true) {
21993
+ const connection = await repairNativeConnection(request);
21994
+ const native = await bridge.host.call("connection");
21995
+ return { ...connection, ...native };
21996
+ }
21997
+ return bridge.capabilities();
21998
+ }
21693
21999
  if (request.operation === "status") {
21694
22000
  const catalog = await bridge.store.read();
21695
- const projectPath = request.projectPath ? await realpath6(request.projectPath).catch(() => resolve10(request.projectPath)) : void 0;
22001
+ const projectPath = request.projectPath ? await realpath6(request.projectPath).catch(() => resolve11(request.projectPath)) : void 0;
21696
22002
  const sources = Object.values(catalog.sources).filter((source) => !projectPath || bridge.store.path(source.locator) === projectPath);
21697
22003
  const sourceIds = new Set(sources.map((source) => source.id));
21698
22004
  const bindings = Object.values(catalog.bindings).filter((binding) => sourceIds.has(binding.sourceId)).map((binding) => {
@@ -21711,7 +22017,7 @@ async function execute(request) {
21711
22017
  state: binding.state,
21712
22018
  name,
21713
22019
  outputSpec: spec,
21714
- lastKnownUsageCount: binding.lastReadback?.uses.length ?? null
22020
+ lastKnownUsageCount: binding.lastReadback?.usageScanComplete ? binding.lastReadback.uses.length : null
21715
22021
  };
21716
22022
  });
21717
22023
  const tasks = Object.values(catalog.jobs).filter((job) => {
@@ -21820,7 +22126,7 @@ async function execute(request) {
21820
22126
  return { opened: true, sourceId };
21821
22127
  });
21822
22128
  }
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 Hotion Harness\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");
22129
+ 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 Motion Harness \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
22130
  if (request.operation === "relink") return bridge.relink(input);
21825
22131
  if (request.operation === "recover") {
21826
22132
  const checked = reconcileSchema.parse(input);
@@ -21839,7 +22145,7 @@ async function execute(request) {
21839
22145
  const payload = { ...input };
21840
22146
  if (operation === "send") {
21841
22147
  payload.projectPath ??= request.projectPath;
21842
- if (typeof payload.projectPath === "string") payload.projectPath = resolve10(payload.projectPath);
22148
+ if (typeof payload.projectPath === "string") payload.projectPath = resolve11(payload.projectPath);
21843
22149
  }
21844
22150
  if (operation === "update" && !payload.bindingId) {
21845
22151
  const selected = await bridge.selectedSource();
@@ -21864,7 +22170,7 @@ async function execute(request) {
21864
22170
  ...Array.isArray(value.targets) ? value.targets.map((target) => catalog.bindings[target.bindingId]?.sourceId) : []
21865
22171
  ].filter((value2) => Boolean(value2)));
21866
22172
  return /* @__PURE__ */ new Set([
21867
- ...typeof value.projectPath === "string" ? [resolve10(value.projectPath)] : [],
22173
+ ...typeof value.projectPath === "string" ? [resolve11(value.projectPath)] : [],
21868
22174
  ...[...sourceIds].map((sourceId) => catalog.sources[sourceId] ? bridge.store.path(catalog.sources[sourceId].locator) : `source:${sourceId}`)
21869
22175
  ]);
21870
22176
  };
@@ -21917,11 +22223,11 @@ function assertMigrationReady(blockers, old) {
21917
22223
  );
21918
22224
  }
21919
22225
  async function proposedWorkspaceRoot(path) {
21920
- let existing = resolve10(path);
22226
+ let existing = resolve11(path);
21921
22227
  const suffix = [];
21922
22228
  for (; ; ) {
21923
22229
  try {
21924
- return resolve10(await realpath6(existing), ...suffix);
22230
+ return resolve11(await realpath6(existing), ...suffix);
21925
22231
  } catch (error48) {
21926
22232
  if (error48.code !== "ENOENT") throw error48;
21927
22233
  const parent = dirname9(existing);
@@ -21932,7 +22238,7 @@ async function proposedWorkspaceRoot(path) {
21932
22238
  }
21933
22239
  }
21934
22240
  function assertSeparateMigrationRoots(oldRoot, targetRoot) {
21935
- const prefix = (root) => root.endsWith(sep3) ? root : root + sep3;
22241
+ const prefix = (root) => root.endsWith(sep2) ? root : root + sep2;
21936
22242
  assert2(
21937
22243
  targetRoot !== oldRoot && !targetRoot.startsWith(prefix(oldRoot)) && !oldRoot.startsWith(prefix(targetRoot)),
21938
22244
  "INVALID_REQUEST",
@@ -21970,7 +22276,7 @@ async function withLegacyMigrationLocks(old, action2) {
21970
22276
  function legacyMcpGate() {
21971
22277
  const inspect = async (root) => {
21972
22278
  const old = new Store(root);
21973
- const locks = await stat8(old.path("locks"));
22279
+ const locks = await stat7(old.path("locks"));
21974
22280
  assert2(locks.isDirectory(), "LEGACY_LOCKS_MISSING", "\u65E7\u76EE\u5F55\u7F3A\u5C11\u534F\u4F5C\u9501\u76EE\u5F55\uFF0C\u672A\u9000\u5F79\u914D\u7F6E\u3002");
21975
22281
  const snapshot = await migrationSnapshot(old);
21976
22282
  assertMigrationReady(migrationTaskBlockers(snapshot.catalog), old);
@@ -21995,7 +22301,7 @@ async function migrate(bridge, input) {
21995
22301
  assertSeparateMigrationRoots(old.root, targetRoot);
21996
22302
  const snapshot = await migrationSnapshot(old), catalog = snapshot.catalog;
21997
22303
  const blockers = migrationTaskBlockers(catalog);
21998
- const locksDirectory = await stat8(old.path("locks")).catch((error48) => {
22304
+ const locksDirectory = await stat7(old.path("locks")).catch((error48) => {
21999
22305
  if (error48.code === "ENOENT") return void 0;
22000
22306
  throw error48;
22001
22307
  });
@@ -22072,7 +22378,7 @@ async function migrate(bridge, input) {
22072
22378
  if (error48.code !== "EEXIST" || await fileDigest(destination) !== artifact.sha256) throw error48;
22073
22379
  }
22074
22380
  assert2(
22075
- (await stat8(destination)).size === artifact.bytes && await fileDigest(destination) === artifact.sha256,
22381
+ (await stat7(destination)).size === artifact.bytes && await fileDigest(destination) === artifact.sha256,
22076
22382
  "ARTIFACT_CHANGED",
22077
22383
  "\u8FC1\u79FB\u526F\u672C\u6821\u9A8C\u5931\u8D25\u3002"
22078
22384
  );
@@ -22145,7 +22451,7 @@ if (process.argv[2] === "--worker") {
22145
22451
  } finally {
22146
22452
  supervisor?.write(Buffer.from([0]));
22147
22453
  }
22148
- } else if (process.argv[1] && resolve10(process.argv[1]) === fileURLToPath2(import.meta.url)) {
22454
+ } else if (process.argv[1] && resolve11(process.argv[1]) === fileURLToPath2(import.meta.url)) {
22149
22455
  try {
22150
22456
  let text = "";
22151
22457
  for await (const chunk of process.stdin) {