@naparnik/mcp 0.10.25 → 0.10.38

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.
@@ -226,8 +226,8 @@ var StdioServerTransport = class {
226
226
  function toolSuccess(content, structured) {
227
227
  return { type: "success", content, ...structured !== void 0 ? { structured } : {} };
228
228
  }
229
- function toolMixed(blocks) {
230
- return { type: "success", content: blocks };
229
+ function toolMixed(blocks, structured) {
230
+ return { type: "success", content: blocks, ...structured !== void 0 ? { structured } : {} };
231
231
  }
232
232
  function toolError(error40, code) {
233
233
  return { type: "error", error: error40 };
@@ -727,9 +727,9 @@ function parsePositiveInt(raw, fallback) {
727
727
  }
728
728
 
729
729
  // src/version.ts
730
- var VERSION = "0.10.25";
730
+ var VERSION = "0.10.38";
731
731
  var USER_AGENT = `naparnik-mcp/${VERSION}`;
732
- var MIN_ENGINE = "2026.09.23-406";
732
+ var MIN_ENGINE = "2026.09.24-446";
733
733
  var LAUNCHER_PROTOCOL = 1;
734
734
 
735
735
  // src/contracts/sdk-headers.ts
@@ -1867,8 +1867,7 @@ function parseFailure(err, fallback) {
1867
1867
  return { ok: false, text: mine !== "" ? mine : e?.message ?? fallback };
1868
1868
  }
1869
1869
  function details(err) {
1870
- const e = err;
1871
- return [e?.stdout, e?.stderr, e?.message].filter(Boolean).join("\n").trim();
1870
+ return parseFailure(err, "").text.trim();
1872
1871
  }
1873
1872
  function lastLine(output) {
1874
1873
  const lines = output.trim().split("\n");
@@ -14108,12 +14107,20 @@ function blockCandidate(dir, candidate, text2) {
14108
14107
  };
14109
14108
  }
14110
14109
  writeCandidate(dir, { ...candidate, state: "blocked" });
14110
+ const lead = candidate.baseCurrent === null ? `\u0412\u0435\u0440\u0441\u0438\u044F ${candidate.version} \u043D\u0435 \u0432\u0441\u0442\u0430\u043B\u0430.` : `\u041D\u043E\u0432\u0430\u044F \u0432\u0435\u0440\u0441\u0438\u044F ${candidate.version} \u043D\u0435 \u0432\u0441\u0442\u0430\u043B\u0430 \u2014 \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u043F\u0440\u0435\u0436\u043D\u044F\u044F ${candidate.baseCurrent}, \u043C\u043E\u043D\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043C\u043E\u0436\u043D\u043E.`;
14111
14111
  return {
14112
14112
  ok: false,
14113
- text: text2.includes("\u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C:") ? text2 : `${text2}
14114
- \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u0438\u0441\u043F\u0440\u0430\u0432\u044C\u0442\u0435 \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u0443\u044E \u043F\u0440\u0438\u0447\u0438\u043D\u0443 \u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 setup.`
14113
+ text: text2.includes("\u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C:") ? `${lead}
14114
+ ${text2}` : `${lead}
14115
+ ${text2}
14116
+ \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0432\u0442\u043E\u0440\u0438 setup \u043F\u043E\u0437\u0436\u0435 \u2014 \u0441\u0432\u044F\u0437\u044C \u043C\u043E\u0433\u043B\u0430 \u043E\u0431\u043E\u0440\u0432\u0430\u0442\u044C\u0441\u044F. \u041E\u0442\u043A\u0430\u0436\u0435\u0442 \u0442\u0435\u043C \u0436\u0435 \u2014 \u044D\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044F \u0441\u043B\u043E\u043C\u0430\u043D\u0430: \u043C\u043E\u043D\u0442\u0438\u0440\u0443\u0439 \u043D\u0430 \u043F\u0440\u0435\u0436\u043D\u0435\u0439 \u0438 \u0434\u043E\u0436\u0434\u0438\u0441\u044C \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0439.`
14115
14117
  };
14116
14118
  }
14119
+ function commandWords(trouble) {
14120
+ const text2 = parseFailure(trouble, describeFailure(trouble)).text;
14121
+ if (!text2.includes("Traceback (most recent call last):")) return text2;
14122
+ return lastLine(text2);
14123
+ }
14117
14124
  function sameCandidateState(actual, expected) {
14118
14125
  if (actual === null) return false;
14119
14126
  const samePayload = actual.payload === void 0 && expected.payload === void 0 || actual.payload !== void 0 && expected.payload !== void 0 && samePayloadProof(actual.payload, expected.payload);
@@ -14297,7 +14304,7 @@ async function activatePreparedCandidateLocked(engine, manifest, trial, extras =
14297
14304
  if (installedVenvTrouble !== null) throw new Error(installedVenvTrouble);
14298
14305
  } catch (trouble) {
14299
14306
  return blockCandidate(dir, candidate, `\u041E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u0435 \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u043D\u0435 \u0433\u043E\u0442\u043E\u0432\u043E \u2014 current \u043D\u0435 \u043C\u0435\u043D\u044F\u043B.
14300
- ${describeFailure(trouble)}`);
14307
+ ${commandWords(trouble)}`);
14301
14308
  }
14302
14309
  }
14303
14310
  const python = engine.candidatePython(place);
@@ -14341,7 +14348,7 @@ ${smoke}`);
14341
14348
  dir,
14342
14349
  candidate,
14343
14350
  `\u041E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u0441\u0440\u0435\u0434\u0430 \u043A\u0430\u043D\u0434\u0438\u0434\u0430\u0442\u0430 \u043D\u0435 \u0433\u043E\u0442\u043E\u0432\u0430 \u2014 current \u0438 \u043E\u0431\u0449\u0438\u0435 \u0440\u0430\u0431\u043E\u0447\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044B \u043D\u0435 \u043C\u0435\u043D\u044F\u043B.
14344
- ${describeFailure(trouble)}`
14351
+ ${commandWords(trouble)}`
14345
14352
  );
14346
14353
  }
14347
14354
  const firstCompatibility = await compatibilityProof(engine, dir, candidate.version, python, place);
@@ -15616,38 +15623,6 @@ function retell(state, told, tell) {
15616
15623
  if (tell === void 0) return;
15617
15624
  for (const line of freshLines(state.text, told)) tell(line);
15618
15625
  }
15619
- var STAGE_WORDS = {
15620
- silence: "\u0443\u0431\u0435\u0440\u0443 \u043F\u0430\u0443\u0437\u044B",
15621
- voice: "\u0432\u044B\u0440\u043E\u0432\u043D\u044F\u044E \u0433\u043E\u043B\u043E\u0441",
15622
- speech: "\u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u044E \u0440\u0435\u0447\u044C",
15623
- phrases: "\u0440\u0430\u0437\u043B\u043E\u0436\u0443 \u0440\u0435\u0447\u044C \u043D\u0430 \u0444\u0440\u0430\u0437\u044B",
15624
- plan: "\u043F\u0440\u0438\u0434\u0443\u043C\u0430\u044E, \u0447\u0442\u043E \u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0438 \u043A\u043E\u0433\u0434\u0430",
15625
- world: "\u043D\u0430\u0440\u0438\u0441\u0443\u044E \u0444\u043E\u043D \u0437\u0430 \u0433\u0435\u0440\u043E\u0435\u043C",
15626
- cutout: "\u043E\u0442\u0434\u0435\u043B\u044E \u0433\u0435\u0440\u043E\u044F \u043E\u0442 \u0444\u043E\u043D\u0430",
15627
- "hero-on-world": "\u043F\u043E\u0441\u0442\u0430\u0432\u043B\u044E \u0433\u0435\u0440\u043E\u044F \u043D\u0430 \u0444\u043E\u043D",
15628
- shots: "\u0440\u0430\u0441\u0441\u0442\u0430\u0432\u043B\u044E \u043A\u0440\u0443\u043F\u043D\u043E\u0441\u0442\u0438 \u043F\u043E \u043F\u043B\u0430\u043D\u0443",
15629
- screen: "\u0432\u0441\u0442\u0430\u0432\u043B\u044E \u0437\u0430\u043F\u0438\u0441\u044C \u044D\u043A\u0440\u0430\u043D\u0430",
15630
- inserts: "\u043D\u0430\u0440\u0438\u0441\u0443\u044E \u0433\u0440\u0430\u0444\u0438\u043A\u0443 \u043F\u043E \u043F\u043B\u0430\u043D\u0443",
15631
- subtitles: "\u043D\u0430\u0440\u0438\u0441\u0443\u044E \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044B",
15632
- layers: "\u043F\u043E\u043B\u043E\u0436\u0443 \u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0438 \u043F\u043E\u0432\u0435\u0440\u0445",
15633
- accents: "\u0440\u0430\u0441\u0441\u0442\u0430\u0432\u043B\u044E \u0437\u0432\u0443\u043A\u043E\u0432\u044B\u0435 \u0430\u043A\u0446\u0435\u043D\u0442\u044B",
15634
- mix: "\u0441\u0432\u0435\u0434\u0443 \u0437\u0432\u0443\u043A",
15635
- intro: "\u043F\u043E\u0441\u0442\u0430\u0432\u043B\u044E \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0443 \u0432 \u043D\u0430\u0447\u0430\u043B\u043E"
15636
- };
15637
- var NEAR_STEPS = 3;
15638
- function montageLadder(stages) {
15639
- const words = stages.map((stage) => STAGE_WORDS[stage]).filter((word) => word !== void 0);
15640
- if (words.length === 0) return [];
15641
- const near = words.slice(0, NEAR_STEPS);
15642
- const far = words.slice(NEAR_STEPS);
15643
- const lines = [`\u0421\u043D\u0430\u0447\u0430\u043B\u0430 ${near.join(", \u043F\u043E\u0442\u043E\u043C ")}.`];
15644
- if (far.length > 0) {
15645
- lines.push(
15646
- `\u0414\u0430\u043B\u044C\u0448\u0435: ${far.join(", ")}. \u0428\u0430\u0433\u043E\u0432 \u0432\u0441\u0435\u0433\u043E \u0434\u043E ${stages.length} \u2014 \u0447\u0442\u043E \u043D\u0435 \u043F\u043E\u043D\u0430\u0434\u043E\u0431\u0438\u0442\u0441\u044F, \u043F\u0440\u043E\u043F\u0443\u0449\u0443.`
15647
- );
15648
- }
15649
- return lines;
15650
- }
15651
15626
  var PAUSES_LADDER = [
15652
15627
  "\u0423\u0431\u0435\u0440\u0443 \u043C\u043E\u043B\u0447\u0430\u043D\u0438\u0435 \u0438 \u0437\u0430\u043F\u0438\u043D\u043A\u0438 \u2014 \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0442\u0440\u043E\u0433\u0430\u044E.",
15653
15628
  "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044B, \u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0438 \u043F\u043E\u0432\u0435\u0440\u0445 \u0438 \u0437\u0432\u0443\u043A \u2014 \u044D\u0442\u043E \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u0430\u044F \u0440\u0430\u0431\u043E\u0442\u0430, \u0435\u0451 \u0437\u0434\u0435\u0441\u044C \u043D\u0435\u0442."
@@ -17171,31 +17146,6 @@ function aboutModels(passport) {
17171
17146
  function fromList(list, description) {
17172
17147
  return list !== void 0 && list.length > 0 ? external_exports.enum([...list]).describe(description) : external_exports.string().describe(description);
17173
17148
  }
17174
- function capabilitiesToSchema(passport, taken = /* @__PURE__ */ new Set()) {
17175
- const skills = passport?.["capabilities"];
17176
- if (skills === void 0) return {};
17177
- const schema = {};
17178
- for (const [name, o] of Object.entries(skills)) {
17179
- if (taken.has(name)) continue;
17180
- schema[name] = o["kind"] === "yes-no" ? external_exports.boolean().describe(o["about"]).optional() : external_exports.string().describe(o["about"]).optional();
17181
- }
17182
- return schema;
17183
- }
17184
- function readCapabilities(args, passport) {
17185
- const skills = passport?.["capabilities"];
17186
- if (skills === void 0) return [];
17187
- const line = [];
17188
- for (const [name, o] of Object.entries(skills)) {
17189
- const key = `--${name.split("_").join("-")}`;
17190
- if (o["kind"] === "yes-no") {
17191
- if (args[name] === true) line.push(key);
17192
- continue;
17193
- }
17194
- const value = args[name];
17195
- if (typeof value === "string") line.push(key, o["kind"] === "file" ? path(value) : value);
17196
- }
17197
- return line;
17198
- }
17199
17149
  function asToolResult(outcome) {
17200
17150
  return outcome.ok ? toolSuccess(outcome.text) : toolError(outcome.text);
17201
17151
  }
@@ -17217,7 +17167,6 @@ var KNOB_KIND = {
17217
17167
  "yes-no": "\u0434\u0430/\u043D\u0435\u0442"
17218
17168
  };
17219
17169
  var FROM_MINE = "mine";
17220
- var FROM_VENDOR = "vendor";
17221
17170
  function catalogInWords(data) {
17222
17171
  const lines = [];
17223
17172
  const version2 = data.engine?.version;
@@ -17276,12 +17225,10 @@ function catalogInWords(data) {
17276
17225
  const said = knobs.map((k) => `${k.name} (${k.kind !== void 0 ? KNOB_KIND[k.kind] ?? k.kind : "\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435"})`).join(", ");
17277
17226
  lines.push(`\u0420\u0443\u0447\u043A\u0438 \u043C\u043E\u043D\u0442\u0430\u0436\u0430, \u0438\u0445 \u043F\u0435\u0440\u0435\u0434\u0430\u044E\u0442 \u0432 render: ${said}.`);
17278
17227
  }
17279
- const skills = data.skills ?? [];
17280
- if (skills.length > 0) {
17281
- const said = skills.map((s) => s.origin === FROM_VENDOR ? `${s.name} \u2014 ${s.about ?? ""} (\u0447\u0435\u0440\u0435\u0437 ${s.read ?? ""})` : `${s.read ?? s.name} \u2014 ${s.about ?? ""}`).join("; ");
17282
- lines.push(
17283
- `\u0421\u043A\u0438\u043B\u043B\u044B \u043D\u0430 \u0434\u0438\u0441\u043A\u0435, \u0447\u0438\u0442\u0430\u0442\u044C plan \u0441 read, \u0440\u043E\u043B\u0438\u043A \u0434\u043B\u044F \u044D\u0442\u043E\u0433\u043E \u043D\u0435 \u043D\u0443\u0436\u0435\u043D: ${said}. \u0413\u043E\u0434\u044F\u0442\u0441\u044F \u0438 \u043D\u0435 \u0434\u043B\u044F \u0440\u043E\u043B\u0438\u043A\u0430: \u043F\u0440\u0435\u0437\u0435\u043D\u0442\u0430\u0446\u0438\u044F, \u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0430, \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430.`
17284
- );
17228
+ const index = data.handbook?.index;
17229
+ if (index !== void 0 && index.trim() !== "") {
17230
+ lines.push(`\u0421\u041F\u0420\u0410\u0412\u041E\u0427\u041D\u0418\u041A \u041C\u041E\u041D\u0422\u0410\u0416\u0401\u0420\u0410 \u2014 \u043E\u0433\u043B\u0430\u0432\u043B\u0435\u043D\u0438\u0435, \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u0447\u0438\u0442\u0430\u0439 plan \u0441 read:
17231
+ ${index.trim()}`);
17285
17232
  }
17286
17233
  const style = data.style;
17287
17234
  if (style?.name !== void 0) {
@@ -17289,6 +17236,11 @@ function catalogInWords(data) {
17289
17236
  style.own === true ? `\u0421\u0442\u0438\u043B\u044C: \u0441\u0432\u043E\u0439 \u043F\u0430\u043A \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \xAB${style.name}\xBB \u2014 \u0432\u044B\u0431\u0440\u0430\u043D\u043D\u043E\u0435 \u0437\u0430\u043F\u043E\u043C\u0438\u043D\u0430\u0435\u0442\u0441\u044F \u0432 \u043D\u0435\u0433\u043E.` : `\u0421\u0442\u0438\u043B\u044C: \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0439 \xAB${style.name}\xBB, \u0441\u0432\u043E\u0435\u0433\u043E \u043F\u0430\u043A\u0430 \u0443 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u0435\u0449\u0451 \u043D\u0435\u0442.`
17290
17237
  );
17291
17238
  }
17239
+ const mine = data.mine?.summary ?? [];
17240
+ if (mine.length > 0) {
17241
+ lines.push(`\u0421\u0432\u043E\u0451 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 (\u0437\u0430\u043F\u043E\u043C\u043D\u0435\u043D\u043E, \u0443\u0436\u0435 \u0432 \u043A\u0430\u0436\u0434\u043E\u043C \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\u0435; \xAB\u0437\u0430\u0431\u0443\u0434\u044C\xBB \u2014 plan_edit forget):
17242
+ ${mine.map((line) => `\u2014 ${line}`).join("\n")}`);
17243
+ }
17292
17244
  for (const said of data.warnings ?? []) lines.push(said);
17293
17245
  return lines.join("\n");
17294
17246
  }
@@ -17314,60 +17266,6 @@ async function askCatalog(engine, pack, video) {
17314
17266
  }
17315
17267
  return catalogInWords(data);
17316
17268
  }
17317
- async function startMontage(engine, opts) {
17318
- const trouble = await engine.pythonTrouble();
17319
- if (trouble !== null) return toolError(trouble);
17320
- const python = engine.packPython();
17321
- if (python === null) {
17322
- return toolError(
17323
- "\u041E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u0435 \u043C\u043E\u043D\u0442\u0430\u0436\u0430 \u0435\u0449\u0451 \u043D\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E \u2014 \u043C\u043E\u043D\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u043C.\n\u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0437\u043E\u0432\u0438 setup, \u043E\u043D \u0441\u043A\u0430\u0436\u0435\u0442, \u0447\u0435\u0433\u043E \u043D\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442, \u0430 \u0441 what \u043E\u043D \u044D\u0442\u043E \u0438 \u043F\u043E\u0441\u0442\u0430\u0432\u0438\u0442."
17324
- );
17325
- }
17326
- const passport = await engine.passport();
17327
- if (passport === null) {
17328
- return toolError(
17329
- // ⚠ ВТОРАЯ ПРИЧИНА НАЗВАНА С 2026-09-09, И ОНА ТЕПЕРЬ ЧАСТАЯ. Пак
17330
- // переименован (`first-montage` → `montage`), а начинка живёт версионными
17331
- // папками: у того, чья начинка старее оболочки, пака по новому имени
17332
- // просто нет. `check_setup` про это не скажет ничего внятного — лечит
17333
- // обновление начинки, и назвать его надо здесь.
17334
- "\u041D\u0435 \u0441\u043C\u043E\u0433 \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C \u043F\u0430\u0441\u043F\u043E\u0440\u0442 \u043F\u0430\u043A\u0430 \u043C\u043E\u043D\u0442\u0430\u0436\u0430 (pack.json).\n\u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0437\u043E\u0432\u0438 setup \u2014 \u043E\u043D \u0441\u043A\u0430\u0436\u0435\u0442, \u0447\u0442\u043E \u0441 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u043E\u0439 \u043D\u0435 \u0442\u0430\u043A. \u0415\u0441\u043B\u0438 \u043D\u0430\u0447\u0438\u043D\u043A\u0430 \u0441\u0442\u0430\u0432\u0438\u043B\u0430\u0441\u044C \u0434\u0430\u0432\u043D\u043E, \u0434\u0435\u043B\u043E \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u0432 \u043D\u0435\u0439: \u043F\u0430\u043A \u043F\u0435\u0440\u0435\u0435\u0445\u0430\u043B, \u0438 \u0441\u0442\u0430\u0440\u0430\u044F \u043D\u0430\u0447\u0438\u043D\u043A\u0430 \u0435\u0433\u043E \u043D\u0435 \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u0442 \u2014 \u0442\u043E\u0433\u0434\u0430 \u043F\u043E\u043C\u043E\u0433\u0430\u0435\u0442 setup \u0441 what=engine."
17335
- );
17336
- }
17337
- if (opts.tell !== void 0) {
17338
- for (const line of opts.ladder ?? montageLadder(passport["stages"])) opts.tell(line);
17339
- opts.tell(opts.hint);
17340
- }
17341
- const launch = await engine.background({
17342
- place: opts.place,
17343
- executable: python,
17344
- key: opts.key,
17345
- startJob: [
17346
- "job-create",
17347
- "--video",
17348
- opts.video,
17349
- "--what",
17350
- opts.what,
17351
- "--command",
17352
- JSON.stringify(opts.command),
17353
- ...opts.style !== void 0 ? ["--style", opts.style] : []
17354
- ],
17355
- args: (id) => [passport["entry"], opts.video, "--job", id, ...opts.args],
17356
- advice: "\u043F\u043E\u0437\u043E\u0432\u0438 setup \u2014 \u0441\u043A\u043E\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043E, \u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u0435 \u043D\u0435\u043F\u043E\u043B\u043D\u043E\u0435"
17357
- });
17358
- if ("refusal" in launch) return toolError(launch.refusal);
17359
- return toolSuccess(
17360
- `\u0417\u0430\u0434\u0430\u0447\u0430 ${launch.id}: ${opts.what}
17361
- \u0412\u0441\u0451 \u0434\u0435\u043B\u0430\u0435\u0442\u0441\u044F \u043D\u0430 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F. ${opts.hint}
17362
- \u0420\u0430\u0431\u043E\u0442\u0430 \u043F\u0435\u0440\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u044B: \u043D\u043E\u043C\u0435\u0440 \u0437\u0430\u0434\u0430\u0447\u0438 \u0437\u0430\u043F\u043E\u043C\u043D\u0438 \u0438 \u043F\u043E\u0437\u043E\u0432\u0438 wait \u0441 job "${launch.id}" \u2014 \u043E\u043D \u043F\u043E\u0434\u043E\u0436\u0434\u0451\u0442 \u0438 \u0440\u0430\u0441\u0441\u043A\u0430\u0436\u0435\u0442 \u0445\u043E\u0434 \u043F\u043E \u0448\u0430\u0433\u0430\u043C, \u043F\u0435\u0440\u0435\u0441\u043A\u0430\u0437\u044B\u0432\u0430\u0439 \u0435\u0433\u043E \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0443 \u0441\u0440\u0430\u0437\u0443. ${AWAY_NOTE}`,
17363
- startedJob({
17364
- id: launch.id,
17365
- what: opts.what,
17366
- ahead: (opts.ladder ?? montageLadder(passport["stages"])).join(" "),
17367
- message: opts.hint
17368
- })
17369
- );
17370
- }
17371
17269
  function fromWords(text2, contract) {
17372
17270
  let data;
17373
17271
  try {
@@ -17385,6 +17283,47 @@ function folderAnswer(text2) {
17385
17283
  const read = fromWords(text2);
17386
17284
  return "refusal" in read ? toolError(read.refusal) : toolSuccess(read.words, read.data);
17387
17285
  }
17286
+ var DRAFT_CONTRACT = "naparnik-draft/1";
17287
+ var VIEW_CONTRACT = "naparnik-view/1";
17288
+ var EDIT_CONTRACT = "naparnik-edit/1";
17289
+ function answerOrRefusal(text2, contract) {
17290
+ const read = fromWords(text2, contract);
17291
+ if ("refusal" in read) {
17292
+ const plain = text2.trim();
17293
+ return { refusal: plain.startsWith("{") || plain === "" ? read.refusal : plain };
17294
+ }
17295
+ return read.data["ok"] === false ? { refusal: read.words } : read;
17296
+ }
17297
+ async function draftDocument(engine, place, asked, key) {
17298
+ const answer = await engine.command([
17299
+ "document-draft",
17300
+ "--video",
17301
+ asked.video,
17302
+ "--pack",
17303
+ place.pack,
17304
+ ...asked.style !== void 0 ? ["--style", path(asked.style)] : [],
17305
+ ...(asked.also ?? []).flatMap((one) => ["--also", path(one)]),
17306
+ ...asked.ask !== void 0 ? ["--ask", JSON.stringify(asked.ask)] : [],
17307
+ "--json"
17308
+ ], key !== void 0 ? { key } : {});
17309
+ return answer.ok ? answerOrRefusal(answer.text, DRAFT_CONTRACT) : { refusal: answer.text };
17310
+ }
17311
+ async function editOperations(engine, place, asked, key) {
17312
+ const answer = await engine.command([
17313
+ "document-edit",
17314
+ "--project",
17315
+ path(asked.reel),
17316
+ "--ops",
17317
+ JSON.stringify(asked.ops),
17318
+ ...asked.stamps !== void 0 ? ["--stamps", JSON.stringify(asked.stamps)] : [],
17319
+ "--by",
17320
+ asked.by ?? "model",
17321
+ "--pack",
17322
+ place.pack,
17323
+ "--json"
17324
+ ], key !== void 0 ? { key } : {});
17325
+ return answer.ok ? answerOrRefusal(answer.text, EDIT_CONTRACT) : { refusal: answer.text };
17326
+ }
17388
17327
  function nameOrRefusal(candidate) {
17389
17328
  const looksLikePath2 = candidate.includes("/") || candidate.includes("\\") || candidate.startsWith("~") || candidate.startsWith(".") || candidate.length > 1 && candidate[1] === ":";
17390
17329
  if (!looksLikePath2) return { name: candidate };
@@ -17743,6 +17682,218 @@ function wordsOf(content) {
17743
17682
  if (typeof content === "string") return content;
17744
17683
  return content.map((block) => block.type === "text" ? block.text : "").join("\n");
17745
17684
  }
17685
+ async function startRender(engine, asked, key, tell) {
17686
+ const place = engine.place();
17687
+ if (place === null) return toolError(engine.whyNoEngine());
17688
+ const where = fileOrRefusal(asked.video);
17689
+ if ("refusal" in where) return toolError(where.refusal);
17690
+ if (asked.onlyPauses !== true) return startDocumentRender(engine, where.path, key, tell);
17691
+ if (tell !== void 0) for (const line of PAUSES_LADDER) tell(line);
17692
+ const ask2 = { pauses: {} };
17693
+ if (asked.tempo !== void 0 && asked.tempo !== 1) ask2["tempo"] = asked.tempo;
17694
+ const draft = await draftDocument(engine, place, { video: where.path, style: asked.style, ask: ask2 }, key);
17695
+ if ("refusal" in draft) return toolError(draft.refusal);
17696
+ const reel = String(draft.data["project"] ?? where.path);
17697
+ const agreement = await editOperations(engine, place, { reel, ops: [{ op: "agree" }] }, key);
17698
+ if ("refusal" in agreement) return toolError(agreement.refusal);
17699
+ return startDocumentRender(engine, reel, key, tell);
17700
+ }
17701
+ async function startDocumentRender(engine, reel, key, tell) {
17702
+ const place = engine.place();
17703
+ if (place === null) return toolError(engine.whyNoEngine());
17704
+ const trouble = await engine.pythonTrouble();
17705
+ if (trouble !== null) return toolError(trouble);
17706
+ const python = engine.packPython();
17707
+ if (python === null) {
17708
+ return toolError("\u041E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u0435 \u043C\u043E\u043D\u0442\u0430\u0436\u0430 \u0435\u0449\u0451 \u043D\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0437\u043E\u0432\u0438 setup.");
17709
+ }
17710
+ if (tell !== void 0) for (const line of RENDER_LADDER) tell(line);
17711
+ const what = `\u043C\u043E\u043D\u0442\u0430\u0436 ${basename(reel)}`;
17712
+ const launch = await engine.background({
17713
+ place,
17714
+ executable: python,
17715
+ key,
17716
+ startJob: [
17717
+ "job-create",
17718
+ "--video",
17719
+ reel,
17720
+ "--what",
17721
+ what,
17722
+ "--command",
17723
+ JSON.stringify({ tool: "render", args: {} })
17724
+ ],
17725
+ args: (id) => [
17726
+ place.consolePy,
17727
+ "document-render",
17728
+ "--project",
17729
+ reel,
17730
+ "--pack",
17731
+ place.pack,
17732
+ "--job",
17733
+ id
17734
+ ],
17735
+ advice: "\u043F\u043E\u0437\u043E\u0432\u0438 setup \u2014 \u0441\u043A\u043E\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043E, \u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u0435 \u043D\u0435\u043F\u043E\u043B\u043D\u043E\u0435"
17736
+ });
17737
+ if ("refusal" in launch) return toolError(launch.refusal);
17738
+ return toolSuccess(
17739
+ `\u0417\u0430\u0434\u0430\u0447\u0430 ${launch.id}: ${what}
17740
+ \u0414\u0430\u043B\u044C\u0448\u0435 \u043F\u043E\u0437\u043E\u0432\u0438 wait \u0441 \u044D\u0442\u0438\u043C \u043D\u043E\u043C\u0435\u0440\u043E\u043C. ${AWAY_NOTE}`,
17741
+ startedJob({
17742
+ id: launch.id,
17743
+ what,
17744
+ ahead: RENDER_LADDER.join(" "),
17745
+ message: "\u0420\u043E\u043B\u0438\u043A \u0441\u043E\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044F \u043D\u0430 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F."
17746
+ })
17747
+ );
17748
+ }
17749
+ var RENDER_LADDER = [
17750
+ "\u041F\u0440\u043E\u0432\u0435\u0440\u044E, \u0447\u0442\u043E \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u0441\u043E\u0433\u043B\u0430\u0441\u043E\u0432\u0430\u043D \u0438 \u043D\u0435 \u043F\u0440\u0430\u0432\u043B\u0435\u043D \u043C\u0438\u043C\u043E plan_edit.",
17751
+ "\u041F\u043E\u0441\u0447\u0438\u0442\u0430\u044E \u044D\u0444\u0444\u0435\u043A\u0442\u044B \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A\u0430 (\u0432\u044B\u0440\u0435\u0437 \u0433\u0435\u0440\u043E\u044F, \u0448\u0443\u043C\u043E\u0434\u0430\u0432) \u0442\u0430\u043C, \u0433\u0434\u0435 \u0438\u0445 \u0432\u0438\u0434\u043D\u043E, \u2014 \u043F\u043E\u0442\u043E\u043C \u0441\u043E\u0431\u0435\u0440\u0443 \u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0443 \u0438 \u0437\u0432\u0443\u043A."
17752
+ ];
17753
+ async function followWork(engine, asked, pace = realPace, tell) {
17754
+ const ask2 = () => engine.command(["job", asked.job]);
17755
+ const seconds2 = waitSeconds(asked.seconds ?? WAIT_LIMIT_SECONDS);
17756
+ if (seconds2 === 0) return asJobResult(await ask2());
17757
+ const state = await followJob({
17758
+ ask: ask2,
17759
+ seconds: seconds2,
17760
+ pace,
17761
+ // ⚠ Рассказ есть только если КЛИЕНТ его попросил (токен хода работы в
17762
+ // `_meta`). Нет — ждём молча и отвечаем итогом: ждать всё равно дешевле
17763
+ // пяти кругов переписки «спроси ещё раз».
17764
+ ...tell !== void 0 ? { tell } : {}
17765
+ });
17766
+ if (state.ok && stillWorking(state.text)) {
17767
+ const words = `${state.text}
17768
+ \u0416\u0434\u0430\u043B ${seconds2} \u0441, \u0440\u0430\u0431\u043E\u0442\u0430 \u0435\u0449\u0451 \u0438\u0434\u0451\u0442. \u0421\u043A\u0430\u0436\u0438 \u044D\u0442\u043E \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0443 \u0438 \u043F\u043E\u0437\u043E\u0432\u0438 wait \u0435\u0449\u0451 \u0440\u0430\u0437 \u2014 \u0442\u0430\u043A \u043E\u043D \u0443\u0441\u043B\u044B\u0448\u0438\u0442 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0435 \u0448\u0430\u0433\u0438.`;
17769
+ const job = readJob(state.text);
17770
+ return job === null ? toolSuccess(words) : toolSuccess(words, job);
17771
+ }
17772
+ return asJobResult(state);
17773
+ }
17774
+ async function listJobs(engine, asked) {
17775
+ return asToolResult(
17776
+ await engine.command([
17777
+ "jobs",
17778
+ ...asked.video !== void 0 ? ["--video", path(asked.video)] : [],
17779
+ ...asked.limit !== void 0 ? ["--count", String(asked.limit)] : []
17780
+ ])
17781
+ );
17782
+ }
17783
+ function renderTool(engine, _passport, key) {
17784
+ return defineTool({
17785
+ name: "render",
17786
+ title: "\u0421\u043E\u0431\u0440\u0430\u0442\u044C \u0440\u043E\u043B\u0438\u043A",
17787
+ description: '\u0421\u043E\u0431\u0438\u0440\u0430\u0435\u0442 \u0441\u043E\u0433\u043B\u0430\u0441\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u0440\u043E\u043B\u0438\u043A\u0430 \u043D\u0430 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430: \u044D\u0444\u0444\u0435\u043A\u0442\u044B \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A\u0430 (\u0432\u044B\u0440\u0435\u0437 \u0433\u0435\u0440\u043E\u044F, \u0448\u0443\u043C\u043E\u0434\u0430\u0432), \u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0443, \u0437\u0432\u0443\u043A, \u0433\u043E\u0442\u043E\u0432\u044B\u0439 \u0444\u0430\u0439\u043B. \u0417\u043E\u0432\u0438 \u041F\u041E\u0421\u041B\u0415 \u0442\u043E\u0433\u043E, \u043A\u0430\u043A \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u0441\u043A\u0430\u0437\u0430\u043B \xAB\u0434\u0430\xBB \u043D\u0430 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0438\u0437 plan \u0438 \u0442\u044B \u0437\u0430\u043F\u0438\u0441\u0430\u043B \u044D\u0442\u043E plan_edit \u0441 {"op": "agree"}. \u0421\u043E\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044F \u0422\u041E\u041B\u042C\u041A\u041E \u0441\u043E\u0433\u043B\u0430\u0441\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442, \u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u0437\u0430\u043F\u0438\u0441\u0430\u043D\u043D\u044B\u0439 \u0447\u0435\u0440\u0435\u0437 plan_edit: \u0444\u0430\u0439\u043B, \u043F\u043E\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043D\u044B\u0439 \u043C\u0438\u043C\u043E \u043D\u0435\u0433\u043E, \u0434\u0432\u0438\u0436\u043E\u043A \u043D\u0435 \u0441\u043E\u0431\u0435\u0440\u0451\u0442 \u2014 \xAB\u043F\u0440\u0438\u0448\u043B\u0438 \u043F\u0440\u0430\u0432\u043A\u0443 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F\u043C\u0438\xBB.\n\u041E\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u0434\u0430\u043B\u044C\u0448\u0435 wait, \u043E\u043D \u043F\u043E\u0434\u043E\u0436\u0434\u0451\u0442 \u0438 \u0440\u0430\u0441\u0441\u043A\u0430\u0436\u0435\u0442 \u0445\u043E\u0434. \u041F\u043E\u0432\u0442\u043E\u0440 \u0431\u0435\u0437 \u043F\u0440\u0430\u0432\u043E\u043A \u043E\u0442\u0434\u0430\u0451\u0442 \u0433\u043E\u0442\u043E\u0432\u043E\u0435 \u0441\u0440\u0430\u0437\u0443.\n\u041F\u0440\u043E\u0441\u044F\u0442 \xAB\u043F\u0440\u043E\u0441\u0442\u043E \u0443\u0431\u0435\u0440\u0438 \u043F\u0430\u0443\u0437\u044B\xBB \u2014 only_pauses=true \u0441 video: \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0441 \u043E\u0434\u043D\u0438\u043C\u0438 \u043F\u0430\u0443\u0437\u0430\u043C\u0438, \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u0435 \u0438 \u0441\u0431\u043E\u0440\u043A\u0430 \u043E\u0434\u043D\u0438\u043C \u0432\u044B\u0437\u043E\u0432\u043E\u043C; tempo \u0440\u044F\u0434\u043E\u043C \u2014 \xAB\u0438 \u0443\u0441\u043A\u043E\u0440\u044C\xBB. \u041F\u0430\u0443\u0437\u044B \u0443\u0431\u0438\u0440\u0430\u044E\u0442\u0441\u044F \u043F\u043E \u0441\u043B\u043E\u0432\u0430\u043C, \u043F\u043E\u044D\u0442\u043E\u043C\u0443 \u043D\u0443\u0436\u043D\u0430 \u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u043D\u043D\u0430\u044F \u0440\u0435\u0447\u044C.\n\u0420\u0430\u0431\u043E\u0442\u0430 \u0438\u0434\u0451\u0442 \u043D\u0430 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430, \u043A \u043D\u0430\u043C \u0432\u0438\u0434\u0435\u043E \u043D\u0435 \u0443\u0445\u043E\u0434\u0438\u0442 \u2014 \u043D\u0430\u0432\u0435\u0440\u0445 \u0438\u0434\u0451\u0442 \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E\u0434\u043F\u0438\u0441\u043A\u0438 \u043F\u043E \u043A\u043B\u044E\u0447\u0443.',
17788
+ // Полоса хода работы: монтаж идёт минутами, и всё это время в ленте не
17789
+ // происходило бы ничего. ⚠ Ожидание — у `wait`, и полосы там нет: иначе
17790
+ // каждая проверка рисовала бы новую поверх этой.
17791
+ ui: { resourceUri: RUNBAR_RESOURCE_URI },
17792
+ args: external_exports.object({
17793
+ video: external_exports.string().describe(
17794
+ "\u041F\u0443\u0442\u044C \u043A \u0432\u0438\u0434\u0435\u043E\u0444\u0430\u0439\u043B\u0443 \u0440\u043E\u043B\u0438\u043A\u0430. \u0417\u0430\u0432\u0435\u0434\u0451\u043D\u043D\u044B\u0439 \u0440\u043E\u043B\u0438\u043A \u043C\u043E\u0436\u043D\u043E \u043D\u0430\u0437\u0432\u0430\u0442\u044C \u0438 \u043F\u0430\u043F\u043A\u043E\u0439 \u2014 \u043A\u043B\u044E\u0447\u043E\u043C reel"
17795
+ ).optional(),
17796
+ reel: external_exports.string().describe(
17797
+ "\u041F\u0430\u043F\u043A\u0430 \u0440\u043E\u043B\u0438\u043A\u0430: \u0441\u043E\u0431\u0435\u0440\u0443 \u0435\u0433\u043E \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 reel.json"
17798
+ ).optional(),
17799
+ only_pauses: external_exports.boolean().describe(
17800
+ "\u0422\u043E\u043B\u044C\u043A\u043E \u0443\u0431\u0440\u0430\u0442\u044C \u043F\u0430\u0443\u0437\u044B: \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0441 \u043E\u0434\u043D\u0438\u043C \u0440\u0430\u0437\u0434\u0435\u043B\u043E\u043C pauses, \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u0435 \u0438 \u0441\u0431\u043E\u0440\u043A\u0430 \u0440\u0430\u0437\u043E\u043C"
17801
+ ).optional(),
17802
+ tempo: external_exports.number().describe(
17803
+ "\u0422\u043E\u043B\u044C\u043A\u043E \u0432\u043C\u0435\u0441\u0442\u0435 \u0441 only_pauses: \u0443\u0441\u043A\u043E\u0440\u0438\u0442\u044C \u0440\u0435\u0447\u044C, 1.0 \u2014 \u0431\u0435\u0437 \u0443\u0441\u043A\u043E\u0440\u0435\u043D\u0438\u044F"
17804
+ ).optional(),
17805
+ style: external_exports.string().describe(
17806
+ "\u0422\u043E\u043B\u044C\u043A\u043E \u0432\u043C\u0435\u0441\u0442\u0435 \u0441 only_pauses: \u043F\u0430\u043F\u043A\u0430 \u043F\u0430\u043A\u0430 \u0444\u0438\u0440\u043C\u0435\u043D\u043D\u043E\u0433\u043E \u0441\u0442\u0438\u043B\u044F"
17807
+ ).optional()
17808
+ }).check((ctx) => {
17809
+ const asked = ctx.value;
17810
+ const say = (message, where) => {
17811
+ ctx.issues.push({ code: "custom", message, input: asked, path: [where] });
17812
+ };
17813
+ if (asked.video === void 0 && asked.reel === void 0) {
17814
+ say(
17815
+ "\u041D\u0435 \u0441\u043A\u0430\u0437\u0430\u043D\u043E, \u0447\u0442\u043E \u0441\u043E\u0431\u0438\u0440\u0430\u0442\u044C: \u043D\u0430\u0437\u043E\u0432\u0438 video (\u0444\u0430\u0439\u043B) \u0438\u043B\u0438 reel (\u043F\u0430\u043F\u043A\u0443 \u0437\u0430\u0432\u0435\u0434\u0451\u043D\u043D\u043E\u0433\u043E \u0440\u043E\u043B\u0438\u043A\u0430). \u0427\u0442\u043E \u0443 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u0435\u0441\u0442\u044C, \u043F\u043E\u043A\u0430\u0436\u0435\u0442 plan \u0431\u0435\u0437 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u0432",
17816
+ "video"
17817
+ );
17818
+ }
17819
+ if (asked.video !== void 0 && asked.reel !== void 0) {
17820
+ say("\xABvideo\xBB \u0438 \xABreel\xBB \u2014 \u044D\u0442\u043E \u043E\u0434\u043D\u043E \u0438 \u0442\u043E \u0436\u0435 \u043C\u0435\u0441\u0442\u043E, \u043D\u0430\u0437\u0432\u0430\u043D\u043D\u043E\u0435 \u0434\u0432\u0430\u0436\u0434\u044B. \u041E\u0441\u0442\u0430\u0432\u044C \u043E\u0434\u043D\u043E", "reel");
17821
+ }
17822
+ if (asked.only_pauses === true) return;
17823
+ const extra = ["tempo", "style"].filter((name) => asked[name] !== void 0);
17824
+ if (extra.length > 0) {
17825
+ say(
17826
+ `${extra.join(", ")} \u2014 \u0447\u0430\u0441\u0442\u044C \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430, \u0430 \u043D\u0435 \u0441\u0431\u043E\u0440\u043A\u0438: \u0442\u0435\u043C\u043F \u2014 plan \u0441 ask {"tempo": \u2026} \u0438\u043B\u0438 plan_edit, \u0441\u0442\u0438\u043B\u044C \u2014 plan \u0441\u043E style. \u0417\u0434\u0435\u0441\u044C \u043E\u043D\u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u0432\u043C\u0435\u0441\u0442\u0435 \u0441 only_pauses`,
17827
+ extra[0] ?? "tempo"
17828
+ );
17829
+ }
17830
+ }),
17831
+ async execute(args, ctx) {
17832
+ return startRender(
17833
+ engine,
17834
+ {
17835
+ video: args.video ?? args.reel ?? "",
17836
+ onlyPauses: args.only_pauses,
17837
+ tempo: args.tempo,
17838
+ style: args.style
17839
+ },
17840
+ key,
17841
+ ctx?.emitProgress
17842
+ );
17843
+ }
17844
+ });
17845
+ }
17846
+ function waitTool(engine, pace = realPace) {
17847
+ return defineTool({
17848
+ name: "wait",
17849
+ title: "\u0414\u043E\u0436\u0434\u0430\u0442\u044C\u0441\u044F \u0440\u0430\u0431\u043E\u0442\u044B",
17850
+ description: `\u0416\u0434\u0451\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 \u0438 \u043F\u043E \u0445\u043E\u0434\u0443 \u0440\u0430\u0441\u0441\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442, \u043A\u0430\u043A\u043E\u0439 \u0448\u0430\u0433 \u043F\u043E\u0448\u0451\u043B \u0438 \u043A\u0430\u043A\u043E\u0439 \u0437\u0430\u043A\u043E\u043D\u0447\u0438\u043B\u0441\u044F \u2014 \u043F\u0435\u0440\u0435\u0441\u043A\u0430\u0437\u044B\u0432\u0430\u0439 \u044D\u0442\u043E \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0443 \u0441\u0440\u0430\u0437\u0443, \u043D\u0435 \u0434\u043E\u0436\u0438\u0434\u0430\u044F\u0441\u044C \u043A\u043E\u043D\u0446\u0430. \u0422\u0430\u043A \u0438 \u0441\u043F\u0440\u0430\u0448\u0438\u0432\u0430\u0439: \u043E\u043F\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044C \u043F\u043E \u043A\u0440\u0443\u0433\u0443 \u043D\u0435 \u043D\u0430\u0434\u043E, \u0436\u0434\u0451\u0442 \u043E\u043D \u0434\u043E ${WAIT_LIMIT_SECONDS} \u0441\u0435\u043A\u0443\u043D\u0434 \u0438 \u0432\u0435\u0440\u043D\u0451\u0442\u0441\u044F \u0440\u0430\u043D\u044C\u0448\u0435, \u0435\u0441\u043B\u0438 \u0440\u0430\u0431\u043E\u0442\u0430 \u043A\u043E\u043D\u0447\u0438\u0442\u0441\u044F.
17851
+ \u0411\u0435\u0437 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u0432 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u043D\u043E\u043C\u0435\u0440, \u0440\u043E\u043B\u0438\u043A, \u0447\u0435\u043C \u043A\u043E\u043D\u0447\u0438\u043B\u043E\u0441\u044C. \u0417\u043E\u0432\u0438, \u043A\u043E\u0433\u0434\u0430 \u043D\u043E\u043C\u0435\u0440 \u043F\u043E\u0442\u0435\u0440\u044F\u043B\u0441\u044F: \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440, \u043F\u043E\u0441\u043B\u0435 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A\u0430 \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u044B \u0438\u043B\u0438 \u043A\u043E\u0433\u0434\u0430 \u0432\u044B\u0437\u043E\u0432 \u043E\u0431\u043E\u0440\u0432\u0430\u043B\u0441\u044F \u043F\u043E\u0441\u0440\u0435\u0434\u0438 \u0440\u0430\u0431\u043E\u0442\u044B. \u0421 video \u2014 \u0437\u0430\u0434\u0430\u0447\u0438 \u043E\u0434\u043D\u043E\u0433\u043E \u0440\u043E\u043B\u0438\u043A\u0430.
17852
+ \u0417\u0430\u0434\u0430\u0447\u0438 \u043B\u0435\u0436\u0430\u0442 \u043D\u0430 \u0434\u0438\u0441\u043A\u0435 \u0438 \u043F\u0435\u0440\u0435\u0436\u0438\u0432\u0430\u044E\u0442 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u044B. \u041F\u043E\u0434\u043F\u0438\u0441\u043A\u0430 \u043D\u0435 \u043D\u0443\u0436\u043D\u0430: \u0437\u0430\u0431\u0440\u0430\u0442\u044C \u0443\u0436\u0435 \u0441\u0434\u0435\u043B\u0430\u043D\u043D\u043E\u0435 \u043C\u043E\u0436\u043D\u043E \u0432\u0441\u0435\u0433\u0434\u0430.`,
17853
+ args: external_exports.object({
17854
+ job: external_exports.string().describe(
17855
+ "\u041D\u043E\u043C\u0435\u0440 \u0437\u0430\u0434\u0430\u0447\u0438, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 2026-08-19T14-03-12Z-a3f1. \u0415\u0433\u043E \u043D\u0430\u0437\u0432\u0430\u043B \u0442\u043E\u0442 \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442, \u0447\u0442\u043E \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u043B \u0440\u0430\u0431\u043E\u0442\u0443"
17856
+ ).optional(),
17857
+ seconds: external_exports.number().describe(
17858
+ `\u0421\u043A\u043E\u043B\u044C\u043A\u043E \u0441\u0435\u043A\u0443\u043D\u0434 \u0436\u0434\u0430\u0442\u044C. \u041F\u043E\u0442\u043E\u043B\u043E\u043A ${WAIT_LIMIT_SECONDS}: \u043F\u0440\u043E\u0441\u044C\u0431\u0430 \u0431\u043E\u043B\u044C\u0448\u0435 \u043C\u043E\u043B\u0447\u0430 \u043E\u0431\u0440\u0435\u0436\u0435\u0442\u0441\u044F. \u0411\u0435\u0437 \u043D\u0435\u0433\u043E \u0436\u0434\u0451\u0442 \u0441\u0442\u043E\u043B\u044C\u043A\u043E, \u0441\u043A\u043E\u043B\u044C\u043A\u043E \u043C\u043E\u0436\u043D\u043E`
17859
+ ).optional(),
17860
+ video: external_exports.string().describe("\u0422\u043E\u043B\u044C\u043A\u043E \u0437\u0430\u0434\u0430\u0447\u0438 \u044D\u0442\u043E\u0433\u043E \u0440\u043E\u043B\u0438\u043A\u0430 (\u0431\u0435\u0437 job)").optional(),
17861
+ limit: external_exports.number().describe("\u0421\u043A\u043E\u043B\u044C\u043A\u043E \u0437\u0430\u0434\u0430\u0447 \u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C, \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E 15").optional()
17862
+ }).check((ctx) => {
17863
+ const asked = ctx.value;
17864
+ if (asked.job === void 0) {
17865
+ if (asked.seconds !== void 0) {
17866
+ ctx.issues.push({
17867
+ code: "custom",
17868
+ message: "\xABseconds\xBB \u2014 \u044D\u0442\u043E \u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0436\u0434\u0430\u0442\u044C \u041E\u0414\u041D\u0423 \u0437\u0430\u0434\u0430\u0447\u0443: \u043D\u0430\u0437\u043E\u0432\u0438 \u0435\u0451 \u043D\u043E\u043C\u0435\u0440 \u0432 \xABjob\xBB",
17869
+ input: asked,
17870
+ path: ["seconds"]
17871
+ });
17872
+ }
17873
+ return;
17874
+ }
17875
+ for (const key of ["video", "limit"]) {
17876
+ if (asked[key] !== void 0) {
17877
+ ctx.issues.push({
17878
+ code: "custom",
17879
+ message: `\xAB${key}\xBB \u043E\u0442\u043D\u043E\u0441\u0438\u0442\u0441\u044F \u043A \u0421\u041F\u0418\u0421\u041A\u0423 \u0437\u0430\u0434\u0430\u0447, \u0430 \u0441 \xABjob\xBB \u0436\u0434\u0443\u0442 \u043E\u0434\u043D\u0443. \u041F\u043E\u0437\u043E\u0432\u0438 \u0431\u0435\u0437 \xABjob\xBB, \u0447\u0442\u043E\u0431\u044B \u0443\u0432\u0438\u0434\u0435\u0442\u044C \u0441\u043F\u0438\u0441\u043E\u043A`,
17880
+ input: asked,
17881
+ path: [key]
17882
+ });
17883
+ }
17884
+ }
17885
+ }),
17886
+ readOnly: true,
17887
+ async execute(args, ctx) {
17888
+ const place = engine.place();
17889
+ if (place === null) return toolError(engine.whyNoEngine());
17890
+ if (args.job === void 0) {
17891
+ return listJobs(engine, { video: args.video, limit: args.limit });
17892
+ }
17893
+ return followWork(engine, { job: args.job, seconds: args.seconds }, pace, ctx?.emitProgress);
17894
+ }
17895
+ });
17896
+ }
17746
17897
  async function listReels(engine, workspace) {
17747
17898
  const place = engine.place();
17748
17899
  if (place === null) return toolError(engine.whyNoEngine());
@@ -17778,18 +17929,7 @@ async function openReel(engine, asked) {
17778
17929
  if (!answer.ok) return toolError(answer.text);
17779
17930
  return folderAnswer(answer.text);
17780
17931
  }
17781
- var PLAN_DRAFT = "naparnik-plan-draft/1";
17782
- var COMPOSITION_VIEW = "naparnik-composition-view/1";
17783
17932
  var SKILLS_READ = "naparnik-skills-read/1";
17784
- function answerOrRefusal(text2, contract) {
17785
- const read = fromWords(text2, contract);
17786
- if ("refusal" in read) {
17787
- const plain = text2.trim();
17788
- return { refusal: plain.startsWith("{") || plain === "" ? read.refusal : plain };
17789
- }
17790
- const said = read.data;
17791
- return said.ok === false ? { refusal: read.words } : read;
17792
- }
17793
17933
  async function readSkills(engine, asked) {
17794
17934
  const place = engine.place();
17795
17935
  if (place === null) return toolError(engine.whyNoEngine());
@@ -17805,19 +17945,21 @@ async function readSkills(engine, asked) {
17805
17945
  const read = answerOrRefusal(answer.text, SKILLS_READ);
17806
17946
  return "refusal" in read ? toolError(read.refusal) : toolSuccess(read.words, read.data);
17807
17947
  }
17808
- async function viewComposition(engine, reel) {
17948
+ async function viewDocument(engine, reel) {
17809
17949
  const place = engine.place();
17810
17950
  if (place === null) return toolError(engine.whyNoEngine());
17811
17951
  const where = fileOrRefusal(reel);
17812
17952
  if ("refusal" in where) return toolError(where.refusal);
17813
17953
  const answer = await engine.command([
17814
- "composition-view",
17954
+ "document-view",
17815
17955
  "--project",
17816
17956
  path(where.path),
17957
+ "--pack",
17958
+ place.pack,
17817
17959
  "--json"
17818
17960
  ]);
17819
17961
  if (!answer.ok) return toolError(answer.text);
17820
- const read = answerOrRefusal(answer.text, COMPOSITION_VIEW);
17962
+ const read = answerOrRefusal(answer.text, VIEW_CONTRACT);
17821
17963
  return "refusal" in read ? toolError(read.refusal) : toolSuccess(read.words, read.data);
17822
17964
  }
17823
17965
  async function whereToDraft(engine, video, also, workspace) {
@@ -17888,91 +18030,51 @@ async function planDraft(engine, asked, key, tell) {
17888
18030
 
17889
18031
  ` : "";
17890
18032
  const withHead = (text2) => `${head2}${text2}`;
17891
- const answer = await engine.command([
17892
- "plan-draft",
17893
- "--video",
17894
- plan.speech,
17895
- "--pack",
17896
- place.pack,
17897
- ...asked.style !== void 0 ? ["--style", path(asked.style)] : [],
17898
- "--json"
17899
- ], key !== void 0 ? { key } : {});
17900
- if (!answer.ok) return toolError(withHead(answer.text));
17901
- const read = answerOrRefusal(answer.text, PLAN_DRAFT);
18033
+ const also = plan.toOpen.length > 0 ? [] : asked.also ?? [];
18034
+ const read = await draftDocument(
18035
+ engine,
18036
+ place,
18037
+ { video: plan.speech, style: asked.style, ask: asked.ask, also },
18038
+ key
18039
+ );
17902
18040
  if ("refusal" in read) return toolError(withHead(read.refusal));
17903
- return toolSuccess(withHead(read.words), read.data);
18041
+ return withSheets(withHead(read.words), read.data);
18042
+ }
18043
+ async function withSheets(text2, data) {
18044
+ const material = data["material"];
18045
+ const images = Array.isArray(material?.images) ? material.images.filter((one) => typeof one === "string") : [];
18046
+ if (images.length === 0) return toolSuccess(text2, data);
18047
+ const pictures = [];
18048
+ const lost = [];
18049
+ for (const file2 of images) {
18050
+ try {
18051
+ pictures.push({ type: "image", base64: (await readFile(file2)).toString("base64"), mediaType: "image/jpeg" });
18052
+ } catch {
18053
+ lost.push(basename(file2));
18054
+ }
18055
+ }
18056
+ const told = lost.length === 0 ? text2 : `${text2}
18057
+ \u26A0 \u0421\u0435\u0442\u043A\u0430 \u0440\u0430\u0441\u043A\u0430\u0434\u0440\u043E\u0432\u043A\u0438 \u043D\u0435 \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u043B\u0430\u0441\u044C: ${lost.join(", ")}. \u041A\u0430\u0434\u0440 \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A\u0430 \u043F\u043E\u043A\u0430\u0436\u0435\u0442 preview \u0441 video, moment \u0438 from_where=source.`;
18058
+ return toolMixed([{ type: "text", text: told }, ...pictures], data);
17904
18059
  }
17905
18060
  var DRAFT_LADDER = [
17906
- "\u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u0440\u0435\u0447\u044C: \u0443\u0431\u0435\u0440\u0443 \u043F\u0430\u0443\u0437\u044B, \u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u044E \u0441\u043B\u043E\u0432\u0430, \u0440\u0430\u0437\u043B\u043E\u0436\u0443 \u0438\u0445 \u043D\u0430 \u0444\u0440\u0430\u0437\u044B.",
17907
- "\u041F\u043E\u0442\u043E\u043C \u043F\u0440\u0438\u0434\u0443\u043C\u0430\u044E, \u0447\u0442\u043E \u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0438 \u043A\u043E\u0433\u0434\u0430, \u2014 \u0438 \u043F\u043E\u043A\u0430\u0436\u0443 \u044D\u0442\u043E \u0441\u043B\u043E\u0432\u0430\u043C\u0438, \u0434\u043E \u0441\u0431\u043E\u0440\u043A\u0438.",
17908
- "\u041F\u0435\u0440\u0432\u044B\u0439 \u0440\u0430\u0437 \u0438\u0434\u0451\u0442 \u043C\u0438\u043D\u0443\u0442\u0430\u043C\u0438: \u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u0432\u0430\u043D\u0438\u0435 \u0440\u0435\u0447\u0438 \u0441\u0430\u043C\u043E\u0435 \u0434\u043E\u043B\u0433\u043E\u0435. \u041E\u0431\u043E\u0440\u0432\u0451\u0442\u0441\u044F \u2014 \u043F\u043E\u0437\u043E\u0432\u0438 wait, \u0440\u0430\u0431\u043E\u0442\u0430 \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0435\u0442\u0441\u044F, \u0430 \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u044B\u0439 \u043F\u043B\u0430\u043D \u0441\u0442\u043E\u0438\u0442 \u0441\u0435\u043A\u0443\u043D\u0434."
18061
+ "\u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u044E \u0440\u0435\u0447\u044C \u2014 \u0435\u0441\u043B\u0438 \u043F\u0440\u043E\u0441\u044C\u0431\u0435 \u043E\u043D\u0430 \u043D\u0443\u0436\u043D\u0430.",
18062
+ "\u041F\u043E\u0442\u043E\u043C \u0441\u043E\u0431\u0435\u0440\u0443 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430: \u043F\u0430\u0443\u0437\u044B, \u043F\u043E\u0434\u043F\u0438\u0441\u0438, \u043A\u0440\u0443\u043F\u043D\u043E\u0441\u0442\u0438, \u0437\u0432\u0443\u043A \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0442\u043E, \u0447\u0442\u043E \u043F\u0440\u043E\u0441\u0438\u043B\u0438.",
18063
+ "\u041F\u0435\u0440\u0432\u044B\u0439 \u0440\u0430\u0437 \u0438\u0434\u0451\u0442 \u043C\u0438\u043D\u0443\u0442\u0430\u043C\u0438: \u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u0432\u0430\u043D\u0438\u0435 \u0440\u0435\u0447\u0438 \u0441\u0430\u043C\u043E\u0435 \u0434\u043E\u043B\u0433\u043E\u0435. \u041E\u0431\u043E\u0440\u0432\u0451\u0442\u0441\u044F \u2014 \u043F\u043E\u0437\u043E\u0432\u0438 wait, \u0440\u0430\u0431\u043E\u0442\u0430 \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0435\u0442\u0441\u044F, \u0430 \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u044B\u0439 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0441\u0442\u043E\u0438\u0442 \u0441\u0435\u043A\u0443\u043D\u0434."
17909
18064
  ];
17910
- function aboutAgreement(said) {
17911
- const lines = [];
17912
- if (said.agreed === true) lines.push("\u041F\u043B\u0430\u043D \u0441\u043E\u0433\u043B\u0430\u0441\u043E\u0432\u0430\u043D \u2014 \u043C\u043E\u0436\u043D\u043E \u0441\u043E\u0431\u0438\u0440\u0430\u0442\u044C.");
17913
- if (said.agreed === false) {
17914
- lines.push(
17915
- "\u0421\u043E\u0433\u043B\u0430\u0441\u0438\u044F \u043D\u0435\u0442: \u044D\u0442\u043E\u0439 \u0440\u0435\u0434\u0430\u043A\u0446\u0438\u0438 \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u0435\u0449\u0451 \u043D\u0435 \u0432\u0438\u0434\u0435\u043B. \u041F\u0435\u0440\u0435\u0441\u043A\u0430\u0436\u0438 \u0435\u043C\u0443, \u0447\u0442\u043E \u0432\u044B\u0448\u043B\u043E, \u0438 \u043D\u0430 \xAB\u0434\u0430\xBB \u043F\u043E\u0437\u043E\u0432\u0438 plan_edit \u0441 confirm \u2014 \u043C\u043E\u0436\u043D\u043E \u0442\u0435\u043C \u0436\u0435 \u0432\u044B\u0437\u043E\u0432\u043E\u043C, \u0447\u0442\u043E \u0438 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0443\u044E \u043F\u0440\u0430\u0432\u043A\u0443."
17916
- );
17917
- }
17918
- if (said.plan_mine === true) {
17919
- lines.push(
17920
- "\u041F\u043B\u0430\u043D \u0440\u043E\u043B\u0438\u043A\u0430 \u0442\u0435\u043F\u0435\u0440\u044C \u0422\u0412\u041E\u0419: \u0441\u043E\u0431\u0438\u0440\u0430\u0442\u044C\u0441\u044F \u0431\u0443\u0434\u0435\u0442 \u043E\u043D, \u043D\u0430\u0448 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435 \u043F\u0440\u0438\u043C\u0435\u043D\u044F\u0435\u0442\u0441\u044F. \u0412\u0435\u0440\u043D\u0443\u0442\u044C \u043D\u0430\u0448 \u2014 plan_edit \u0441 draft."
17921
- );
17922
- }
17923
- return lines;
17924
- }
17925
- async function editPlan(engine, asked, key, tell) {
18065
+ async function editDocument(engine, asked, key, tell) {
17926
18066
  const place = engine.place();
17927
18067
  if (place === null) return toolError(engine.whyNoEngine());
17928
- const asked_ = await engine.command([
17929
- "plan-edit",
17930
- "--project",
17931
- path(asked.reel),
17932
- ...asked.ops.length > 0 ? ["--ops", JSON.stringify(asked.ops)] : [],
17933
- ...asked.plan !== void 0 ? ["--plan", JSON.stringify(asked.plan)] : [],
17934
- ...asked.project !== void 0 ? ["--composition", JSON.stringify(asked.project)] : [],
17935
- ...asked.draft === true ? ["--draft"] : [],
17936
- ...asked.confirm === true ? ["--confirm"] : [],
17937
- "--by",
17938
- asked.by ?? "model",
17939
- "--json"
17940
- ], key !== void 0 ? { key } : {});
17941
- if (!asked_.ok) return toolError(asked_.text);
17942
- let said;
17943
- try {
17944
- said = JSON.parse(lastLine(asked_.text));
17945
- } catch {
17946
- return toolSuccess(asked_.text);
17947
- }
17948
- const many = (said.overrides ?? []).length;
17949
- const done = typeof said.words === "string" && said.words !== "" ? said.words : [
17950
- `\u041F\u0440\u0430\u0432\u043E\u043A \u0432 \u043F\u043B\u0430\u043D\u0435 \u0440\u043E\u043B\u0438\u043A\u0430: ${many}. \u0420\u043E\u043B\u0438\u043A: ${said.project ?? asked.reel}`,
17951
- ...aboutAgreement(said)
17952
- ].join("\n");
17953
- if (asked.rebuild !== true) {
17954
- return toolSuccess(
17955
- `${done}
17956
- \u0427\u0442\u043E\u0431\u044B \u0443\u0432\u0438\u0434\u0435\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442, \u043F\u043E\u0437\u043E\u0432\u0438 plan_edit \u0435\u0449\u0451 \u0440\u0430\u0437 \u0441 rebuild \u0438\u043B\u0438 \u0441\u043E\u0431\u0435\u0440\u0438 render \u2014 \u043F\u0435\u0440\u0435\u0441\u0431\u043E\u0440\u043A\u0430 \u0438\u0437 \u043A\u044D\u0448\u0430 \u0441\u0442\u043E\u0438\u0442 \u0441\u0435\u043A\u0443\u043D\u0434.`
17957
- );
17958
- }
17959
- if (said.video === null || said.video === void 0) {
17960
- return toolError(
17961
- `${done}
17962
- \u0410 \u043F\u0435\u0440\u0435\u0441\u043E\u0431\u0440\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u043C: \u0432 \u0431\u0440\u0438\u0444\u0435 \u0440\u043E\u043B\u0438\u043A\u0430 \u043D\u0435 \u0437\u0430\u043F\u0438\u0441\u0430\u043D \u0444\u0430\u0439\u043B \u0441 \u0440\u0435\u0447\u044C\u044E.
17963
- \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0437\u043E\u0432\u0438 render \u0441 \u043F\u0443\u0442\u0451\u043C \u043A \u0432\u0438\u0434\u0435\u043E \u2014 \u043E\u043D \u0438 \u0437\u0430\u043F\u0438\u0448\u0435\u0442 \u0444\u0430\u0439\u043B \u0432 \u0431\u0440\u0438\u0444.`
17964
- );
17965
- }
17966
- return startMontage(engine, {
17967
- key,
17968
- place,
17969
- ...tell !== void 0 ? { tell } : {},
17970
- video: said.video,
17971
- what: `\u043F\u0440\u0430\u0432\u043A\u0430 ${basename(said.video)}`,
17972
- command: { "tool": "montage", "args": {} },
17973
- args: [],
17974
- hint: "\u041F\u0440\u0430\u0432\u043A\u0430 \u043F\u043B\u0430\u043D\u0430: \u0437\u0430\u043D\u043E\u0432\u043E \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E \u0442\u0440\u043E\u043D\u0443\u0442\u043E\u0435, \u043E\u0431\u044B\u0447\u043D\u043E \u0441\u0435\u043A\u0443\u043D\u0434\u044B."
17975
- });
18068
+ const read = await editOperations(engine, place, asked, key);
18069
+ if ("refusal" in read) return toolError(read.refusal);
18070
+ if (asked.rebuild !== true) return toolSuccess(read.words, read.data);
18071
+ const project = typeof read.data["project"] === "string" ? read.data["project"] : asked.reel;
18072
+ const started = await startDocumentRender(engine, project, key, tell);
18073
+ if (started.type === "error") return started;
18074
+ const text2 = typeof started.content === "string" ? started.content : "";
18075
+ return toolSuccess(`${read.words}
18076
+
18077
+ ${text2}`, started.structured);
17976
18078
  }
17977
18079
  var RECIPE_CONTRACT = "naparnik-recipe-view/1";
17978
18080
  var STEP_NEEDS = {
@@ -18042,7 +18144,11 @@ function planTool(engine, key) {
18042
18144
  return defineTool({
18043
18145
  name: "plan",
18044
18146
  title: "\u0427\u0442\u043E \u043F\u043E\u043A\u0430\u0436\u0435\u043C \u0432 \u0440\u043E\u043B\u0438\u043A\u0435",
18045
- description: "\u0427\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0440\u043E\u043B\u0438\u043A\u0430 \u0421\u041B\u041E\u0412\u0410\u041C\u0418 \u2014 \u0434\u043E \u0441\u0431\u043E\u0440\u043A\u0438. \u0411\u0435\u0437 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u0432 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442, \u0447\u0442\u043E \u0443 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u0432 \u043F\u0430\u043F\u043A\u0435: \u0440\u043E\u043B\u0438\u043A\u0438 \u0441 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435\u043C \u0438 \u0444\u0430\u0439\u043B\u044B, \u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u0440\u043E\u043B\u0438\u043A\u043E\u043C \u0435\u0449\u0451 \u043D\u0435 \u0441\u0442\u0430\u043B\u0438. \u0417\u043E\u0432\u0438 \u043F\u0435\u0440\u0432\u044B\u043C, \u043A\u043E\u0433\u0434\u0430 \u043D\u0435 \u0437\u043D\u0430\u0435\u0448\u044C, \u043E \u043A\u0430\u043A\u043E\u043C \u0440\u043E\u043B\u0438\u043A\u0435 \u0440\u0435\u0447\u044C: \u0434\u043E\u0433\u0430\u0434\u043A\u0430 \u0442\u0443\u0442 \u0434\u043E\u0440\u043E\u0436\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u0430.\n\u0421 video \u0437\u0430\u0432\u043E\u0434\u0438\u0442 \u0440\u043E\u043B\u0438\u043A (\u0435\u0441\u043B\u0438 \u044D\u0442\u043E\u0442 \u0444\u0430\u0439\u043B \u0435\u0449\u0451 \u043D\u0435 \u0432 \u0440\u043E\u043B\u0438\u043A\u0435) \u0438 \u043F\u0440\u0438\u0434\u0443\u043C\u044B\u0432\u0430\u0435\u0442 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A: \u0447\u0442\u043E \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C \u0438 \u043A\u043E\u0433\u0434\u0430, \u043D\u043E\u043C\u0435\u0440\u0430 \u0441\u043B\u043E\u0432 \u043D\u0430 \u0433\u0440\u0430\u043D\u0438\u0446\u0430\u0445, \u0438\u043C\u044F \u043A\u0430\u0436\u0434\u043E\u0439 \u0432\u0441\u0442\u0430\u0432\u043A\u0438, \u0434\u0432\u0438\u0436\u0435\u043D\u0438\u0435 \u0441\u043B\u043E\u0432\u0430\u043C\u0438 \u0438 \u043F\u0443\u0441\u0442\u044B\u0435 \u043F\u043E\u0434\u043F\u0438\u0441\u0438, \u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u043D\u0430\u0434\u043E \u043F\u0440\u0438\u0434\u0443\u043C\u0430\u0442\u044C. \u0422\u0435\u043C \u0436\u0435 \u043E\u0442\u0432\u0435\u0442\u043E\u043C \u043D\u0430\u0437\u044B\u0432\u0430\u0435\u0442, \u0427\u0422\u041E \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C \u043F\u043E\u0434 \u044D\u0442\u043E\u0442 \u0440\u043E\u043B\u0438\u043A: \u043F\u0440\u043E\u0447\u0442\u0438 \u044D\u0442\u043E (plan \u0441 read), \u043E\u0431\u0441\u0443\u0434\u0438 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0441 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u043E\u043C, \u043F\u043E\u043F\u0440\u0430\u0432\u044C plan_edit \u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u043E\u0441\u043B\u0435 \u0435\u0433\u043E \xAB\u0434\u0430\xBB \u0437\u043E\u0432\u0438 render.\n\u041F\u0435\u0440\u0432\u044B\u0439 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0438\u0434\u0451\u0442 \u043C\u0438\u043D\u0443\u0442\u0430\u043C\u0438: \u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u0451\u0442\u0441\u044F \u0440\u0435\u0447\u044C. \u041E\u0431\u043E\u0440\u0432\u0430\u043B\u0441\u044F \u0432\u044B\u0437\u043E\u0432 \u2014 \u0440\u0430\u0431\u043E\u0442\u0430 \u043D\u0435 \u043F\u0440\u043E\u043F\u0430\u043B\u0430: \u043F\u043E\u0437\u043E\u0432\u0438 wait, \u0430 \u043F\u043E\u0442\u043E\u043C plan \u043F\u043E \u0442\u043E\u043C\u0443 \u0436\u0435 \u0440\u043E\u043B\u0438\u043A\u0443 \u0435\u0449\u0451 \u0440\u0430\u0437, \u0432\u0442\u043E\u0440\u043E\u0439 \u0440\u0430\u0437 \u044D\u0442\u043E \u0441\u0435\u043A\u0443\u043D\u0434\u044B.\n\u0421 reel \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442 \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0439 \u043E\u0431\u0449\u0438\u0439 naparnik-project/1 \u0446\u0435\u043B\u0438\u043A\u043E\u043C \u0438 \u0433\u043E\u0432\u043E\u0440\u0438\u0442, \u0441\u043E\u0433\u043B\u0430\u0441\u043E\u0432\u0430\u043D\u0430 \u043B\u0438 \u0438\u043C\u0435\u043D\u043D\u043E \u044D\u0442\u0430 \u0440\u0435\u0434\u0430\u043A\u0446\u0438\u044F.\n\u0421 read \u043E\u0442\u0434\u0430\u0451\u0442 \u0442\u0435\u043A\u0441\u0442 \u043D\u0430\u0437\u0432\u0430\u043D\u043D\u044B\u0445 \u0444\u0430\u0439\u043B\u043E\u0432 \u0441\u043A\u0438\u043B\u043B\u043E\u0432 \u0438 \u0437\u043D\u0430\u043D\u0438\u0439 \u2014 \u0442\u0435\u0445, \u0447\u0442\u043E \u043D\u0430\u0437\u0432\u0430\u043B \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A. \u0427\u0438\u0442\u0430\u0439 \u043F\u043E 3\u20134 \u0437\u0430 \u0432\u044B\u0437\u043E\u0432 \u0438 \u043D\u0435 \u0432\u044B\u0434\u0443\u043C\u044B\u0432\u0430\u0439 \u043F\u0443\u0442\u0435\u0439: \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E \u0442\u043E, \u0447\u0442\u043E \u043D\u0430\u0437\u0432\u0430\u043D\u043E.",
18147
+ description: `\u0427\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0440\u043E\u043B\u0438\u043A\u0430 \u2014 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u043C\u043E\u043D\u0442\u0430\u0436\u0430 reel.json \u0438 \u0435\u0433\u043E \u043F\u0435\u0440\u0435\u0441\u043A\u0430\u0437 \u0441\u043B\u043E\u0432\u0430\u043C\u0438, \u0434\u043E \u0441\u0431\u043E\u0440\u043A\u0438. \u0411\u0435\u0437 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u0432 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442, \u0447\u0442\u043E \u0443 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u0432 \u043F\u0430\u043F\u043A\u0435: \u0440\u043E\u043B\u0438\u043A\u0438 \u0441 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435\u043C \u0438 \u0444\u0430\u0439\u043B\u044B, \u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u0440\u043E\u043B\u0438\u043A\u043E\u043C \u0435\u0449\u0451 \u043D\u0435 \u0441\u0442\u0430\u043B\u0438. \u0417\u043E\u0432\u0438 \u043F\u0435\u0440\u0432\u044B\u043C, \u043A\u043E\u0433\u0434\u0430 \u043D\u0435 \u0437\u043D\u0430\u0435\u0448\u044C, \u043E \u043A\u0430\u043A\u043E\u043C \u0440\u043E\u043B\u0438\u043A\u0435 \u0440\u0435\u0447\u044C.
18148
+ \u0421 video \u0437\u0430\u0432\u043E\u0434\u0438\u0442 \u0440\u043E\u043B\u0438\u043A (\u0435\u0441\u043B\u0438 \u0444\u0430\u0439\u043B \u0435\u0449\u0451 \u043D\u0435 \u0432 \u0440\u043E\u043B\u0438\u043A\u0435) \u0438 \u0441\u043E\u0431\u0438\u0440\u0430\u0435\u0442 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A: \u043F\u043E\u0441\u0442\u0430\u0432\u0449\u0438\u043A\u0438 \u043A\u043B\u0430\u0434\u0443\u0442 \u043A\u043B\u0438\u043F\u044B \u043F\u043E \u0440\u0430\u0437\u0434\u0435\u043B\u0430\u043C \u043F\u0440\u043E\u0441\u044C\u0431\u044B. \u0423\u0437\u043A\u0430\u044F \u043F\u0440\u043E\u0441\u044C\u0431\u0430 \u2014 ask \u0441 \u0435\u0451 \u0440\u0430\u0437\u0434\u0435\u043B\u0430\u043C\u0438: {"tempo": 1.2} \u2014 \xAB\u0443\u0441\u043A\u043E\u0440\u044C \u0432 1,2 \u0440\u0430\u0437\u0430\xBB (\u0447\u0438\u0441\u043B\u043E \u043D\u0430\u0437\u044B\u0432\u0430\u0435\u0442 \u0447\u0435\u043B\u043E\u0432\u0435\u043A), {"loudness": {}, "voice": {}} \u2014 \xAB\u043F\u043E\u0434\u043D\u0438\u043C\u0438 \u0433\u0440\u043E\u043C\u043A\u043E\u0441\u0442\u044C \u0438 \u0443\u0431\u0435\u0440\u0438 \u0448\u0443\u043C\xBB; \u0440\u0430\u0437\u0434\u0435\u043B \u0441\u043E \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435\u043C true \u2014 \xAB\u043A\u0430\u043A \u0440\u0435\u0448\u0438\u0442 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\xBB. ask \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u0435\u043D: \xAB\u0441\u043C\u043E\u043D\u0442\u0438\u0440\u0443\u0439\xBB \u0446\u0435\u043B\u0438\u043A\u043E\u043C \u2014 ${FULL_WORDS}. \u041F\u043E\u043B\u043D\u044B\u0439 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0438 \u043F\u0440\u043E\u0441\u044C\u0431\u0430 \u043F\u0440\u043E \u043A\u0430\u0434\u0440 \u043F\u0440\u0438\u043D\u043E\u0441\u044F\u0442 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B: \u0444\u0430\u0439\u043B\u044B \u0441\u043B\u043E\u0432\u0430\u043C\u0438 \u0438 \u0440\u0430\u0441\u043A\u0430\u0434\u0440\u043E\u0432\u043A\u0443 \u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0430\u043C\u0438 \u2014 \u043F\u043E\u0441\u043C\u043E\u0442\u0440\u0438 \u0434\u043E \u043F\u043B\u0430\u043D\u0430. \u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u043C \u0431\u043B\u043E\u043A\u043E\u043C \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u043D\u0430\u0437\u044B\u0432\u0430\u0435\u0442 2\u20134 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u0441\u043F\u0440\u0430\u0432\u043E\u0447\u043D\u0438\u043A\u0430: \u043F\u0440\u043E\u0447\u0442\u0438 \u0438\u0445 (plan \u0441 read), \u043F\u0435\u0440\u0435\u0441\u043A\u0430\u0436\u0438 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0443 \u043F\u043E\u0441\u0442\u0440\u043E\u0447\u043D\u043E, \u043F\u043E\u043F\u0440\u0430\u0432\u044C plan_edit \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F\u043C\u0438 \u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u043E\u0441\u043B\u0435 \u0435\u0433\u043E \xAB\u0434\u0430\xBB \u0437\u043E\u0432\u0438 render.
18149
+ \u041F\u0435\u0440\u0432\u044B\u0439 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0441 \u0440\u0435\u0447\u044C\u044E \u0438\u0434\u0451\u0442 \u043C\u0438\u043D\u0443\u0442\u0430\u043C\u0438. \u041E\u0431\u043E\u0440\u0432\u0430\u043B\u0441\u044F \u0432\u044B\u0437\u043E\u0432 \u2014 \u0440\u0430\u0431\u043E\u0442\u0430 \u043D\u0435 \u043F\u0440\u043E\u043F\u0430\u043B\u0430: \u043F\u043E\u0437\u043E\u0432\u0438 wait, \u0430 \u043F\u043E\u0442\u043E\u043C plan \u043F\u043E \u0442\u043E\u043C\u0443 \u0436\u0435 \u0440\u043E\u043B\u0438\u043A\u0443 \u0435\u0449\u0451 \u0440\u0430\u0437, \u0432\u0442\u043E\u0440\u043E\u0439 \u0440\u0430\u0437 \u044D\u0442\u043E \u0441\u0435\u043A\u0443\u043D\u0434\u044B.
18150
+ \u0421 reel \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u0440\u043E\u043B\u0438\u043A\u0430: \u0434\u043E\u0440\u043E\u0436\u043A\u0438, \u043A\u043B\u0438\u043F\u044B \u043F\u043E id, \u0441\u043E\u0433\u043B\u0430\u0441\u043E\u0432\u0430\u043D \u043B\u0438 \u043E\u043D.
18151
+ \u0421 read \u043E\u0442\u0434\u0430\u0451\u0442 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u0421\u043F\u0440\u0430\u0432\u043E\u0447\u043D\u0438\u043A\u0430 \u043C\u043E\u043D\u0442\u0430\u0436\u0451\u0440\u0430 (\u043F\u0435\u0447\u0430\u0442\u044C \u043F\u0435\u0440\u0432\u043E\u0439 \u0441\u0442\u0440\u043E\u043A\u043E\u0439), \u0442\u0430\u0431\u043B\u0438\u0446\u044B \u0432\u043A\u0443\u0441\u0430 \u0438 \u0447\u0443\u0436\u0438\u0435 \u0444\u0430\u0439\u043B\u044B \u2014 \u043F\u0443\u0442\u0438 \u0438\u0437 \u043E\u0433\u043B\u0430\u0432\u043B\u0435\u043D\u0438\u044F (\u0435\u0433\u043E \u0434\u0430\u0451\u0442 setup), \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\u0430 \u0438\u043B\u0438 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B. \u0427\u0438\u0442\u0430\u0439 2\u20134 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u043E\u0434\u043D\u0438\u043C \u0432\u044B\u0437\u043E\u0432\u043E\u043C \u0438 \u043D\u0435 \u0432\u044B\u0434\u0443\u043C\u044B\u0432\u0430\u0439 \u043F\u0443\u0442\u0435\u0439.`,
18046
18152
  // Полоса хода работы в ленте: черновик считается минутами, и всё это время
18047
18153
  // в ленте не происходило бы ничего. ⚠ Ожидание задачи — у `wait`, и полосы
18048
18154
  // у него нет: она объявлена на инструменте, и каждый вызов ожидания рисовал
@@ -18053,7 +18159,14 @@ function planTool(engine, key) {
18053
18159
  "\u041F\u0443\u0442\u044C \u043A \u0432\u0438\u0434\u0435\u043E\u0444\u0430\u0439\u043B\u0443 \u0441 \u0440\u0435\u0447\u044C\u044E \u2014 \u043F\u043E \u043D\u0435\u043C\u0443 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044F \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A. \u0424\u0430\u0439\u043B \u043B\u0435\u0436\u0438\u0442 \u0432 \u043F\u0430\u043F\u043A\u0435 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u0438 \u0440\u043E\u043B\u0438\u043A\u043E\u043C \u0435\u0449\u0451 \u043D\u0435 \u0441\u0442\u0430\u043B \u2014 \u0437\u0430\u0432\u0435\u0434\u0443 \u0440\u043E\u043B\u0438\u043A \u0441\u0430\u043C"
18054
18160
  ).optional(),
18055
18161
  reel: external_exports.string().describe(
18056
- "\u041F\u0430\u043F\u043A\u0430 \u0437\u0430\u0432\u0435\u0434\u0451\u043D\u043D\u043E\u0433\u043E \u0440\u043E\u043B\u0438\u043A\u0430 \u0441 \u043E\u0431\u0449\u0438\u043C naparnik-project/1. \u041F\u043E\u043A\u0430\u0436\u0443 \u0442\u043E\u0447\u043D\u044B\u0439 JSON \u0438 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u044F; \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043F\u0435\u0440\u0435\u0441\u0447\u0438\u0442\u044B\u0432\u0430\u044E"
18162
+ "\u041F\u0430\u043F\u043A\u0430 \u0437\u0430\u0432\u0435\u0434\u0451\u043D\u043D\u043E\u0433\u043E \u0440\u043E\u043B\u0438\u043A\u0430: \u043F\u043E\u043A\u0430\u0436\u0443 \u0435\u0433\u043E \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 reel.json \u2014 \u0434\u043E\u0440\u043E\u0436\u043A\u0438, \u043A\u043B\u0438\u043F\u044B \u043F\u043E id \u0438 \u0441\u043E\u0433\u043B\u0430\u0441\u043E\u0432\u0430\u043D \u043B\u0438 \u043E\u043D; \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043F\u0435\u0440\u0435\u0441\u0447\u0438\u0442\u044B\u0432\u0430\u044E"
18163
+ ).optional(),
18164
+ // ⚠ ПОЛЯ РАЗДЕЛОВ СВОБОДНЫЕ, И ЭТО НЕ ЛЕНЬ: дом просьбы — поставщики пака
18165
+ // (`SECTIONS` шагов и их `supply`), судья — движок, и отказ приходит его
18166
+ // словами. Имена разделов описание повторяет, потому что его читает
18167
+ // модель; сторож копии — `plan-tools.test.ts`, сверка с `SECTIONS` пака.
18168
+ ask: external_exports.looseObject({}).describe(
18169
+ `\u0423\u0437\u043A\u0430\u044F \u043F\u0440\u043E\u0441\u044C\u0431\u0430 \u0440\u0430\u0437\u0434\u0435\u043B\u0430\u043C\u0438 \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0432\u043C\u0435\u0441\u0442\u0435 \u0441 video: ${ASK_SECTIONS.join(", ")}; tempo \u2014 \u0432\u043E \u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0440\u0430\u0437 \u0443\u0441\u043A\u043E\u0440\u0438\u0442\u044C, \u0447\u0438\u0441\u043B\u043E \u043E\u0442 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430. \u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 true \u2014 \xAB\u043A\u0430\u043A \u0440\u0435\u0448\u0438\u0442 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\xBB. {} \u2014 \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A \u043A\u0430\u043A \u0441\u043D\u044F\u0442 (\u0446\u0432\u0435\u0442, \u0440\u0430\u0441\u043A\u043B\u0430\u0434\u043A\u0430); {"speech": {}} \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0441\u043B\u043E\u0432\u0430 \u0441 \u043D\u043E\u043C\u0435\u0440\u0430\u043C\u0438 (fix_word, \u043A\u0443\u0441\u043E\u043A \u0441\u043E \u0441\u043B\u043E\u0432\u0430). ${FULL_WORDS} \u2014 \u043F\u043E\u043B\u043D\u044B\u0439 \u043C\u043E\u043D\u0442\u0430\u0436, \u0442\u043E\u043B\u044C\u043A\u043E \u043D\u0430 \xAB\u0441\u043C\u043E\u043D\u0442\u0438\u0440\u0443\u0439\xBB \u0446\u0435\u043B\u0438\u043A\u043E\u043C. \u0421 video \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u0435\u043D: \u0431\u0435\u0437 \u043D\u0435\u0433\u043E \u2014 \u043E\u0442\u043A\u0430\u0437`
18057
18170
  ).optional(),
18058
18171
  also: external_exports.array(external_exports.string()).describe(
18059
18172
  "\u0427\u0442\u043E \u0435\u0449\u0451 \u0438\u0434\u0451\u0442 \u0432 \u042D\u0422\u041E\u0422 \u0440\u043E\u043B\u0438\u043A: \u0437\u0430\u043F\u0438\u0441\u044C \u044D\u043A\u0440\u0430\u043D\u0430, \u043C\u0443\u0437\u044B\u043A\u0430, \u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0438. \u0420\u043E\u043B\u0438 \u0440\u0435\u0448\u0430\u0435\u0442 \u0437\u0430\u043C\u0435\u0440, \u0430 \u043D\u0435 \u0438\u043C\u044F \u0444\u0430\u0439\u043B\u0430. \u0422\u043E\u043B\u044C\u043A\u043E \u0432\u043C\u0435\u0441\u0442\u0435 \u0441 video \u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0440\u0438 \u0437\u0430\u0432\u0435\u0434\u0435\u043D\u0438\u0438 \u0440\u043E\u043B\u0438\u043A\u0430"
@@ -18067,15 +18180,12 @@ function planTool(engine, key) {
18067
18180
  style: external_exports.string().describe(
18068
18181
  "\u041F\u0430\u043F\u043A\u0430 \u043F\u0430\u043A\u0430 \u0444\u0438\u0440\u043C\u0435\u043D\u043D\u043E\u0433\u043E \u0441\u0442\u0438\u043B\u044F: \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044F \u0442\u0430\u043A, \u043A\u0430\u043A \u0435\u0433\u043E \u043F\u043E\u0442\u043E\u043C \u0441\u043E\u0431\u0435\u0440\u0443\u0442"
18069
18182
  ).optional(),
18070
- // ⚠ ТАБЛИЦЫ ВКУСА НАЗВАНЫ ПРИМЕРОМ НАРОЧНО. Дверь к ним открыта движком
18071
- // (`engine/catalog/handbook.py`, корень `taste`), но модель о них не узнает ниоткуда:
18072
- // черновик называет их не всегда, а решение владельца 2026-09-18 разрешило
18073
- // ей писать план ролика целиком — и числа для него она обязана брать из
18074
- // наших замеров, а не из головы. Про «по одной-две за вызов» сказано тут
18075
- // же: таблицы тяжёлые, а ответ движка обрезан 48 КБ, и вызов на шесть
18076
- // таблиц вернулся бы частями, то есть лишними ходами.
18183
+ // ⚠ ПУТИ — КАК ИХ ПЕЧАТАЕТ ОГЛАВЛЕНИЕ СПРАВОЧНИКА (пакет Б1.14): без
18184
+ // приставки — страница `handbook/`, `taste/…` — таблица вкуса, `vendor/…` —
18185
+ // чужой файл. Заслоны чтения живут в движке (`engine/handbook/reader.py`).
18186
+ // Таблицы вкуса тяжёлые, а ответ движка обрезан 48 КБ: по одной-две.
18077
18187
  read: external_exports.array(external_exports.string()).describe(
18078
- `\u0424\u0430\u0439\u043B\u044B \u0441\u043A\u0438\u043B\u043B\u043E\u0432, \u0437\u043D\u0430\u043D\u0438\u0439 \u0438 \u0422\u0410\u0411\u041B\u0418\u0426 \u0412\u041A\u0423\u0421\u0410, \u043D\u0430\u0437\u0432\u0430\u043D\u043D\u044B\u0435 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\u043E\u043C: \xABdirector/SKILL.md\xBB, \xABvendor/taste-skill/SKILL.md\xBB, \xABtaste/rhythm.json\xBB. \u0414\u043E ${FILES_PER_READ} \u0437\u0430 \u0432\u044B\u0437\u043E\u0432, \u043F\u0443\u0442\u0438 \u043E\u0442 \u043F\u0430\u043F\u043A\u0438 \u0441\u043A\u0438\u043B\u043B\u043E\u0432 \u043F\u0430\u043A\u0430 \u2014 \u043A\u0430\u043A \u0438\u0445 \u043D\u0430\u043F\u0435\u0447\u0430\u0442\u0430\u043B \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A, \u0431\u0435\u0437 \xAB../\xBB \u0438 \u0431\u0435\u0437 \u0441\u0432\u043E\u0438\u0445 \u043F\u0443\u0442\u0435\u0439. \u0422\u0430\u0431\u043B\u0438\u0446\u044B \u0432\u043A\u0443\u0441\u0430 \u0442\u044F\u0436\u0451\u043B\u044B\u0435: \u0431\u0435\u0440\u0438 \u0438\u0445 \u043F\u043E \u043E\u0434\u043D\u043E\u0439-\u0434\u0432\u0435 \u0437\u0430 \u0432\u044B\u0437\u043E\u0432, \u0438\u043D\u0430\u0447\u0435 \u043E\u0442\u0432\u0435\u0442 \u043F\u0440\u0438\u0434\u0451\u0442 \u0447\u0430\u0441\u0442\u044F\u043C\u0438`
18188
+ `\u041F\u0443\u0442\u0438 \u043A\u0430\u043A \u0438\u0445 \u043D\u0430\u043F\u0435\u0447\u0430\u0442\u0430\u043B\u0438 \u043E\u0433\u043B\u0430\u0432\u043B\u0435\u043D\u0438\u0435 \u0441\u043F\u0440\u0430\u0432\u043E\u0447\u043D\u0438\u043A\u0430, \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0438\u043B\u0438 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430: \xABdocument/clips.md\xBB, \xABtaste/rhythm.json\xBB, \xABvendor/taste-skill/SKILL.md\xBB. \u0414\u043E ${FILES_PER_READ} \u0437\u0430 \u0432\u044B\u0437\u043E\u0432, \u0431\u0435\u0437 \xAB../\xBB \u0438 \u0431\u0435\u0437 \u0441\u0432\u043E\u0438\u0445 \u043F\u0443\u0442\u0435\u0439. \u0422\u0430\u0431\u043B\u0438\u0446\u044B \u0432\u043A\u0443\u0441\u0430 \u0442\u044F\u0436\u0451\u043B\u044B\u0435: \u043F\u043E \u043E\u0434\u043D\u043E\u0439-\u0434\u0432\u0435 \u0437\u0430 \u0432\u044B\u0437\u043E\u0432, \u0438\u043D\u0430\u0447\u0435 \u043E\u0442\u0432\u0435\u0442 \u043F\u0440\u0438\u0434\u0451\u0442 \u0447\u0430\u0441\u0442\u044F\u043C\u0438`
18079
18189
  ).optional(),
18080
18190
  part: external_exports.number().describe(
18081
18191
  "\u041A\u0430\u043A\u0430\u044F \u0447\u0430\u0441\u0442\u044C \u043E\u0442\u0432\u0435\u0442\u0430 \u043D\u0443\u0436\u043D\u0430, \u0435\u0441\u043B\u0438 \u0444\u0430\u0439\u043B \u0434\u043B\u0438\u043D\u043D\u044B\u0439: \u0441\u0447\u0451\u0442 \u0441 \u0435\u0434\u0438\u043D\u0438\u0446\u044B. \u0421\u043A\u043E\u043B\u044C\u043A\u043E \u0438\u0445 \u0432\u0441\u0435\u0433\u043E, \u0441\u043A\u0430\u0436\u0435\u0442 \u0441\u0430\u043C \u043E\u0442\u0432\u0435\u0442"
@@ -18104,7 +18214,13 @@ function planTool(engine, key) {
18104
18214
  if (asked.part !== void 0 && asked.read === void 0) {
18105
18215
  say("\xABpart\xBB \u2014 \u044D\u0442\u043E \u0447\u0430\u0441\u0442\u044C \u043E\u0442\u0432\u0435\u0442\u0430 \u0447\u0442\u0435\u043D\u0438\u044F: \u043E\u043D \u0431\u044B\u0432\u0430\u0435\u0442 \u0442\u043E\u043B\u044C\u043A\u043E \u0432\u043C\u0435\u0441\u0442\u0435 \u0441 \xABread\xBB", "part");
18106
18216
  }
18107
- for (const key2 of ["also", "together"]) {
18217
+ if (asked.video !== void 0 && asked.ask === void 0) {
18218
+ say(
18219
+ `\u041D\u0430\u0437\u043E\u0432\u0438 \u043F\u0440\u043E\u0441\u044C\u0431\u0443: ask \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0442\u043E, \u0447\u0442\u043E \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u043F\u043E\u043F\u0440\u043E\u0441\u0438\u043B ({"tempo": <\u0432\u043E \u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0440\u0430\u0437 \u043E\u043D \u0441\u043A\u0430\u0437\u0430\u043B>}, {"pauses": {}}, {"subtitles": {}}); \u0446\u0432\u0435\u0442, \u0440\u0430\u0441\u043A\u043B\u0430\u0434\u043A\u0430, split-screen \u2014 {}; \u0438\u0441\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u0441\u043B\u043E\u0432\u043E \u2014 {"speech": {}}. \xAB\u0421\u043C\u043E\u043D\u0442\u0438\u0440\u0443\u0439\xBB \u0446\u0435\u043B\u0438\u043A\u043E\u043C \u2014 ${FULL_WORDS}`,
18220
+ "ask"
18221
+ );
18222
+ }
18223
+ for (const key2 of ["also", "together", "ask"]) {
18108
18224
  if (asked[key2] !== void 0 && asked.video === void 0) {
18109
18225
  say(`\xAB${key2}\xBB \u043E\u0442\u043D\u043E\u0441\u0438\u0442\u0441\u044F \u043A \u0437\u0430\u0432\u0435\u0434\u0435\u043D\u0438\u044E \u0440\u043E\u043B\u0438\u043A\u0430 \u0438 \u0431\u044B\u0432\u0430\u0435\u0442 \u0442\u043E\u043B\u044C\u043A\u043E \u0432\u043C\u0435\u0441\u0442\u0435 \u0441 \xABvideo\xBB`, key2);
18110
18226
  }
@@ -18114,7 +18230,7 @@ function planTool(engine, key) {
18114
18230
  if (args.read !== void 0) {
18115
18231
  return readSkills(engine, { files: args.read, part: args.part });
18116
18232
  }
18117
- if (args.reel !== void 0) return viewComposition(engine, args.reel);
18233
+ if (args.reel !== void 0) return viewDocument(engine, args.reel);
18118
18234
  if (args.video === void 0) return listReels(engine, args.workspace);
18119
18235
  return planDraft(
18120
18236
  engine,
@@ -18123,7 +18239,8 @@ function planTool(engine, key) {
18123
18239
  also: args.also,
18124
18240
  together: args.together,
18125
18241
  workspace: args.workspace,
18126
- style: args.style
18242
+ style: args.style,
18243
+ ask: args.ask
18127
18244
  },
18128
18245
  key,
18129
18246
  ctx?.emitProgress
@@ -18131,127 +18248,74 @@ function planTool(engine, key) {
18131
18248
  }
18132
18249
  });
18133
18250
  }
18134
- var MOVES = ["fade", "up", "down", "left", "right", "pop", "cut"];
18135
- var DRIFTS = ["none", "up", "down", "left", "right"];
18136
- var SPEEDS = ["slow", "normal", "fast"];
18137
- var SLOTS = ["top", "middle", "bottom"];
18251
+ var FULL_ASK = "all";
18252
+ var FULL_WORDS = `{"${FULL_ASK}": true}`;
18253
+ var ASK_SECTIONS = [
18254
+ "tempo",
18255
+ "pauses",
18256
+ "loudness",
18257
+ "voice",
18258
+ "music",
18259
+ "subtitles",
18260
+ "shots",
18261
+ "world",
18262
+ "inserts",
18263
+ "accents",
18264
+ "intro",
18265
+ "screen",
18266
+ "zoom",
18267
+ "webcam",
18268
+ "regions"
18269
+ ];
18270
+ var OPS = [
18271
+ "set",
18272
+ "unset",
18273
+ "add",
18274
+ "remove",
18275
+ "add_track",
18276
+ "add_group",
18277
+ "fix_word",
18278
+ "add_source",
18279
+ "add_package",
18280
+ "repin",
18281
+ "agree",
18282
+ "remember",
18283
+ "forget"
18284
+ ];
18138
18285
  function opSchema() {
18139
- return external_exports.object({
18140
- op: external_exports.string().describe(
18141
- "hero | remove | add | move | text | accent | word | world | motion | intro | part"
18142
- ),
18143
- from_word: external_exports.number().describe("hero: \u043F\u0435\u0440\u0432\u043E\u0435 \u0441\u043B\u043E\u0432\u043E \u043E\u0442\u0440\u0435\u0437\u043A\u0430").optional(),
18144
- // ⚠ ВТОРОЕ ЧИСЛО — СЛЕДУЮЩЕЕ ЗА ОТРЕЗКОМ, А НЕ ПОСЛЕДНЕЕ В НЁМ. Так их
18145
- // считает план (`lib/draft/build.py`: время конца берётся у слова `to_word - 1`),
18146
- // так же они печатаются в черновике словами, и так же их ждёт правка.
18147
- // До 2026-09-18 здесь стояло «последнее слово отрезка» — и модель, списав
18148
- // число из черновика, промахивалась на одно слово на каждой границе.
18149
- to_word: external_exports.number().describe(
18150
- "hero: \u0441\u043B\u043E\u0432\u043E \u0421\u041B\u0415\u0414\u0423\u042E\u0429\u0415\u0415 \u0437\u0430 \u043E\u0442\u0440\u0435\u0437\u043A\u043E\u043C \u2014 \u043E\u043D\u043E \u0441\u0430\u043C\u043E \u0432 \u043E\u0442\u0440\u0435\u0437\u043E\u043A \u043D\u0435 \u0432\u0445\u043E\u0434\u0438\u0442. \u0420\u043E\u0432\u043D\u043E \u0442\u043E \u0447\u0438\u0441\u043B\u043E, \u0447\u0442\u043E \u043D\u0430\u043F\u0435\u0447\u0430\u0442\u0430\u043D\u043E \u0432 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\u0435"
18151
- ).optional(),
18152
- at_word: external_exports.number().describe("add, move: \u043D\u0430 \u043A\u0430\u043A\u043E\u043C \u0441\u043B\u043E\u0432\u0435").optional(),
18153
- until_word: external_exports.number().describe(
18154
- "add: \u0441\u043B\u043E\u0432\u043E \u0421\u041B\u0415\u0414\u0423\u042E\u0429\u0415\u0415 \u0437\u0430 \u043E\u0442\u0440\u0435\u0437\u043A\u043E\u043C \u2014 \u043E\u043D\u043E \u0441\u0430\u043C\u043E \u043D\u0435 \u0432\u0445\u043E\u0434\u0438\u0442"
18155
- ).optional(),
18156
- word: external_exports.number().describe("accent, word: \u043D\u043E\u043C\u0435\u0440 \u0441\u043B\u043E\u0432\u0430").optional(),
18157
- insert: external_exports.string().describe(
18158
- "remove, move, text, motion: \u0438\u043C\u044F \u0432\u0441\u0442\u0430\u0432\u043A\u0438 \u0438\u0437 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\u0430, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 chips-1"
18159
- ).optional(),
18160
- item: external_exports.number().describe("text: \u043D\u043E\u043C\u0435\u0440 \u043F\u0443\u043D\u043A\u0442\u0430 \u0441\u043F\u0438\u0441\u043A\u0430, \u0441 \u0435\u0434\u0438\u043D\u0438\u0446\u044B").optional(),
18161
- template: external_exports.string().describe("add: \u0448\u0430\u0431\u043B\u043E\u043D \u0432\u0441\u0442\u0430\u0432\u043A\u0438").optional(),
18162
- text: external_exports.string().describe(
18163
- "add: \u043F\u043E\u0434\u043F\u0438\u0441\u044C \u043D\u043E\u0432\u043E\u0439 \u0432\u0441\u0442\u0430\u0432\u043A\u0438; intro: \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438 \u2014 \u0443 \u043D\u0435\u0451 \u044D\u0442\u043E \u043F\u043E\u043B\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E"
18164
- ).optional(),
18165
- // ⚠ СЕКУНДА САМОЙ ЗАПИСИ, А НЕ СЕКУНДА РОЛИКА, И ПОЛЕ У НЕЁ СВОЁ. Окон
18166
- // записи экрана в плане бывает несколько, и каждое следующее продолжает
18167
- // предыдущее само (решение владельца 2026-09-18). Поле нужно там, где
18168
- // продолжение не годится: «а тут покажи с середины». Имя то же, что у
18169
- // слоя в плане наложений, — это одна и та же мысль, и второго имени для
18170
- // неё быть не должно.
18171
- file_start: external_exports.number().describe(
18172
- "add: \u0441 \u043A\u0430\u043A\u043E\u0439 \u0441\u0435\u043A\u0443\u043D\u0434\u044B \u0421\u0410\u041C\u041E\u0419 \u0437\u0430\u043F\u0438\u0441\u0438 \u044D\u043A\u0440\u0430\u043D\u0430 \u0438\u0433\u0440\u0430\u0442\u044C \u044D\u0442\u043E \u043E\u043A\u043D\u043E. \u041D\u0435 \u043F\u0438\u0448\u0435\u0448\u044C \u2014 \u043E\u043A\u043D\u043E \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0435\u0442 \u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0435\u0435 \u0441 \u0442\u043E\u0433\u043E \u043C\u0435\u0441\u0442\u0430, \u0433\u0434\u0435 \u043E\u043D\u043E \u043E\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u043B\u043E\u0441\u044C"
18173
- ).optional(),
18174
- value: external_exports.string().describe(
18175
- "hero: full|window|close-up|none; accent: accent|normal; text: \u043F\u043E\u0434\u043F\u0438\u0441\u044C; word: \u043A\u0430\u043A \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E; world: grid|file|none; part: on|off"
18176
- ).optional(),
18177
- // ⚠ У ЭТИХ ДВУХ СТРОК ПЛАНА НЕТ ИМЕНИ ВСТАВКИ, ПОЭТОМУ И ПОЯВИЛОСЬ ОТДЕЛЬНОЕ
18178
- // ПОЛЕ. Вставку человек убирает по её имени (`remove`, `chips-1`), а
18179
- // субтитры и звуковые удары — это сами себе строка плана, целиком
18180
- // (`engine/brief.py`, `PARTS`).
18181
- what: external_exports.string().describe(
18182
- "part: \u043A\u0430\u043A\u0443\u044E \u0441\u0442\u0440\u043E\u043A\u0443 \u043F\u043B\u0430\u043D\u0430 \u0432\u044B\u0447\u0435\u0440\u043A\u043D\u0443\u0442\u044C \u0438\u043B\u0438 \u0432\u0435\u0440\u043D\u0443\u0442\u044C \u0446\u0435\u043B\u0438\u043A\u043E\u043C \u2014 subtitles | sfx"
18183
- ).optional(),
18184
- // Движение вставки словами: канвы модель не знает, а движок знает — в
18185
- // пиксели и секунды слова переводит шаг вставок по таблицам вкуса.
18186
- enter: external_exports.string().describe(
18187
- `motion, intro: \u043A\u0430\u043A \u0432\u0441\u0442\u0430\u0432\u043A\u0430 \u0438\u043B\u0438 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0430 \u043F\u0440\u0438\u0445\u043E\u0434\u0438\u0442 \u2014 ${MOVES.join(" | ")}. fade \u2014 \u043F\u0440\u043E\u044F\u0432\u043B\u044F\u0435\u0442\u0441\u044F; up/down/left/right \u2014 \u0432\u044A\u0435\u0437\u0436\u0430\u0435\u0442 \u0441 \u044D\u0442\u043E\u0439 \u0441\u0442\u043E\u0440\u043E\u043D\u044B; pop \u2014 \u0432\u044B\u0441\u043A\u0430\u043A\u0438\u0432\u0430\u0435\u0442; cut \u2014 \u0440\u0435\u0437\u043E\u043C`
18188
- ).optional(),
18189
- exit: external_exports.string().describe(
18190
- `motion, intro: \u043A\u0430\u043A \u0443\u0445\u043E\u0434\u0438\u0442 \u2014 ${MOVES.join(" | ")}. \u0421\u0442\u043E\u0440\u043E\u043D\u0430 \u0442\u0443\u0442 \u0437\u043D\u0430\u0447\u0438\u0442, \u041A\u0423\u0414\u0410 \u0443\u0435\u0437\u0436\u0430\u0435\u0442: left \u2014 \u0432\u043B\u0435\u0432\u043E`
18191
- ).optional(),
18192
- drift: external_exports.string().describe(
18193
- `motion, intro: \u043C\u0435\u0434\u043B\u0435\u043D\u043D\u043E\u0435 \u0441\u043C\u0435\u0449\u0435\u043D\u0438\u0435 \u0437\u0430 \u0436\u0438\u0437\u043D\u044C \u0432\u0441\u0442\u0430\u0432\u043A\u0438 \u2014 ${DRIFTS.join(" | ")}; none \u2014 \u0441\u0442\u043E\u0438\u0442 \u043D\u0430 \u043C\u0435\u0441\u0442\u0435`
18194
- ).optional(),
18195
- speed: external_exports.string().describe(
18196
- `motion, intro: \u0441\u043A\u043E\u0440\u043E\u0441\u0442\u044C \u0432\u0445\u043E\u0434\u0430 \u0438 \u0443\u0445\u043E\u0434\u0430 \u2014 ${SPEEDS.join(" | ")}. normal \u2014 \u043A\u0430\u043A \u0437\u0430\u043C\u0435\u0440\u0435\u043D\u043E`
18197
- ).optional(),
18198
- slot: external_exports.string().describe(
18199
- `motion, intro: \u0433\u0434\u0435 \u0432\u0441\u0442\u0430\u0432\u043A\u0430 \u0441\u0442\u043E\u0438\u0442 \u043F\u043E \u0432\u0435\u0440\u0442\u0438\u043A\u0430\u043B\u0438 \u0432\u043D\u0443\u0442\u0440\u0438 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E\u0439 \u0440\u0430\u043C\u043A\u0438 \u2014 ${SLOTS.join(" | ")}`
18200
- ).optional(),
18201
- // Карточка в начале ролика: её вторая строка, длительность и снятие.
18202
- // ⚠ «text» СЛУЖИТ ДВУМ ОПЕРАЦИЯМ, и это не путаница: у `add` это подпись
18203
- // новой вставки, у `intro` — заголовок карточки. Развести их вторым именем
18204
- // значило бы завести модели два слова на одно и то же — «что написать».
18205
- note: external_exports.string().describe(
18206
- "intro: \u0432\u0442\u043E\u0440\u0430\u044F \u0441\u0442\u0440\u043E\u043A\u0430 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0438, \u043F\u043E\u043C\u0435\u043B\u044C\u0447\u0435 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430"
18207
- ).optional(),
18208
- // ⚠ ЧИСЛО УМОЛЧАНИЯ ЗДЕСЬ НЕ НАЗЫВАЕТСЯ НАРОЧНО. Его дом один — «params»
18209
- // паспорта шага (`steps/intro/step.json`), и покупатель вправе поправить
18210
- // его в своей копии шага. Назови мы семёрку здесь — модель обещала бы её
18211
- // тому, у кого стоит другое число.
18212
- seconds: external_exports.number().describe(
18213
- "intro: \u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0441\u0435\u043A\u0443\u043D\u0434 \u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044F \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0430. \u041D\u0435 \u043D\u0430\u0437\u0432\u0430\u043B \u2014 \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u0435 \u0448\u0430\u0433\u0430"
18214
- ).optional(),
18215
- off: external_exports.boolean().describe("intro: \u0443\u0431\u0440\u0430\u0442\u044C \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0443 \u0438\u0437 \u043D\u0430\u0447\u0430\u043B\u0430 \u0440\u043E\u043B\u0438\u043A\u0430").optional()
18286
+ return external_exports.looseObject({
18287
+ op: external_exports.string().describe(OPS.join(" | "))
18216
18288
  });
18217
18289
  }
18218
18290
  function planEditTool(engine, key) {
18219
18291
  return defineTool({
18220
18292
  name: "plan_edit",
18221
- title: "\u041F\u043E\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u043F\u043B\u0430\u043D \u0440\u043E\u043B\u0438\u043A\u0430",
18222
- description: "\u041F\u0440\u0430\u0432\u043A\u0430 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\u0430 \u0438 \u0443\u0436\u0435 \u0441\u043E\u0431\u0440\u0430\u043D\u043D\u043E\u0433\u043E: \xAB\u043F\u043E\u043A\u0430\u0436\u0438 \u043C\u0435\u043D\u044F \u0446\u0435\u043B\u0438\u043A\u043E\u043C \u0432\u043E\u0442 \u0442\u0443\u0442\xBB, \xAB\u0443\u0431\u0435\u0440\u0438 \u0441\u043F\u0438\u0441\u043E\u043A\xBB, \xAB\u0432 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u0435 \u043D\u0435 \u0442\u043E \u0441\u043B\u043E\u0432\u043E\xBB, \xAB\u043F\u0443\u0441\u0442\u044C \u0432\u044B\u0435\u0437\u0436\u0430\u0435\u0442 \u0441\u043B\u0435\u0432\u0430\xBB, \xAB\u043F\u043E\u0434\u043F\u0438\u0448\u0438 \u0442\u0440\u0435\u0442\u0438\u0439 \u043F\u0443\u043D\u043A\u0442\xBB. \u041E\u0434\u043D\u0430 \u043F\u0440\u043E\u0441\u044C\u0431\u0430 \u2014 \u043E\u0434\u043D\u0430 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F; \u0441 rebuild \u0441\u0440\u0430\u0437\u0443 \u043F\u0435\u0440\u0435\u0441\u043E\u0431\u0438\u0440\u0430\u0435\u0442, \u0438 \u044D\u0442\u043E \u0441\u0442\u043E\u0438\u0442 \u0441\u0435\u043A\u0443\u043D\u0434, \u0430 \u043D\u0435 \u043C\u0438\u043D\u0443\u0442: \u0437\u0430\u043D\u043E\u0432\u043E \u0434\u0435\u043B\u0430\u0435\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E \u0442\u0440\u043E\u043D\u0443\u0442\u043E\u0435.\n\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u0438: hero (\u043A\u0440\u0443\u043F\u043D\u043E\u0441\u0442\u044C \u043D\u0430 \u043E\u0442\u0440\u0435\u0437\u043A\u0435 \u0441\u043B\u043E\u0432), remove, add, move, text (\u043F\u043E\u0434\u043F\u0438\u0441\u044C \u0432\u0441\u0442\u0430\u0432\u043A\u0438 \u0438\u043B\u0438 \u0435\u0451 \u043F\u0443\u043D\u043A\u0442\u0430), accent (\u0441\u043B\u043E\u0432\u043E \u043A\u0440\u0443\u043F\u043D\u0435\u0435 \u0432 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u0430\u0445), word (\u0438\u0441\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u043D\u043D\u043E\u0435 \u0441\u043B\u043E\u0432\u043E), world (\u0444\u043E\u043D \u0437\u0430 \u0433\u0435\u0440\u043E\u0435\u043C), motion (\u043A\u0430\u043A \u0432\u0441\u0442\u0430\u0432\u043A\u0430 \u043F\u0440\u0438\u0445\u043E\u0434\u0438\u0442, \u0443\u0445\u043E\u0434\u0438\u0442 \u0438 \u0433\u0434\u0435 \u0441\u0442\u043E\u0438\u0442), intro (\u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0430 \u0432 \u043D\u0430\u0447\u0430\u043B\u0435 \u0440\u043E\u043B\u0438\u043A\u0430: text, note, seconds; \u0443\u0431\u0440\u0430\u0442\u044C \u2014 off; \u0441\u043B\u043E\u0432\u0430 \u0434\u0432\u0438\u0436\u0435\u043D\u0438\u044F \u0443 \u043D\u0435\u0451 \u0442\u0435 \u0436\u0435 \u2014 enter, exit, drift, speed, slot), part (\u0432\u044B\u0447\u0435\u0440\u043A\u043D\u0443\u0442\u044C \u0446\u0435\u043B\u0438\u043A\u043E\u043C \u0441\u0442\u0440\u043E\u043A\u0443 \u043F\u043B\u0430\u043D\u0430, \u0443 \u043A\u043E\u0442\u043E\u0440\u043E\u0439 \u043D\u0435\u0442 \u0438\u043C\u0435\u043D\u0438 \u0432\u0441\u0442\u0430\u0432\u043A\u0438: what=subtitles|sfx, value=on|off \u2014 \xAB\u0431\u0435\u0437 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043E\u0432\xBB, \xAB\u0431\u0435\u0437 \u0437\u0432\u0443\u043A\u043E\u0432\u044B\u0445 \u0443\u0434\u0430\u0440\u043E\u0432\xBB).\nintro \u2014 \u0435\u0434\u0438\u043D\u0441\u0442\u0432\u0435\u043D\u043D\u0430\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F, \u043A\u043E\u0442\u043E\u0440\u0430\u044F \u041C\u0415\u041D\u042F\u0415\u0422 \u0414\u041B\u0418\u041D\u0423 \u0440\u043E\u043B\u0438\u043A\u0430: \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0430 \u0432\u0441\u0442\u0430\u0451\u0442 \u041F\u0415\u0420\u0415\u0414 \u043D\u0438\u043C, \u0430 \u0441\u0430\u043C \u0440\u043E\u043B\u0438\u043A \u043E\u0441\u0442\u0430\u0451\u0442\u0441\u044F \u043A\u0430\u0434\u0440 \u0432 \u043A\u0430\u0434\u0440 \u043F\u0440\u0435\u0436\u043D\u0438\u043C. \u0420\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u0438 \u0432 \xAB\u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0430\u0443\u0437\u044B\xBB.\n\u041D\u043E\u043C\u0435\u0440\u0430 \u0441\u043B\u043E\u0432 \u0438 \u0438\u043C\u0435\u043D\u0430 \u0432\u0441\u0442\u0430\u0432\u043E\u043A \u0431\u0435\u0440\u0438 \u0418\u0417 \u0427\u0415\u0420\u041D\u041E\u0412\u0418\u041A\u0410 (plan \u0441 video). \u041D\u0435 \u0432\u044B\u0434\u0443\u043C\u044B\u0432\u0430\u0439 \u0438\u0445: \u043F\u0440\u0430\u0432\u043A\u0430 \u043C\u0438\u043C\u043E \u0446\u0435\u043B\u0438 \u0431\u0443\u0434\u0435\u0442 \u043E\u0442\u043A\u043B\u043E\u043D\u0435\u043D\u0430 \u0441\u043B\u043E\u0432\u0430\u043C\u0438.\nconfirm \u2014 \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u0441\u043A\u0430\u0437\u0430\u043B \xAB\u0434\u0430\xBB \u043D\u0430 \u043D\u044B\u043D\u0435\u0448\u043D\u044E\u044E \u0440\u0435\u0434\u0430\u043A\u0446\u0438\u044E; \u0431\u0435\u0437 \u044D\u0442\u043E\u0433\u043E \u0441\u0431\u043E\u0440\u043A\u0430 \u043F\u043B\u0430\u043D \u043D\u0435 \u0432\u043E\u0437\u044C\u043C\u0451\u0442. \u041B\u042E\u0411\u0410\u042F \u043F\u0440\u0430\u0432\u043A\u0430 \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u0435 \u0441\u043D\u0438\u043C\u0430\u0435\u0442, \u043F\u043E\u044D\u0442\u043E\u043C\u0443 confirm \u0448\u043B\u0451\u0442\u0441\u044F \u0442\u0435\u043C \u0436\u0435 \u0432\u044B\u0437\u043E\u0432\u043E\u043C, \u0447\u0442\u043E \u0438 \u043F\u0440\u0430\u0432\u043A\u0430, \u2014 \u043F\u043E\u0441\u043B\u0435 \u0442\u043E\u0433\u043E \u043A\u0430\u043A \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u0443\u0441\u043B\u044B\u0448\u0430\u043B, \u0447\u0442\u043E \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u043E\u0441\u044C.\nplan \u2014 \u0432\u0435\u0441\u044C \u043F\u043B\u0430\u043D \u0440\u043E\u043B\u0438\u043A\u0430 \u0446\u0435\u043B\u0438\u043A\u043E\u043C, \u043D\u0430\u043F\u0438\u0441\u0430\u043D\u043D\u044B\u0439 \u0442\u043E\u0431\u043E\u0439: \u0434\u0432\u0438\u0436\u043E\u043A \u043F\u0440\u043E\u0432\u0435\u0440\u0438\u0442 \u0435\u0433\u043E \u043F\u043E \u0441\u0445\u0435\u043C\u0435 \u0438 \u043F\u043E \u043F\u043E\u0440\u043E\u0433\u0430\u043C \u0432\u043A\u0443\u0441\u0430 \u0438 \u043F\u0440\u0438 \u043D\u0430\u0440\u0443\u0448\u0435\u043D\u0438\u0438 \u043E\u0442\u043A\u0430\u0436\u0435\u0442 \u0441\u043B\u043E\u0432\u0430\u043C\u0438. \u0422\u0430\u043A \u0434\u0435\u043B\u0430\u044E\u0442, \u043A\u043E\u0433\u0434\u0430 \u043F\u0440\u0430\u0432\u043A\u0430\u043C\u0438 \u0443\u0436\u0435 \u043D\u0435 \u043E\u0431\u043E\u0439\u0442\u0438\u0441\u044C. draft \u2014 \u043E\u0431\u0440\u0430\u0442\u043D\u043E\u0435: \u0437\u0430\u0431\u044B\u0442\u044C \u0442\u0432\u043E\u0439 \u043F\u043B\u0430\u043D \u0438 \u0432\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F \u043A \u043D\u0430\u0448\u0435\u043C\u0443 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\u0443. \u041F\u0440\u043E\u0441\u044C\u0431\u0430 \u0443\u0437\u043A\u0430\u044F (\xAB\u043F\u0440\u043E\u0441\u0442\u043E \u0443\u0441\u043A\u043E\u0440\u044C\xBB) \u2014 \u043F\u043B\u0430\u043D\u0430 \u043D\u0435 \u043F\u0438\u0448\u0438 \u0432\u043E\u0432\u0441\u0435, \u0438\u043D\u0430\u0447\u0435 \u0432 \u0440\u043E\u043B\u0438\u043A\u0435 \u043F\u043E\u044F\u0432\u0438\u0442\u0441\u044F \u0442\u043E, \u043E \u0447\u0451\u043C \u043D\u0438\u043A\u0442\u043E \u043D\u0435 \u043F\u0440\u043E\u0441\u0438\u043B.\nproject \u2014 \u0432\u0435\u0441\u044C \u043E\u0431\u0449\u0438\u0439 naparnik-project/1 \u0446\u0435\u043B\u0438\u043A\u043E\u043C. \u0414\u0432\u0438\u0436\u043E\u043A \u0441\u0430\u043C \u0438\u0437\u043C\u0435\u0440\u044F\u0435\u0442 \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A\u0438 \u0438 \u043F\u0440\u043E\u0432\u0435\u0440\u044F\u0435\u0442 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442; \u043F\u043E\u0441\u043B\u0435 \u043F\u043E\u043A\u0430\u0437\u0430 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0443 confirm \u043F\u0440\u0438\u0432\u044F\u0437\u044B\u0432\u0430\u0435\u0442 \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u0435 \u043A \u0442\u043E\u0447\u043D\u043E\u0439 \u0440\u0435\u0434\u0430\u043A\u0446\u0438\u0438 \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u044F\u043C.\n\u0421\u043E step \u043F\u0440\u0430\u0432\u0438\u0442 \u043D\u0435 \u043F\u043B\u0430\u043D, \u0430 \u041F\u041E\u0420\u042F\u0414\u041E\u041A \u0428\u0410\u0413\u041E\u0412 \u043C\u043E\u043D\u0442\u0430\u0436\u0430: show \u2014 \u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0439, mine \u2014 \u0437\u0430\u0432\u0435\u0441\u0442\u0438 \u0441\u0432\u043E\u044E \u043A\u043E\u043F\u0438\u044E \u043D\u0430\u0448\u0435\u0433\u043E, insert \u2014 \u043F\u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0441\u0432\u043E\u0439 \u0448\u0430\u0433 \u0434\u043E \u0438\u043B\u0438 \u043F\u043E\u0441\u043B\u0435 \u044D\u0442\u0430\u043F\u0430, replace \u2014 \u043F\u043E\u0434\u043C\u0435\u043D\u0438\u0442\u044C \u0448\u0430\u0433 \u0443 \u044D\u0442\u0430\u043F\u0430, remove \u2014 \u0443\u0431\u0440\u0430\u0442\u044C \u044D\u0442\u0430\u043F. \u041F\u0438\u0448\u0435\u0442 \u0442\u043E\u043B\u044C\u043A\u043E \u0432 \u043F\u0430\u043F\u043A\u0443 mine \u0434\u043E\u043C\u0430 \u041D\u0430\u043F\u0430\u0440\u043D\u0438\u043A\u0430: \u043D\u0430\u0448 \u043F\u043E\u0440\u044F\u0434\u043E\u043A \u043D\u0435 \u0442\u0440\u043E\u0433\u0430\u0435\u0442\u0441\u044F \u043D\u0438\u043A\u043E\u0433\u0434\u0430, \u0438 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u0434\u0432\u0438\u0436\u043A\u0430 \u0442\u0432\u043E\u044E \u043A\u043E\u043F\u0438\u044E \u043D\u0435 \u0437\u0430\u043C\u0435\u043D\u044F\u0435\u0442. \u0421\u0432\u043E\u0439 \u0448\u0430\u0433 \u043F\u0440\u043E\u0432\u0435\u0440\u044F\u0435\u0442\u0441\u044F \u043F\u0440\u0438 \u0432\u0441\u0442\u0430\u0432\u043A\u0435 \u2014 \u0447\u0442\u043E \u0432 \u043D\u0451\u043C \u0447\u0438\u043D\u0438\u0442\u044C, \u0441\u043A\u0430\u0436\u0443\u0442 \u0441\u043B\u043E\u0432\u0430\u043C\u0438.",
18293
+ title: "\u041F\u043E\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u0440\u043E\u043B\u0438\u043A\u0430",
18294
+ description: `\u041F\u0440\u0430\u0432\u043A\u0430 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430 \u0440\u043E\u043B\u0438\u043A\u0430 reel.json \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F\u043C\u0438 \u043F\u043E id \u2014 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u0446\u0435\u043B\u0438\u043A\u043E\u043C \u043D\u0435 \u043F\u0435\u0440\u0435\u043F\u0438\u0441\u044B\u0432\u0430\u0435\u0442\u0441\u044F. \u041E\u0434\u043D\u0430 \u043F\u0440\u043E\u0441\u044C\u0431\u0430 \u2014 \u043E\u0434\u043D\u0430 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F: \xAB\u0437\u0432\u0443\u043A\u0438 \u0433\u0440\u043E\u043C\u0447\u0435\xBB \u2014 \u043E\u0434\u043D\u0430 \u0441\u0442\u0440\u043E\u043A\u0430 {"op": "set", "target": "defaults", "path": "sound.gain", "value": 7}. \u041F\u0430\u0447\u043A\u0430 \u043F\u0440\u0438\u043C\u0435\u043D\u044F\u0435\u0442\u0441\u044F \u0446\u0435\u043B\u0438\u043A\u043E\u043C \u0438\u043B\u0438 \u043D\u0438\u043A\u0430\u043A. \u041E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u2014 document/edits.md \u0441\u043F\u0440\u0430\u0432\u043E\u0447\u043D\u0438\u043A\u0430: ${OPS.join(", ")}.
18295
+ stamps \u2014 \u043F\u0435\u0447\u0430\u0442\u0438 \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u043D\u043D\u044B\u0445 \u0441\u0442\u0440\u0430\u043D\u0438\u0446 (\xABdocument/clips.md@1a2b3c4d\xBB \u2014 \u043F\u0435\u0440\u0432\u0430\u044F \u0441\u0442\u0440\u043E\u043A\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u0432 \u043E\u0442\u0432\u0435\u0442\u0435 plan \u0441 read). \u041F\u0440\u0430\u0432\u043A\u0430 \u043A\u043B\u0438\u043F\u043E\u0432, \u043A\u043E\u0440\u043D\u044F, \u043E\u0431\u0449\u0435\u0433\u043E, \u0441\u0432\u043E\u0435\u0433\u043E \u043F\u0430\u043A\u0435\u0442\u0430 \u0438\u043B\u0438 \u0448\u0430\u0433\u0430 \u0431\u0435\u0437 \u043F\u0435\u0447\u0430\u0442\u0438 \u043E\u0442\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442 \u0438 \u043F\u0440\u0438\u043D\u043E\u0441\u0438\u0442 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0443 \u0446\u0435\u043B\u0438\u043A\u043E\u043C: \u043F\u0440\u043E\u0447\u0442\u0438 \u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0438 \u0432\u044B\u0437\u043E\u0432.
18296
+ \xAB\u0417\u0430\u043F\u043E\u043C\u043D\u0438\xBB, \xAB\u0432\u0441\u0435\u0433\u0434\u0430 \u0442\u0430\u043A\xBB \u2014 remember (\u0441\u0432\u043E\u0451 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430, work/remember.md): \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u043D\u0435 \u043C\u0435\u043D\u044F\u0435\u0442, \u043B\u043E\u0436\u0438\u0442\u0441\u044F \u0432 \u043A\u0430\u0436\u0434\u044B\u0439 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A; \u043F\u0435\u0447\u0430\u0442\u0438 \u043D\u0435 \u043D\u0443\u0436\u043D\u043E.
18297
+ \xAB\u0414\u0430\xBB \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u2014 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F {"op": "agree"}: \u0442\u0435\u043C \u0436\u0435 \u0432\u044B\u0437\u043E\u0432\u043E\u043C, \u0447\u0442\u043E \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u043F\u0440\u0430\u0432\u043A\u0430, \u0438\u043B\u0438 \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E; \u043F\u0435\u0447\u0430\u0442\u0438 \u0435\u0439 \u043D\u0435 \u043D\u0443\u0436\u043D\u043E. \u041B\u044E\u0431\u0430\u044F \u043F\u0440\u0430\u0432\u043A\u0430 \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u0435 \u0441\u043D\u0438\u043C\u0430\u0435\u0442. \u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u043F\u0440\u0430\u0432\u0438\u0442\u0441\u044F \u0422\u041E\u041B\u042C\u041A\u041E \u0437\u0434\u0435\u0441\u044C: \u0444\u0430\u0439\u043B, \u043F\u043E\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043D\u044B\u0439 \u043C\u0438\u043C\u043E plan_edit, \u043D\u0435 \u0441\u043E\u0433\u043B\u0430\u0441\u0443\u0435\u0442\u0441\u044F \u0438 \u043D\u0435 \u0441\u043E\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044F.
18298
+ rebuild \u2014 \u0441\u0440\u0430\u0437\u0443 \u0441\u043E\u0431\u0440\u0430\u0442\u044C \u0441\u043E\u0433\u043B\u0430\u0441\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442: \u043E\u0442\u0432\u0435\u0447\u0443 \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0437\u0430\u0434\u0430\u0447\u0438, \u0434\u0430\u043B\u044C\u0448\u0435 wait.
18299
+ \u0421\u043E step \u043F\u0440\u0430\u0432\u0438\u0442 \u043D\u0435 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442, \u0430 \u041F\u041E\u0420\u042F\u0414\u041E\u041A \u0428\u0410\u0413\u041E\u0412 \u0441\u0442\u0430\u0440\u043E\u0433\u043E \u043C\u043E\u043D\u0442\u0430\u0436\u0430: show, mine, insert, replace, remove. render \u043F\u043E \u044D\u0442\u043E\u043C\u0443 \u043F\u043E\u0440\u044F\u0434\u043A\u0443 \u041D\u0415 \u0441\u043E\u0431\u0438\u0440\u0430\u0435\u0442, \u0438 \u0440\u043E\u043B\u0438\u043A \u043E\u0442 step \u043D\u0435 \u043C\u0435\u043D\u044F\u0435\u0442\u0441\u044F. \u0421\u0432\u043E\u0439 \u044D\u0444\u0444\u0435\u043A\u0442 \u0432 \u0440\u043E\u043B\u0438\u043A\u0435 \u2014 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0435\u0439 set \u0441 uses: "mine:<\u0438\u043C\u044F>".`,
18223
18300
  ui: { resourceUri: RUNBAR_RESOURCE_URI },
18224
18301
  args: external_exports.object({
18225
18302
  reel: external_exports.string().describe(
18226
18303
  "\u041F\u0430\u043F\u043A\u0430 \u0440\u043E\u043B\u0438\u043A\u0430 \u0438\u043B\u0438 \u043F\u0443\u0442\u044C \u043A \u0432\u0438\u0434\u0435\u043E\u0444\u0430\u0439\u043B\u0443 \u2014 \u0447\u0442\u043E \u0435\u0441\u0442\u044C \u043F\u043E\u0434 \u0440\u0443\u043A\u043E\u0439"
18227
18304
  ).optional(),
18228
- ops: external_exports.array(opSchema()).describe("\u0421\u043F\u0438\u0441\u043E\u043A \u043F\u0440\u0430\u0432\u043E\u043A; \u043F\u0440\u0438\u043C\u0435\u043D\u044F\u044E\u0442\u0441\u044F \u043F\u043E \u043F\u043E\u0440\u044F\u0434\u043A\u0443").optional(),
18229
- by: external_exports.enum(["model", "human"]).describe(
18230
- "\u041A\u0442\u043E \u0432\u043F\u0438\u0441\u0430\u043B \u043F\u0440\u0430\u0432\u043A\u0443. \xABmodel\xBB \u2014 \u0442\u044B \u0441\u0430\u043C \u0437\u0430\u043A\u0440\u044B\u043B \u043F\u0443\u0441\u0442\u043E\u0439 \u0441\u043B\u043E\u0442 \u043F\u043E\u0434\u043F\u0438\u0441\u0438; \xABhuman\xBB \u2014 \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u043F\u043E\u043F\u0440\u043E\u0441\u0438\u043B \u0441\u043B\u043E\u0432\u0430\u043C\u0438. \u0423\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u0435 \u2014 model"
18231
- ).optional(),
18232
- rebuild: external_exports.boolean().describe(
18233
- "\u0421\u0440\u0430\u0437\u0443 \u043F\u0435\u0440\u0435\u0441\u043E\u0431\u0440\u0430\u0442\u044C \u0440\u043E\u043B\u0438\u043A. \u041E\u0442\u0432\u0435\u0447\u0443 \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0437\u0430\u0434\u0430\u0447\u0438, \u0434\u0430\u043B\u044C\u0448\u0435 wait"
18305
+ ops: external_exports.array(opSchema()).describe(
18306
+ '\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u043F\u043E \u043F\u043E\u0440\u044F\u0434\u043A\u0443; \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u0435 \u2014 {"op": "agree"}'
18234
18307
  ).optional(),
18235
- confirm: external_exports.boolean().describe(
18236
- "\u0427\u0435\u043B\u043E\u0432\u0435\u043A \u0441\u043E\u0433\u043B\u0430\u0441\u043E\u0432\u0430\u043B \u043D\u044B\u043D\u0435\u0448\u043D\u044E\u044E \u0440\u0435\u0434\u0430\u043A\u0446\u0438\u044E \u043F\u043B\u0430\u043D\u0430. \u041B\u044E\u0431\u0430\u044F \u043F\u0440\u0430\u0432\u043A\u0430 \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u0435 \u0441\u043D\u0438\u043C\u0430\u0435\u0442 \u2014 \u0448\u043B\u0438 \u044D\u0442\u0438\u043C \u0436\u0435 \u0432\u044B\u0437\u043E\u0432\u043E\u043C, \u0447\u0442\u043E \u0438 \u043F\u0440\u0430\u0432\u043A\u0443"
18308
+ stamps: external_exports.array(external_exports.string()).describe(
18309
+ "\u041F\u0435\u0447\u0430\u0442\u0438 \u0441\u0442\u0440\u0430\u043D\u0438\u0446 \u0441\u043F\u0440\u0430\u0432\u043E\u0447\u043D\u0438\u043A\u0430, \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u043D\u043D\u044B\u0445 \u0432 \u044D\u0442\u043E\u043C \u0440\u0430\u0437\u0433\u043E\u0432\u043E\u0440\u0435: \xAB\u043F\u0443\u0442\u044C@\u043A\u043E\u0434\xBB"
18237
18310
  ).optional(),
18238
- // ⚠ СХЕМЫ ПЛАНА ЗДЕСЬ НЕТ НАРОЧНО, И ЭТО НЕ ЛЕНЬ. Дом договора
18239
- // `naparnik-plan/1` один — движок (`packs/montage/lib/draft/build.py`), и он же
18240
- // единственный судья: проверяет по схеме и по порогам брака таблиц вкуса.
18241
- // Перепиши мы состав плана сюда — у договора появилась бы вторая правда,
18242
- // которая расходится с первой молча, а узнаёт об этом человек собранным
18243
- // роликом. Поля свободные, а отказ приходит от того, кто план исполняет.
18244
- plan: external_exports.looseObject({}).describe(
18245
- "\u0412\u0415\u0421\u042C \u043F\u043B\u0430\u043D \u0440\u043E\u043B\u0438\u043A\u0430 \u0446\u0435\u043B\u0438\u043A\u043E\u043C, \u043D\u0430\u043F\u0438\u0441\u0430\u043D\u043D\u044B\u0439 \u0442\u043E\u0431\u043E\u0439, \u2014 \u0434\u043E\u0433\u043E\u0432\u043E\u0440 naparnik-plan/1. \u0427\u0438\u0441\u043B\u0430 \u0431\u0435\u0440\u0438 \u0438\u0437 \u0442\u0430\u0431\u043B\u0438\u0446 \u0432\u043A\u0443\u0441\u0430 (plan \u0441 read), \u0430 \u043D\u0435 \u0438\u0437 \u0433\u043E\u043B\u043E\u0432\u044B: \u0434\u0432\u0438\u0436\u043E\u043A \u043F\u0440\u043E\u0432\u0435\u0440\u0438\u0442 \u043F\u043B\u0430\u043D \u0438 \u043E\u0442\u043A\u0430\u0436\u0435\u0442 \u0441\u043B\u043E\u0432\u0430\u043C\u0438, \u043D\u0430\u0437\u0432\u0430\u0432, \u0447\u0442\u043E \u043D\u0430\u0440\u0443\u0448\u0435\u043D\u043E \u0438 \u043A\u0430\u043A\u0430\u044F \u043D\u043E\u0440\u043C\u0430"
18246
- ).optional(),
18247
- project: external_exports.looseObject({}).describe(
18248
- "\u0412\u0415\u0421\u042C \u043E\u0431\u0449\u0438\u0439 \u043F\u0440\u043E\u0435\u043A\u0442 \u043C\u043E\u043D\u0442\u0430\u0436\u0430 \u0446\u0435\u043B\u0438\u043A\u043E\u043C, \u0434\u043E\u0433\u043E\u0432\u043E\u0440 naparnik-project/1: \u0438\u0441\u0442\u043E\u0447\u043D\u0438\u043A\u0438, \u0434\u043E\u0440\u043E\u0436\u043A\u0438, \u043A\u043B\u0438\u043F\u044B, \u044D\u0444\u0444\u0435\u043A\u0442\u044B \u0438 \u0432\u044B\u0445\u043E\u0434. \u0414\u0432\u0438\u0436\u043E\u043A \u0438\u0437\u043C\u0435\u0440\u0438\u0442 \u0444\u0430\u0439\u043B\u044B \u0438 \u043F\u0440\u043E\u0432\u0435\u0440\u0438\u0442 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u0434\u043E \u0437\u0430\u043F\u0438\u0441\u0438. \u041B\u044E\u0431\u0430\u044F \u043D\u043E\u0432\u0430\u044F \u0440\u0435\u0434\u0430\u043A\u0446\u0438\u044F \u0441\u043D\u0438\u043C\u0430\u0435\u0442 \u043F\u0440\u0435\u0436\u043D\u0435\u0435 \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u0435"
18311
+ by: external_exports.enum(["model", "human"]).describe(
18312
+ "\u041A\u0442\u043E \u043F\u0440\u0430\u0432\u0438\u0442 \u0438 \u043A\u0442\u043E \u0441\u043A\u0430\u0437\u0430\u043B \xAB\u0434\u0430\xBB: model \u2014 \u0442\u044B \u0441 \u0435\u0433\u043E \u0441\u043B\u043E\u0432, human \u2014 \u043E\u043D \u0441\u0430\u043C. \u0423\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u0435 \u2014 model"
18249
18313
  ).optional(),
18250
- draft: external_exports.boolean().describe(
18251
- "\u0417\u0430\u0431\u044B\u0442\u044C \u043D\u0430\u043F\u0438\u0441\u0430\u043D\u043D\u044B\u0439 \u0442\u043E\u0431\u043E\u0439 \u043F\u043B\u0430\u043D \u0438 \u0432\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F \u043A \u043D\u0430\u0448\u0435\u043C\u0443 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\u0443"
18314
+ rebuild: external_exports.boolean().describe(
18315
+ "\u0421\u0440\u0430\u0437\u0443 \u0441\u043E\u0431\u0440\u0430\u0442\u044C \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u043F\u043E\u0441\u043B\u0435 \u043F\u0440\u0430\u0432\u043A\u0438. \u041E\u0442\u0432\u0435\u0447\u0443 \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0437\u0430\u0434\u0430\u0447\u0438, \u0434\u0430\u043B\u044C\u0448\u0435 wait"
18252
18316
  ).optional(),
18253
18317
  step: external_exports.enum(["show", "mine", "insert", "remove", "replace"]).describe(
18254
- "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u041F\u041E\u0420\u042F\u0414\u041A\u041E\u041C \u0428\u0410\u0413\u041E\u0412 \u043C\u043E\u043D\u0442\u0430\u0436\u0430, \u0430 \u043D\u0435 \u0441 \u043F\u043B\u0430\u043D\u043E\u043C \u0440\u043E\u043B\u0438\u043A\u0430"
18318
+ "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u041F\u041E\u0420\u042F\u0414\u041A\u041E\u041C \u0428\u0410\u0413\u041E\u0412 \u043C\u043E\u043D\u0442\u0430\u0436\u0430, \u0430 \u043D\u0435 \u0441 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u043E\u043C \u0440\u043E\u043B\u0438\u043A\u0430"
18255
18319
  ).optional(),
18256
18320
  name: external_exports.string().describe(
18257
18321
  '\u0418\u043C\u044F \u0428\u0410\u0413\u0410, \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0441\u0442\u0430\u0432\u0438\u043C (\u0434\u043B\u044F step="insert"). \u041E\u0434\u043D\u043E \u0441\u043B\u043E\u0432\u043E \u2014 \u0442\u0430\u043A, \u043A\u0430\u043A \u043D\u0430\u0437\u044B\u0432\u0430\u0435\u0442\u0441\u044F \u0435\u0433\u043E \u043F\u0430\u043F\u043A\u0430 \u0432 mine/steps'
@@ -18270,54 +18334,31 @@ function planEditTool(engine, key) {
18270
18334
  const say = (message, where) => {
18271
18335
  ctx.issues.push({ code: "custom", message, input: asked, path: [where] });
18272
18336
  };
18273
- const planKeys = ["reel", "ops", "by", "rebuild", "confirm", "plan", "project", "draft"].filter((key2) => asked[key2] !== void 0);
18274
- if (asked.step !== void 0 && planKeys.length > 0) {
18275
- say(
18276
- `\xABstep\xBB \u043F\u0440\u0430\u0432\u0438\u0442 \u043F\u043E\u0440\u044F\u0434\u043E\u043A \u0448\u0430\u0433\u043E\u0432 \u043C\u043E\u043D\u0442\u0430\u0436\u0430, \u0430 \u043D\u0435 \u043F\u043B\u0430\u043D \u0440\u043E\u043B\u0438\u043A\u0430 \u2014 \u043B\u0438\u0448\u043D\u0435\u0435: ${planKeys.join(", ")}. \u041F\u043E\u0437\u043E\u0432\u0438 \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E`,
18277
- "step"
18278
- );
18279
- return;
18280
- }
18281
- if (asked.step === void 0) {
18282
- const stepKeys = STEP_KEYS.filter((key2) => asked[key2] !== void 0);
18283
- if (stepKeys.length > 0) {
18337
+ const editKeys = ["reel", "ops", "stamps", "by", "rebuild"].filter((key2) => asked[key2] !== void 0);
18338
+ if (asked.step !== void 0) {
18339
+ if (editKeys.length > 0) {
18284
18340
  say(
18285
- `\xAB${stepKeys.join(", ")}\xBB \u043E\u0442\u043D\u043E\u0441\u044F\u0442\u0441\u044F \u043A \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044E \u0441\u043E \u0441\u0432\u043E\u0438\u043C \u0448\u0430\u0433\u043E\u043C \u2014 \u043D\u0430\u0437\u043E\u0432\u0438 \xABstep\xBB`,
18341
+ `\xABstep\xBB \u043F\u0440\u0430\u0432\u0438\u0442 \u043F\u043E\u0440\u044F\u0434\u043E\u043A \u0448\u0430\u0433\u043E\u0432 \u043C\u043E\u043D\u0442\u0430\u0436\u0430, \u0430 \u043D\u0435 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u0440\u043E\u043B\u0438\u043A\u0430 \u2014 \u043B\u0438\u0448\u043D\u0435\u0435: ${editKeys.join(", ")}. \u041F\u043E\u0437\u043E\u0432\u0438 \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E`,
18286
18342
  "step"
18287
18343
  );
18288
18344
  }
18289
- if (asked.reel === void 0) {
18290
- say(
18291
- "\u041D\u0435 \u0437\u0430\u0434\u0430\u043D \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u0439 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442 \xABreel\xBB: \u043F\u0440\u0430\u0432\u043A\u0430 \u043F\u043B\u0430\u043D\u0430 \u2014 \u044D\u0442\u043E \u0440\u043E\u043B\u0438\u043A \u0438 \u0442\u043E, \u0447\u0442\u043E \u0441 \u043D\u0438\u043C \u0434\u0435\u043B\u0430\u0435\u043C. \u041F\u043E\u0440\u044F\u0434\u043E\u043A \u0448\u0430\u0433\u043E\u0432 \u043C\u043E\u043D\u0442\u0430\u0436\u0430 \u043F\u0440\u0430\u0432\u0438\u0442\u0441\u044F \u043A\u043B\u044E\u0447\u043E\u043C \xABstep\xBB",
18292
- "reel"
18293
- );
18294
- }
18295
- if (asked.plan !== void 0 && asked.draft === true) {
18296
- say(
18297
- "\xABplan\xBB \u043A\u043B\u0430\u0434\u0451\u0442 \u0442\u0432\u043E\u0439 \u043F\u043B\u0430\u043D \u0440\u043E\u043B\u0438\u043A\u0430, \xABdraft\xBB \u0435\u0433\u043E \u0441\u0442\u0438\u0440\u0430\u0435\u0442 \u2014 \u044D\u0442\u043E \u0434\u0432\u0435 \u043F\u0440\u043E\u0442\u0438\u0432\u043E\u043F\u043E\u043B\u043E\u0436\u043D\u044B\u0435 \u043F\u0440\u043E\u0441\u044C\u0431\u044B. \u041E\u0441\u0442\u0430\u0432\u044C \u043E\u0434\u043D\u0443",
18298
- "draft"
18299
- );
18300
- }
18301
- if (asked.project !== void 0 && (asked.ops !== void 0 || asked.plan !== void 0 || asked.draft === true)) {
18302
- say(
18303
- "\xABproject\xBB \u2014 \u0432\u0435\u0441\u044C \u043E\u0431\u0449\u0438\u0439 naparnik-project/1; ops/plan/draft \u043F\u0440\u0430\u0432\u044F\u0442 \u0441\u0442\u0430\u0440\u044B\u0439 \u0440\u0430\u0437\u0433\u043E\u0432\u043E\u0440\u043D\u044B\u0439 \u043F\u043B\u0430\u043D. \u041E\u0441\u0442\u0430\u0432\u044C \u043E\u0434\u043D\u0443 \u0432\u0435\u0442\u043A\u0443",
18304
- "project"
18305
- );
18306
- }
18307
- const asking = [
18308
- asked.ops !== void 0 ? "ops" : "",
18309
- asked.plan !== void 0 ? "plan" : "",
18310
- asked.project !== void 0 ? "project" : "",
18311
- asked.confirm === true ? "confirm" : "",
18312
- asked.draft === true ? "draft" : "",
18313
- asked.rebuild === true ? "rebuild" : ""
18314
- ].filter((one) => one !== "");
18315
- if (asking.length === 0) {
18316
- say(
18317
- "\u0414\u0435\u043B\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u0433\u043E: \u043D\u0438 \u043F\u0440\u0430\u0432\u043E\u043A, \u043D\u0438 \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u044F. \xABops\xBB \u2014 \u043F\u0440\u0430\u0432\u043A\u0438 \u043F\u043B\u0430\u043D\u0430, \xABplan\xBB \u2014 \u0432\u0435\u0441\u044C \u043F\u043B\u0430\u043D \u0440\u043E\u043B\u0438\u043A\u0430 \u0446\u0435\u043B\u0438\u043A\u043E\u043C, \xABconfirm\xBB \u2014 \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u0441\u043A\u0430\u0437\u0430\u043B \xAB\u0434\u0430\xBB \u043D\u0430 \u043D\u044B\u043D\u0435\u0448\u043D\u044E\u044E \u0440\u0435\u0434\u0430\u043A\u0446\u0438\u044E, \xABdraft\xBB \u2014 \u0432\u0435\u0440\u043D\u0443\u0442\u044C \u043D\u0430\u0448 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A. \u041F\u043E\u0440\u044F\u0434\u043E\u043A \u0448\u0430\u0433\u043E\u0432 \u043C\u043E\u043D\u0442\u0430\u0436\u0430 \u043F\u0440\u0430\u0432\u0438\u0442\u0441\u044F \u043A\u043B\u044E\u0447\u043E\u043C \xABstep\xBB",
18318
- "ops"
18319
- );
18320
- }
18345
+ return;
18346
+ }
18347
+ const stepKeys = STEP_KEYS.filter((key2) => asked[key2] !== void 0);
18348
+ if (stepKeys.length > 0) {
18349
+ say(`\xAB${stepKeys.join(", ")}\xBB \u043E\u0442\u043D\u043E\u0441\u044F\u0442\u0441\u044F \u043A \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044E \u0441\u043E \u0441\u0432\u043E\u0438\u043C \u0448\u0430\u0433\u043E\u043C \u2014 \u043D\u0430\u0437\u043E\u0432\u0438 \xABstep\xBB`, "step");
18350
+ }
18351
+ if (asked.reel === void 0) {
18352
+ say(
18353
+ "\u041D\u0435 \u0437\u0430\u0434\u0430\u043D \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u0439 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442 \xABreel\xBB: \u043F\u0440\u0430\u0432\u043A\u0430 \u2014 \u044D\u0442\u043E \u0440\u043E\u043B\u0438\u043A \u0438 \u0442\u043E, \u0447\u0442\u043E \u0441 \u043D\u0438\u043C \u0434\u0435\u043B\u0430\u0435\u043C. \u041F\u043E\u0440\u044F\u0434\u043E\u043A \u0448\u0430\u0433\u043E\u0432 \u043C\u043E\u043D\u0442\u0430\u0436\u0430 \u043F\u0440\u0430\u0432\u0438\u0442\u0441\u044F \u043A\u043B\u044E\u0447\u043E\u043C \xABstep\xBB",
18354
+ "reel"
18355
+ );
18356
+ }
18357
+ if (asked.ops === void 0 || asked.ops.length === 0) {
18358
+ say(
18359
+ '\u0414\u0435\u043B\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u0433\u043E: \u043D\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0439. \u041F\u0440\u0430\u0432\u043A\u0430 \u2014 ops \u0441\u043E \u0441\u043F\u0438\u0441\u043A\u043E\u043C \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0439, \xAB\u0434\u0430\xBB \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u2014 [{"op": "agree"}]. \u041F\u043E\u0440\u044F\u0434\u043E\u043A \u0448\u0430\u0433\u043E\u0432 \u043C\u043E\u043D\u0442\u0430\u0436\u0430 \u043F\u0440\u0430\u0432\u0438\u0442\u0441\u044F \u043A\u043B\u044E\u0447\u043E\u043C \xABstep\xBB',
18360
+ "ops"
18361
+ );
18321
18362
  }
18322
18363
  }),
18323
18364
  async execute(args, ctx) {
@@ -18330,17 +18371,14 @@ function planEditTool(engine, key) {
18330
18371
  with: args.with
18331
18372
  });
18332
18373
  }
18333
- return editPlan(
18374
+ return editDocument(
18334
18375
  engine,
18335
18376
  {
18336
18377
  reel: args.reel ?? "",
18337
18378
  ops: args.ops ?? [],
18379
+ stamps: args.stamps,
18338
18380
  by: args.by,
18339
- rebuild: args.rebuild,
18340
- confirm: args.confirm,
18341
- plan: args.plan,
18342
- project: args.project,
18343
- draft: args.draft
18381
+ rebuild: args.rebuild
18344
18382
  },
18345
18383
  key,
18346
18384
  ctx?.emitProgress
@@ -18348,334 +18386,6 @@ function planEditTool(engine, key) {
18348
18386
  }
18349
18387
  });
18350
18388
  }
18351
- function universalOptions(asked) {
18352
- const found = /* @__PURE__ */ new Set();
18353
- const known = [
18354
- ["only_pauses", asked.onlyPauses],
18355
- ["style", asked.style],
18356
- ["preset", asked.preset],
18357
- ["model", asked.model],
18358
- ["tempo", asked.tempo],
18359
- ["keep_pauses", asked.keepPauses],
18360
- ["redo", asked.redo],
18361
- ["from_scratch", asked.fromScratch],
18362
- ["even_without_speech", asked.evenWithoutSpeech]
18363
- ];
18364
- for (const [name, value] of known) {
18365
- if (value !== void 0) found.add(name);
18366
- }
18367
- for (const [name, value] of Object.entries(asked.args ?? {})) {
18368
- if (name !== "reel" && value !== void 0) found.add(name);
18369
- }
18370
- return [...found].sort();
18371
- }
18372
- async function startRender(engine, asked, passport, key, tell) {
18373
- const place = engine.place();
18374
- if (place === null) return toolError(engine.whyNoEngine());
18375
- const where = fileOrRefusal(asked.video);
18376
- if ("refusal" in where) return toolError(where.refusal);
18377
- if (asked.reel === true) {
18378
- const viewed = await engine.command([
18379
- "composition-view",
18380
- "--project",
18381
- path(where.path),
18382
- "--json"
18383
- ]);
18384
- if (!viewed.ok) return toolError(viewed.text);
18385
- try {
18386
- const lines = viewed.text.trim().split("\n");
18387
- const answer = JSON.parse(lines[lines.length - 1] ?? "{}");
18388
- if (answer.universal === true) {
18389
- const extra = universalOptions(asked);
18390
- if (extra.length > 0) {
18391
- return toolError(
18392
- `\u041E\u0431\u0449\u0438\u0439 naparnik-project/1 \u0443\u0436\u0435 \u0445\u0440\u0430\u043D\u0438\u0442 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u043C\u043E\u043D\u0442\u0430\u0436\u0430 \u0432 \u0441\u0430\u043C\u043E\u043C project, \u043F\u043E\u044D\u0442\u043E\u043C\u0443 render \u043D\u0435 \u043F\u0440\u0438\u043C\u0435\u043D\u0438\u0442 \u043A \u043D\u0435\u043C\u0443 legacy-\u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B: ${extra.join(", ")}.
18393
- \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u0432\u043D\u0435\u0441\u0438 \u044D\u0442\u0438 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432 project \u0447\u0435\u0440\u0435\u0437 plan_edit \u0438 \u043F\u043E\u0437\u043E\u0432\u0438 render \u0442\u043E\u043B\u044C\u043A\u043E \u0441 reel.`
18394
- );
18395
- }
18396
- return startComposition(engine, where.path, key, tell);
18397
- }
18398
- } catch {
18399
- return toolError(
18400
- "\u0414\u0432\u0438\u0436\u043E\u043A \u043D\u0435 \u0441\u043C\u043E\u0433 \u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0438\u0442\u044C \u0432\u0438\u0434 \u043F\u0440\u043E\u0435\u043A\u0442\u0430. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043E\u0431\u043D\u043E\u0432\u0438 \u043D\u0430\u0447\u0438\u043D\u043A\u0443 \u0447\u0435\u0440\u0435\u0437 setup."
18401
- );
18402
- }
18403
- }
18404
- const onlyPauses = asked.onlyPauses === true;
18405
- const line = onlyPauses ? ["--without-subs"] : [];
18406
- if (asked.style !== void 0) line.push("--style", path(asked.style));
18407
- if (asked.preset !== void 0) line.push("--preset", asked.preset);
18408
- if (asked.model !== void 0) line.push("--model", asked.model);
18409
- if (asked.tempo !== void 0 && asked.tempo !== 1) line.push("--tempo", String(asked.tempo));
18410
- if (asked.keepPauses === true) line.push("--keep-pauses");
18411
- if (asked.fromScratch === true) line.push("--afresh");
18412
- if (asked.evenWithoutSpeech === true) line.push("--anyway");
18413
- if (asked.redo !== void 0 && asked.redo.length > 0) line.push("--only", ...asked.redo);
18414
- line.push(...readCapabilities(asked.args ?? {}, passport));
18415
- const what = onlyPauses ? `\u043F\u0430\u0443\u0437\u044B ${basename(where.path)}` : `\u043C\u043E\u043D\u0442\u0430\u0436 ${basename(where.path)}`;
18416
- return startMontage(engine, {
18417
- key,
18418
- place,
18419
- ...onlyPauses ? { ladder: PAUSES_LADDER } : {},
18420
- ...tell !== void 0 ? { tell } : {},
18421
- video: where.path,
18422
- what,
18423
- // ⚠ КЛЮЧИ ЭТОГО СЛОВАРЯ — ДВИЖКОВЫЕ, И ПЕРЕИМЕНОВЫВАТЬ ИХ НЕЛЬЗЯ. По ним
18424
- // движок узнаёт повторный вызов с той же настройкой — то самое «повторный
18425
- // монтаж почти ничего не считает». Имя инструмента тут прежнее (`montage`,
18426
- // `cut_pauses`) нарочно: смени его — и каждое задание выглядело бы новым, а
18427
- // кэш перестал бы срабатывать молча.
18428
- command: onlyPauses ? { "tool": "cut_pauses", "args": { style: asked.style, tempo: asked.tempo } } : {
18429
- "tool": "montage",
18430
- "args": {
18431
- style: asked.style,
18432
- preset: asked.preset,
18433
- model: asked.model,
18434
- tempo: asked.tempo,
18435
- keep_pauses: asked.keepPauses === true
18436
- }
18437
- },
18438
- ...asked.style !== void 0 ? { style: path(asked.style) } : {},
18439
- args: line,
18440
- hint: onlyPauses ? "\u0411\u044B\u0441\u0442\u0440\u043E, \u043E\u0431\u044B\u0447\u043D\u043E \u043C\u0435\u043D\u044C\u0448\u0435 \u043C\u0438\u043D\u0443\u0442\u044B." : "\u041F\u0435\u0440\u0432\u044B\u0439 \u0440\u0430\u0437 \u2014 \u043C\u0438\u043D\u0443\u0442\u044B; \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u044B\u0439 \u0441 \u0442\u043E\u0439 \u0436\u0435 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u043E\u0439 \u2014 \u0441\u0435\u043A\u0443\u043D\u0434\u044B."
18441
- });
18442
- }
18443
- async function startComposition(engine, reel, key, tell) {
18444
- const place = engine.place();
18445
- if (place === null) return toolError(engine.whyNoEngine());
18446
- const trouble = await engine.pythonTrouble();
18447
- if (trouble !== null) return toolError(trouble);
18448
- const python = engine.packPython();
18449
- if (python === null) {
18450
- return toolError("\u041E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u0435 \u043C\u043E\u043D\u0442\u0430\u0436\u0430 \u0435\u0449\u0451 \u043D\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E. \u0427\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C: \u043F\u043E\u0437\u043E\u0432\u0438 setup.");
18451
- }
18452
- if (tell !== void 0) {
18453
- tell("\u041F\u0440\u043E\u0432\u0435\u0440\u044E \u0442\u043E\u0447\u043D\u0443\u044E \u0440\u0435\u0434\u0430\u043A\u0446\u0438\u044E \u043F\u0440\u043E\u0435\u043A\u0442\u0430 \u0438 \u0435\u0433\u043E \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A\u0438.");
18454
- tell("\u0421\u043E\u0431\u0435\u0440\u0443 \u044D\u0444\u0444\u0435\u043A\u0442\u044B, \u0432\u0438\u0434\u0435\u043E \u0438 \u0437\u0432\u0443\u043A \u043F\u043E \u043E\u0431\u0449\u0435\u0439 \u043A\u043E\u043C\u043F\u043E\u0437\u0438\u0446\u0438\u0438.");
18455
- }
18456
- const launch = await engine.background({
18457
- place,
18458
- executable: python,
18459
- key,
18460
- startJob: [
18461
- "job-create",
18462
- "--video",
18463
- reel,
18464
- "--composition",
18465
- "--what",
18466
- `\u043C\u043E\u043D\u0442\u0430\u0436 ${basename(reel)}`,
18467
- "--command",
18468
- JSON.stringify({ tool: "composition", args: {} })
18469
- ],
18470
- args: (id) => [
18471
- place.consolePy,
18472
- "composition-render",
18473
- "--project",
18474
- reel,
18475
- "--job",
18476
- id
18477
- ],
18478
- advice: "\u043F\u043E\u0437\u043E\u0432\u0438 setup \u2014 \u0441\u043A\u043E\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043E, \u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u0435 \u043D\u0435\u043F\u043E\u043B\u043D\u043E\u0435"
18479
- });
18480
- if ("refusal" in launch) return toolError(launch.refusal);
18481
- return toolSuccess(
18482
- `\u0417\u0430\u0434\u0430\u0447\u0430 ${launch.id}: \u043C\u043E\u043D\u0442\u0430\u0436 ${basename(reel)}
18483
- \u0414\u0430\u043B\u044C\u0448\u0435 \u043F\u043E\u0437\u043E\u0432\u0438 wait \u0441 \u044D\u0442\u0438\u043C \u043D\u043E\u043C\u0435\u0440\u043E\u043C. ${AWAY_NOTE}`,
18484
- startedJob({
18485
- id: launch.id,
18486
- what: `\u043C\u043E\u043D\u0442\u0430\u0436 ${basename(reel)}`,
18487
- ahead: "\u041F\u0440\u043E\u0432\u0435\u0440\u044E \u043F\u0440\u043E\u0435\u043A\u0442. \u0421\u043E\u0431\u0435\u0440\u0443 \u044D\u0444\u0444\u0435\u043A\u0442\u044B, \u0432\u0438\u0434\u0435\u043E \u0438 \u0437\u0432\u0443\u043A.",
18488
- message: "\u041E\u0431\u0449\u0438\u0439 \u043F\u0440\u043E\u0435\u043A\u0442 \u0441\u043E\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044F \u043D\u0430 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F."
18489
- })
18490
- );
18491
- }
18492
- async function followWork(engine, asked, pace = realPace, tell) {
18493
- const ask2 = () => engine.command(["job", asked.job]);
18494
- const seconds2 = waitSeconds(asked.seconds ?? WAIT_LIMIT_SECONDS);
18495
- if (seconds2 === 0) return asJobResult(await ask2());
18496
- const state = await followJob({
18497
- ask: ask2,
18498
- seconds: seconds2,
18499
- pace,
18500
- // ⚠ Рассказ есть только если КЛИЕНТ его попросил (токен хода работы в
18501
- // `_meta`). Нет — ждём молча и отвечаем итогом: ждать всё равно дешевле
18502
- // пяти кругов переписки «спроси ещё раз».
18503
- ...tell !== void 0 ? { tell } : {}
18504
- });
18505
- if (state.ok && stillWorking(state.text)) {
18506
- const words = `${state.text}
18507
- \u0416\u0434\u0430\u043B ${seconds2} \u0441, \u0440\u0430\u0431\u043E\u0442\u0430 \u0435\u0449\u0451 \u0438\u0434\u0451\u0442. \u0421\u043A\u0430\u0436\u0438 \u044D\u0442\u043E \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0443 \u0438 \u043F\u043E\u0437\u043E\u0432\u0438 wait \u0435\u0449\u0451 \u0440\u0430\u0437 \u2014 \u0442\u0430\u043A \u043E\u043D \u0443\u0441\u043B\u044B\u0448\u0438\u0442 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0435 \u0448\u0430\u0433\u0438.`;
18508
- const job = readJob(state.text);
18509
- return job === null ? toolSuccess(words) : toolSuccess(words, job);
18510
- }
18511
- return asJobResult(state);
18512
- }
18513
- async function listJobs(engine, asked) {
18514
- return asToolResult(
18515
- await engine.command([
18516
- "jobs",
18517
- ...asked.video !== void 0 ? ["--video", path(asked.video)] : [],
18518
- ...asked.limit !== void 0 ? ["--count", String(asked.limit)] : []
18519
- ])
18520
- );
18521
- }
18522
- function renderDeclared(passport) {
18523
- return external_exports.object({
18524
- video: external_exports.string().describe(
18525
- "\u041F\u0443\u0442\u044C \u043A \u0432\u0438\u0434\u0435\u043E\u0444\u0430\u0439\u043B\u0443 \u043D\u0430 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430. \u0417\u0430\u0432\u0435\u0434\u0451\u043D\u043D\u044B\u0439 \u0440\u043E\u043B\u0438\u043A \u043C\u043E\u0436\u043D\u043E \u043D\u0430\u0437\u0432\u0430\u0442\u044C \u0438 \u043F\u0430\u043F\u043A\u043E\u0439 \u2014 \u043A\u043B\u044E\u0447\u043E\u043C reel"
18526
- ).optional(),
18527
- reel: external_exports.string().describe(
18528
- "\u041F\u0430\u043F\u043A\u0430 \u0437\u0430\u0432\u0435\u0434\u0451\u043D\u043D\u043E\u0433\u043E \u0440\u043E\u043B\u0438\u043A\u0430. \u0422\u043E \u0436\u0435, \u0447\u0442\u043E video, \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0440\u043E\u043B\u0438\u043A\u0430 \u0446\u0435\u043B\u0438\u043A\u043E\u043C: \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A\u0438, \u0431\u0440\u0438\u0444 \u0438 \u043F\u0440\u0430\u0432\u043A\u0438 \u043F\u043B\u0430\u043D\u0430 \u0434\u0432\u0438\u0436\u043E\u043A \u0432\u043E\u0437\u044C\u043C\u0451\u0442 \u0438\u0437 \u043D\u0435\u0451 \u0441\u0430\u043C"
18529
- ).optional(),
18530
- only_pauses: external_exports.boolean().describe(
18531
- "\u0422\u043E\u043B\u044C\u043A\u043E \u0443\u0431\u0440\u0430\u0442\u044C \u043C\u043E\u043B\u0447\u0430\u043D\u0438\u0435 \u0438 \u0437\u0430\u043F\u0438\u043D\u043A\u0438. \u0420\u0435\u0447\u044C \u043F\u0440\u0438 \u044D\u0442\u043E\u043C \u041D\u0415 \u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u0451\u0442\u0441\u044F \u0438 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\u0430 \u043D\u0435\u0442: \u0447\u0435\u043B\u043E\u0432\u0435\u043A, \u043F\u043E\u043F\u0440\u043E\u0441\u0438\u0432\u0448\u0438\u0439 \xAB\u043F\u0440\u043E\u0441\u0442\u043E \u0443\u0431\u0435\u0440\u0438 \u0442\u0438\u0448\u0438\u043D\u0443\xBB, \u043D\u0435 \u0436\u0434\u0451\u0442 \u043C\u0438\u043D\u0443\u0442\u044B \u0438 \u043D\u0435 \u043A\u0430\u0447\u0430\u0435\u0442 \u043F\u043E\u043B\u0442\u043E\u0440\u0430 \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442\u0430. \u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044B \u0438 \u0433\u0440\u0430\u0444\u0438\u043A\u0443 \u044D\u0442\u0438\u043C \u043D\u0435 \u0441\u043E\u0431\u0440\u0430\u0442\u044C"
18532
- ).optional(),
18533
- style: external_exports.string().describe(
18534
- "\u041F\u0430\u043F\u043A\u0430 \u043F\u0430\u043A\u0430 \u0444\u0438\u0440\u043C\u0435\u043D\u043D\u043E\u0433\u043E \u0441\u0442\u0438\u043B\u044F. \u041D\u0435 \u0443\u043A\u0430\u0437\u0430\u043D \u2014 \u0431\u0435\u0440\u0451\u0442\u0441\u044F \u0441\u0442\u0438\u043B\u044C \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E, \u0430 \u0435\u0441\u043B\u0438 \u0438 \u0435\u0433\u043E \u043D\u0435\u0442, \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0439 \u043D\u0435\u0439\u0442\u0440\u0430\u043B\u044C\u043D\u044B\u0439"
18535
- ).optional(),
18536
- preset: external_exports.string().describe(
18537
- "\u0418\u043C\u044F \u043F\u0440\u0435\u0441\u0435\u0442\u0430 \u0432\u0438\u0434\u0430 \u0418\u0417 \u041F\u0410\u041A\u0410 \u0421\u0422\u0418\u041B\u042F \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430. \u041D\u0435 \u0432\u044B\u0434\u0443\u043C\u044B\u0432\u0430\u0439 \u0438\u043C\u0435\u043D\u0430: \u0443 \u043D\u0435\u0433\u043E \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043E\u0434\u0438\u043D \u043F\u0440\u0435\u0441\u0435\u0442 \u0438\u043B\u0438 \u0441\u0432\u043E\u0438"
18538
- ).optional(),
18539
- model: fromList(
18540
- passport?.["models"],
18541
- `\u041C\u043E\u0434\u0435\u043B\u044C \u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u0432\u0430\u043D\u0438\u044F \u0440\u0435\u0447\u0438. ${aboutModels(passport)}`
18542
- ).optional(),
18543
- tempo: external_exports.number().describe("\u0423\u0441\u043A\u043E\u0440\u0435\u043D\u0438\u0435 \u0440\u0435\u0447\u0438, 1.0 \u2014 \u0431\u0435\u0437 \u0443\u0441\u043A\u043E\u0440\u0435\u043D\u0438\u044F").optional(),
18544
- keep_pauses: external_exports.boolean().describe("\u041D\u0435 \u0442\u0440\u043E\u0433\u0430\u0442\u044C \u043F\u0430\u0443\u0437\u044B, \u0442\u043E\u043B\u044C\u043A\u043E \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044B").optional(),
18545
- redo: external_exports.array(fromList(passport?.["stages"], "\u0418\u043C\u044F \u0448\u0430\u0433\u0430 \u043C\u043E\u043D\u0442\u0430\u0436\u0430")).describe(
18546
- "\u0421\u043E\u0431\u0440\u0430\u0442\u044C \u043D\u0430\u0437\u0432\u0430\u043D\u043D\u044B\u0435 \u0448\u0430\u0433\u0438 \u0437\u0430\u043D\u043E\u0432\u043E, \u0434\u0430\u0436\u0435 \u0435\u0441\u043B\u0438 \u0433\u043E\u0442\u043E\u0432\u043E\u0435 \u0443\u0436\u0435 \u043B\u0435\u0436\u0438\u0442. \u041D\u0443\u0436\u043D\u043E \u0440\u0435\u0434\u043A\u043E \u2014 \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440, \u043A\u043E\u0433\u0434\u0430 \u043F\u043E\u0434\u043C\u0435\u043D\u0438\u043B\u0438 \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A \u0442\u0435\u043C \u0436\u0435 \u0438\u043C\u0435\u043D\u0435\u043C" + (passport !== null ? `. \u0428\u0430\u0433\u0438: ${passport["stages"].join(", ")}` : "")
18547
- ).optional(),
18548
- from_scratch: external_exports.boolean().describe(
18549
- "\u0421\u0447\u0438\u0442\u0430\u0442\u044C \u0432\u0441\u0451 \u0437\u0430\u043D\u043E\u0432\u043E, \u043A\u044D\u0448 \u043D\u0435 \u0442\u0440\u043E\u0433\u0430\u0442\u044C. \u0414\u043E\u0440\u043E\u0433\u043E: \u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u0432\u0430\u043D\u0438\u0435 \u0440\u0435\u0447\u0438 \u044D\u0442\u043E \u043C\u0438\u043D\u0443\u0442\u044B. \u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u043F\u043E\u043F\u0440\u043E\u0431\u0443\u0439 redo \u0441 \u043E\u0434\u043D\u0438\u043C \u0448\u0430\u0433\u043E\u043C"
18550
- ).optional(),
18551
- even_without_speech: external_exports.boolean().describe(
18552
- "\u0421\u043E\u0431\u0440\u0430\u0442\u044C, \u0434\u0430\u0436\u0435 \u0435\u0441\u043B\u0438 \u043C\u043E\u043D\u0442\u0430\u0436 \u0433\u043E\u0432\u043E\u0440\u0438\u0442 \xAB\u0440\u0435\u0447\u0438 \u0432 \u0444\u0430\u0439\u043B\u0435 \u043D\u0435\u0442\xBB. \u0421\u0442\u0430\u0432\u044C \u0422\u041E\u041B\u042C\u041A\u041E \u043F\u043E\u0441\u043B\u0435 \u0442\u043E\u0433\u043E, \u043A\u0430\u043A \u0441\u043F\u0440\u043E\u0441\u0438\u043B \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u0438 \u043E\u043D \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u043B, \u0447\u0442\u043E \u0440\u0435\u0447\u044C \u0442\u0430\u043C \u0435\u0441\u0442\u044C: \u043D\u0430 \u043A\u043B\u0438\u043F\u0430\u0445 \u043F\u043E\u0434 \u043C\u0443\u0437\u044B\u043A\u0443 \u0434\u0432\u0438\u0436\u043E\u043A \u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u0432\u0430\u043D\u0438\u044F \u0432\u044B\u0434\u0443\u043C\u044B\u0432\u0430\u0435\u0442 \u0441\u043B\u043E\u0432\u0430, \u0438 \u043E\u043D\u0438 \u043F\u043E\u043F\u0430\u0434\u0443\u0442 \u0432 \u043A\u0430\u0434\u0440"
18553
- ).optional()
18554
- });
18555
- }
18556
- var NOT_FOR_PAUSES = ["preset", "model", "keep_pauses", "redo", "even_without_speech"];
18557
- function renderArgs(passport) {
18558
- const ours = renderDeclared(passport);
18559
- const packKeys = capabilitiesToSchema(passport, new Set(Object.keys(ours.shape)));
18560
- return ours.extend(packKeys);
18561
- }
18562
- function renderTool(engine, passport, key) {
18563
- return defineTool({
18564
- name: "render",
18565
- title: "\u0421\u043E\u0431\u0440\u0430\u0442\u044C \u0440\u043E\u043B\u0438\u043A",
18566
- description: "\u0421\u043E\u0431\u0438\u0440\u0430\u0435\u0442 \u0440\u043E\u043B\u0438\u043A \u043D\u0430 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430: \u0443\u0431\u0438\u0440\u0430\u0435\u0442 \u043F\u0430\u0443\u0437\u044B, \u0441\u0442\u0430\u0432\u0438\u0442 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044B \u043F\u043E \u0441\u043B\u043E\u0432\u0430\u043C, \u0440\u0438\u0441\u0443\u0435\u0442 \u0433\u0440\u0430\u0444\u0438\u043A\u0443 \u043F\u043E \u043F\u043B\u0430\u043D\u0443, \u0441\u0432\u043E\u0434\u0438\u0442 \u0437\u0432\u0443\u043A. \u0417\u043E\u0432\u0438 \u041F\u041E\u0421\u041B\u0415 \u0442\u043E\u0433\u043E, \u043A\u0430\u043A \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u0441\u043A\u0430\u0437\u0430\u043B \xAB\u0434\u0430\xBB \u043D\u0430 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u0438\u0437 plan: \u0441\u043E\u0431\u0440\u0430\u043D\u043D\u044B\u0439 \u043A\u0430\u0434\u0440 \u0441\u043F\u043E\u0440\u0438\u0442\u044C \u0434\u043E\u0440\u043E\u0436\u0435, \u0447\u0435\u043C \u0441\u0442\u0440\u043E\u0447\u043A\u0443 \u043F\u043B\u0430\u043D\u0430.\n\u0421\u043E\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044F \u0422\u041E\u041B\u042C\u041A\u041E \u0441\u043E\u0433\u043B\u0430\u0441\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u043F\u043B\u0430\u043D, \u0438 \xAB\u0434\u0430\xBB \u0432 \u0447\u0430\u0442\u0435 \u0441\u0430\u043C\u043E \u043F\u043E \u0441\u0435\u0431\u0435 \u043D\u0435 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044F: \u0437\u0430\u043F\u0438\u0448\u0438 \u0435\u0433\u043E \u0432\u044B\u0437\u043E\u0432\u043E\u043C plan_edit \u0441 confirm \u2014 \u0442\u0435\u043C \u0436\u0435, \u043A\u043E\u0442\u043E\u0440\u044B\u043C \u0448\u043B\u0451\u0448\u044C \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u044E\u044E \u043F\u0440\u0430\u0432\u043A\u0443. \u041B\u044E\u0431\u0430\u044F \u043F\u0440\u0430\u0432\u043A\u0430 \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u0435 \u0441\u043D\u0438\u043C\u0430\u0435\u0442, \u043F\u043E\u044D\u0442\u043E\u043C\u0443 \u043F\u043E\u0440\u044F\u0434\u043E\u043A \u0442\u0430\u043A\u043E\u0439: \u043F\u043E\u043F\u0440\u0430\u0432\u0438\u043B, \u043F\u0435\u0440\u0435\u0441\u043A\u0430\u0437\u0430\u043B \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0443, \u0443\u0441\u043B\u044B\u0448\u0430\u043B \xAB\u0434\u0430\xBB, \u043F\u043E\u0437\u0432\u0430\u043B plan_edit \u0441 confirm, \u0438 \u0442\u043E\u043B\u044C\u043A\u043E \u0442\u0435\u043F\u0435\u0440\u044C render.\n\u0415\u0441\u043B\u0438 reel \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u0442 \u043E\u0431\u0449\u0438\u0439 naparnik-project/1, render \u0441\u0430\u043C \u0432\u044B\u0431\u0438\u0440\u0430\u0435\u0442 \u0443\u043D\u0438\u0432\u0435\u0440\u0441\u0430\u043B\u044C\u043D\u0443\u044E \u0441\u0431\u043E\u0440\u043A\u0443; \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E\u0433\u043E \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u0430 \u0434\u043B\u044F \u043D\u0435\u0451 \u043D\u0435\u0442. \u0412\u0441\u0435 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0442\u0430\u043A\u043E\u0433\u043E \u043C\u043E\u043D\u0442\u0430\u0436\u0430 \u0443\u0436\u0435 \u043B\u0435\u0436\u0430\u0442 \u0432 project: \u0432\u043C\u0435\u0441\u0442\u0435 \u0441 reel \u043D\u0435 \u043F\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0439 style, preset, tempo \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u0441\u0442\u0430\u0440\u043E\u0433\u043E \u043C\u043E\u043D\u0442\u0430\u0436\u0430 \u2014 \u043D\u0443\u0436\u043D\u0443\u044E \u043F\u0440\u0430\u0432\u043A\u0443 \u0441\u043D\u0430\u0447\u0430\u043B\u0430 \u0437\u0430\u043F\u0438\u0448\u0438 \u0447\u0435\u0440\u0435\u0437 plan_edit.\n\u041E\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u0434\u0430\u043B\u044C\u0448\u0435 wait, \u043E\u043D \u043F\u043E\u0434\u043E\u0436\u0434\u0451\u0442 \u0438 \u0440\u0430\u0441\u0441\u043A\u0430\u0436\u0435\u0442 \u0445\u043E\u0434. \u041F\u043E\u0432\u0442\u043E\u0440\u043D\u044B\u0439 \u0432\u044B\u0437\u043E\u0432 \u0441 \u0442\u043E\u0439 \u0436\u0435 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u043E\u0439 \u043F\u043E\u0447\u0442\u0438 \u043D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u0434\u0435\u043B\u0430\u0435\u0442 \u0437\u0430\u043D\u043E\u0432\u043E: \u0432\u0441\u0451 \u0431\u0435\u0440\u0451\u0442\u0441\u044F \u0438\u0437 \u043A\u044D\u0448\u0430.\n\u041F\u0440\u043E\u0441\u044F\u0442 \xAB\u043F\u0440\u043E\u0441\u0442\u043E \u0443\u0431\u0435\u0440\u0438 \u043F\u0430\u0443\u0437\u044B\xBB, \xAB\u0443\u0431\u0435\u0440\u0438 \u0442\u0438\u0448\u0438\u043D\u0443\xBB \u2014 only_pauses=true: \u0440\u0435\u0447\u044C \u043F\u0440\u0438 \u044D\u0442\u043E\u043C \u043D\u0435 \u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u0451\u0442\u0441\u044F, \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\u0430 \u043D\u0435\u0442 \u0438 \u0441\u043E\u0433\u043B\u0430\u0441\u043E\u0432\u044B\u0432\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u0433\u043E. \u041A\u0430\u0440\u0442\u043E\u0447\u043A\u0430 \u0432 \u043D\u0430\u0447\u0430\u043B\u0435 (plan_edit, \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F intro) \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u0438 \u0437\u0434\u0435\u0441\u044C: \u043E\u043D\u0430 \u043D\u0435 \u043F\u0440\u043E \u0440\u0435\u0447\u044C, \u0430 \u043F\u0440\u043E \u0442\u043E, \u0447\u0442\u043E \u0432\u0441\u0442\u0430\u0451\u0442 \u041F\u0415\u0420\u0415\u0414 \u0440\u043E\u043B\u0438\u043A\u043E\u043C.\n\u0420\u0430\u0431\u043E\u0442\u0430 \u0438\u0434\u0451\u0442 \u043D\u0430 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430, \u043A \u043D\u0430\u043C \u0432\u0438\u0434\u0435\u043E \u043D\u0435 \u0443\u0445\u043E\u0434\u0438\u0442 \u2014 \u043D\u0430\u0432\u0435\u0440\u0445 \u0438\u0434\u0451\u0442 \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E\u0434\u043F\u0438\u0441\u043A\u0438 \u043F\u043E \u043A\u043B\u044E\u0447\u0443.",
18567
- // Полоса хода работы: монтаж идёт минутами, и всё это время в ленте не
18568
- // происходило бы ничего. ⚠ Ожидание — у `wait`, и полосы там нет: иначе
18569
- // каждая проверка рисовала бы новую поверх этой.
18570
- ui: { resourceUri: RUNBAR_RESOURCE_URI },
18571
- // ⚠ КЛЮЧИ ПАКА ДОБАВЛЯЮТСЯ К СХЕМЕ ЧЕРЕЗ `extend`, А ТИП ОСТАЁТСЯ ОТ
18572
- // ОБЪЯВЛЕННОЙ ЧАСТИ. Их набор известен только в рантайме (паспорт пака), и
18573
- // выведенный из них тип превратился бы в словарь со свободными ключами —
18574
- // тогда `args.video` перестал бы быть строкой, а описка в имени поля
18575
- // перестала бы быть ошибкой компиляции. В объявление модели они при этом
18576
- // попадают полностью: схема-то настоящая.
18577
- args: renderArgs(passport).check((ctx) => {
18578
- const asked = ctx.value;
18579
- const say = (message, where) => {
18580
- ctx.issues.push({ code: "custom", message, input: asked, path: [where] });
18581
- };
18582
- const video = asked["video"];
18583
- const reel = asked["reel"];
18584
- if (video === void 0 && reel === void 0) {
18585
- say(
18586
- "\u041D\u0435 \u0441\u043A\u0430\u0437\u0430\u043D\u043E, \u0447\u0442\u043E \u0441\u043E\u0431\u0438\u0440\u0430\u0442\u044C: \u043D\u0430\u0437\u043E\u0432\u0438 video (\u0444\u0430\u0439\u043B) \u0438\u043B\u0438 reel (\u043F\u0430\u043F\u043A\u0443 \u0437\u0430\u0432\u0435\u0434\u0451\u043D\u043D\u043E\u0433\u043E \u0440\u043E\u043B\u0438\u043A\u0430). \u0427\u0442\u043E \u0443 \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0430 \u0435\u0441\u0442\u044C, \u043F\u043E\u043A\u0430\u0436\u0435\u0442 plan \u0431\u0435\u0437 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u0432",
18587
- "video"
18588
- );
18589
- }
18590
- if (video !== void 0 && reel !== void 0) {
18591
- say("\xABvideo\xBB \u0438 \xABreel\xBB \u2014 \u044D\u0442\u043E \u043E\u0434\u043D\u043E \u0438 \u0442\u043E \u0436\u0435 \u043C\u0435\u0441\u0442\u043E, \u043D\u0430\u0437\u0432\u0430\u043D\u043D\u043E\u0435 \u0434\u0432\u0430\u0436\u0434\u044B. \u041E\u0441\u0442\u0430\u0432\u044C \u043E\u0434\u043D\u043E", "reel");
18592
- }
18593
- if (asked["only_pauses"] !== true) return;
18594
- const extra = NOT_FOR_PAUSES.filter((name) => asked[name] !== void 0);
18595
- if (extra.length > 0) {
18596
- say(
18597
- `\xABonly_pauses\xBB \u0440\u0435\u0436\u0435\u0442 \u0442\u0438\u0448\u0438\u043D\u0443 \u0438 \u043D\u0430 \u044D\u0442\u043E\u043C \u043E\u0441\u0442\u0430\u043D\u0430\u0432\u043B\u0438\u0432\u0430\u0435\u0442\u0441\u044F \u2014 \u043B\u0438\u0448\u043D\u0435\u0435: ${extra.join(", ")}. \u041F\u043E\u0437\u043E\u0432\u0438 \u043B\u0438\u0431\u043E \u0441 only_pauses, \u043B\u0438\u0431\u043E \u0437\u0430 \u043F\u043E\u043B\u043D\u044B\u043C \u043C\u043E\u043D\u0442\u0430\u0436\u043E\u043C`,
18598
- "only_pauses"
18599
- );
18600
- }
18601
- }),
18602
- async execute(args, ctx) {
18603
- const all = args;
18604
- const video = args.video ?? args.reel ?? "";
18605
- return startRender(
18606
- engine,
18607
- {
18608
- video,
18609
- reel: args.reel !== void 0,
18610
- onlyPauses: args.only_pauses,
18611
- style: args.style,
18612
- preset: args.preset,
18613
- model: args.model,
18614
- tempo: args.tempo,
18615
- keepPauses: args.keep_pauses,
18616
- redo: args.redo,
18617
- fromScratch: args.from_scratch,
18618
- evenWithoutSpeech: args.even_without_speech,
18619
- args: all
18620
- },
18621
- passport,
18622
- key,
18623
- ctx?.emitProgress
18624
- );
18625
- }
18626
- });
18627
- }
18628
- function waitTool(engine, pace = realPace) {
18629
- return defineTool({
18630
- name: "wait",
18631
- title: "\u0414\u043E\u0436\u0434\u0430\u0442\u044C\u0441\u044F \u0440\u0430\u0431\u043E\u0442\u044B",
18632
- description: `\u0416\u0434\u0451\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 \u0438 \u043F\u043E \u0445\u043E\u0434\u0443 \u0440\u0430\u0441\u0441\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442, \u043A\u0430\u043A\u043E\u0439 \u0448\u0430\u0433 \u043F\u043E\u0448\u0451\u043B \u0438 \u043A\u0430\u043A\u043E\u0439 \u0437\u0430\u043A\u043E\u043D\u0447\u0438\u043B\u0441\u044F \u2014 \u043F\u0435\u0440\u0435\u0441\u043A\u0430\u0437\u044B\u0432\u0430\u0439 \u044D\u0442\u043E \u0447\u0435\u043B\u043E\u0432\u0435\u043A\u0443 \u0441\u0440\u0430\u0437\u0443, \u043D\u0435 \u0434\u043E\u0436\u0438\u0434\u0430\u044F\u0441\u044C \u043A\u043E\u043D\u0446\u0430. \u0422\u0430\u043A \u0438 \u0441\u043F\u0440\u0430\u0448\u0438\u0432\u0430\u0439: \u043E\u043F\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044C \u043F\u043E \u043A\u0440\u0443\u0433\u0443 \u043D\u0435 \u043D\u0430\u0434\u043E, \u0436\u0434\u0451\u0442 \u043E\u043D \u0434\u043E ${WAIT_LIMIT_SECONDS} \u0441\u0435\u043A\u0443\u043D\u0434 \u0438 \u0432\u0435\u0440\u043D\u0451\u0442\u0441\u044F \u0440\u0430\u043D\u044C\u0448\u0435, \u0435\u0441\u043B\u0438 \u0440\u0430\u0431\u043E\u0442\u0430 \u043A\u043E\u043D\u0447\u0438\u0442\u0441\u044F.
18633
- \u0411\u0435\u0437 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u0432 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u0442 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u043D\u043E\u043C\u0435\u0440, \u0440\u043E\u043B\u0438\u043A, \u0447\u0435\u043C \u043A\u043E\u043D\u0447\u0438\u043B\u043E\u0441\u044C. \u0417\u043E\u0432\u0438, \u043A\u043E\u0433\u0434\u0430 \u043D\u043E\u043C\u0435\u0440 \u043F\u043E\u0442\u0435\u0440\u044F\u043B\u0441\u044F: \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440, \u043F\u043E\u0441\u043B\u0435 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A\u0430 \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u044B \u0438\u043B\u0438 \u043A\u043E\u0433\u0434\u0430 \u0432\u044B\u0437\u043E\u0432 \u043E\u0431\u043E\u0440\u0432\u0430\u043B\u0441\u044F \u043F\u043E\u0441\u0440\u0435\u0434\u0438 \u0440\u0430\u0431\u043E\u0442\u044B. \u0421 video \u2014 \u0437\u0430\u0434\u0430\u0447\u0438 \u043E\u0434\u043D\u043E\u0433\u043E \u0440\u043E\u043B\u0438\u043A\u0430.
18634
- \u0417\u0430\u0434\u0430\u0447\u0438 \u043B\u0435\u0436\u0430\u0442 \u043D\u0430 \u0434\u0438\u0441\u043A\u0435 \u0438 \u043F\u0435\u0440\u0435\u0436\u0438\u0432\u0430\u044E\u0442 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u044B. \u041F\u043E\u0434\u043F\u0438\u0441\u043A\u0430 \u043D\u0435 \u043D\u0443\u0436\u043D\u0430: \u0437\u0430\u0431\u0440\u0430\u0442\u044C \u0443\u0436\u0435 \u0441\u0434\u0435\u043B\u0430\u043D\u043D\u043E\u0435 \u043C\u043E\u0436\u043D\u043E \u0432\u0441\u0435\u0433\u0434\u0430.`,
18635
- args: external_exports.object({
18636
- job: external_exports.string().describe(
18637
- "\u041D\u043E\u043C\u0435\u0440 \u0437\u0430\u0434\u0430\u0447\u0438, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 2026-08-19T14-03-12Z-a3f1. \u0415\u0433\u043E \u043D\u0430\u0437\u0432\u0430\u043B \u0442\u043E\u0442 \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442, \u0447\u0442\u043E \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u043B \u0440\u0430\u0431\u043E\u0442\u0443"
18638
- ).optional(),
18639
- seconds: external_exports.number().describe(
18640
- `\u0421\u043A\u043E\u043B\u044C\u043A\u043E \u0441\u0435\u043A\u0443\u043D\u0434 \u0436\u0434\u0430\u0442\u044C. \u041F\u043E\u0442\u043E\u043B\u043E\u043A ${WAIT_LIMIT_SECONDS}: \u043F\u0440\u043E\u0441\u044C\u0431\u0430 \u0431\u043E\u043B\u044C\u0448\u0435 \u043C\u043E\u043B\u0447\u0430 \u043E\u0431\u0440\u0435\u0436\u0435\u0442\u0441\u044F. \u0411\u0435\u0437 \u043D\u0435\u0433\u043E \u0436\u0434\u0451\u0442 \u0441\u0442\u043E\u043B\u044C\u043A\u043E, \u0441\u043A\u043E\u043B\u044C\u043A\u043E \u043C\u043E\u0436\u043D\u043E`
18641
- ).optional(),
18642
- video: external_exports.string().describe("\u0422\u043E\u043B\u044C\u043A\u043E \u0437\u0430\u0434\u0430\u0447\u0438 \u044D\u0442\u043E\u0433\u043E \u0440\u043E\u043B\u0438\u043A\u0430 (\u0431\u0435\u0437 job)").optional(),
18643
- limit: external_exports.number().describe("\u0421\u043A\u043E\u043B\u044C\u043A\u043E \u0437\u0430\u0434\u0430\u0447 \u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C, \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E 15").optional()
18644
- }).check((ctx) => {
18645
- const asked = ctx.value;
18646
- if (asked.job === void 0) {
18647
- if (asked.seconds !== void 0) {
18648
- ctx.issues.push({
18649
- code: "custom",
18650
- message: "\xABseconds\xBB \u2014 \u044D\u0442\u043E \u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0436\u0434\u0430\u0442\u044C \u041E\u0414\u041D\u0423 \u0437\u0430\u0434\u0430\u0447\u0443: \u043D\u0430\u0437\u043E\u0432\u0438 \u0435\u0451 \u043D\u043E\u043C\u0435\u0440 \u0432 \xABjob\xBB",
18651
- input: asked,
18652
- path: ["seconds"]
18653
- });
18654
- }
18655
- return;
18656
- }
18657
- for (const key of ["video", "limit"]) {
18658
- if (asked[key] !== void 0) {
18659
- ctx.issues.push({
18660
- code: "custom",
18661
- message: `\xAB${key}\xBB \u043E\u0442\u043D\u043E\u0441\u0438\u0442\u0441\u044F \u043A \u0421\u041F\u0418\u0421\u041A\u0423 \u0437\u0430\u0434\u0430\u0447, \u0430 \u0441 \xABjob\xBB \u0436\u0434\u0443\u0442 \u043E\u0434\u043D\u0443. \u041F\u043E\u0437\u043E\u0432\u0438 \u0431\u0435\u0437 \xABjob\xBB, \u0447\u0442\u043E\u0431\u044B \u0443\u0432\u0438\u0434\u0435\u0442\u044C \u0441\u043F\u0438\u0441\u043E\u043A`,
18662
- input: asked,
18663
- path: [key]
18664
- });
18665
- }
18666
- }
18667
- }),
18668
- readOnly: true,
18669
- async execute(args, ctx) {
18670
- const place = engine.place();
18671
- if (place === null) return toolError(engine.whyNoEngine());
18672
- if (args.job === void 0) {
18673
- return listJobs(engine, { video: args.video, limit: args.limit });
18674
- }
18675
- return followWork(engine, { job: args.job, seconds: args.seconds }, pace, ctx?.emitProgress);
18676
- }
18677
- });
18678
- }
18679
18389
  async function showFrame(engine, asked) {
18680
18390
  const video = asked.video;
18681
18391
  const moment = asked.moment;