editorbrain 0.7.0 → 0.8.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
CHANGED
|
@@ -5,13 +5,13 @@ Editorial references, brand context and portable video projects for Claude Code
|
|
|
5
5
|
Inspect the CLI without configuring your agent:
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
npx editorbrain@0.
|
|
8
|
+
npx editorbrain@0.8.0 help
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
For a persistent installation:
|
|
12
12
|
|
|
13
13
|
```sh
|
|
14
|
-
npm install -g editorbrain@0.
|
|
14
|
+
npm install -g editorbrain@0.8.0
|
|
15
15
|
editorbrain login --url https://api.editorbrain.com
|
|
16
16
|
editorbrain status --url https://api.editorbrain.com
|
|
17
17
|
editorbrain projects list
|
package/bin/editorbrain.mjs
CHANGED
|
@@ -103,6 +103,7 @@ function validateDocument(path, content) {
|
|
|
103
103
|
if (isProject) {
|
|
104
104
|
for (const key of ["id", "brand", "style", "outputProfile"]) if (typeof doc[key] !== "string" || !identifier.test(doc[key])) add(`${key} must be a valid identifier`);
|
|
105
105
|
if (!object(doc.intent) || !nonempty(doc.intent.topic) || !nonempty(doc.intent.goal)) add("intent requires topic and goal");
|
|
106
|
+
if (doc.reviewMode !== void 0 && !["direct", "directions", "sample"].includes(doc.reviewMode)) add("reviewMode must be direct, directions or sample");
|
|
106
107
|
if (doc.script !== void 0 && typeof doc.script !== "string") add("script must be text");
|
|
107
108
|
if (doc.overrides !== void 0) {
|
|
108
109
|
if (!object(doc.overrides)) add("overrides must be an object");
|
|
@@ -542,7 +543,7 @@ var Client = class {
|
|
|
542
543
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
543
544
|
let response;
|
|
544
545
|
try {
|
|
545
|
-
response = await this.fetcher(`${this.url}${path}`, { method, headers, body: options.body === void 0 ? void 0 : JSON.stringify(options.body), redirect: "error", signal: AbortSignal.timeout(2e4) });
|
|
546
|
+
response = await this.fetcher(`${this.url}${path}`, { method, headers, body: options.body === void 0 ? void 0 : JSON.stringify(options.body), redirect: "error", signal: AbortSignal.timeout(Math.min(18e4, Math.max(1e3, options.timeoutMs ?? 2e4))) });
|
|
546
547
|
} catch {
|
|
547
548
|
if (readOnly && attempt < 2) {
|
|
548
549
|
await this.runtime.sleep(250 * 2 ** attempt + this.runtime.random() * 100);
|
|
@@ -776,7 +777,7 @@ import { createHash } from "node:crypto";
|
|
|
776
777
|
import { constants as constants2 } from "node:fs";
|
|
777
778
|
import { lstat as lstat2, open as open2, readdir as readdir2, rename as rename2 } from "node:fs/promises";
|
|
778
779
|
import { fileURLToPath } from "node:url";
|
|
779
|
-
var previousSkillHashes = { "SKILL.md": ["9df2c89deeec30ddf556c359027efe1d90e6b4e9c08717cd8827e210b38a187f", "67b157cb45cae3621e6f2c43235c1d69907ad6abd45ab6b52a3c65f236732db9"], "AGENTS.md": ["4f3ef860ade3a31aa7c6a6aab5cf6ec2a700850bf19ea2320324c12c2e0fbf5b"], "references/cli-mcp.md": ["5d3a79343fbd76cdae5bdbe12fb9c944d5dff4f489ac6534fd96e0cb8630b988", "8e011c31368cef2117a28ee972b39aab9535eeb0f601a4a0f9d6fc019b22c1c2"], "references/production-and-review.md": ["055c6df9e0f167be148b0a5c0bba5b43e108eb1f58f478d88b3536c6589ac7b3"], "references/workspace-files.md": ["e72af2871f42cd776be1bfff8009ed5562780e7f8a65b12c27887f3880631f81", "00780c64bd0244c6afb18d786b7512b43e315c376e8f88c67d6ba53d91275ccf"] };
|
|
780
|
+
var previousSkillHashes = { "SKILL.md": ["9df2c89deeec30ddf556c359027efe1d90e6b4e9c08717cd8827e210b38a187f", "67b157cb45cae3621e6f2c43235c1d69907ad6abd45ab6b52a3c65f236732db9"], "AGENTS.md": ["4f3ef860ade3a31aa7c6a6aab5cf6ec2a700850bf19ea2320324c12c2e0fbf5b", "1b07de01698a0040b47ea0eddb1b017f70a69e81acd0bf9710647ca5e02f5125"], "references/cli-mcp.md": ["5d3a79343fbd76cdae5bdbe12fb9c944d5dff4f489ac6534fd96e0cb8630b988", "8e011c31368cef2117a28ee972b39aab9535eeb0f601a4a0f9d6fc019b22c1c2", "666082653efc000f8a7cc5f1836c80bbdda5f0f57cdbbdcb393f2b84aeb93a01"], "references/production-and-review.md": ["055c6df9e0f167be148b0a5c0bba5b43e108eb1f58f478d88b3536c6589ac7b3"], "references/workspace-files.md": ["e72af2871f42cd776be1bfff8009ed5562780e7f8a65b12c27887f3880631f81", "00780c64bd0244c6afb18d786b7512b43e315c376e8f88c67d6ba53d91275ccf"] };
|
|
780
781
|
var destinations = {
|
|
781
782
|
codex: { directory: ".agents/skills/editorbrain", entryPoint: "AGENTS.md" },
|
|
782
783
|
claude: { directory: ".claude/skills/editorbrain", entryPoint: "CLAUDE.md" }
|
|
@@ -1361,6 +1362,8 @@ editorbrain push [--dir folder] [--dry-run]
|
|
|
1361
1362
|
editorbrain projects list
|
|
1362
1363
|
editorbrain documents list [--prefix path]
|
|
1363
1364
|
editorbrain documents get <path>
|
|
1365
|
+
editorbrain workflow check [--project id] [--previous-version hash]
|
|
1366
|
+
editorbrain search edit [--script file | --video file | --asset sha256 | --project id] [--requirements text] [--assets tag,tag] [--mode styles|events|both] [--review direct|directions|sample]
|
|
1364
1367
|
editorbrain library search [query]
|
|
1365
1368
|
editorbrain library get <video-id> [--document relative-source-path] [--sha256 source-hash]
|
|
1366
1369
|
editorbrain library media <video-id> --sha256 media-hash --out file
|
|
@@ -1388,7 +1391,7 @@ function parseArgs(argv) {
|
|
|
1388
1391
|
const positional = [];
|
|
1389
1392
|
const flags = {};
|
|
1390
1393
|
const booleans = /* @__PURE__ */ new Set(["help", "version", "offline", "dry-run", "key-stdin", "invite-stdin", "no-browser", "skip-mcp", "all"]);
|
|
1391
|
-
const known = /* @__PURE__ */ new Set(["dir", "brand", "style", "project", "topic", "goal", "name", "adapter", "out", "url", "document", "mime", "label", "role", "limit", "cursor", "timeout", "assets", "capabilities", "duration", "agent", "workspace", "prefix", "sha256", "kind", "channel", "epistemic-status", "event-offset", "relation-offset", ...booleans]);
|
|
1394
|
+
const known = /* @__PURE__ */ new Set(["dir", "brand", "style", "project", "topic", "goal", "name", "adapter", "out", "url", "document", "mime", "label", "role", "limit", "cursor", "timeout", "assets", "capabilities", "duration", "agent", "workspace", "prefix", "sha256", "kind", "channel", "epistemic-status", "event-offset", "relation-offset", "script", "video", "asset", "requirements", "mode", "review", "previous-version", ...booleans]);
|
|
1392
1395
|
for (let i = 0; i < argv.length; i++) {
|
|
1393
1396
|
const arg = argv[i];
|
|
1394
1397
|
if (!arg.startsWith("--")) {
|
|
@@ -1735,6 +1738,46 @@ async function main() {
|
|
|
1735
1738
|
}
|
|
1736
1739
|
throw new Error("Use narrative search [query] or narrative get <video-id>.");
|
|
1737
1740
|
}
|
|
1741
|
+
if (command === "workflow" && subcommand === "check") {
|
|
1742
|
+
const client = new Client(await config(args));
|
|
1743
|
+
output(await client.request("/v1/workflow/check", { method: "POST", body: { projectId: str(args, "project"), previousVersion: str(args, "previous-version") } }));
|
|
1744
|
+
return;
|
|
1745
|
+
}
|
|
1746
|
+
if (command === "search" && subcommand === "edit") {
|
|
1747
|
+
const client = new Client(await config(args));
|
|
1748
|
+
const scriptPath = str(args, "script"), videoPath = str(args, "video");
|
|
1749
|
+
let script, assetId = str(args, "asset");
|
|
1750
|
+
const readInput = async (path, max) => {
|
|
1751
|
+
const handle = await open4(resolve4(path), constants4.O_RDONLY | constants4.O_NOFOLLOW);
|
|
1752
|
+
try {
|
|
1753
|
+
const stat = await handle.stat();
|
|
1754
|
+
if (!stat.isFile() || stat.size < 1 || stat.size > max) throw new Error(`Input must be a regular file of at most ${max} bytes.`);
|
|
1755
|
+
return await handle.readFile();
|
|
1756
|
+
} finally {
|
|
1757
|
+
await handle.close();
|
|
1758
|
+
}
|
|
1759
|
+
};
|
|
1760
|
+
if (videoPath && assetId) throw new Error("Use --video or --asset, not both.");
|
|
1761
|
+
if (scriptPath) {
|
|
1762
|
+
script = new TextDecoder("utf-8", { fatal: true }).decode(await readInput(scriptPath, 64e3));
|
|
1763
|
+
if (script.length > 16e3) throw new Error("Script must contain at most 16000 characters.");
|
|
1764
|
+
}
|
|
1765
|
+
const mode = str(args, "mode") ?? "both", reviewMode = str(args, "review");
|
|
1766
|
+
if (!["styles", "events", "both"].includes(mode)) throw new Error("--mode must be styles, events or both.");
|
|
1767
|
+
if (reviewMode && !["direct", "directions", "sample"].includes(reviewMode)) throw new Error("--review must be direct, directions or sample.");
|
|
1768
|
+
if (assetId && !/^[a-f0-9]{64}$/.test(assetId)) throw new Error("--asset requires an owned production asset SHA-256.");
|
|
1769
|
+
if (videoPath) {
|
|
1770
|
+
const bytes = await readInput(videoPath, 12 * 1024 * 1024);
|
|
1771
|
+
const mimeType = { ".mp4": "video/mp4", ".mov": "video/quicktime", ".webm": "video/webm" }[extname(videoPath).toLowerCase()];
|
|
1772
|
+
if (!mimeType) throw new Error("Use MP4, MOV or WebM.");
|
|
1773
|
+
assetId = await sha256(bytes);
|
|
1774
|
+
const uploaded = await client.media(`/v1/assets/${assetId}?name=${encodeURIComponent(basename(videoPath))}`, { content: bytes, mimeType });
|
|
1775
|
+
if ((await uploaded.json()).sha256 !== assetId) throw new Error("Upload hash mismatch.");
|
|
1776
|
+
}
|
|
1777
|
+
if (!script && !assetId && !str(args, "project")) throw new Error("Provide --script, --video, --asset or --project with a saved script.");
|
|
1778
|
+
output(await client.request("/v1/search/edit", { method: "POST", timeoutMs: 18e4, body: { script, assetId, projectId: str(args, "project"), requirements: str(args, "requirements") ?? "", availableAssets: (str(args, "assets") ?? "").split(",").filter(Boolean), mode, reviewMode } }));
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1738
1781
|
if (command === "library") {
|
|
1739
1782
|
const client = new Client(await config(args));
|
|
1740
1783
|
if (subcommand === "search") {
|
package/package.json
CHANGED
|
@@ -25,7 +25,8 @@ editing question. Existing proposals or other project documents can be discovere
|
|
|
25
25
|
Read [the workspace file map](references/workspace-files.md) for the full structure, required/optional files and token precedence. Start with `videos/<project-id>/project.json` to discover the selected brand, style and output profile. Read their actual files plus the brief and direction; do not assume that all documents under the workspace are included automatically by `resolve`.
|
|
26
26
|
|
|
27
27
|
- Consult style packs for methods and the reference library for their execution. Search by communicative function as well as topic: comparison, demonstration, reveal, cumulative typography, collage, atmosphere, callback.
|
|
28
|
-
-
|
|
28
|
+
- Start with `search_for_edit` / `editorbrain search edit`, supplying the actual script or owned video and the project ID for brand constraints. It analyzes new material before semantic retrieval and candidate review; inspect its uncertainty, source hashes, coverage and missing assets. Its model reading is not human verification. Legacy literal search and rule-based recommendations remain lookup tools, not equivalents to this content-first flow.
|
|
29
|
+
- Read `check_workflow` at the start, before proposals, before paid resource generation, and before the full render. Precedence: current explicit user request > project reviewMode > workspace default. Direct means proceed and review; directions means offer 2–3 fitting options with labelled library evidence; sample means show a representative customer-material frame or short clip and obtain approval. Do not require a new approval when the relevant version is already approved. Use a moving sample when rhythm or sound is what needs review. Save the workflow version and any approval with the project direction. A receipt acknowledges reading, not actual compliance.
|
|
29
30
|
- Retrieve evidence to answer a concrete question. Use representative images for composition; intervals and source video for movement; the audio review and accessible audio for sound; narrative events and relations for hooks, development, payoff and CTA.
|
|
30
31
|
- Read source documents using paths actually returned by the reference manifest. Pin hashes where supported. A script summary is not word-level alignment, and a provider candidate is not a verified measurement.
|
|
31
32
|
- Check coverage, truncation and pagination. Retrieve the relevant remaining pages or source document before generalizing to an entire reference. Do not claim complete analysis from a partial tool response.
|
|
@@ -9,6 +9,8 @@ The public product is EditorBrain. The npm package is `editorbrain`; `editorbrai
|
|
|
9
9
|
|
|
10
10
|
Convert reference evidence into an appropriate edit for this project. Reading the library starts the work; quality is demonstrated in the delivered video.
|
|
11
11
|
|
|
12
|
+
Before selecting a style, use `check_workflow` (CLI: `editorbrain workflow check`) and `search_for_edit` (CLI: `editorbrain search edit`) with the actual script or owned production video and project ID. Respect the returned review mode: direct editing, a choice of directions, or approval of a customer-material sample. Check the preference version again before costly generation and full rendering; a web change cannot interrupt a running tool. Honor current explicit user instructions and existing approval. If these tools are unavailable, report the version limitation and inspect material and evidence explicitly; literal search is not an equivalent quality ranking.
|
|
13
|
+
|
|
12
14
|
1. Read the bundled [AGENTS.md](AGENTS.md) before using the workflow. It is this skill's editorial contract; do not assume your host auto-loads it.
|
|
13
15
|
2. Read [CLI and MCP](references/cli-mcp.md) when connecting, locating documents, retrieving reference media or saving work. Discover the installed CLI help and connected MCP tool schemas; they take precedence over examples for version-specific arguments.
|
|
14
16
|
3. Read [Workspace files](references/workspace-files.md) when configuring a brand/style, creating projects, resolving preferences, saving feedback or upgrading an installed skill.
|
|
@@ -132,3 +132,37 @@ Codex can use `codex mcp login editorbrain`; Claude Code completes OAuth from `/
|
|
|
132
132
|
`editorbrain narrative search [query] --kind hook --channel visual` finds candidates. `narrative get <video-id> --sha256 <document-hash> --event-offset 0 --relation-offset 0 --limit 50` pages through one pinned narrative document; follow returned offsets. Missing narrative coverage stays explicit.
|
|
133
133
|
|
|
134
134
|
`editorbrain library media <video-id> --sha256 <media-hash> --out <new-file>` downloads an authorized frame/audio/video and verifies its hash (90 MiB maximum). It will not overwrite an existing file. Downloading is not reviewing: inspect it with available visual/audio tools and record the intervals actually checked. Neither CLI nor MCP ingest customer references.
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
## Content-first search and web preferences (0.8+)
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
editorbrain workflow check --project my-video
|
|
141
|
+
editorbrain search edit --script ./script.txt --project my-video --mode both
|
|
142
|
+
editorbrain search edit --video ./analysis-proxy.mp4 --project my-video
|
|
143
|
+
editorbrain workflow check --project my-video --previous-version <returned-hash>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
MCP equivalents: `check_workflow` and `search_for_edit`. Use their current schemas.
|
|
147
|
+
A topic alone is insufficient. A project may supply its saved script; passing a video
|
|
148
|
+
uploads that selected production asset to the workspace, then sends it to the configured
|
|
149
|
+
analysis provider. This is customer material, not a new library reference. No automatic
|
|
150
|
+
scraping, FFmpeg installation, asset generation or rendering occurs.
|
|
151
|
+
|
|
152
|
+
Video inputs currently accept MP4/MOV/WebM up to 12 MiB and 24,000 analysis input tokens.
|
|
153
|
+
For a larger source, prepare a complete analysis proxy with the available media tools;
|
|
154
|
+
keep the original and record duration/coverage. If using excerpts, disclose omitted
|
|
155
|
+
content. Never treat coarse model timing as frame-accurate or inferred sound as verified.
|
|
156
|
+
Scripts accept up to 16,000 characters. Search may take longer than a literal lookup.
|
|
157
|
+
|
|
158
|
+
Results include source hashes, observed/inferred limitations, applicable evidence,
|
|
159
|
+
missing resources, current workflow version and per-stage elapsed time/token usage.
|
|
160
|
+
A null token count means the provider did not report it, not zero. Follow pinned
|
|
161
|
+
source paths and retrieve needed example media; do not enumerate the entire library.
|
|
162
|
+
If no fit exists, disclose the gap rather than fabricate a matching style. Source,
|
|
163
|
+
reference access or preference changes during a search invalidate that result.
|
|
164
|
+
|
|
165
|
+
Web preferences are pulled at checkpoints, not pushed into arbitrary agent chats.
|
|
166
|
+
`check_workflow` records a receipt; it cannot stop a tool already running. After a
|
|
167
|
+
version change, reconcile the next step and relevant approval with the current user
|
|
168
|
+
instruction. Do not repeat approval just because an unrelated preference changed.
|
|
@@ -79,3 +79,13 @@ Save reusable feedback at its stated scope: project-only changes in the project,
|
|
|
79
79
|
Updating the global CLI does not replace skills already copied into a project. Run `editorbrain skill install --dir <workspace> --agent both` and inspect `conflicts`, `preserved`, `warnings` and `readInstructions`.
|
|
80
80
|
|
|
81
81
|
If skill files differ, the installer keeps them. Prepare the new version in a separate temporary directory, compare it with the project's installed copy, and merge changes while preserving custom instructions. Do not assume a successful exit means all guidance was upgraded. Root `AGENTS.md`/`CLAUDE.md` remain user-owned: if already present, use the returned skill path explicitly, or add a narrowly scoped pointer when the user asks to integrate it. There is no automatic global installation for every future project.
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
## Review preference
|
|
85
|
+
|
|
86
|
+
`videos/<id>/project.json` optionally stores `reviewMode`: `direct`, `directions`, or
|
|
87
|
+
`sample`. Omit it to inherit the workspace default saved in the web app. The current
|
|
88
|
+
explicit user instruction takes precedence. Read the effective value with
|
|
89
|
+
`check_workflow` / `editorbrain workflow check`; local files alone cannot reveal a
|
|
90
|
+
new web preference. Store received versions and scoped approvals in `direction.md`.
|
|
91
|
+
Brand colors/fonts and editing effects/music remain in their existing files.
|