@higgsfield/video-editor-mcp 1.1.0 → 2.0.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 +63 -26
- package/dist/cli.mjs +284 -112
- package/dist/guide.md +2 -3
- package/dist/index.html +1 -1
- package/dist/launcher.mjs +34 -14
- package/dist/server.mjs +209 -265
- package/node_modules/@higgsfield/higgsedit/dist/api.d.ts +481 -0
- package/node_modules/@higgsfield/higgsedit/dist/{chunk-PFQYUJQL.mjs → chunk-3XVMJSV2.mjs} +1 -1
- package/node_modules/@higgsfield/higgsedit/dist/{chunk-F4CMIG5G.mjs → chunk-4VE54E4U.mjs} +3 -1
- package/node_modules/@higgsfield/higgsedit/dist/{chunk-2JYLVSVV.mjs → chunk-55JARHLA.mjs} +205 -65
- package/node_modules/@higgsfield/higgsedit/dist/{chunk-YLVXQIPX.mjs → chunk-E4N76T2R.mjs} +1 -1
- package/node_modules/@higgsfield/higgsedit/dist/{chunk-OCIZ36XD.mjs → chunk-ECRSOIKI.mjs} +1 -1
- package/node_modules/@higgsfield/higgsedit/dist/{chunk-IEPPEDEU.mjs → chunk-ENALCTAD.mjs} +1 -1
- package/node_modules/@higgsfield/higgsedit/dist/chunk-HY2E7IWX.mjs +43 -0
- package/node_modules/@higgsfield/higgsedit/dist/{chunk-NARTAWRN.mjs → chunk-HYCUOCUQ.mjs} +9 -4
- package/node_modules/@higgsfield/higgsedit/dist/{chunk-C3GSB3XZ.mjs → chunk-NLEIBCAK.mjs} +1 -7
- package/node_modules/@higgsfield/higgsedit/dist/{chunk-2WKNH7OL.mjs → chunk-O3AVYZ6U.mjs} +1 -1
- package/node_modules/@higgsfield/higgsedit/dist/chunk-UXO22E3P.mjs +22 -0
- package/node_modules/@higgsfield/higgsedit/dist/{chunk-BH2QF635.mjs → chunk-V5XTCFYK.mjs} +4 -100
- package/node_modules/@higgsfield/higgsedit/dist/chunk-W2TANYEH.mjs +118 -0
- package/node_modules/@higgsfield/higgsedit/dist/{chunk-DVN4LUXV.mjs → chunk-XY5CCUOZ.mjs} +2 -6
- package/node_modules/@higgsfield/higgsedit/dist/{chunk-KIWGVAPJ.mjs → chunk-Y7SAX2P4.mjs} +8 -12
- package/node_modules/@higgsfield/higgsedit/dist/chunk-YNAIRXOP.mjs +22 -0
- package/node_modules/@higgsfield/higgsedit/dist/{chunk-WENFTPXQ.mjs → chunk-ZO3NDQD3.mjs} +1 -1
- package/node_modules/@higgsfield/higgsedit/dist/higgsedit.mjs +13 -13
- package/node_modules/@higgsfield/higgsedit/package.json +4 -1
- package/package.json +3 -3
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/skills/video-editing/SKILL.md +109 -95
- package/plugin/mcp.json +0 -10
- package/plugin/plugin.json +0 -41
- package/plugin/skills/motion-craft/SKILL.md +0 -87
- package/plugin/skills/motion-craft/agents/openai.yaml +0 -6
- package/plugin/skills/motion-craft/references/causality.md +0 -25
- package/plugin/skills/motion-craft/references/composition.md +0 -20
- package/plugin/skills/motion-craft/references/easing.md +0 -19
- package/plugin/skills/motion-craft/references/qc.md +0 -33
- package/plugin/skills/motion-craft/references/recipes.md +0 -31
- package/plugin/skills/motion-craft/references/stepped.md +0 -43
- package/plugin/skills/motion-craft/references/timing.md +0 -60
- package/plugin/skills/motion-craft/references/tsx.md +0 -60
- package/plugin/skills/motion-craft/references/typography.md +0 -22
- package/plugin/skills/video-editing/agents/openai.yaml +0 -6
- package/plugin/skills/video-editing/references/animation-contract.md +0 -45
- package/plugin/skills/video-editing/references/assembly.md +0 -58
- package/plugin/skills/video-editing/references/caption-systems.md +0 -29
- package/plugin/skills/video-editing/references/caption-titling.md +0 -41
- package/plugin/skills/video-editing/references/clip-geometry.md +0 -37
- package/plugin/skills/video-editing/references/compose.md +0 -283
- package/plugin/skills/video-editing/references/editor-measured.md +0 -37
- package/plugin/skills/video-editing/references/failure-modes.md +0 -37
- package/plugin/skills/video-editing/references/local-setup.md +0 -25
- package/plugin/skills/video-editing/references/motion-language.md +0 -27
- package/plugin/skills/video-editing/references/provenance.md +0 -7
- package/plugin/skills/video-editing/references/sandbox.md +0 -31
- package/plugin/skills/video-editing/references/shot-blueprints.md +0 -24
- package/plugin/skills/video-editing/references/title-animation.md +0 -29
- package/plugin/skills/video-editing/references/tsx-projects.md +0 -187
- package/plugin/skills/video-editing/references/workflows.md +0 -41
package/dist/cli.mjs
CHANGED
|
@@ -9,8 +9,8 @@ var __export = (target, all) => {
|
|
|
9
9
|
|
|
10
10
|
// src/video-editor-local/setup.ts
|
|
11
11
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
12
|
-
import { existsSync as
|
|
13
|
-
import { dirname as dirname4, join as
|
|
12
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync5, rmSync as rmSync4 } from "node:fs";
|
|
13
|
+
import { dirname as dirname4, join as join6 } from "node:path";
|
|
14
14
|
import { pathToFileURL } from "node:url";
|
|
15
15
|
|
|
16
16
|
// src/video-editor-local/higgsedit.ts
|
|
@@ -32,19 +32,10 @@ function findCli(env = process.env, from = import.meta.url) {
|
|
|
32
32
|
return path && existsSync(path) ? path : void 0;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
// src/video-editor-local/
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
|
|
39
|
-
mkdirSync as mkdirSync3,
|
|
40
|
-
readFileSync as readFileSync3,
|
|
41
|
-
renameSync as renameSync2,
|
|
42
|
-
rmSync as rmSync2,
|
|
43
|
-
statSync as statSync2,
|
|
44
|
-
writeFileSync as writeFileSync2
|
|
45
|
-
} from "node:fs";
|
|
46
|
-
import { homedir as homedir2 } from "node:os";
|
|
47
|
-
import { dirname as dirname3, join as join4 } from "node:path";
|
|
35
|
+
// src/video-editor-local/install.ts
|
|
36
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync4, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
37
|
+
import { homedir as homedir3 } from "node:os";
|
|
38
|
+
import { join as join5, sep } from "node:path";
|
|
48
39
|
|
|
49
40
|
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
50
41
|
var external_exports = {};
|
|
@@ -1237,13 +1228,13 @@ function unwrapMessage(message) {
|
|
|
1237
1228
|
}
|
|
1238
1229
|
function finalizeIssue(iss, ctx, config2) {
|
|
1239
1230
|
const message = iss.message ? iss.message : unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config2.customError?.(iss)) ?? unwrapMessage(config2.localeError?.(iss)) ?? "Invalid input";
|
|
1240
|
-
const { inst: _inst, continue: _continue, input: _input, ...
|
|
1241
|
-
|
|
1242
|
-
|
|
1231
|
+
const { inst: _inst, continue: _continue, input: _input, ...rest2 } = iss;
|
|
1232
|
+
rest2.path ?? (rest2.path = []);
|
|
1233
|
+
rest2.message = message;
|
|
1243
1234
|
if (ctx?.reportInput) {
|
|
1244
|
-
|
|
1235
|
+
rest2.input = _input;
|
|
1245
1236
|
}
|
|
1246
|
-
return
|
|
1237
|
+
return rest2;
|
|
1247
1238
|
}
|
|
1248
1239
|
function getSizableOrigin(input) {
|
|
1249
1240
|
if (input instanceof Set)
|
|
@@ -2630,11 +2621,11 @@ var $ZodCIDRv6 = /* @__PURE__ */ $constructor("$ZodCIDRv6", (inst, def) => {
|
|
|
2630
2621
|
try {
|
|
2631
2622
|
if (parts.length !== 2)
|
|
2632
2623
|
throw new Error();
|
|
2633
|
-
const [address,
|
|
2634
|
-
if (!
|
|
2624
|
+
const [address, prefix2] = parts;
|
|
2625
|
+
if (!prefix2)
|
|
2635
2626
|
throw new Error();
|
|
2636
|
-
const prefixNum = Number(
|
|
2637
|
-
if (`${prefixNum}` !==
|
|
2627
|
+
const prefixNum = Number(prefix2);
|
|
2628
|
+
if (`${prefixNum}` !== prefix2)
|
|
2638
2629
|
throw new Error();
|
|
2639
2630
|
if (prefixNum < 0 || prefixNum > 128)
|
|
2640
2631
|
throw new Error();
|
|
@@ -3583,8 +3574,8 @@ var $ZodTuple = /* @__PURE__ */ $constructor("$ZodTuple", (inst, def) => {
|
|
|
3583
3574
|
}
|
|
3584
3575
|
if (def.rest) {
|
|
3585
3576
|
let i = items.length - 1;
|
|
3586
|
-
const
|
|
3587
|
-
for (const el of
|
|
3577
|
+
const rest2 = input.slice(items.length);
|
|
3578
|
+
for (const el of rest2) {
|
|
3588
3579
|
i++;
|
|
3589
3580
|
const result = def.rest._zod.run({ value: el, issues: [] }, ctx);
|
|
3590
3581
|
if (result instanceof Promise) {
|
|
@@ -11042,12 +11033,12 @@ function _includes(includes, params) {
|
|
|
11042
11033
|
});
|
|
11043
11034
|
}
|
|
11044
11035
|
// @__NO_SIDE_EFFECTS__
|
|
11045
|
-
function _startsWith(
|
|
11036
|
+
function _startsWith(prefix2, params) {
|
|
11046
11037
|
return new $ZodCheckStartsWith({
|
|
11047
11038
|
check: "string_format",
|
|
11048
11039
|
format: "starts_with",
|
|
11049
11040
|
...normalizeParams(params),
|
|
11050
|
-
prefix
|
|
11041
|
+
prefix: prefix2
|
|
11051
11042
|
});
|
|
11052
11043
|
}
|
|
11053
11044
|
// @__NO_SIDE_EFFECTS__
|
|
@@ -11151,11 +11142,11 @@ function _intersection(Class2, left, right) {
|
|
|
11151
11142
|
function _tuple(Class2, items, _paramsOrRest, _params) {
|
|
11152
11143
|
const hasRest = _paramsOrRest instanceof $ZodType;
|
|
11153
11144
|
const params = hasRest ? _params : _paramsOrRest;
|
|
11154
|
-
const
|
|
11145
|
+
const rest2 = hasRest ? _paramsOrRest : null;
|
|
11155
11146
|
return new Class2({
|
|
11156
11147
|
type: "tuple",
|
|
11157
11148
|
items,
|
|
11158
|
-
rest,
|
|
11149
|
+
rest: rest2,
|
|
11159
11150
|
...normalizeParams(params)
|
|
11160
11151
|
});
|
|
11161
11152
|
}
|
|
@@ -12136,30 +12127,30 @@ var tupleProcessor = (schema, ctx, _json, params) => {
|
|
|
12136
12127
|
...params,
|
|
12137
12128
|
path: [...params.path, prefixPath, i]
|
|
12138
12129
|
}));
|
|
12139
|
-
const
|
|
12130
|
+
const rest2 = def.rest ? process2(def.rest, ctx, {
|
|
12140
12131
|
...params,
|
|
12141
12132
|
path: [...params.path, restPath, ...ctx.target === "openapi-3.0" ? [def.items.length] : []]
|
|
12142
12133
|
}) : null;
|
|
12143
12134
|
if (ctx.target === "draft-2020-12") {
|
|
12144
12135
|
json2.prefixItems = prefixItems;
|
|
12145
|
-
if (
|
|
12146
|
-
json2.items =
|
|
12136
|
+
if (rest2) {
|
|
12137
|
+
json2.items = rest2;
|
|
12147
12138
|
}
|
|
12148
12139
|
} else if (ctx.target === "openapi-3.0") {
|
|
12149
12140
|
json2.items = {
|
|
12150
12141
|
anyOf: prefixItems
|
|
12151
12142
|
};
|
|
12152
|
-
if (
|
|
12153
|
-
json2.items.anyOf.push(
|
|
12143
|
+
if (rest2) {
|
|
12144
|
+
json2.items.anyOf.push(rest2);
|
|
12154
12145
|
}
|
|
12155
12146
|
json2.minItems = prefixItems.length;
|
|
12156
|
-
if (!
|
|
12147
|
+
if (!rest2) {
|
|
12157
12148
|
json2.maxItems = prefixItems.length;
|
|
12158
12149
|
}
|
|
12159
12150
|
} else {
|
|
12160
12151
|
json2.items = prefixItems;
|
|
12161
|
-
if (
|
|
12162
|
-
json2.additionalItems =
|
|
12152
|
+
if (rest2) {
|
|
12153
|
+
json2.additionalItems = rest2;
|
|
12163
12154
|
}
|
|
12164
12155
|
}
|
|
12165
12156
|
const { minimum, maximum } = schema._zod.bag;
|
|
@@ -13524,19 +13515,19 @@ var ZodTuple = /* @__PURE__ */ $constructor("ZodTuple", (inst, def) => {
|
|
|
13524
13515
|
$ZodTuple.init(inst, def);
|
|
13525
13516
|
ZodType.init(inst, def);
|
|
13526
13517
|
inst._zod.processJSONSchema = (ctx, json2, params) => tupleProcessor(inst, ctx, json2, params);
|
|
13527
|
-
inst.rest = (
|
|
13518
|
+
inst.rest = (rest2) => inst.clone({
|
|
13528
13519
|
...inst._zod.def,
|
|
13529
|
-
rest
|
|
13520
|
+
rest: rest2
|
|
13530
13521
|
});
|
|
13531
13522
|
});
|
|
13532
13523
|
function tuple(items, _paramsOrRest, _params) {
|
|
13533
13524
|
const hasRest = _paramsOrRest instanceof $ZodType;
|
|
13534
13525
|
const params = hasRest ? _params : _paramsOrRest;
|
|
13535
|
-
const
|
|
13526
|
+
const rest2 = hasRest ? _paramsOrRest : null;
|
|
13536
13527
|
return new ZodTuple({
|
|
13537
13528
|
type: "tuple",
|
|
13538
13529
|
items,
|
|
13539
|
-
rest,
|
|
13530
|
+
rest: rest2,
|
|
13540
13531
|
...util_exports.normalizeParams(params)
|
|
13541
13532
|
});
|
|
13542
13533
|
}
|
|
@@ -14400,9 +14391,9 @@ function convertBaseSchema(schema, ctx) {
|
|
|
14400
14391
|
const items = schema.items;
|
|
14401
14392
|
if (prefixItems && Array.isArray(prefixItems)) {
|
|
14402
14393
|
const tupleItems = prefixItems.map((item) => convertSchema(item, ctx));
|
|
14403
|
-
const
|
|
14404
|
-
if (
|
|
14405
|
-
zodSchema = z.tuple(tupleItems).rest(
|
|
14394
|
+
const rest2 = items && typeof items === "object" && !Array.isArray(items) ? convertSchema(items, ctx) : void 0;
|
|
14395
|
+
if (rest2) {
|
|
14396
|
+
zodSchema = z.tuple(tupleItems).rest(rest2);
|
|
14406
14397
|
} else {
|
|
14407
14398
|
zodSchema = z.tuple(tupleItems);
|
|
14408
14399
|
}
|
|
@@ -14414,9 +14405,9 @@ function convertBaseSchema(schema, ctx) {
|
|
|
14414
14405
|
}
|
|
14415
14406
|
} else if (Array.isArray(items)) {
|
|
14416
14407
|
const tupleItems = items.map((item) => convertSchema(item, ctx));
|
|
14417
|
-
const
|
|
14418
|
-
if (
|
|
14419
|
-
zodSchema = z.tuple(tupleItems).rest(
|
|
14408
|
+
const rest2 = schema.additionalItems && typeof schema.additionalItems === "object" ? convertSchema(schema.additionalItems, ctx) : void 0;
|
|
14409
|
+
if (rest2) {
|
|
14410
|
+
zodSchema = z.tuple(tupleItems).rest(rest2);
|
|
14420
14411
|
} else {
|
|
14421
14412
|
zodSchema = z.tuple(tupleItems);
|
|
14422
14413
|
}
|
|
@@ -14602,8 +14593,8 @@ var ensureCodexHome = () => mkdirSync(process.env.CODEX_HOME ?? join2(homedir(),
|
|
|
14602
14593
|
function installCodex(name, entry2, ours) {
|
|
14603
14594
|
ensureCodexHome();
|
|
14604
14595
|
const codex = findCodex();
|
|
14605
|
-
const
|
|
14606
|
-
const current =
|
|
14596
|
+
const run2 = (...args) => spawnSync(codex, args, { encoding: "utf8" });
|
|
14597
|
+
const current = run2("mcp", "get", name, "--json");
|
|
14607
14598
|
if (current.status === 0) {
|
|
14608
14599
|
const { transport } = JSON.parse(current.stdout);
|
|
14609
14600
|
if (transport?.command === entry2.command && transport.args?.join("\0") === entry2.args.join("\0"))
|
|
@@ -14612,15 +14603,16 @@ function installCodex(name, entry2, ours) {
|
|
|
14612
14603
|
throw new Error(
|
|
14613
14604
|
`${name} already exists with a different configuration; review it with \`codex mcp get ${name}\`. Nothing changed.`
|
|
14614
14605
|
);
|
|
14615
|
-
const removed =
|
|
14606
|
+
const removed = run2("mcp", "remove", name);
|
|
14616
14607
|
if (removed.status !== 0) throw new Error(removed.stderr || `Could not update ${name}.`);
|
|
14617
14608
|
}
|
|
14618
|
-
const added =
|
|
14609
|
+
const added = run2("mcp", "add", name, "--", entry2.command, ...entry2.args);
|
|
14619
14610
|
if (added.status !== 0) throw new Error(added.stderr || "Codex registration failed.");
|
|
14620
14611
|
return `Registered ${name}. Start a new chat to use it.`;
|
|
14621
14612
|
}
|
|
14622
14613
|
|
|
14623
14614
|
// src/adapters/codex-plugin.ts
|
|
14615
|
+
var marketplaceName = (channel) => `higgsfield-video-editor-updates-${channel}`;
|
|
14624
14616
|
var PLUGIN_ROLLBACK_ERROR = "Plugin refresh failed and rollback requires attention.";
|
|
14625
14617
|
var identity = external_exports.object({
|
|
14626
14618
|
name: external_exports.string().regex(/^[a-z][a-z0-9-]{0,63}$/),
|
|
@@ -14649,7 +14641,7 @@ function validateTree(root) {
|
|
|
14649
14641
|
}
|
|
14650
14642
|
}
|
|
14651
14643
|
function bindPackageRuntime(root, dist) {
|
|
14652
|
-
for (const file2 of ["
|
|
14644
|
+
for (const file2 of [".mcp.json"]) {
|
|
14653
14645
|
const path = join3(root, file2);
|
|
14654
14646
|
if (!existsSync2(path)) continue;
|
|
14655
14647
|
const config2 = external_exports.object({ mcpServers: external_exports.record(external_exports.string(), external_exports.unknown()) }).parse(JSON.parse(readFileSync2(path, "utf8")));
|
|
@@ -14672,14 +14664,34 @@ function bundledPlugin(options) {
|
|
|
14672
14664
|
if (!existsSync2(root)) return null;
|
|
14673
14665
|
if (!lstatSync(root).isDirectory()) throw new Error("Plugin bundle must be a directory");
|
|
14674
14666
|
validateTree(root);
|
|
14675
|
-
const manifest = identity.parse(
|
|
14676
|
-
const codex = identity.parse(
|
|
14667
|
+
const manifest = identity.parse(
|
|
14677
14668
|
JSON.parse(readFileSync2(join3(root, ".codex-plugin/plugin.json"), "utf8"))
|
|
14678
14669
|
);
|
|
14679
|
-
if (manifest.
|
|
14670
|
+
if (manifest.version !== options.version)
|
|
14680
14671
|
throw new Error("Plugin identity/version must match its package and Codex manifest");
|
|
14681
14672
|
return { root, name: manifest.name };
|
|
14682
14673
|
}
|
|
14674
|
+
var marketplaceList = external_exports.object({
|
|
14675
|
+
marketplaces: external_exports.array(external_exports.object({ name: external_exports.string(), root: external_exports.string() }))
|
|
14676
|
+
});
|
|
14677
|
+
function listMarketplaces(codex, runner, install) {
|
|
14678
|
+
const list = () => marketplaceList.parse(JSON.parse(runner(codex, ["plugin", "marketplace", "list", "--json"]))).marketplaces;
|
|
14679
|
+
try {
|
|
14680
|
+
return list();
|
|
14681
|
+
} catch (error51) {
|
|
14682
|
+
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
14683
|
+
const broken = [...message.matchAll(/^- `([^`]+)` at /gm)].map((match) => match[1]);
|
|
14684
|
+
if (!broken.length) throw error51;
|
|
14685
|
+
const ours = broken.filter((name) => name.startsWith("higgsfield-video-editor-"));
|
|
14686
|
+
if (install && ours.length === broken.length) {
|
|
14687
|
+
for (const name of ours) runner(codex, ["plugin", "marketplace", "remove", name]);
|
|
14688
|
+
return list();
|
|
14689
|
+
}
|
|
14690
|
+
throw new Error(
|
|
14691
|
+
`The ChatGPT desktop app has plugin registrations whose folders are gone: ${broken.join(", ")}. Run \`codex plugin marketplace remove <name>\` for each, then try again.`
|
|
14692
|
+
);
|
|
14693
|
+
}
|
|
14694
|
+
}
|
|
14683
14695
|
function refreshBundledPlugin(options, install = false, runner = run) {
|
|
14684
14696
|
const marker = join3(options.root, "plugin-registration.json");
|
|
14685
14697
|
if (!install && !existsSync2(marker)) return void 0;
|
|
@@ -14692,21 +14704,20 @@ function refreshBundledPlugin(options, install = false, runner = run) {
|
|
|
14692
14704
|
if (previous && previous.name !== bundle.name)
|
|
14693
14705
|
throw new Error("Plugin identity changed; refusing to replace it");
|
|
14694
14706
|
const codex = previous?.codex ?? findCodex("plugin");
|
|
14695
|
-
const
|
|
14707
|
+
const marketplace = marketplaceName(options.channel);
|
|
14696
14708
|
const root = join3(options.root, "marketplace");
|
|
14697
14709
|
mkdirSync2(root, { recursive: true });
|
|
14698
|
-
const
|
|
14699
|
-
|
|
14700
|
-
(marketplace) => marketplace.name === marketplaceName
|
|
14710
|
+
const existing = listMarketplaces(codex, runner, install).find(
|
|
14711
|
+
(entry2) => entry2.name === marketplace
|
|
14701
14712
|
);
|
|
14702
14713
|
if (existing && realpathSync(existing.root) !== realpathSync(root))
|
|
14703
14714
|
throw new Error("Marketplace name belongs to another source; nothing changed");
|
|
14704
14715
|
const installedSchema = external_exports.object({
|
|
14705
14716
|
installed: external_exports.array(external_exports.object({ pluginId: external_exports.string(), enabled: external_exports.boolean() }))
|
|
14706
14717
|
});
|
|
14707
|
-
const selector = `${bundle.name}@${
|
|
14718
|
+
const selector = `${bundle.name}@${marketplace}`;
|
|
14708
14719
|
const current = installedSchema.parse(
|
|
14709
|
-
JSON.parse(runner(codex, ["plugin", "list", "--marketplace",
|
|
14720
|
+
JSON.parse(runner(codex, ["plugin", "list", "--marketplace", marketplace, "--json"]))
|
|
14710
14721
|
).installed.find((plugin) => plugin.pluginId === selector);
|
|
14711
14722
|
if (!install && (!current || !current.enabled))
|
|
14712
14723
|
throw new Error("Plugin was removed or disabled; refusing to reinstall or re-enable it");
|
|
@@ -14741,7 +14752,7 @@ function refreshBundledPlugin(options, install = false, runner = run) {
|
|
|
14741
14752
|
if (current) runner(codex, ["plugin", "add", selector, "--json"]);
|
|
14742
14753
|
else runner(codex, ["plugin", "remove", selector]);
|
|
14743
14754
|
}
|
|
14744
|
-
if (addedMarketplace) runner(codex, ["plugin", "marketplace", "remove",
|
|
14755
|
+
if (addedMarketplace) runner(codex, ["plugin", "marketplace", "remove", marketplace]);
|
|
14745
14756
|
if (oldCatalog === null) rmSync(catalog, { force: true });
|
|
14746
14757
|
if (oldMarker !== null) writeAtomic(marker, oldMarker);
|
|
14747
14758
|
else rmSync(marker, { force: true });
|
|
@@ -14750,7 +14761,7 @@ function refreshBundledPlugin(options, install = false, runner = run) {
|
|
|
14750
14761
|
writeAtomic(
|
|
14751
14762
|
catalog,
|
|
14752
14763
|
JSON.stringify({
|
|
14753
|
-
name:
|
|
14764
|
+
name: marketplace,
|
|
14754
14765
|
interface: { displayName: "Higgsfield Video Editor Updates" },
|
|
14755
14766
|
plugins: [
|
|
14756
14767
|
{
|
|
@@ -14782,6 +14793,18 @@ function refreshBundledPlugin(options, install = false, runner = run) {
|
|
|
14782
14793
|
}
|
|
14783
14794
|
|
|
14784
14795
|
// src/video-editor-local/updates.ts
|
|
14796
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
14797
|
+
import {
|
|
14798
|
+
existsSync as existsSync3,
|
|
14799
|
+
mkdirSync as mkdirSync3,
|
|
14800
|
+
readFileSync as readFileSync3,
|
|
14801
|
+
renameSync as renameSync2,
|
|
14802
|
+
rmSync as rmSync2,
|
|
14803
|
+
statSync as statSync2,
|
|
14804
|
+
writeFileSync as writeFileSync2
|
|
14805
|
+
} from "node:fs";
|
|
14806
|
+
import { homedir as homedir2 } from "node:os";
|
|
14807
|
+
import { dirname as dirname3, join as join4 } from "node:path";
|
|
14785
14808
|
var UPDATE_PACKAGE = "@higgsfield/video-editor-mcp";
|
|
14786
14809
|
var UPDATE_REGISTRY = "https://registry.npmjs.org/";
|
|
14787
14810
|
var CHECK_INTERVAL = 60 * 60 * 1e3;
|
|
@@ -14843,8 +14866,8 @@ function newerVersion(candidate, current) {
|
|
|
14843
14866
|
}
|
|
14844
14867
|
return false;
|
|
14845
14868
|
}
|
|
14846
|
-
function packageDist(
|
|
14847
|
-
return join4(
|
|
14869
|
+
function packageDist(prefix2) {
|
|
14870
|
+
return join4(prefix2, "node_modules", UPDATE_PACKAGE, "dist");
|
|
14848
14871
|
}
|
|
14849
14872
|
function validPackage(dist, version2) {
|
|
14850
14873
|
try {
|
|
@@ -14871,7 +14894,7 @@ function saveState(root, state) {
|
|
|
14871
14894
|
writeFileSync2(temp, JSON.stringify(state));
|
|
14872
14895
|
renameSync2(temp, join4(root, "state.json"));
|
|
14873
14896
|
}
|
|
14874
|
-
var
|
|
14897
|
+
var defaultRunner = (command2, args, timeout, cwd) => execFileSync2(command2, args, {
|
|
14875
14898
|
cwd,
|
|
14876
14899
|
env: Object.fromEntries(
|
|
14877
14900
|
Object.entries(process.env).filter(([name]) => !name.toLowerCase().startsWith("npm_config_"))
|
|
@@ -14882,7 +14905,7 @@ var run2 = (command2, args, timeout, cwd) => execFileSync2(command2, args, {
|
|
|
14882
14905
|
maxBuffer: 1024 * 1024,
|
|
14883
14906
|
stdio: ["ignore", "pipe", "pipe"]
|
|
14884
14907
|
});
|
|
14885
|
-
function updateEditor(options, force = false, runner =
|
|
14908
|
+
function updateEditor(options, force = false, runner = defaultRunner) {
|
|
14886
14909
|
const { root, channel } = options;
|
|
14887
14910
|
if (!force && !checkDue(root)) return "Already checked within the last hour.";
|
|
14888
14911
|
mkdirSync3(root, { recursive: true });
|
|
@@ -14987,6 +15010,71 @@ function updateEditor(options, force = false, runner = run2) {
|
|
|
14987
15010
|
}
|
|
14988
15011
|
}
|
|
14989
15012
|
|
|
15013
|
+
// src/video-editor-local/install.ts
|
|
15014
|
+
var INSTALL_PREFIX = join5(homedir3(), ".higgsfield", "video-editor-mcp");
|
|
15015
|
+
var installedCli = (prefix2 = INSTALL_PREFIX) => join5(prefix2, "node_modules", UPDATE_PACKAGE, "dist", "cli.mjs");
|
|
15016
|
+
function installPrefixOf(dist) {
|
|
15017
|
+
const parts = dist.split(sep);
|
|
15018
|
+
if (parts.includes("_npx")) return void 0;
|
|
15019
|
+
if (parts.slice(-4).join("/") !== `node_modules/${UPDATE_PACKAGE}/dist`) return void 0;
|
|
15020
|
+
return parts.slice(0, -4).join(sep);
|
|
15021
|
+
}
|
|
15022
|
+
function installPackage(version2, prefix2 = INSTALL_PREFIX, runner = defaultRunner) {
|
|
15023
|
+
mkdirSync4(prefix2, { recursive: true });
|
|
15024
|
+
const userConfig = join5(prefix2, "npmrc");
|
|
15025
|
+
const globalConfig2 = join5(prefix2, "npmrc-global");
|
|
15026
|
+
writeFileSync3(userConfig, `registry=${UPDATE_REGISTRY}
|
|
15027
|
+
`);
|
|
15028
|
+
writeFileSync3(globalConfig2, "");
|
|
15029
|
+
runner(
|
|
15030
|
+
"npm",
|
|
15031
|
+
[
|
|
15032
|
+
"install",
|
|
15033
|
+
"--prefix",
|
|
15034
|
+
prefix2,
|
|
15035
|
+
"--ignore-scripts",
|
|
15036
|
+
"--no-audit",
|
|
15037
|
+
"--no-fund",
|
|
15038
|
+
"--save-exact",
|
|
15039
|
+
"--engine-strict",
|
|
15040
|
+
`--registry=${UPDATE_REGISTRY}`,
|
|
15041
|
+
`--userconfig=${userConfig}`,
|
|
15042
|
+
`--globalconfig=${globalConfig2}`,
|
|
15043
|
+
"--fetch-retries=2",
|
|
15044
|
+
`${UPDATE_PACKAGE}@${version2}`
|
|
15045
|
+
],
|
|
15046
|
+
3e5,
|
|
15047
|
+
prefix2
|
|
15048
|
+
);
|
|
15049
|
+
const cli = installedCli(prefix2);
|
|
15050
|
+
if (!existsSync4(cli))
|
|
15051
|
+
throw new Error(`${UPDATE_PACKAGE}@${version2} did not install under ${prefix2}.`);
|
|
15052
|
+
return cli;
|
|
15053
|
+
}
|
|
15054
|
+
var registration2 = external_exports.object({ name: external_exports.string().min(1), codex: external_exports.string().min(1) });
|
|
15055
|
+
function uninstallEditor(prefix2 = INSTALL_PREFIX, runner = defaultRunner) {
|
|
15056
|
+
const lines = [];
|
|
15057
|
+
for (const channel of ["latest", "next"]) {
|
|
15058
|
+
const marker = join5(prefix2, "public-updates", channel, "plugin-registration.json");
|
|
15059
|
+
if (!existsSync4(marker)) continue;
|
|
15060
|
+
const { name, codex } = registration2.parse(JSON.parse(readFileSync4(marker, "utf8")));
|
|
15061
|
+
const marketplace = marketplaceName(channel);
|
|
15062
|
+
for (const args of [
|
|
15063
|
+
["plugin", "remove", `${name}@${marketplace}`],
|
|
15064
|
+
["plugin", "marketplace", "remove", marketplace]
|
|
15065
|
+
]) {
|
|
15066
|
+
try {
|
|
15067
|
+
runner(codex, args, 2e4, prefix2);
|
|
15068
|
+
} catch {
|
|
15069
|
+
}
|
|
15070
|
+
}
|
|
15071
|
+
lines.push(`Removed the ${name} plugin from the ChatGPT desktop app.`);
|
|
15072
|
+
}
|
|
15073
|
+
rmSync3(prefix2, { recursive: true, force: true });
|
|
15074
|
+
lines.push(`Removed ${prefix2}. Your projects were not touched.`);
|
|
15075
|
+
return lines.join("\n");
|
|
15076
|
+
}
|
|
15077
|
+
|
|
14990
15078
|
// src/adapters/claude.ts
|
|
14991
15079
|
var claudeConfig = (name, entry2) => ({
|
|
14992
15080
|
mcpServers: { [name]: entry2 }
|
|
@@ -14995,38 +15083,142 @@ var claudeConfig = (name, entry2) => ({
|
|
|
14995
15083
|
// src/video-editor-local/setup.ts
|
|
14996
15084
|
var NAME = "higgsfield-use-video-editor";
|
|
14997
15085
|
var DIST = dirname4(import.meta.filename);
|
|
14998
|
-
var SERVER =
|
|
14999
|
-
var LAUNCHER =
|
|
15000
|
-
var PANEL =
|
|
15086
|
+
var SERVER = join6(DIST, "server.mjs");
|
|
15087
|
+
var LAUNCHER = join6(DIST, "launcher.mjs");
|
|
15088
|
+
var PANEL = join6(DIST, "index.html");
|
|
15001
15089
|
var entry = { command: process.execPath, args: [LAUNCHER] };
|
|
15090
|
+
var INSTALL = `npx ${UPDATE_PACKAGE} install`;
|
|
15091
|
+
var prefix = installPrefixOf(DIST);
|
|
15092
|
+
var persistent = prefix !== void 0;
|
|
15002
15093
|
function doctor() {
|
|
15003
15094
|
const [major = 0, minor = 0] = process.versions.node.split(".").map(Number);
|
|
15004
15095
|
const cli = findCli({}, pathToFileURL(SERVER).href);
|
|
15005
|
-
const
|
|
15096
|
+
const report = cli ? spawnSync2(process.execPath, [cli, "doctor", "--json"], { encoding: "utf8" }) : void 0;
|
|
15097
|
+
let diagnosis;
|
|
15098
|
+
try {
|
|
15099
|
+
diagnosis = report ? JSON.parse(report.stdout) : void 0;
|
|
15100
|
+
} catch {
|
|
15101
|
+
diagnosis = void 0;
|
|
15102
|
+
}
|
|
15006
15103
|
return [
|
|
15007
15104
|
{ name: "node", ok: major > 22 || major === 22 && minor >= 12, detail: process.version },
|
|
15008
15105
|
{ name: "platform", ok: process.platform === "darwin", detail: process.platform },
|
|
15009
|
-
{ name: "server", ok:
|
|
15010
|
-
{ name: "launcher", ok:
|
|
15011
|
-
{ name: "panel", ok:
|
|
15106
|
+
{ name: "server", ok: existsSync5(SERVER), detail: SERVER },
|
|
15107
|
+
{ name: "launcher", ok: existsSync5(LAUNCHER), detail: LAUNCHER },
|
|
15108
|
+
{ name: "panel", ok: existsSync5(PANEL), detail: PANEL },
|
|
15012
15109
|
{
|
|
15013
15110
|
name: "higgsedit",
|
|
15014
|
-
ok:
|
|
15015
|
-
detail:
|
|
15111
|
+
ok: diagnosis !== void 0,
|
|
15112
|
+
detail: cli ? diagnosis ? cli : ((report?.stdout || report?.stderr) ?? "").trim().slice(-500) || "did not answer" : "the bundled CLI is missing"
|
|
15113
|
+
},
|
|
15114
|
+
{
|
|
15115
|
+
name: "ffmpeg",
|
|
15116
|
+
ok: typeof diagnosis?.ffmpeg?.path === "string",
|
|
15117
|
+
detail: diagnosis?.ffmpeg?.path ?? diagnosis?.ffmpeg?.missing ?? "unknown until higgsedit answers"
|
|
15016
15118
|
}
|
|
15017
15119
|
];
|
|
15018
15120
|
}
|
|
15019
|
-
function
|
|
15020
|
-
|
|
15021
|
-
|
|
15022
|
-
|
|
15121
|
+
function listing() {
|
|
15122
|
+
try {
|
|
15123
|
+
const manifest = JSON.parse(
|
|
15124
|
+
readFileSync5(join6(dirname4(DIST), "plugin/.codex-plugin/plugin.json"), "utf8")
|
|
15023
15125
|
);
|
|
15024
|
-
|
|
15025
|
-
|
|
15126
|
+
return {
|
|
15127
|
+
displayName: manifest.interface?.displayName ?? "Higgsfield Video Editor",
|
|
15128
|
+
defaultPrompt: manifest.interface?.defaultPrompt ?? []
|
|
15129
|
+
};
|
|
15130
|
+
} catch {
|
|
15131
|
+
return { displayName: "Higgsfield Video Editor", defaultPrompt: [] };
|
|
15132
|
+
}
|
|
15026
15133
|
}
|
|
15027
|
-
|
|
15134
|
+
function requirePersistent() {
|
|
15135
|
+
if (!persistent) throw new Error(`Run \`${INSTALL}\` first.`);
|
|
15136
|
+
if (!existsSync5(SERVER)) throw new Error(`The server is missing at ${SERVER}; reinstall the package.`);
|
|
15137
|
+
}
|
|
15138
|
+
function installPlugin() {
|
|
15139
|
+
ensureCodexHome();
|
|
15140
|
+
const options = updateOptions(DIST);
|
|
15141
|
+
const lock = join6(options.root, "update.lock");
|
|
15142
|
+
mkdirSync5(options.root, { recursive: true });
|
|
15143
|
+
try {
|
|
15144
|
+
mkdirSync5(lock);
|
|
15145
|
+
} catch {
|
|
15146
|
+
throw new Error("Another update is running; retry after it finishes.");
|
|
15147
|
+
}
|
|
15148
|
+
try {
|
|
15149
|
+
const dist = selectedDist(options);
|
|
15150
|
+
const refreshed = refreshBundledPlugin(
|
|
15151
|
+
dist === DIST ? options : { ...options, dist, version: readUpdateState(options.root).active },
|
|
15152
|
+
true
|
|
15153
|
+
);
|
|
15154
|
+
return refreshed ? "Registered the plugin with the ChatGPT desktop app." : "This package has no plugin bundle.";
|
|
15155
|
+
} finally {
|
|
15156
|
+
rmSync4(lock, { recursive: true, force: true });
|
|
15157
|
+
}
|
|
15158
|
+
}
|
|
15159
|
+
function handOver(args) {
|
|
15160
|
+
const result = spawnSync2(process.execPath, [installedCli(), ...args], { stdio: "inherit" });
|
|
15161
|
+
process.exitCode = result.status ?? 1;
|
|
15162
|
+
}
|
|
15163
|
+
var HELP = `Usage: npx ${UPDATE_PACKAGE} <install|uninstall|doctor|config|update>
|
|
15164
|
+
|
|
15165
|
+
install install the editor under ${INSTALL_PREFIX} and register it with the ChatGPT desktop app
|
|
15166
|
+
uninstall remove that registration and the installed editor (projects are kept)
|
|
15167
|
+
doctor check Node, ffmpeg, the bundled higgsedit CLI, the server and the panel
|
|
15168
|
+
config print the MCP server entry for another client (Claude Code, Codex CLI)
|
|
15169
|
+
update check npm for a newer version now
|
|
15170
|
+
|
|
15171
|
+
Lower level: install-plugin, install-codex (the MCP server alone; remove it with \`codex mcp remove ${NAME}\`).`;
|
|
15172
|
+
var [command = "help", ...rest] = process.argv.slice(2);
|
|
15173
|
+
var delegated = ["uninstall", "doctor", "config", "update", "install-codex", "install-plugin"];
|
|
15028
15174
|
try {
|
|
15029
|
-
if (command === "
|
|
15175
|
+
if (command === "install") {
|
|
15176
|
+
const { version: version2 } = updateOptions(DIST);
|
|
15177
|
+
if (!persistent) {
|
|
15178
|
+
console.log(`Installing ${UPDATE_PACKAGE} ${version2} under ${INSTALL_PREFIX}...`);
|
|
15179
|
+
installPackage(version2);
|
|
15180
|
+
handOver(["install", ...rest]);
|
|
15181
|
+
} else {
|
|
15182
|
+
const checks = doctor();
|
|
15183
|
+
const failed = checks.filter((check2) => !check2.ok);
|
|
15184
|
+
let registered = false;
|
|
15185
|
+
let plugin;
|
|
15186
|
+
try {
|
|
15187
|
+
plugin = installPlugin();
|
|
15188
|
+
registered = true;
|
|
15189
|
+
} catch (error51) {
|
|
15190
|
+
plugin = `Not registered with the ChatGPT desktop app: ${error51 instanceof Error ? error51.message : String(error51)}`;
|
|
15191
|
+
}
|
|
15192
|
+
const { displayName, defaultPrompt } = listing();
|
|
15193
|
+
const next = registered ? [
|
|
15194
|
+
"",
|
|
15195
|
+
`Start a new chat, type @ and pick ${displayName}, then try:`,
|
|
15196
|
+
...defaultPrompt.map((prompt) => ` @${displayName} ${prompt}`),
|
|
15197
|
+
"",
|
|
15198
|
+
`Other MCP clients (Claude Code, the Codex CLI): npx ${UPDATE_PACKAGE} config`
|
|
15199
|
+
] : [
|
|
15200
|
+
"",
|
|
15201
|
+
"For an MCP client (Claude Code, the Codex CLI), add this server:",
|
|
15202
|
+
JSON.stringify(claudeConfig(NAME, entry), null, 2)
|
|
15203
|
+
];
|
|
15204
|
+
console.log(
|
|
15205
|
+
[
|
|
15206
|
+
`Installed ${UPDATE_PACKAGE} ${version2}.`,
|
|
15207
|
+
plugin,
|
|
15208
|
+
...failed.map((check2) => `Needs attention: ${check2.name} (${check2.detail})`),
|
|
15209
|
+
...next
|
|
15210
|
+
].join("\n")
|
|
15211
|
+
);
|
|
15212
|
+
if (failed.some((check2) => ["server", "launcher", "panel", "higgsedit"].includes(check2.name)))
|
|
15213
|
+
process.exitCode = 1;
|
|
15214
|
+
}
|
|
15215
|
+
} else if (delegated.includes(command) && !persistent && existsSync5(installedCli())) {
|
|
15216
|
+
handOver([command, ...rest]);
|
|
15217
|
+
} else if (command === "uninstall") {
|
|
15218
|
+
if (prefix === void 0) throw new Error(`Nothing is installed under ${INSTALL_PREFIX}.`);
|
|
15219
|
+
console.log(uninstallEditor(prefix));
|
|
15220
|
+
} else if (command === "config") {
|
|
15221
|
+
requirePersistent();
|
|
15030
15222
|
console.log(JSON.stringify(claudeConfig(NAME, entry), null, 2));
|
|
15031
15223
|
} else if (command === "doctor") {
|
|
15032
15224
|
const checks = doctor();
|
|
@@ -15036,41 +15228,21 @@ try {
|
|
|
15036
15228
|
);
|
|
15037
15229
|
process.exitCode = ok ? 0 : 1;
|
|
15038
15230
|
} else if (command === "install-codex") {
|
|
15039
|
-
|
|
15231
|
+
requirePersistent();
|
|
15040
15232
|
console.log(installCodex(NAME, entry, [SERVER, LAUNCHER]));
|
|
15041
15233
|
} else if (command === "install-plugin") {
|
|
15042
|
-
|
|
15043
|
-
|
|
15044
|
-
const lock = join5(options.root, "update.lock");
|
|
15045
|
-
mkdirSync4(options.root, { recursive: true });
|
|
15046
|
-
try {
|
|
15047
|
-
mkdirSync4(lock);
|
|
15048
|
-
} catch {
|
|
15049
|
-
throw new Error("Another update is running; retry install-plugin after it finishes.");
|
|
15050
|
-
}
|
|
15051
|
-
try {
|
|
15052
|
-
const dist = selectedDist(options);
|
|
15053
|
-
const refreshed = refreshBundledPlugin(
|
|
15054
|
-
dist === DIST ? options : { ...options, dist, version: readUpdateState(options.root).active },
|
|
15055
|
-
true
|
|
15056
|
-
);
|
|
15057
|
-
console.log(
|
|
15058
|
-
refreshed ? "Installed the bundled plugin. Reload the desktop app to load its skills." : "This package has no plugin bundle yet."
|
|
15059
|
-
);
|
|
15060
|
-
} finally {
|
|
15061
|
-
rmSync3(lock, { recursive: true, force: true });
|
|
15062
|
-
}
|
|
15234
|
+
requirePersistent();
|
|
15235
|
+
console.log(`${installPlugin()} Reload the desktop app to load its skills.`);
|
|
15063
15236
|
} else if (command === "update") {
|
|
15237
|
+
requirePersistent();
|
|
15064
15238
|
const result = updateEditor(updateOptions(DIST), true);
|
|
15065
15239
|
console.log(result);
|
|
15066
15240
|
if (result.startsWith("Update failed")) process.exitCode = 1;
|
|
15067
15241
|
} else if (["help", "--help", "-h"].includes(command)) {
|
|
15068
|
-
console.log(
|
|
15069
|
-
`Usage: fnf-video-editor <doctor|config|install-codex|install-plugin|update>
|
|
15070
|
-
The MCP server is fnf-video-editor-mcp (stdio). Remove it with: codex mcp remove ${NAME}`
|
|
15071
|
-
);
|
|
15242
|
+
console.log(HELP);
|
|
15072
15243
|
} else {
|
|
15073
|
-
throw new Error(`Unknown command '${command}'.
|
|
15244
|
+
throw new Error(`Unknown command '${command}'.
|
|
15245
|
+
${HELP}`);
|
|
15074
15246
|
}
|
|
15075
15247
|
} catch (error51) {
|
|
15076
15248
|
console.error(error51 instanceof Error ? error51.message : String(error51));
|
package/dist/guide.md
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# Local project guide
|
|
2
2
|
|
|
3
|
-
The open folder is a
|
|
4
|
-
|
|
5
|
-
`sandbox_exec` on it.
|
|
3
|
+
The open folder is a higgsedit project: the TSX is the document, and every edit below changes it on the
|
|
4
|
+
user's disk. Nothing is uploaded.
|
|
6
5
|
|
|
7
6
|
## Project
|
|
8
7
|
|