editorbrain 0.31.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/bin/editorbrain.mjs +454 -259
- package/package.json +1 -1
- package/skill/editorbrain/SKILL.md +4 -2
- package/skill/editorbrain/references/cli-mcp.md +1 -1
- package/skill/editorbrain/references/production-continuity.md +93 -0
- package/skill/editorbrain/references/workspace-files.md +3 -1
- package/skill/editorbrain-formats/SKILL.md +51 -0
- package/skill/editorbrain-formats/references/aspirational-list-demo.md +140 -0
- package/skill/editorbrain-formats/references/numbered-tutorial.md +135 -0
package/bin/editorbrain.mjs
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// packages/cli/src/sfx.ts
|
|
4
|
-
import { readdir as readdir2, lstat as lstat3 } from "node:fs/promises";
|
|
5
|
-
import { join as join2, extname as extname2, basename } from "node:path";
|
|
6
|
-
|
|
7
3
|
// packages/core/src/creative-direction.ts
|
|
8
4
|
var creativePreferenceSections = [
|
|
9
5
|
{ id: "brand", title: "Marca y tipograf\xEDa", question: "\xBFConservamos tus colores, fuentes e idioma, o quieres ajustarlos?" },
|
|
@@ -57125,13 +57121,6 @@ function canonicalFiles(files) {
|
|
|
57125
57121
|
return result2;
|
|
57126
57122
|
}
|
|
57127
57123
|
|
|
57128
|
-
// packages/cli/src/media-runtime.ts
|
|
57129
|
-
import { spawn } from "node:child_process";
|
|
57130
|
-
import { createHash } from "node:crypto";
|
|
57131
|
-
import { constants } from "node:fs";
|
|
57132
|
-
import { lstat, open, realpath } from "node:fs/promises";
|
|
57133
|
-
import { dirname, extname, parse, resolve } from "node:path";
|
|
57134
|
-
|
|
57135
57124
|
// packages/cli/src/errors.ts
|
|
57136
57125
|
var CliError = class extends Error {
|
|
57137
57126
|
constructor(code, message, hint, retryable = false, details = {}) {
|
|
@@ -57154,7 +57143,346 @@ function errorOutput(error) {
|
|
|
57154
57143
|
return { error: safe, code: "COMMAND_FAILED", retryable: false, hint: "Read the command help and run editorbrain doctor. Do not retry writes blindly." };
|
|
57155
57144
|
}
|
|
57156
57145
|
|
|
57146
|
+
// packages/cli/src/production-output.ts
|
|
57147
|
+
import { constants as constants2 } from "node:fs";
|
|
57148
|
+
import { mkdir as mkdir2, open as open2 } from "node:fs/promises";
|
|
57149
|
+
import { dirname as dirname2 } from "node:path";
|
|
57150
|
+
|
|
57151
|
+
// packages/cli/src/io.ts
|
|
57152
|
+
import { constants } from "node:fs";
|
|
57153
|
+
import { lstat, mkdir, open, readdir, realpath, rename, unlink, link } from "node:fs/promises";
|
|
57154
|
+
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
57155
|
+
import { randomUUID } from "node:crypto";
|
|
57156
|
+
async function ensureRoot(directory, create = false) {
|
|
57157
|
+
const root = resolve(directory);
|
|
57158
|
+
if (create) await mkdir(root, { recursive: true });
|
|
57159
|
+
const info = await lstat(root);
|
|
57160
|
+
if (info.isSymbolicLink() || !info.isDirectory()) throw new Error("Workspace root must be a real directory, not a symlink");
|
|
57161
|
+
return realpath(root);
|
|
57162
|
+
}
|
|
57163
|
+
async function checkedPath(root, path, document2 = true) {
|
|
57164
|
+
if (document2) safeDocumentPath(path);
|
|
57165
|
+
const target = resolve(root, path);
|
|
57166
|
+
const rel = relative(root, target);
|
|
57167
|
+
if (!rel || rel.startsWith(`..${sep}`) || rel === ".." || resolve(path) === path) throw new Error("Path escapes workspace");
|
|
57168
|
+
let cursor = root;
|
|
57169
|
+
for (const segment of rel.split(sep)) {
|
|
57170
|
+
cursor = join(cursor, segment);
|
|
57171
|
+
try {
|
|
57172
|
+
const info = await lstat(cursor);
|
|
57173
|
+
if (info.isSymbolicLink()) throw new Error(`Symlinks are not allowed: ${path}`);
|
|
57174
|
+
} catch (error) {
|
|
57175
|
+
if (error.code !== "ENOENT") throw error;
|
|
57176
|
+
}
|
|
57177
|
+
}
|
|
57178
|
+
return target;
|
|
57179
|
+
}
|
|
57180
|
+
async function readText(root, path, document2 = true) {
|
|
57181
|
+
const target = await checkedPath(root, path, document2);
|
|
57182
|
+
const handle = await open(target, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
57183
|
+
try {
|
|
57184
|
+
const info = await handle.stat();
|
|
57185
|
+
if (!info.isFile()) throw new Error(`Not a regular file: ${path}`);
|
|
57186
|
+
if (document2 && info.size > MAX_DOCUMENT_BYTES) throw new Error(`Document exceeds 128 KiB: ${path}`);
|
|
57187
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(await handle.readFile());
|
|
57188
|
+
} finally {
|
|
57189
|
+
await handle.close();
|
|
57190
|
+
}
|
|
57191
|
+
}
|
|
57192
|
+
async function atomicWrite(root, path, content, options = {}) {
|
|
57193
|
+
const target = await checkedPath(root, path, options.document ?? true);
|
|
57194
|
+
await mkdir(dirname(target), { recursive: true });
|
|
57195
|
+
await checkedPath(root, path, options.document ?? true);
|
|
57196
|
+
const temporary = join(dirname(target), `.eh-${randomUUID()}.tmp`);
|
|
57197
|
+
const handle = await open(temporary, "wx", options.mode ?? 420);
|
|
57198
|
+
try {
|
|
57199
|
+
await handle.writeFile(content, "utf8");
|
|
57200
|
+
await handle.close();
|
|
57201
|
+
await checkedPath(root, path, options.document ?? true);
|
|
57202
|
+
if (options.overwrite === false) {
|
|
57203
|
+
await link(temporary, target);
|
|
57204
|
+
await unlink(temporary);
|
|
57205
|
+
} else await rename(temporary, target);
|
|
57206
|
+
} catch (error) {
|
|
57207
|
+
await handle.close().catch(() => {
|
|
57208
|
+
});
|
|
57209
|
+
await unlink(temporary).catch(() => {
|
|
57210
|
+
});
|
|
57211
|
+
throw error;
|
|
57212
|
+
}
|
|
57213
|
+
}
|
|
57214
|
+
async function readWorkspace(root) {
|
|
57215
|
+
const files = /* @__PURE__ */ Object.create(null);
|
|
57216
|
+
async function walk(path) {
|
|
57217
|
+
const directory = await checkedPath(root, path, false);
|
|
57218
|
+
let entries;
|
|
57219
|
+
try {
|
|
57220
|
+
entries = await readdir(directory, { withFileTypes: true });
|
|
57221
|
+
} catch (error) {
|
|
57222
|
+
if (error.code === "ENOENT") return;
|
|
57223
|
+
throw error;
|
|
57224
|
+
}
|
|
57225
|
+
for (const entry of entries) {
|
|
57226
|
+
const child = `${path}/${entry.name}`;
|
|
57227
|
+
if (entry.isSymbolicLink()) throw new Error(`Symlinks are not allowed: ${child}`);
|
|
57228
|
+
if (entry.name.startsWith(".")) continue;
|
|
57229
|
+
if (entry.isDirectory()) {
|
|
57230
|
+
if (path.startsWith("videos/") && ["assets", "renders"].includes(entry.name)) continue;
|
|
57231
|
+
await walk(child);
|
|
57232
|
+
} else if (entry.isFile() && /\.(json|md)$/.test(entry.name)) {
|
|
57233
|
+
safeDocumentPath(child);
|
|
57234
|
+
files[child] = await readText(root, child);
|
|
57235
|
+
}
|
|
57236
|
+
}
|
|
57237
|
+
}
|
|
57238
|
+
await walk(".editorharness");
|
|
57239
|
+
await walk(".editorbrain");
|
|
57240
|
+
await walk("videos");
|
|
57241
|
+
return canonicalFiles(files);
|
|
57242
|
+
}
|
|
57243
|
+
async function readProjectWorkspace(root, projectId) {
|
|
57244
|
+
assertIdentifier(projectId);
|
|
57245
|
+
const projectPath = `videos/${projectId}/project.json`;
|
|
57246
|
+
const projectContent = await readText(root, projectPath);
|
|
57247
|
+
const checked = validateDocument(projectPath, projectContent);
|
|
57248
|
+
if (!checked.valid) throw new ValidationError(checked.issues);
|
|
57249
|
+
const project = JSON.parse(projectContent);
|
|
57250
|
+
const files = { [projectPath]: projectContent };
|
|
57251
|
+
for (const path of /* @__PURE__ */ new Set([...projectSources(project), ...optionalProjectSources(project)])) {
|
|
57252
|
+
if (path === projectPath) continue;
|
|
57253
|
+
const aliases2 = path.startsWith(".editorbrain/") ? [path, path.replace(/^\.editorbrain\//, ".editorharness/")] : [path];
|
|
57254
|
+
for (const alias of aliases2) {
|
|
57255
|
+
try {
|
|
57256
|
+
files[alias] = await readText(root, alias);
|
|
57257
|
+
} catch (error) {
|
|
57258
|
+
if (error.code !== "ENOENT") throw error;
|
|
57259
|
+
}
|
|
57260
|
+
}
|
|
57261
|
+
}
|
|
57262
|
+
if (await readText(root, projectPath) !== projectContent) throw new Error("The selected project changed while reading its context. Retry before editing.");
|
|
57263
|
+
return canonicalFiles(files);
|
|
57264
|
+
}
|
|
57265
|
+
|
|
57266
|
+
// packages/cli/src/production-output.ts
|
|
57267
|
+
async function productionOutputPath(root, relativePath) {
|
|
57268
|
+
if (!relativePath.startsWith(".editorbrain-local/") || relativePath.split(/[\\/]/).some((p) => !p || p === ".." || p === ".") || /[\\\x00-\x1f\x7f]/.test(relativePath)) {
|
|
57269
|
+
throw new CliError("LOCAL_OUTPUT_REQUIRED", "Production output must be inside .editorbrain-local/.", "Use --out .editorbrain-local/<project>/inventory.json, or omit --out for JSON stdout. These reports are not synced.");
|
|
57270
|
+
}
|
|
57271
|
+
return checkedPath(root, relativePath, false);
|
|
57272
|
+
}
|
|
57273
|
+
async function prepareSampleDirectory(root, path) {
|
|
57274
|
+
const target = await productionOutputPath(root, path);
|
|
57275
|
+
await mkdir2(dirname2(target), { recursive: true });
|
|
57276
|
+
await productionOutputPath(root, path);
|
|
57277
|
+
return target;
|
|
57278
|
+
}
|
|
57279
|
+
async function readProductionJson(root, path) {
|
|
57280
|
+
const target = await checkedPath(root, path, false);
|
|
57281
|
+
const handle = await open2(target, constants2.O_RDONLY | constants2.O_NOFOLLOW | constants2.O_NONBLOCK);
|
|
57282
|
+
try {
|
|
57283
|
+
const stat = await handle.stat();
|
|
57284
|
+
if (!stat.isFile() || stat.size > 16 * 1024 * 1024) throw new CliError("INVALID_REPORT", "Expected a regular JSON file of at most 16 MiB.", "Select a local inventory, plan or check profile.");
|
|
57285
|
+
return JSON.parse(await handle.readFile("utf8"));
|
|
57286
|
+
} finally {
|
|
57287
|
+
await handle.close();
|
|
57288
|
+
}
|
|
57289
|
+
}
|
|
57290
|
+
async function saveProductionReport(root, path, report) {
|
|
57291
|
+
const target = await productionOutputPath(root, path);
|
|
57292
|
+
if (!path.endsWith(".json")) throw new CliError("INVALID_ARGUMENT", "Report output needs a .json extension.", "Use a new path under .editorbrain-local/.");
|
|
57293
|
+
await atomicWrite(root, path, stableJson(report), { document: false, overwrite: false, mode: 384 });
|
|
57294
|
+
return target;
|
|
57295
|
+
}
|
|
57296
|
+
function summarizeProductionReport(value) {
|
|
57297
|
+
const r = value;
|
|
57298
|
+
const base = { schemaVersion: r.schemaVersion, kind: r.kind, summary: true, mediaUploaded: false, quality: "not_assessed" };
|
|
57299
|
+
if (r.kind === "editorbrain.media-inventory") return {
|
|
57300
|
+
...base,
|
|
57301
|
+
complete: r.complete,
|
|
57302
|
+
contentReviewed: false,
|
|
57303
|
+
counts: { assets: r.assets.length, failures: r.failures.length, skipped: r.skipped.length },
|
|
57304
|
+
assets: r.assets.slice(0, 8),
|
|
57305
|
+
failures: r.failures.slice(0, 5),
|
|
57306
|
+
omitted: { assets: Math.max(0, r.assets.length - 8), failures: Math.max(0, r.failures.length - 5), skipped: r.skipped.length },
|
|
57307
|
+
next: "Inspect selected source content. Use media sample for specific frames. Read the saved report or rerun with --details for omitted metadata; no content was reviewed automatically."
|
|
57308
|
+
};
|
|
57309
|
+
if (r.kind === "editorbrain.media-samples") return { ...base, sourceSha256: r.source.sha256, frames: r.frames, contentReviewed: false, next: "View these frames to inspect composition. They do not prove motion or sound." };
|
|
57310
|
+
if (r.kind === "editorbrain.production-plan-check") return {
|
|
57311
|
+
...base,
|
|
57312
|
+
valid: r.valid,
|
|
57313
|
+
inventoryComplete: r.inventoryComplete,
|
|
57314
|
+
observations: r.observations,
|
|
57315
|
+
sourceFilesReverified: false,
|
|
57316
|
+
counts: { sources: r.coverage.length, findings: r.findings.length, repeatedPairs: r.repeatedPairs ?? 0 },
|
|
57317
|
+
findings: [...r.findings].sort((a, b) => ({ error: 0, warning: 1, info: 2 })[a.severity] - { error: 0, warning: 1, info: 2 }[b.severity]).slice(0, 8),
|
|
57318
|
+
omittedFindings: Math.max(0, r.findings.length - 8),
|
|
57319
|
+
next: "Review source reuse and inspection gaps in the saved report. Observations are agent-declared, not independently certified."
|
|
57320
|
+
};
|
|
57321
|
+
if (r.kind === "editorbrain.render-check") return {
|
|
57322
|
+
...base,
|
|
57323
|
+
complete: r.complete,
|
|
57324
|
+
technicalStatus: r.technicalStatus,
|
|
57325
|
+
file: r.file,
|
|
57326
|
+
checks: r.checks,
|
|
57327
|
+
findings: r.findings.slice(0, 8),
|
|
57328
|
+
findingsSummary: r.findingsSummary,
|
|
57329
|
+
omittedFindings: Math.max(0, r.findings.length - 8),
|
|
57330
|
+
next: "Reconcile technical candidates with the brief; inspect the actual video/audio. Technical checks do not assess narrative, aesthetics or SFX audibility."
|
|
57331
|
+
};
|
|
57332
|
+
if (r.kind === "editorbrain.media-source-search") return {
|
|
57333
|
+
...base,
|
|
57334
|
+
complete: r.complete,
|
|
57335
|
+
results: r.results.slice(0, 5).map((item) => ({ provider: item.provider, id: item.id.slice(0, 180), title: item.title.slice(0, 180), sourceUrl: item.sourceUrl.length <= 1500 ? item.sourceUrl : null, author: item.author?.slice(0, 120) ?? null, license: { id: item.license.id, reason: item.license.reason, url: item.license.url && item.license.url.length <= 500 ? item.license.url : null }, contentReviewed: false, rightsVerified: false })),
|
|
57336
|
+
metadataAbbreviated: true,
|
|
57337
|
+
failures: r.failures.slice(0, 5),
|
|
57338
|
+
counts: r.counts,
|
|
57339
|
+
omitted: { results: Math.max(0, r.results.length - 5), failures: Math.max(0, r.failures.length - 5) },
|
|
57340
|
+
searchExhaustive: false,
|
|
57341
|
+
rightsVerified: false,
|
|
57342
|
+
next: "Inspect relevant source pages and media. These archives supplement web image/video search; empty results do not prove absence on the internet."
|
|
57343
|
+
};
|
|
57344
|
+
if (r.kind === "editorbrain.evidence-check") return {
|
|
57345
|
+
...base,
|
|
57346
|
+
valid: r.valid,
|
|
57347
|
+
inventoryComplete: r.inventoryComplete,
|
|
57348
|
+
observations: r.observations,
|
|
57349
|
+
sourceFilesReverified: false,
|
|
57350
|
+
factualTruth: "not_assessed",
|
|
57351
|
+
reuseRights: "not_assessed",
|
|
57352
|
+
findings: r.findings.slice(0, 8),
|
|
57353
|
+
omitted: { findings: Math.max(0, r.findings.length - 8) }
|
|
57354
|
+
};
|
|
57355
|
+
if (r.kind === "editorbrain.audio-check") return {
|
|
57356
|
+
...base,
|
|
57357
|
+
complete: r.complete,
|
|
57358
|
+
technicalStatus: r.technicalStatus,
|
|
57359
|
+
file: r.file,
|
|
57360
|
+
fileStable: r.fileStable,
|
|
57361
|
+
coverage: r.coverage,
|
|
57362
|
+
measurements: r.measurements.slice(0, 8),
|
|
57363
|
+
errorCode: r.errorCode,
|
|
57364
|
+
creativeQuality: r.creativeQuality,
|
|
57365
|
+
omitted: { measurements: Math.max(0, r.measurements.length - 8) },
|
|
57366
|
+
next: "Measurements describe this exact file. Listen for intelligibility, pronunciation, SFX and sync when the modality is available."
|
|
57367
|
+
};
|
|
57368
|
+
if (r.kind === "editorbrain.motion-review") return {
|
|
57369
|
+
...base,
|
|
57370
|
+
samples: r.samples ? { frameCount: r.samples.frameCount, fps: r.samples.fps, radiusFrames: r.samples.radiusFrames, samples: r.samples.samples.slice(0, 12), omittedSamples: Math.max(0, r.samples.samples.length - 12) } : null,
|
|
57371
|
+
geometryReviews: r.geometryReviews.slice(0, 3).map((g) => ({ scope: g.scope, status: g.status, candidates: g.candidates.slice(0, 8), omittedCandidates: Math.max(0, g.candidates.length - 8), checks: g.checks })),
|
|
57372
|
+
omittedGeometryReviews: Math.max(0, r.geometryReviews.length - 3),
|
|
57373
|
+
next: "This plans samples and checks declared boxes only. Render/view those frames; read saved details for omitted candidates and intentional overlaps."
|
|
57374
|
+
};
|
|
57375
|
+
throw new CliError("INVALID_REPORT", "Unknown production report kind.", "Use media inventory/sample or production check/plan-check.");
|
|
57376
|
+
}
|
|
57377
|
+
|
|
57378
|
+
// packages/cli/src/editing-batches.ts
|
|
57379
|
+
async function batchCommand(client, root, command, argument, flags) {
|
|
57380
|
+
const fail2 = () => {
|
|
57381
|
+
throw new CliError(
|
|
57382
|
+
"INVALID_ARGUMENT",
|
|
57383
|
+
"Use batches list/get/create/pause/resume/cancel/retry/detach/claim/renew/release/attention.",
|
|
57384
|
+
"Create with --file batch.json; updates need --expected-revision; leases need --project and --lease-token UUID."
|
|
57385
|
+
);
|
|
57386
|
+
};
|
|
57387
|
+
const lease = ["claim", "renew", "release", "attention"].includes(command), update = ["pause", "resume", "cancel", "retry", "detach"].includes(command);
|
|
57388
|
+
if (!["list", "get", "create"].includes(command) && !lease && !update) fail2();
|
|
57389
|
+
const allowed = [
|
|
57390
|
+
"dir",
|
|
57391
|
+
"url",
|
|
57392
|
+
...command === "create" ? ["file"] : command === "list" ? ["after"] : lease ? ["project", "lease-token"] : update ? [
|
|
57393
|
+
"expected-revision",
|
|
57394
|
+
...["retry", "detach"].includes(command) ? ["project"] : []
|
|
57395
|
+
] : []
|
|
57396
|
+
];
|
|
57397
|
+
for (const key of Object.keys(flags)) if (!allowed.includes(key)) fail2();
|
|
57398
|
+
if (command === "list") {
|
|
57399
|
+
if (argument) fail2();
|
|
57400
|
+
return client.request(
|
|
57401
|
+
"/v1/batches" + (typeof flags.after === "string" ? "?after=" + encodeURIComponent(flags.after) : "")
|
|
57402
|
+
);
|
|
57403
|
+
}
|
|
57404
|
+
if (command === "create") {
|
|
57405
|
+
if (argument || typeof flags.file !== "string") fail2();
|
|
57406
|
+
const body = await readProductionJson(root, flags.file);
|
|
57407
|
+
return client.request("/v1/batches", { method: "POST", body });
|
|
57408
|
+
}
|
|
57409
|
+
if (!argument || !/^[a-f0-9-]{36}$/i.test(argument)) fail2();
|
|
57410
|
+
const path = "/v1/batches/" + argument;
|
|
57411
|
+
if (command === "get") return client.request(path);
|
|
57412
|
+
if (update) {
|
|
57413
|
+
const revision = Number(flags["expected-revision"]);
|
|
57414
|
+
if (!Number.isSafeInteger(revision) || revision < 1 || ["retry", "detach"].includes(command) && typeof flags.project !== "string")
|
|
57415
|
+
fail2();
|
|
57416
|
+
return client.request(path, {
|
|
57417
|
+
method: "POST",
|
|
57418
|
+
body: {
|
|
57419
|
+
action: command,
|
|
57420
|
+
expectedRevision: revision,
|
|
57421
|
+
...["retry", "detach"].includes(command) ? { projectId: flags.project } : {}
|
|
57422
|
+
}
|
|
57423
|
+
});
|
|
57424
|
+
}
|
|
57425
|
+
if (typeof flags.project !== "string" || !/^[a-z0-9][a-z0-9_-]{0,79}$/.test(flags.project) || typeof flags["lease-token"] !== "string" || !/^[a-f0-9-]{36}$/i.test(flags["lease-token"]))
|
|
57426
|
+
fail2();
|
|
57427
|
+
return client.request(path + "/lease", {
|
|
57428
|
+
method: "POST",
|
|
57429
|
+
body: {
|
|
57430
|
+
action: command,
|
|
57431
|
+
projectId: flags.project,
|
|
57432
|
+
leaseToken: flags["lease-token"]
|
|
57433
|
+
}
|
|
57434
|
+
});
|
|
57435
|
+
}
|
|
57436
|
+
|
|
57437
|
+
// packages/cli/src/project-progress-client.ts
|
|
57438
|
+
async function projectProgressCommand(client, command, flags) {
|
|
57439
|
+
const fail2 = (message) => {
|
|
57440
|
+
throw new CliError(
|
|
57441
|
+
"INVALID_ARGUMENT",
|
|
57442
|
+
message,
|
|
57443
|
+
"Use projects progress/start/queue/complete --project ID. Read progress first; pass --expected-version HASH for changes."
|
|
57444
|
+
);
|
|
57445
|
+
};
|
|
57446
|
+
if (!["progress", "start", "queue", "complete"].includes(command))
|
|
57447
|
+
fail2("Unknown project command.");
|
|
57448
|
+
const allowed = [
|
|
57449
|
+
"project",
|
|
57450
|
+
"url",
|
|
57451
|
+
"dir",
|
|
57452
|
+
...command === "progress" ? [] : ["expected-version"],
|
|
57453
|
+
...command === "complete" ? ["revision", "user-confirmed"] : []
|
|
57454
|
+
];
|
|
57455
|
+
for (const name of Object.keys(flags))
|
|
57456
|
+
if (!allowed.includes(name)) fail2(`Unsupported flag --${name}.`);
|
|
57457
|
+
if (typeof flags.project !== "string") fail2("--project is required.");
|
|
57458
|
+
const project = assertIdentifier(flags.project), path = `/v1/projects/${encodeURIComponent(project)}/progress`;
|
|
57459
|
+
if (command === "progress") return client.request(path);
|
|
57460
|
+
if (typeof flags["expected-version"] !== "string" || !/^[a-f0-9]{64}$/.test(flags["expected-version"]))
|
|
57461
|
+
fail2("--expected-version must be the current progress version.");
|
|
57462
|
+
if (command === "complete" && (typeof flags.revision !== "string" || !/^[a-f0-9-]{36}$/.test(flags.revision) || flags["user-confirmed"] !== true))
|
|
57463
|
+
fail2(
|
|
57464
|
+
"Completion requires --revision UUID and --user-confirmed after explicit final-video approval."
|
|
57465
|
+
);
|
|
57466
|
+
return client.request(path, {
|
|
57467
|
+
method: "POST",
|
|
57468
|
+
body: {
|
|
57469
|
+
action: command,
|
|
57470
|
+
expectedVersion: flags["expected-version"],
|
|
57471
|
+
...command === "complete" ? { revisionId: flags.revision, userConfirmed: true } : {}
|
|
57472
|
+
}
|
|
57473
|
+
});
|
|
57474
|
+
}
|
|
57475
|
+
|
|
57476
|
+
// packages/cli/src/sfx.ts
|
|
57477
|
+
import { readdir as readdir2, lstat as lstat3 } from "node:fs/promises";
|
|
57478
|
+
import { join as join2, extname as extname2, basename } from "node:path";
|
|
57479
|
+
|
|
57157
57480
|
// packages/cli/src/media-runtime.ts
|
|
57481
|
+
import { spawn } from "node:child_process";
|
|
57482
|
+
import { createHash } from "node:crypto";
|
|
57483
|
+
import { constants as constants3 } from "node:fs";
|
|
57484
|
+
import { lstat as lstat2, open as open3, realpath as realpath2 } from "node:fs/promises";
|
|
57485
|
+
import { dirname as dirname3, extname, parse, resolve as resolve2 } from "node:path";
|
|
57158
57486
|
var MediaToolError = class extends CliError {
|
|
57159
57487
|
constructor(code, message) {
|
|
57160
57488
|
super(code, message, code === "MEDIA_TOOL_NOT_FOUND" ? "Install FFmpeg/FFprobe separately and make them available on PATH; no account or model is needed." : "Review the local input and reported limit. An incomplete check does not validate the media.");
|
|
@@ -57206,24 +57534,24 @@ function resolveLocalMediaPath(value) {
|
|
|
57206
57534
|
if (!value || value.includes("\0") || /[\r\n]/.test(value) || /^[a-z][a-z\d+.-]*:/i.test(value) && !(process.platform === "win32" && /^[a-z]:[\\/]/i.test(value)) || value.startsWith("\\\\")) {
|
|
57207
57535
|
throw new MediaToolError("MEDIA_LOCAL_PATH_REQUIRED", "Provide a local filesystem path, not a URL, protocol or network share.");
|
|
57208
57536
|
}
|
|
57209
|
-
return
|
|
57537
|
+
return resolve2(value);
|
|
57210
57538
|
}
|
|
57211
57539
|
async function assertNoMediaSymlinks(value) {
|
|
57212
57540
|
const path = resolveLocalMediaPath(value);
|
|
57213
57541
|
let cursor = path;
|
|
57214
57542
|
while (cursor !== parse(cursor).root) {
|
|
57215
|
-
const info = await
|
|
57543
|
+
const info = await lstat2(cursor);
|
|
57216
57544
|
if (info.isSymbolicLink()) {
|
|
57217
|
-
const systemAlias = process.platform === "darwin" && (cursor === "/tmp" || cursor === "/var") && await
|
|
57545
|
+
const systemAlias = process.platform === "darwin" && (cursor === "/tmp" || cursor === "/var") && await realpath2(cursor) === `/private${cursor}`;
|
|
57218
57546
|
if (!systemAlias) throw new MediaToolError("MEDIA_SYMLINK", "Symlink media paths are not followed. Use the original local path.");
|
|
57219
57547
|
}
|
|
57220
|
-
cursor =
|
|
57548
|
+
cursor = dirname3(cursor);
|
|
57221
57549
|
}
|
|
57222
57550
|
return path;
|
|
57223
57551
|
}
|
|
57224
57552
|
async function assertLocalMediaFile(value) {
|
|
57225
57553
|
const path = await assertNoMediaSymlinks(value);
|
|
57226
|
-
const info = await
|
|
57554
|
+
const info = await lstat2(path);
|
|
57227
57555
|
if (!info.isFile()) throw new MediaToolError("MEDIA_NOT_REGULAR", "The media input must be a regular local file.");
|
|
57228
57556
|
if (!SUPPORTED_MEDIA_EXTENSIONS.has(extname(path).toLowerCase())) throw new MediaToolError("MEDIA_FORMAT_UNSUPPORTED", "This file extension is not supported for local media inspection.");
|
|
57229
57557
|
return path;
|
|
@@ -57308,7 +57636,7 @@ var rate2 = (value) => {
|
|
|
57308
57636
|
var sameFile = (a, b) => a.dev === b.dev && a.ino === b.ino && a.size === b.size && a.mtimeMs === b.mtimeMs && a.ctimeMs === b.ctimeMs;
|
|
57309
57637
|
async function probeLocalMedia(value) {
|
|
57310
57638
|
const path = await assertLocalMediaFile(value);
|
|
57311
|
-
const handle = await
|
|
57639
|
+
const handle = await open3(path, constants3.O_RDONLY | (constants3.O_NOFOLLOW ?? 0));
|
|
57312
57640
|
try {
|
|
57313
57641
|
const before = await handle.stat();
|
|
57314
57642
|
if (!before.isFile()) throw new MediaToolError("MEDIA_NOT_REGULAR", "The media input must be a regular local file.");
|
|
@@ -57318,7 +57646,7 @@ async function probeLocalMedia(value) {
|
|
|
57318
57646
|
for await (const chunk of handle.createReadStream({ autoClose: false })) hash6.update(chunk);
|
|
57319
57647
|
const after = await handle.stat();
|
|
57320
57648
|
await assertNoMediaSymlinks(path);
|
|
57321
|
-
const current2 = await
|
|
57649
|
+
const current2 = await lstat2(path);
|
|
57322
57650
|
if (!sameFile(before, after) || !sameFile(after, current2)) throw new MediaToolError("MEDIA_FILE_CHANGED", "The media file changed while it was being inspected. Retry with a stable source.");
|
|
57323
57651
|
let raw;
|
|
57324
57652
|
try {
|
|
@@ -57346,121 +57674,6 @@ async function probeLocalMedia(value) {
|
|
|
57346
57674
|
}
|
|
57347
57675
|
}
|
|
57348
57676
|
|
|
57349
|
-
// packages/cli/src/io.ts
|
|
57350
|
-
import { constants as constants2 } from "node:fs";
|
|
57351
|
-
import { lstat as lstat2, mkdir, open as open2, readdir, realpath as realpath2, rename, unlink, link } from "node:fs/promises";
|
|
57352
|
-
import { dirname as dirname2, join, relative, resolve as resolve2, sep } from "node:path";
|
|
57353
|
-
import { randomUUID } from "node:crypto";
|
|
57354
|
-
async function ensureRoot(directory, create = false) {
|
|
57355
|
-
const root = resolve2(directory);
|
|
57356
|
-
if (create) await mkdir(root, { recursive: true });
|
|
57357
|
-
const info = await lstat2(root);
|
|
57358
|
-
if (info.isSymbolicLink() || !info.isDirectory()) throw new Error("Workspace root must be a real directory, not a symlink");
|
|
57359
|
-
return realpath2(root);
|
|
57360
|
-
}
|
|
57361
|
-
async function checkedPath(root, path, document2 = true) {
|
|
57362
|
-
if (document2) safeDocumentPath(path);
|
|
57363
|
-
const target = resolve2(root, path);
|
|
57364
|
-
const rel = relative(root, target);
|
|
57365
|
-
if (!rel || rel.startsWith(`..${sep}`) || rel === ".." || resolve2(path) === path) throw new Error("Path escapes workspace");
|
|
57366
|
-
let cursor = root;
|
|
57367
|
-
for (const segment of rel.split(sep)) {
|
|
57368
|
-
cursor = join(cursor, segment);
|
|
57369
|
-
try {
|
|
57370
|
-
const info = await lstat2(cursor);
|
|
57371
|
-
if (info.isSymbolicLink()) throw new Error(`Symlinks are not allowed: ${path}`);
|
|
57372
|
-
} catch (error) {
|
|
57373
|
-
if (error.code !== "ENOENT") throw error;
|
|
57374
|
-
}
|
|
57375
|
-
}
|
|
57376
|
-
return target;
|
|
57377
|
-
}
|
|
57378
|
-
async function readText(root, path, document2 = true) {
|
|
57379
|
-
const target = await checkedPath(root, path, document2);
|
|
57380
|
-
const handle = await open2(target, constants2.O_RDONLY | constants2.O_NOFOLLOW);
|
|
57381
|
-
try {
|
|
57382
|
-
const info = await handle.stat();
|
|
57383
|
-
if (!info.isFile()) throw new Error(`Not a regular file: ${path}`);
|
|
57384
|
-
if (document2 && info.size > MAX_DOCUMENT_BYTES) throw new Error(`Document exceeds 128 KiB: ${path}`);
|
|
57385
|
-
return new TextDecoder("utf-8", { fatal: true }).decode(await handle.readFile());
|
|
57386
|
-
} finally {
|
|
57387
|
-
await handle.close();
|
|
57388
|
-
}
|
|
57389
|
-
}
|
|
57390
|
-
async function atomicWrite(root, path, content, options = {}) {
|
|
57391
|
-
const target = await checkedPath(root, path, options.document ?? true);
|
|
57392
|
-
await mkdir(dirname2(target), { recursive: true });
|
|
57393
|
-
await checkedPath(root, path, options.document ?? true);
|
|
57394
|
-
const temporary = join(dirname2(target), `.eh-${randomUUID()}.tmp`);
|
|
57395
|
-
const handle = await open2(temporary, "wx", options.mode ?? 420);
|
|
57396
|
-
try {
|
|
57397
|
-
await handle.writeFile(content, "utf8");
|
|
57398
|
-
await handle.close();
|
|
57399
|
-
await checkedPath(root, path, options.document ?? true);
|
|
57400
|
-
if (options.overwrite === false) {
|
|
57401
|
-
await link(temporary, target);
|
|
57402
|
-
await unlink(temporary);
|
|
57403
|
-
} else await rename(temporary, target);
|
|
57404
|
-
} catch (error) {
|
|
57405
|
-
await handle.close().catch(() => {
|
|
57406
|
-
});
|
|
57407
|
-
await unlink(temporary).catch(() => {
|
|
57408
|
-
});
|
|
57409
|
-
throw error;
|
|
57410
|
-
}
|
|
57411
|
-
}
|
|
57412
|
-
async function readWorkspace(root) {
|
|
57413
|
-
const files = /* @__PURE__ */ Object.create(null);
|
|
57414
|
-
async function walk(path) {
|
|
57415
|
-
const directory = await checkedPath(root, path, false);
|
|
57416
|
-
let entries;
|
|
57417
|
-
try {
|
|
57418
|
-
entries = await readdir(directory, { withFileTypes: true });
|
|
57419
|
-
} catch (error) {
|
|
57420
|
-
if (error.code === "ENOENT") return;
|
|
57421
|
-
throw error;
|
|
57422
|
-
}
|
|
57423
|
-
for (const entry of entries) {
|
|
57424
|
-
const child = `${path}/${entry.name}`;
|
|
57425
|
-
if (entry.isSymbolicLink()) throw new Error(`Symlinks are not allowed: ${child}`);
|
|
57426
|
-
if (entry.name.startsWith(".")) continue;
|
|
57427
|
-
if (entry.isDirectory()) {
|
|
57428
|
-
if (path.startsWith("videos/") && ["assets", "renders"].includes(entry.name)) continue;
|
|
57429
|
-
await walk(child);
|
|
57430
|
-
} else if (entry.isFile() && /\.(json|md)$/.test(entry.name)) {
|
|
57431
|
-
safeDocumentPath(child);
|
|
57432
|
-
files[child] = await readText(root, child);
|
|
57433
|
-
}
|
|
57434
|
-
}
|
|
57435
|
-
}
|
|
57436
|
-
await walk(".editorharness");
|
|
57437
|
-
await walk(".editorbrain");
|
|
57438
|
-
await walk("videos");
|
|
57439
|
-
return canonicalFiles(files);
|
|
57440
|
-
}
|
|
57441
|
-
async function readProjectWorkspace(root, projectId) {
|
|
57442
|
-
assertIdentifier(projectId);
|
|
57443
|
-
const projectPath = `videos/${projectId}/project.json`;
|
|
57444
|
-
const projectContent = await readText(root, projectPath);
|
|
57445
|
-
const checked = validateDocument(projectPath, projectContent);
|
|
57446
|
-
if (!checked.valid) throw new ValidationError(checked.issues);
|
|
57447
|
-
const project = JSON.parse(projectContent);
|
|
57448
|
-
const files = { [projectPath]: projectContent };
|
|
57449
|
-
for (const path of /* @__PURE__ */ new Set([...projectSources(project), ...optionalProjectSources(project)])) {
|
|
57450
|
-
if (path === projectPath) continue;
|
|
57451
|
-
const aliases2 = path.startsWith(".editorbrain/") ? [path, path.replace(/^\.editorbrain\//, ".editorharness/")] : [path];
|
|
57452
|
-
for (const alias of aliases2) {
|
|
57453
|
-
try {
|
|
57454
|
-
files[alias] = await readText(root, alias);
|
|
57455
|
-
} catch (error) {
|
|
57456
|
-
if (error.code !== "ENOENT") throw error;
|
|
57457
|
-
}
|
|
57458
|
-
}
|
|
57459
|
-
}
|
|
57460
|
-
if (await readText(root, projectPath) !== projectContent) throw new Error("The selected project changed while reading its context. Retry before editing.");
|
|
57461
|
-
return canonicalFiles(files);
|
|
57462
|
-
}
|
|
57463
|
-
|
|
57464
57677
|
// packages/cli/src/production-context.ts
|
|
57465
57678
|
async function prepareProductionContext(root, projectId, client) {
|
|
57466
57679
|
const resolved = await resolveProject(await readProjectWorkspace(root, projectId), projectId);
|
|
@@ -57561,123 +57774,6 @@ async function remoteSfx(client, subcommand, params) {
|
|
|
57561
57774
|
// packages/cli/src/media-preview.ts
|
|
57562
57775
|
import { chmod, link as link2, mkdtemp, rm } from "node:fs/promises";
|
|
57563
57776
|
import { dirname as dirname4, join as join3 } from "node:path";
|
|
57564
|
-
|
|
57565
|
-
// packages/cli/src/production-output.ts
|
|
57566
|
-
import { constants as constants3 } from "node:fs";
|
|
57567
|
-
import { mkdir as mkdir2, open as open3 } from "node:fs/promises";
|
|
57568
|
-
import { dirname as dirname3 } from "node:path";
|
|
57569
|
-
async function productionOutputPath(root, relativePath) {
|
|
57570
|
-
if (!relativePath.startsWith(".editorbrain-local/") || relativePath.split(/[\\/]/).some((p) => !p || p === ".." || p === ".") || /[\\\x00-\x1f\x7f]/.test(relativePath)) {
|
|
57571
|
-
throw new CliError("LOCAL_OUTPUT_REQUIRED", "Production output must be inside .editorbrain-local/.", "Use --out .editorbrain-local/<project>/inventory.json, or omit --out for JSON stdout. These reports are not synced.");
|
|
57572
|
-
}
|
|
57573
|
-
return checkedPath(root, relativePath, false);
|
|
57574
|
-
}
|
|
57575
|
-
async function prepareSampleDirectory(root, path) {
|
|
57576
|
-
const target = await productionOutputPath(root, path);
|
|
57577
|
-
await mkdir2(dirname3(target), { recursive: true });
|
|
57578
|
-
await productionOutputPath(root, path);
|
|
57579
|
-
return target;
|
|
57580
|
-
}
|
|
57581
|
-
async function readProductionJson(root, path) {
|
|
57582
|
-
const target = await checkedPath(root, path, false);
|
|
57583
|
-
const handle = await open3(target, constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK);
|
|
57584
|
-
try {
|
|
57585
|
-
const stat = await handle.stat();
|
|
57586
|
-
if (!stat.isFile() || stat.size > 16 * 1024 * 1024) throw new CliError("INVALID_REPORT", "Expected a regular JSON file of at most 16 MiB.", "Select a local inventory, plan or check profile.");
|
|
57587
|
-
return JSON.parse(await handle.readFile("utf8"));
|
|
57588
|
-
} finally {
|
|
57589
|
-
await handle.close();
|
|
57590
|
-
}
|
|
57591
|
-
}
|
|
57592
|
-
async function saveProductionReport(root, path, report) {
|
|
57593
|
-
const target = await productionOutputPath(root, path);
|
|
57594
|
-
if (!path.endsWith(".json")) throw new CliError("INVALID_ARGUMENT", "Report output needs a .json extension.", "Use a new path under .editorbrain-local/.");
|
|
57595
|
-
await atomicWrite(root, path, stableJson(report), { document: false, overwrite: false, mode: 384 });
|
|
57596
|
-
return target;
|
|
57597
|
-
}
|
|
57598
|
-
function summarizeProductionReport(value) {
|
|
57599
|
-
const r = value;
|
|
57600
|
-
const base = { schemaVersion: r.schemaVersion, kind: r.kind, summary: true, mediaUploaded: false, quality: "not_assessed" };
|
|
57601
|
-
if (r.kind === "editorbrain.media-inventory") return {
|
|
57602
|
-
...base,
|
|
57603
|
-
complete: r.complete,
|
|
57604
|
-
contentReviewed: false,
|
|
57605
|
-
counts: { assets: r.assets.length, failures: r.failures.length, skipped: r.skipped.length },
|
|
57606
|
-
assets: r.assets.slice(0, 8),
|
|
57607
|
-
failures: r.failures.slice(0, 5),
|
|
57608
|
-
omitted: { assets: Math.max(0, r.assets.length - 8), failures: Math.max(0, r.failures.length - 5), skipped: r.skipped.length },
|
|
57609
|
-
next: "Inspect selected source content. Use media sample for specific frames. Read the saved report or rerun with --details for omitted metadata; no content was reviewed automatically."
|
|
57610
|
-
};
|
|
57611
|
-
if (r.kind === "editorbrain.media-samples") return { ...base, sourceSha256: r.source.sha256, frames: r.frames, contentReviewed: false, next: "View these frames to inspect composition. They do not prove motion or sound." };
|
|
57612
|
-
if (r.kind === "editorbrain.production-plan-check") return {
|
|
57613
|
-
...base,
|
|
57614
|
-
valid: r.valid,
|
|
57615
|
-
inventoryComplete: r.inventoryComplete,
|
|
57616
|
-
observations: r.observations,
|
|
57617
|
-
sourceFilesReverified: false,
|
|
57618
|
-
counts: { sources: r.coverage.length, findings: r.findings.length, repeatedPairs: r.repeatedPairs ?? 0 },
|
|
57619
|
-
findings: [...r.findings].sort((a, b) => ({ error: 0, warning: 1, info: 2 })[a.severity] - { error: 0, warning: 1, info: 2 }[b.severity]).slice(0, 8),
|
|
57620
|
-
omittedFindings: Math.max(0, r.findings.length - 8),
|
|
57621
|
-
next: "Review source reuse and inspection gaps in the saved report. Observations are agent-declared, not independently certified."
|
|
57622
|
-
};
|
|
57623
|
-
if (r.kind === "editorbrain.render-check") return {
|
|
57624
|
-
...base,
|
|
57625
|
-
complete: r.complete,
|
|
57626
|
-
technicalStatus: r.technicalStatus,
|
|
57627
|
-
file: r.file,
|
|
57628
|
-
checks: r.checks,
|
|
57629
|
-
findings: r.findings.slice(0, 8),
|
|
57630
|
-
findingsSummary: r.findingsSummary,
|
|
57631
|
-
omittedFindings: Math.max(0, r.findings.length - 8),
|
|
57632
|
-
next: "Reconcile technical candidates with the brief; inspect the actual video/audio. Technical checks do not assess narrative, aesthetics or SFX audibility."
|
|
57633
|
-
};
|
|
57634
|
-
if (r.kind === "editorbrain.media-source-search") return {
|
|
57635
|
-
...base,
|
|
57636
|
-
complete: r.complete,
|
|
57637
|
-
results: r.results.slice(0, 5).map((item) => ({ provider: item.provider, id: item.id.slice(0, 180), title: item.title.slice(0, 180), sourceUrl: item.sourceUrl.length <= 1500 ? item.sourceUrl : null, author: item.author?.slice(0, 120) ?? null, license: { id: item.license.id, reason: item.license.reason, url: item.license.url && item.license.url.length <= 500 ? item.license.url : null }, contentReviewed: false, rightsVerified: false })),
|
|
57638
|
-
metadataAbbreviated: true,
|
|
57639
|
-
failures: r.failures.slice(0, 5),
|
|
57640
|
-
counts: r.counts,
|
|
57641
|
-
omitted: { results: Math.max(0, r.results.length - 5), failures: Math.max(0, r.failures.length - 5) },
|
|
57642
|
-
searchExhaustive: false,
|
|
57643
|
-
rightsVerified: false,
|
|
57644
|
-
next: "Inspect relevant source pages and media. These archives supplement web image/video search; empty results do not prove absence on the internet."
|
|
57645
|
-
};
|
|
57646
|
-
if (r.kind === "editorbrain.evidence-check") return {
|
|
57647
|
-
...base,
|
|
57648
|
-
valid: r.valid,
|
|
57649
|
-
inventoryComplete: r.inventoryComplete,
|
|
57650
|
-
observations: r.observations,
|
|
57651
|
-
sourceFilesReverified: false,
|
|
57652
|
-
factualTruth: "not_assessed",
|
|
57653
|
-
reuseRights: "not_assessed",
|
|
57654
|
-
findings: r.findings.slice(0, 8),
|
|
57655
|
-
omitted: { findings: Math.max(0, r.findings.length - 8) }
|
|
57656
|
-
};
|
|
57657
|
-
if (r.kind === "editorbrain.audio-check") return {
|
|
57658
|
-
...base,
|
|
57659
|
-
complete: r.complete,
|
|
57660
|
-
technicalStatus: r.technicalStatus,
|
|
57661
|
-
file: r.file,
|
|
57662
|
-
fileStable: r.fileStable,
|
|
57663
|
-
coverage: r.coverage,
|
|
57664
|
-
measurements: r.measurements.slice(0, 8),
|
|
57665
|
-
errorCode: r.errorCode,
|
|
57666
|
-
creativeQuality: r.creativeQuality,
|
|
57667
|
-
omitted: { measurements: Math.max(0, r.measurements.length - 8) },
|
|
57668
|
-
next: "Measurements describe this exact file. Listen for intelligibility, pronunciation, SFX and sync when the modality is available."
|
|
57669
|
-
};
|
|
57670
|
-
if (r.kind === "editorbrain.motion-review") return {
|
|
57671
|
-
...base,
|
|
57672
|
-
samples: r.samples ? { frameCount: r.samples.frameCount, fps: r.samples.fps, radiusFrames: r.samples.radiusFrames, samples: r.samples.samples.slice(0, 12), omittedSamples: Math.max(0, r.samples.samples.length - 12) } : null,
|
|
57673
|
-
geometryReviews: r.geometryReviews.slice(0, 3).map((g) => ({ scope: g.scope, status: g.status, candidates: g.candidates.slice(0, 8), omittedCandidates: Math.max(0, g.candidates.length - 8), checks: g.checks })),
|
|
57674
|
-
omittedGeometryReviews: Math.max(0, r.geometryReviews.length - 3),
|
|
57675
|
-
next: "This plans samples and checks declared boxes only. Render/view those frames; read saved details for omitted candidates and intentional overlaps."
|
|
57676
|
-
};
|
|
57677
|
-
throw new CliError("INVALID_REPORT", "Unknown production report kind.", "Use media inventory/sample or production check/plan-check.");
|
|
57678
|
-
}
|
|
57679
|
-
|
|
57680
|
-
// packages/cli/src/media-preview.ts
|
|
57681
57777
|
async function prepareMediaPreview(root, file, out, quality = 720, audioStream) {
|
|
57682
57778
|
if (![720, 1080].includes(quality) || !out.endsWith(".mp4")) throw new CliError("INVALID_ARGUMENT", "Use --quality 720 or 1080 and a new .mp4 output.", "Previews belong under .editorbrain-local/.");
|
|
57683
57779
|
const source = await probeLocalMedia(await assertLocalMediaFile(file));
|
|
@@ -57736,6 +57832,16 @@ async function prepareStudioAudio(root, file, out, streamIndex) {
|
|
|
57736
57832
|
// packages/cli/src/client.ts
|
|
57737
57833
|
import { setTimeout as delay } from "node:timers/promises";
|
|
57738
57834
|
var searchErrors = {
|
|
57835
|
+
batch_changed: { status: 409, code: "BATCH_CHANGED", hint: "Read batches get before retrying; preserve new changes." },
|
|
57836
|
+
batch_claim_blocked: { status: 409, code: "BATCH_CLAIM_BLOCKED", hint: "Read the batch. Wait for an available slot or reconcile an expired turn; do not start work without a claim." },
|
|
57837
|
+
batch_budget_exceeded: { status: 409, code: "BATCH_BUDGET_EXCEEDED", hint: "Stop generation. The batch or video budget was reached. Do not increase the budget yourself." },
|
|
57838
|
+
batch_not_running: { status: 409, code: "BATCH_NOT_RUNNING", hint: "The batch is paused/cancelled or the turn expired. Read the batch before continuing." },
|
|
57839
|
+
batch_retry_blocked: { status: 409, code: "BATCH_RETRY_BLOCKED", hint: "Inspect existing jobs and outputs before retrying. Do not duplicate a paid request." },
|
|
57840
|
+
batch_project_busy: { status: 409, code: "BATCH_PROJECT_BUSY", hint: "Wait for existing Studio jobs before grouping these projects." },
|
|
57841
|
+
batch_project_taken: { status: 409, code: "BATCH_PROJECT_TAKEN", hint: "Use the project existing batch or create a separate video project." },
|
|
57842
|
+
studio_context_or_lease_changed: { status: 409, code: "STUDIO_CONTEXT_OR_LEASE_CHANGED", hint: "Refresh the workflow and batch lease before generating." },
|
|
57843
|
+
progress_changed: { status: 409, code: "PROGRESS_CHANGED", hint: "Read projects progress --project ID again. Preserve the latest state; never force an old progress version." },
|
|
57844
|
+
final_not_approved: { status: 409, code: "FINAL_NOT_APPROVED", hint: "Review and approve the latest complete video, resolve pending changes, then record explicit final-delivery acceptance." },
|
|
57739
57845
|
invalid_search_brief: { status: 400, code: "INVALID_SEARCH_BRIEF", hint: "Check references/search-brief.md and the service contract. Older services may reject eventQueries objects with channels. Do not silently remove constraints or retry a changed query as if filtering succeeded." },
|
|
57740
57846
|
source_inspection_required: { status: 422, code: "SOURCE_INSPECTION_REQUIRED", hint: "Inspect the supplied source and declare only modalities actually reviewed. A script requires script inspection; video requires frames, motion or audio." },
|
|
57741
57847
|
search_index_not_ready: { status: 503, code: "SEARCH_INDEX_NOT_READY", hint: "No current authorized evidence is indexed. Report the gap; literal library lookup is available but is not semantic retrieval or proof of fit." }
|
|
@@ -57835,7 +57941,7 @@ var Client = class {
|
|
|
57835
57941
|
const retryAfterMs = retryDelay(response.headers.get("Retry-After"), this.runtime.now());
|
|
57836
57942
|
if (!response.ok) {
|
|
57837
57943
|
let errorBody;
|
|
57838
|
-
if (path === "/v1/search/brief" && [400, 422, 503].includes(response.status)) {
|
|
57944
|
+
if ((path.startsWith("/v1/batches") || path === "/v1/studio/jobs") && response.status === 409 || path === "/v1/search/brief" && [400, 422, 503].includes(response.status) || /^\/v1\/projects\/[^/]+\/progress$/.test(path) && response.status === 409) {
|
|
57839
57945
|
try {
|
|
57840
57946
|
const diagnostic = searchDiagnostic(response.status, await boundedJson(response, 16 * 1024));
|
|
57841
57947
|
errorBody = diagnostic ? { error: { code: diagnostic.serviceCode } } : void 0;
|
|
@@ -58017,7 +58123,7 @@ ${conflicts.join("\n")}`, "Run pull --dry-run and reconcile the reported paths."
|
|
|
58017
58123
|
|
|
58018
58124
|
// packages/cli/src/studio.ts
|
|
58019
58125
|
async function studioCommand(client, root, command, argument, flags) {
|
|
58020
|
-
const allowed = /* @__PURE__ */ new Set(["dir", "url", ...command === "quote" ? ["file"] : command === "run" ? ["max-credits", "user-confirmed"] : []]);
|
|
58126
|
+
const allowed = /* @__PURE__ */ new Set(["dir", "url", ...command === "quote" ? ["file"] : command === "run" ? ["max-credits", "user-confirmed", "batch-lease-token"] : []]);
|
|
58021
58127
|
for (const flag of Object.keys(flags)) if (!allowed.has(flag)) throw new CliError("INVALID_ARGUMENT", `--${flag} is not supported for studio ${command}.`, "Read editorbrain help.");
|
|
58022
58128
|
try {
|
|
58023
58129
|
if (command === "catalog" || command === "jobs") {
|
|
@@ -58035,7 +58141,7 @@ async function studioCommand(client, root, command, argument, flags) {
|
|
|
58035
58141
|
if (command === "run") {
|
|
58036
58142
|
const maxCredits = Number(flags["max-credits"]);
|
|
58037
58143
|
if (flags["user-confirmed"] !== true || !Number.isFinite(maxCredits) || maxCredits <= 0 || maxCredits > 1e4) throw new CliError("SPENDING_APPROVAL_REQUIRED", "Supply --user-confirmed and --max-credits only after the user authorized this quote or budget.", "Preferences and direct editing mode do not authorize spending.");
|
|
58038
|
-
return await client.request("/v1/studio/jobs", { method: "POST", body: { quoteId: argument, maxCredits, userConfirmed: true } });
|
|
58144
|
+
return await client.request("/v1/studio/jobs", { method: "POST", body: { quoteId: argument, maxCredits, userConfirmed: true, ...flags["batch-lease-token"] ? { batchLeaseToken: flags["batch-lease-token"] } : {} } });
|
|
58039
58145
|
}
|
|
58040
58146
|
throw new CliError("INVALID_ARGUMENT", "Use studio catalog, quote, run, get or jobs.", "Read editorbrain help.");
|
|
58041
58147
|
} catch (error) {
|
|
@@ -58348,6 +58454,74 @@ var VERIFIED_GUIDANCE_RELEASES = [
|
|
|
58348
58454
|
"editorbrain/references/style-creator.md": "1b1bc289a5bc308cbbf7f4d699de2933b8934733a2b69b3e98fb1b7420d986f2",
|
|
58349
58455
|
"editorbrain/references/workspace-files.md": "cd3006a7cc4f04ff5dfeb1bd901a21c53455017aa7d19fcde9a6e26f1fbbd5b6"
|
|
58350
58456
|
}
|
|
58457
|
+
},
|
|
58458
|
+
{
|
|
58459
|
+
"version": "0.31.0",
|
|
58460
|
+
"archiveSha256": "34a074361f35b099d673e4f310b566d359bc18ec6f326b055c4e0ce811f07c97",
|
|
58461
|
+
"files": {
|
|
58462
|
+
"editorbrain/AGENTS.md": "2361aaa3202d3f4ea9e941684fbda1a84d9711389cca89f7f6cd3ae03b7ab6d0",
|
|
58463
|
+
"editorbrain/references/audio-production.md": "038504d738db98939aeed14407b15561e4f82c650aace7eb545e77cdffd8dadb",
|
|
58464
|
+
"editorbrain-motion/references/authored-scenes.md": "11109dcd35ab7138fdc18e54605885bb26d9e948f12221e18dea4038987dede2",
|
|
58465
|
+
"editorbrain/references/cli-mcp.md": "3a83731d73dd09b55ee5a250bebd950b5a0daedc2b1c3af23bfc6c36f748d793",
|
|
58466
|
+
"editorbrain-motion/references/code-motion.md": "50382a797adc1e1596086e2408e81ee75ceb6730ca409be9c884646db643a7cd",
|
|
58467
|
+
"editorbrain-motion/references/component-library.md": "e4593622ebe371bba1b1c62f698c6709c36a8d01ddce4a07d40534fca44b797e",
|
|
58468
|
+
"editorbrain/references/editorial-evidence.md": "caf72365b3e7492a62d96b39cd17031fa7c961671ce32bc4649420d8a353a026",
|
|
58469
|
+
"editorbrain/references/first-edit.md": "d71271ab32c6432cce01316917b4504f15411ea59511566a1f6169ac6d09723c",
|
|
58470
|
+
"editorbrain-motion/references/generated-motion.md": "a8d214b53c15f742658abd84f03b768fa2821f8cde94f50aab82a3759a30b36b",
|
|
58471
|
+
"editorbrain/references/integrations.md": "a3500dd79c71ab3ee80a865bb5bf8c94287efb933e07d577738891e276a819a0",
|
|
58472
|
+
"editorbrain/references/local-production.md": "2d170bb217854eda7581f64d8342fffe3b56234bbe56b2715fa93eb3210e6354",
|
|
58473
|
+
"editorbrain/references/media-preferences.md": "d1b92b181fbc226c8d3fda762726dd413944175768651fbfb8200eae44fb2ec8",
|
|
58474
|
+
"editorbrain/references/memory-and-review.md": "2a89d6fc4737b750a380c69630d6fd4f4132aed27656b92e8f0c5748887b70ae",
|
|
58475
|
+
"editorbrain-motion/references/motion-craft.md": "adba1b0cbb3c6327a7665857b0a6d144f97dc843464ccf154d3f76ee3ada905d",
|
|
58476
|
+
"editorbrain/references/motion-review.md": "0fb09a2d61ecd13114ced5cca5daa4580a922cf7d7b3f8698077ceb0e96da6f0",
|
|
58477
|
+
"editorbrain/references/onboarding.md": "875d1b9049c4663780f993c2843528c531a51d6b51380b08ed77d82f618185fb",
|
|
58478
|
+
"editorbrain/references/production-and-review.md": "50f10a98a4f3709a5a585f58e4154f33d6d883b218cd25f3abd72eccc43b15a7",
|
|
58479
|
+
"editorbrain/references/production-continuity.md": "c4b346c9634f3d1ef63b24a97d178e0253c2e45d53f6934076a5417e66e34d9b",
|
|
58480
|
+
"editorbrain/references/real-media.md": "106bee5a34641d53f021ead5d41630d473c2bfc98e4f7ee5500dae837e2e45bb",
|
|
58481
|
+
"editorbrain/references/search-brief.md": "ea2a9c2d5a5cf685c1e5918366901ef2589c4d79aaa78a0dd31e97d6fed42b7b",
|
|
58482
|
+
"editorbrain/references/sfx-library.md": "fa0b02c8765988257e46e16298ecca9cdb0e338a863915e29f831162e237eac4",
|
|
58483
|
+
"editorbrain-motion/SKILL.md": "86617d39341d7325d613b877838258f40f05b4286301dacf8e1ec85ccd502aab",
|
|
58484
|
+
"editorbrain/SKILL.md": "d53070052608fc2535af7cb51bcac2c10097b289450958ca7372cab3fb8364a9",
|
|
58485
|
+
"editorbrain/references/storage-and-previews.md": "8a3057f1c1a2a1e1cd32028059dc897a8461da38c36e812fbd24943d3740b4d5",
|
|
58486
|
+
"editorbrain/references/studio.md": "7a84e43bd72f8590d1a91c7d1bc5f6b60678c1c8eba6523b51b99243e22a1322",
|
|
58487
|
+
"editorbrain/references/style-creator.md": "1b1bc289a5bc308cbbf7f4d699de2933b8934733a2b69b3e98fb1b7420d986f2",
|
|
58488
|
+
"editorbrain/references/workspace-files.md": "18462e7b66ba6204770c654e4a2f7e505c343319671a0447aa55c59f0b9096ec"
|
|
58489
|
+
}
|
|
58490
|
+
},
|
|
58491
|
+
{
|
|
58492
|
+
"version": "0.32.0",
|
|
58493
|
+
"archiveSha256": "30c6c6d97da7de16bb620c0975c2d3f2a4b7a6ea4a56f2eb3c5b0f5f53914f45",
|
|
58494
|
+
"files": {
|
|
58495
|
+
"editorbrain-formats/SKILL.md": "b8b03266a9b7cde8337846144d3032b63b6d9cfbfc4530ae1b06f3dd43074ff2",
|
|
58496
|
+
"editorbrain-formats/references/numbered-tutorial.md": "95754ae7dbfaa678e11ddf1a2b84710dba83a16e2fa4055051bd4f5f4f868a5f",
|
|
58497
|
+
"editorbrain-motion/SKILL.md": "86617d39341d7325d613b877838258f40f05b4286301dacf8e1ec85ccd502aab",
|
|
58498
|
+
"editorbrain-motion/references/authored-scenes.md": "11109dcd35ab7138fdc18e54605885bb26d9e948f12221e18dea4038987dede2",
|
|
58499
|
+
"editorbrain-motion/references/code-motion.md": "50382a797adc1e1596086e2408e81ee75ceb6730ca409be9c884646db643a7cd",
|
|
58500
|
+
"editorbrain-motion/references/component-library.md": "e4593622ebe371bba1b1c62f698c6709c36a8d01ddce4a07d40534fca44b797e",
|
|
58501
|
+
"editorbrain-motion/references/generated-motion.md": "a8d214b53c15f742658abd84f03b768fa2821f8cde94f50aab82a3759a30b36b",
|
|
58502
|
+
"editorbrain-motion/references/motion-craft.md": "adba1b0cbb3c6327a7665857b0a6d144f97dc843464ccf154d3f76ee3ada905d",
|
|
58503
|
+
"editorbrain/AGENTS.md": "2361aaa3202d3f4ea9e941684fbda1a84d9711389cca89f7f6cd3ae03b7ab6d0",
|
|
58504
|
+
"editorbrain/SKILL.md": "b15eb4e2438c0a3e6ec5c3c3170f11c973676d5c6a850cf5d2e9cb3bc7c44e42",
|
|
58505
|
+
"editorbrain/references/audio-production.md": "038504d738db98939aeed14407b15561e4f82c650aace7eb545e77cdffd8dadb",
|
|
58506
|
+
"editorbrain/references/cli-mcp.md": "9febfcac6c1dc763b79ab26ffb07e53bce703cbe4c2332ddcd250e10f2fa75dd",
|
|
58507
|
+
"editorbrain/references/editorial-evidence.md": "caf72365b3e7492a62d96b39cd17031fa7c961671ce32bc4649420d8a353a026",
|
|
58508
|
+
"editorbrain/references/first-edit.md": "d71271ab32c6432cce01316917b4504f15411ea59511566a1f6169ac6d09723c",
|
|
58509
|
+
"editorbrain/references/integrations.md": "a3500dd79c71ab3ee80a865bb5bf8c94287efb933e07d577738891e276a819a0",
|
|
58510
|
+
"editorbrain/references/local-production.md": "2d170bb217854eda7581f64d8342fffe3b56234bbe56b2715fa93eb3210e6354",
|
|
58511
|
+
"editorbrain/references/media-preferences.md": "d1b92b181fbc226c8d3fda762726dd413944175768651fbfb8200eae44fb2ec8",
|
|
58512
|
+
"editorbrain/references/memory-and-review.md": "2a89d6fc4737b750a380c69630d6fd4f4132aed27656b92e8f0c5748887b70ae",
|
|
58513
|
+
"editorbrain/references/motion-review.md": "0fb09a2d61ecd13114ced5cca5daa4580a922cf7d7b3f8698077ceb0e96da6f0",
|
|
58514
|
+
"editorbrain/references/onboarding.md": "875d1b9049c4663780f993c2843528c531a51d6b51380b08ed77d82f618185fb",
|
|
58515
|
+
"editorbrain/references/production-and-review.md": "50f10a98a4f3709a5a585f58e4154f33d6d883b218cd25f3abd72eccc43b15a7",
|
|
58516
|
+
"editorbrain/references/production-continuity.md": "c4b346c9634f3d1ef63b24a97d178e0253c2e45d53f6934076a5417e66e34d9b",
|
|
58517
|
+
"editorbrain/references/real-media.md": "106bee5a34641d53f021ead5d41630d473c2bfc98e4f7ee5500dae837e2e45bb",
|
|
58518
|
+
"editorbrain/references/search-brief.md": "ea2a9c2d5a5cf685c1e5918366901ef2589c4d79aaa78a0dd31e97d6fed42b7b",
|
|
58519
|
+
"editorbrain/references/sfx-library.md": "fa0b02c8765988257e46e16298ecca9cdb0e338a863915e29f831162e237eac4",
|
|
58520
|
+
"editorbrain/references/storage-and-previews.md": "8a3057f1c1a2a1e1cd32028059dc897a8461da38c36e812fbd24943d3740b4d5",
|
|
58521
|
+
"editorbrain/references/studio.md": "7a84e43bd72f8590d1a91c7d1bc5f6b60678c1c8eba6523b51b99243e22a1322",
|
|
58522
|
+
"editorbrain/references/style-creator.md": "1b1bc289a5bc308cbbf7f4d699de2933b8934733a2b69b3e98fb1b7420d986f2",
|
|
58523
|
+
"editorbrain/references/workspace-files.md": "c16fe08b209c65baf8f57054f7cc01f514292fc073b7072298b86c0054da3e19"
|
|
58524
|
+
}
|
|
58351
58525
|
}
|
|
58352
58526
|
];
|
|
58353
58527
|
function isVerifiedHistoricalGuidance(skillName, relativePath, sha2562) {
|
|
@@ -58356,7 +58530,7 @@ function isVerifiedHistoricalGuidance(skillName, relativePath, sha2562) {
|
|
|
58356
58530
|
}
|
|
58357
58531
|
|
|
58358
58532
|
// packages/cli/src/agent-guidance.ts
|
|
58359
|
-
var BUNDLED_SKILLS = ["editorbrain", "editorbrain-motion"];
|
|
58533
|
+
var BUNDLED_SKILLS = ["editorbrain", "editorbrain-motion", "editorbrain-formats"];
|
|
58360
58534
|
var previousSkillHashes = { "SKILL.md": ["9df2c89deeec30ddf556c359027efe1d90e6b4e9c08717cd8827e210b38a187f", "67b157cb45cae3621e6f2c43235c1d69907ad6abd45ab6b52a3c65f236732db9", "1e2fff65a1b303b18b2d65156bef6eb2439a19d77ba2a25b37bcb1819ff009e3", "dacce1c4127f4281df6f7e1681e243444bb6f8a8e74b829e52ee0108c6672348", "09740ab4b275eada65b5040ae6000104ff39094f534a2784e67feb2afc2a59b3", "f18269ad5504fff8a4fc522d463483261f5041e56cb7f1081f9614bc67e0d96f", "5779a28879313070b0d819771ac967d4a133cff1c3dbda2ec44b4dd2abcb17d1", "30f1e64622e70552a1a6129cacc646f56b09b3d7a1fd3f5bf22299bc6bfd0d1e", "6975d917226f75ad55c67543bf7f1c5ef18f4cfe43426c69400c56c1ed497db3", "0029d5da60efc14759a66c4e3299d5da09c4ab8e3f255fe5da9990699c42f3e4", "09d5441cba061349b43b36ab683d966f772d0cec94698823e32c35f2475d287e"], "AGENTS.md": ["4f3ef860ade3a31aa7c6a6aab5cf6ec2a700850bf19ea2320324c12c2e0fbf5b", "1b07de01698a0040b47ea0eddb1b017f70a69e81acd0bf9710647ca5e02f5125", "b5ee3439ff974c668755816149fab76899d7ad9266f63978b30fbc9b7d2cd640", "bacedb7bdedab5abe75c9601717cfdb05a96208fa2e2a42af878e2dfd2ae4251", "ea3b473179857ccc07e9e4f21a6ede9e0906a09e495f4a051069d15aee1556cd", "faa2bba99ae3023be7f588d02177a4abf583d3a8a65f617b8cff7a3ceed09dfc", "83c75394bc7eaab6662a76d89339361e836cc1a988237720eeeacdd6b62e726f", "b685cb7ff21d5bfe19d96ce0139c17b7eb014b7ecda8ec5321558b0004bfdc71", "9da0b84e166ad3799dd0c644adaa3ce8727f383e5571b0a212c3d34f5c05ab40", "12f5dce738eb974ddd96f4bd00d8de5be236a54dbb20720f6f4ab455bcc319d9"], "references/cli-mcp.md": ["5d3a79343fbd76cdae5bdbe12fb9c944d5dff4f489ac6534fd96e0cb8630b988", "8e011c31368cef2117a28ee972b39aab9535eeb0f601a4a0f9d6fc019b22c1c2", "666082653efc000f8a7cc5f1836c80bbdda5f0f57cdbbdcb393f2b84aeb93a01", "78b737796a8685b1135e0acb91b620c51845b62e31dba04eb51dd9dd38b41008", "8b2e01bfd937237919f5ade794eed01dc6e32b556ede9de3a0ccc28cbdd988d1", "ca88b2816a795a5ebe834074b178469367634b80ad837e3697182ea585af1c05", "490daf154b428b536d0a6f590030c854b2fc8ca6adb995c6ecd5a162f85e471e", "9f98affecd69752c17f52fb51ae74b26a1cadea5919b8b74b7865a20661c4418", "19fc85e92cef203f4162e2bfb2dd2df8ef90472bc8f81dfb568b65a714335ff9", "f697c525a32d8ed6c0752d833cb98cca8b9aec9eadf456e178dfbc9fc246c58c", "d2a3dd980fb712110861ac9802288bb025ac5ea0055f1e56d70d649412a4d733", "955d60d1be71d0eb134ae9fc35a771d41303fae8fe63daa99bfce514a6522e14"], "references/production-and-review.md": ["055c6df9e0f167be148b0a5c0bba5b43e108eb1f58f478d88b3536c6589ac7b3", "4a4035b87a6c024b419847ab8592bddfeb9b2d9c184f65880c47d661f0bb250e", "c3669af0717a5fafbf7cc8b01bd66f74d4c82028715323a870a1298d25250d5e"], "references/workspace-files.md": ["e72af2871f42cd776be1bfff8009ed5562780e7f8a65b12c27887f3880631f81", "00780c64bd0244c6afb18d786b7512b43e315c376e8f88c67d6ba53d91275ccf", "97053b092e0ff36e3cfb764095fcb4a4fca94e722567e774b53bc118279f40e5", "70fc660e7ed3d70c16c33c62c8e0399b99c3251808f093ef3d4ea5e8d39e4c8a", "28c62c1e28842142607f5168ee79b18fd797900dd66dd9ac5eb3cfcf8a09f781", "b86eae85cf86dbf4409b10f4d8df1f1649fc408ce1a240f7cf26d5bb69aabfd1", "fc65f343e50b91327653bdc5d94f35af9c86c097bb46810b4b2f7c9a1c200166", "8a650485bc4f26bbebf6d6a66957bdea87b156632e52a27e9becc194b003a9fc"], "references/first-edit.md": ["cb1e9d3272b2b22ae095aed02e33067c646da48e7b64cf71ff81197f6e67b673", "5a02253d9907f5e6705304565da7b2d1787e84ae17616414b295a8526ec3e4a5", "586b1f18bab01ad6b2bb0efd95cfdc8f8002ecfd022ae91021779ab1d5e432c9"], "references/memory-and-review.md": ["51a274e522270f1fc295d0c0b9a1c23672ce01abea097c2499c9a8db56c0c289"], "references/search-brief.md": ["137203383a7873593136428520f5f9cd6ce1ab6cfeab365c277175786eba3ab3", "df93154562bb89a9f22d31260c17406565f5f308c407643c85d15e528ef2c086", "a472eeb61a2a60172d5cdb71f80be3d18f59e248028ab107b6cd1b68535ff588"], "references/style-creator.md": ["1b1bc289a5bc308cbbf7f4d699de2933b8934733a2b69b3e98fb1b7420d986f2"], "references/local-production.md": ["0a13c65cd60e40ba703095f5e33a1ea66433323b38345c2034fb73c602c438ee"], "references/integrations.md": ["a3500dd79c71ab3ee80a865bb5bf8c94287efb933e07d577738891e276a819a0"], "references/media-preferences.md": ["970b97fbd55b8e9e05fd7e51b4a953cd1b96b9bee7830382aa7514f1b240b3aa", "481c643a5e6516413a6cae970b5170573c981d0effd7d4e146c5cd07c0ee3b1f", "8f11e1956ed06ab73ba58d8c880f0d2292eb76829b07d2de2eaaed1965885158", "e94bc13c05ffd57eceecc4ceaa42df2b83904c12f8c552e161c98f13e6427e5b", "00e50c6231a917639c8d9eb39bff61b0b90e3a1886a4d4684ef6d85fa754e87c"] };
|
|
58361
58535
|
var destinations = {
|
|
58362
58536
|
codex: { directory: ".agents/skills/editorbrain", entryPoint: "AGENTS.md" },
|
|
@@ -58364,6 +58538,7 @@ var destinations = {
|
|
|
58364
58538
|
};
|
|
58365
58539
|
var previousHashesBySkill = {
|
|
58366
58540
|
editorbrain: previousSkillHashes,
|
|
58541
|
+
"editorbrain-formats": {},
|
|
58367
58542
|
"editorbrain-motion": { "references/code-motion.md": ["9c9bd4c7c6ef8c607e4de6198408e4a49e6d6c4deda681dd7aadada1e46c1a80", "dc7446d5349fd107d6c722fcf62ad6ad6dfc7b9a1d4829c0adfbc00e41a9c8a5", "08fd07e904424a98ec4dd68732d55e15fa9f6edffe14e4ee0241f0483acb82be"], "references/generated-motion.md": ["a8d214b53c15f742658abd84f03b768fa2821f8cde94f50aab82a3759a30b36b"], "SKILL.md": ["f732ba6c896e01a844df92a353a77d18da1be7f09ce557bf7a543e3066a667d2", "0920c79979dc029fae3526a565e5eab75d5b7f1f51c369fb7ef0d652b95876eb", "0b6f6e6990528579fdff4275a2bcf0b0fe6f0f2de59ae84d0f57b81a07185cec"], "references/component-library.md": ["ad7142f9bbd52903b61f401104dfdbb430535f358946e58788f9f740d8f44b56", "7ff9e079116c410be0dc80fb470e79226c380b6fcc7d6eb72cb94443dd8915a4", "c2ab96ee61dc1e9480cb6f7fd160c016b35ff946e3d8ffe31267d127718482c8", "fea1fb710d23830c3ed14c3e4bed7bc53540ae2e2e662b74fe6eb6307b010d28"] }
|
|
58368
58543
|
};
|
|
58369
58544
|
function installedSkillDirectory(agent, skillName = "editorbrain") {
|
|
@@ -58421,11 +58596,11 @@ async function prepareAgentGuidance(root, agent = "both", sourceDirectory, compa
|
|
|
58421
58596
|
root = await ensureRoot(root);
|
|
58422
58597
|
parseAgentTarget(agent);
|
|
58423
58598
|
const agents = agent === "both" ? ["codex", "claude"] : [agent];
|
|
58424
|
-
const companions = companionSources ?? (sourceDirectory === void 0 ?
|
|
58425
|
-
"editorbrain
|
|
58426
|
-
|
|
58599
|
+
const companions = companionSources ?? (sourceDirectory === void 0 ? Object.fromEntries(
|
|
58600
|
+
BUNDLED_SKILLS.filter((name) => name !== "editorbrain").map((name) => [name, bundledSkillDirectory(void 0, name)])
|
|
58601
|
+
) : {});
|
|
58427
58602
|
for (const name of Object.keys(companions)) {
|
|
58428
|
-
if (name
|
|
58603
|
+
if (name === "editorbrain" || !BUNDLED_SKILLS.includes(name)) throw new Error(`Unknown companion skill: ${name}`);
|
|
58429
58604
|
}
|
|
58430
58605
|
const sources = /* @__PURE__ */ new Map([
|
|
58431
58606
|
["editorbrain", await loadSkill(sourceDirectory ?? bundledSkillDirectory())]
|
|
@@ -63497,7 +63672,16 @@ editorbrain register --url https://server --name workspace --invite-stdin
|
|
|
63497
63672
|
editorbrain status
|
|
63498
63673
|
editorbrain pull [--project id | --all] [--dir folder] [--dry-run]
|
|
63499
63674
|
editorbrain push [--dir folder] [--dry-run]
|
|
63675
|
+
editorbrain batches list [--after UUID]
|
|
63676
|
+
editorbrain batches create --file batch.json
|
|
63677
|
+
editorbrain batches get BATCH_ID
|
|
63678
|
+
editorbrain batches pause|resume|cancel BATCH_ID --expected-revision N
|
|
63679
|
+
editorbrain batches retry|detach BATCH_ID --project ID --expected-revision N
|
|
63680
|
+
editorbrain batches claim|renew|release|attention BATCH_ID --project ID --lease-token UUID
|
|
63500
63681
|
editorbrain projects list
|
|
63682
|
+
editorbrain projects progress --project ID
|
|
63683
|
+
editorbrain projects start|queue --project ID --expected-version HASH
|
|
63684
|
+
editorbrain projects complete --project ID --expected-version HASH --revision UUID --user-confirmed
|
|
63501
63685
|
editorbrain documents list [--prefix path]
|
|
63502
63686
|
editorbrain documents get <path> [--revision N]
|
|
63503
63687
|
editorbrain documents history <path> [--before N]
|
|
@@ -63516,7 +63700,7 @@ editorbrain studio prepare --file source.mp4 --out .editorbrain-local/studio/aud
|
|
|
63516
63700
|
editorbrain studio catalog
|
|
63517
63701
|
editorbrain billing status
|
|
63518
63702
|
editorbrain studio quote --file request.json [--dir folder]
|
|
63519
|
-
editorbrain studio run QUOTE_ID --max-credits N --user-confirmed
|
|
63703
|
+
editorbrain studio run QUOTE_ID --max-credits N --user-confirmed [--batch-lease-token UUID]
|
|
63520
63704
|
editorbrain studio get JOB_ID
|
|
63521
63705
|
editorbrain studio jobs
|
|
63522
63706
|
editorbrain integrations catalog
|
|
@@ -63602,6 +63786,9 @@ function parseArgs(argv) {
|
|
|
63602
63786
|
known.add("preview-kind");
|
|
63603
63787
|
known.add("preset");
|
|
63604
63788
|
known.add("context-version");
|
|
63789
|
+
known.add("expected-version");
|
|
63790
|
+
known.add("lease-token");
|
|
63791
|
+
known.add("batch-lease-token");
|
|
63605
63792
|
for (let i = 0; i < argv.length; i++) {
|
|
63606
63793
|
const arg = argv[i];
|
|
63607
63794
|
if (!arg.startsWith("--")) {
|
|
@@ -64187,6 +64374,14 @@ async function main() {
|
|
|
64187
64374
|
}
|
|
64188
64375
|
throw new Error("Use keys list, keys create --label name, or keys revoke <key-id>");
|
|
64189
64376
|
}
|
|
64377
|
+
if (command === "batches") {
|
|
64378
|
+
output(await batchCommand(new Client(await config(args)), await ensureRoot(str(args, "dir") ?? process.cwd()), subcommand, argument, args.flags));
|
|
64379
|
+
return;
|
|
64380
|
+
}
|
|
64381
|
+
if (command === "projects" && ["progress", "start", "queue", "complete"].includes(subcommand)) {
|
|
64382
|
+
output(await projectProgressCommand(new Client(await config(args)), subcommand, args.flags));
|
|
64383
|
+
return;
|
|
64384
|
+
}
|
|
64190
64385
|
if (command === "projects" && subcommand === "list") {
|
|
64191
64386
|
output({ projects: await listProjects(new Client(await config(args))) });
|
|
64192
64387
|
return;
|