feat: initial commit - Jhonny Editor
- Adicionado estrutura completa do projeto - Configurado MCP server para Premiere Pro - Adicionado documentação e skills - Configurado Gitignore para o projeto
This commit is contained in:
Executable
+130
@@ -0,0 +1,130 @@
|
||||
import { buildToolScript } from "../bridge/script-builder.js";
|
||||
import { sendCommand, type BridgeOptions, type CommandResult } from "../bridge/file-bridge.js";
|
||||
import {
|
||||
buildProjectIntakeReport,
|
||||
MAX_PROJECT_INTAKE_ITEMS,
|
||||
} from "../intake/project-intake.js";
|
||||
|
||||
export interface ProjectIntakeToolDependencies {
|
||||
captureSnapshot?: (maxItems: number) => Promise<CommandResult>;
|
||||
}
|
||||
|
||||
function boundedMaxItems(value: unknown): number {
|
||||
if (value === undefined) return MAX_PROJECT_INTAKE_ITEMS;
|
||||
if (typeof value !== "number" || !Number.isInteger(value) || value < 1 || value > MAX_PROJECT_INTAKE_ITEMS) {
|
||||
throw new Error(`max_items must be an integer from 1 through ${MAX_PROJECT_INTAKE_ITEMS}`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture only the bounded fields required by the pure intake evaluator. The
|
||||
* script does not require an active sequence and never changes Premiere.
|
||||
*/
|
||||
export function projectIntakeCaptureScript(maxItems: number): string {
|
||||
return buildToolScript(`
|
||||
var project = app.project;
|
||||
if (!project || !project.rootItem) return __error("No project is open");
|
||||
|
||||
var maximumItems = ${maxItems};
|
||||
var items = [];
|
||||
var truncated = false;
|
||||
|
||||
function itemType(item) {
|
||||
if (item.type === 2) return "bin";
|
||||
if (item.type === 1 || item.type === 4) return "clip";
|
||||
return "other";
|
||||
}
|
||||
|
||||
function walk(parent, parentId, depth) {
|
||||
if (!parent || !parent.children || depth > 32) {
|
||||
if (depth > 32) truncated = true;
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < parent.children.numItems; i++) {
|
||||
if (items.length >= maximumItems) { truncated = true; return; }
|
||||
var item = parent.children[i];
|
||||
var entry = {
|
||||
id: String(item.nodeId),
|
||||
name: String(item.name),
|
||||
type: itemType(item),
|
||||
parentId: String(parentId || "root")
|
||||
};
|
||||
try { if (item.treePath) entry.treePath = String(item.treePath); } catch(e) {}
|
||||
try {
|
||||
var mediaPath = item.getMediaPath();
|
||||
if (mediaPath) entry.mediaPath = String(mediaPath);
|
||||
} catch(e) {}
|
||||
try { entry.offline = Boolean(item.isOffline()); } catch(e) {}
|
||||
try { entry.hasProxy = Boolean(item.hasProxy()); } catch(e) {}
|
||||
try {
|
||||
var interpretation = item.getFootageInterpretation();
|
||||
if (interpretation && interpretation.frameRate) entry.frameRate = Number(interpretation.frameRate);
|
||||
} catch(e) {}
|
||||
items.push(entry);
|
||||
if (item.type === 2) walk(item, item.nodeId, depth + 1);
|
||||
if (truncated && items.length >= maximumItems) return;
|
||||
}
|
||||
}
|
||||
|
||||
walk(project.rootItem, "root", 0);
|
||||
var projectId = "";
|
||||
try { if (project.documentID) projectId = String(project.documentID); } catch(e) {}
|
||||
if (!projectId) projectId = String(project.name);
|
||||
|
||||
return __result({
|
||||
project: { id: projectId, name: String(project.name) },
|
||||
items: items,
|
||||
truncated: truncated,
|
||||
unavailableEvidence: []
|
||||
});
|
||||
`);
|
||||
}
|
||||
|
||||
export function getProjectIntakeTools(
|
||||
bridgeOptions: BridgeOptions,
|
||||
dependencies: ProjectIntakeToolDependencies = {},
|
||||
) {
|
||||
const capture = dependencies.captureSnapshot
|
||||
?? ((maxItems: number) => sendCommand(projectIntakeCaptureScript(maxItems), bridgeOptions));
|
||||
|
||||
return {
|
||||
preview_project_intake: {
|
||||
description: "Inspect a bounded Premiere project against an explicit facility intake template and return a path-redacted report plus a non-mutating organization proposal. It never changes Premiere or persists the template.",
|
||||
parameters: {
|
||||
type: "object" as const,
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
template: {
|
||||
type: "object",
|
||||
description: "Versioned facility policy. Unknown fields and unsafe matching expressions are rejected by the intake engine.",
|
||||
},
|
||||
include_paths: {
|
||||
type: "boolean",
|
||||
description: "Include observed media paths in findings. Defaults to false; hashes are returned instead.",
|
||||
},
|
||||
max_items: {
|
||||
type: "integer",
|
||||
minimum: 1,
|
||||
maximum: MAX_PROJECT_INTAKE_ITEMS,
|
||||
description: `Maximum project items to inspect; defaults to ${MAX_PROJECT_INTAKE_ITEMS}. Truncation returns an incomplete report.`,
|
||||
},
|
||||
},
|
||||
required: ["template"],
|
||||
},
|
||||
handler: async (args: { template: unknown; include_paths?: boolean; max_items?: number }) => {
|
||||
try {
|
||||
const maxItems = boundedMaxItems(args.max_items);
|
||||
const captured = await capture(maxItems);
|
||||
if (!captured.success) return captured;
|
||||
return {
|
||||
success: true,
|
||||
data: buildProjectIntakeReport(captured.data, args.template, { includePaths: args.include_paths === true }),
|
||||
};
|
||||
} catch (error) {
|
||||
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user