feat: use 0.2 as the default schema (#145)

This commit is contained in:
Samuel Attard 2025-11-01 12:31:25 -07:00 • committed by GitHub
commit 98126b777e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 74 additions and 33 deletions

View file

@ -99,4 +99,4 @@
"@babel/parser": "7.27.3"
},
"packageManager": "yarn@4.10.3+sha512.c38cafb5c7bb273f3926d04e55e1d8c9dfa7d9c3ea1f36a4868fa028b9e5f72298f0b7f401ad5eb921749eb012eb1c3bb74bf7503df3ee43fd600d14a018266f"
}
}

View file

@ -2,8 +2,8 @@ import { confirm, input, select } from "@inquirer/prompts";
import { existsSync, readFileSync, writeFileSync } from "fs";
import { basename, join, resolve } from "path";
import { LATEST_MANIFEST_VERSION } from "../shared/constants.js";
import type { McpbManifestLatest } from "../types.js";
import { DEFAULT_MANIFEST_VERSION } from "../shared/constants.js";
import type { McpbManifest } from "../types.js";
interface PackageJson {
name?: string;
@ -878,14 +878,14 @@ export function buildManifest(
resources: string;
default_locale: string;
},
): McpbManifestLatest {
): McpbManifest {
const { name, displayName, version, description, authorName } = basicInfo;
const { authorEmail, authorUrl } = authorInfo;
const { serverType, entryPoint, mcp_config } = serverConfig;
const { keywords, license, repository } = optionalFields;
return {
manifest_version: LATEST_MANIFEST_VERSION,
manifest_version: DEFAULT_MANIFEST_VERSION,
name,
...(displayName && displayName !== name
? { display_name: displayName }

View file

@ -13,11 +13,9 @@ import { basename, join, relative, resolve, sep } from "path";
import { getAllFilesWithCount, readMcpbIgnorePatterns } from "../node/files.js";
import { validateManifest } from "../node/validate.js";
import {
LATEST_MANIFEST_SCHEMA,
LATEST_MANIFEST_VERSION,
} from "../shared/constants.js";
import { MANIFEST_SCHEMAS } from "../shared/constants.js";
import { getLogger } from "../shared/log.js";
import { getManifestVersionFromRawData } from "../shared/manifestVersionResolve.js";
import { initExtension } from "./init.js";
interface PackOptions {
@ -95,7 +93,18 @@ export async function packExtension({
try {
const manifestContent = readFileSync(manifestPath, "utf-8");
const manifestData = JSON.parse(manifestContent);
manifest = LATEST_MANIFEST_SCHEMA.parse(manifestData);
const manifestVersion = getManifestVersionFromRawData(manifestData);
if (!manifestVersion) {
logger.error(
`ERROR: Manifest version mismatch. Expected "${Object.keys(MANIFEST_SCHEMAS).join(" or ")}", found "${manifestVersion}"`,
);
logger.error(
` Please update the manifest_version in your manifest.json to a supported version`,
);
return false;
}
manifest = MANIFEST_SCHEMAS[manifestVersion].parse(manifestData);
} catch (error) {
logger.error("ERROR: Failed to parse manifest.json");
if (error instanceof Error) {
@ -104,17 +113,6 @@ export async function packExtension({
return false;
}
const manifestVersion = manifest.manifest_version || manifest.dxt_version;
if (manifestVersion !== LATEST_MANIFEST_VERSION) {
logger.error(
`ERROR: Manifest version mismatch. Expected "${LATEST_MANIFEST_VERSION}", found "${manifestVersion}"`,
);
logger.error(
` Please update the manifest_version in your manifest.json to "${LATEST_MANIFEST_VERSION}"`,
);
return false;
}
// Determine output path
const extensionName = basename(resolvedPath);
const finalOutputPath = outputPath

View file

@ -7,9 +7,10 @@ import prettyBytes from "pretty-bytes";
import { unpackExtension } from "../cli/unpack.js";
import {
LATEST_MANIFEST_SCHEMA,
LATEST_MANIFEST_SCHEMA_LOOSE,
MANIFEST_SCHEMAS,
MANIFEST_SCHEMAS_LOOSE,
} from "../shared/constants.js";
import { getManifestVersionFromRawData } from "../shared/manifestVersionResolve.js";
/**
* Check if a buffer contains a valid PNG file signature
@ -119,8 +120,13 @@ export function validateManifest(inputPath: string): boolean {
const manifestContent = readFileSync(manifestPath, "utf-8");
const manifestData = JSON.parse(manifestContent);
const manifestVersion = getManifestVersionFromRawData(manifestData);
if (!manifestVersion) {
console.log("Unrecognized or unsupported manifest version");
return false;
}
const result = LATEST_MANIFEST_SCHEMA.safeParse(manifestData);
const result = MANIFEST_SCHEMAS[manifestVersion].safeParse(manifestData);
if (result.success) {
console.log("Manifest schema validation passes!");
@ -192,7 +198,12 @@ export async function cleanMcpb(inputPath: string) {
const manifestPath = resolve(unpackPath, "manifest.json");
const originalManifest = await fs.readFile(manifestPath, "utf-8");
const manifestData = JSON.parse(originalManifest);
const result = LATEST_MANIFEST_SCHEMA_LOOSE.safeParse(manifestData);
const manifestVersion = getManifestVersionFromRawData(manifestData);
if (!manifestVersion) {
throw new Error("Unrecognized or unsupported manifest version");
}
const result =
MANIFEST_SCHEMAS_LOOSE[manifestVersion].safeParse(manifestData);
if (!result.success) {
throw new Error(

View file

@ -9,9 +9,15 @@ import { McpbManifestSchema as CurrentLooseManifestSchema } from "../schemas_loo
/**
* Latest manifest version - the version that new manifests should use
* @deprecated
*/
export const LATEST_MANIFEST_VERSION = "0.3" as const;
/**
* Default manifest version for new packages
*/
export const DEFAULT_MANIFEST_VERSION = "0.2" as const;
/**
* Map of manifest versions to their strict schemas
*/
@ -32,10 +38,12 @@ export const MANIFEST_SCHEMAS_LOOSE = {
/**
* Get the latest manifest schema based on LATEST_MANIFEST_VERSION
* @deprecated
*/
export const LATEST_MANIFEST_SCHEMA = CurrentManifestSchema;
/**
* Get the latest loose manifest schema based on LATEST_MANIFEST_VERSION
* @deprecated
*/
export const LATEST_MANIFEST_SCHEMA_LOOSE = CurrentLooseManifestSchema;

View file

@ -0,0 +1,24 @@
import { MANIFEST_SCHEMAS } from "./constants.js";
export function getManifestVersionFromRawData(manifestData: unknown) {
let manifestVersion: keyof typeof MANIFEST_SCHEMAS | null = null;
if (
typeof manifestData === "object" &&
manifestData &&
"manifest_version" in manifestData &&
typeof manifestData.manifest_version === "string" &&
Object.keys(MANIFEST_SCHEMAS).includes(manifestData.manifest_version)
) {
manifestVersion =
manifestData.manifest_version as keyof typeof MANIFEST_SCHEMAS;
} else if (
typeof manifestData === "object" &&
manifestData &&
"dxt_version" in manifestData &&
typeof manifestData.dxt_version === "string" &&
Object.keys(MANIFEST_SCHEMAS).includes(manifestData.dxt_version)
) {
manifestVersion = manifestData.dxt_version as keyof typeof MANIFEST_SCHEMAS;
}
return manifestVersion;
}

View file

@ -2,7 +2,7 @@ import { execSync } from "node:child_process";
import fs from "node:fs";
import { join } from "node:path";
import { LATEST_MANIFEST_VERSION } from "../src/schemas/index.js";
import { DEFAULT_MANIFEST_VERSION } from "../src/shared/constants";
interface ExecSyncError extends Error {
stdout: Buffer;
@ -113,7 +113,7 @@ describe("DXT CLI", () => {
fs.writeFileSync(
manifestWithIcon,
JSON.stringify({
manifest_version: LATEST_MANIFEST_VERSION,
manifest_version: DEFAULT_MANIFEST_VERSION,
name: "test-with-icon",
version: "1.0.0",
description: "Test with icon",
@ -140,7 +140,7 @@ describe("DXT CLI", () => {
fs.writeFileSync(
manifestWithUrl,
JSON.stringify({
manifest_version: LATEST_MANIFEST_VERSION,
manifest_version: DEFAULT_MANIFEST_VERSION,
name: "test-with-url",
version: "1.0.0",
description: "Test with URL",
@ -177,7 +177,7 @@ describe("DXT CLI", () => {
fs.writeFileSync(
join(tempDir, "manifest.json"),
JSON.stringify({
manifest_version: LATEST_MANIFEST_VERSION,
manifest_version: DEFAULT_MANIFEST_VERSION,
name: "Test Extension",
version: "1.0.0",
description: "A test extension",
@ -274,7 +274,7 @@ describe("DXT CLI", () => {
fs.writeFileSync(
join(tempExecDir, "manifest.json"),
JSON.stringify({
manifest_version: LATEST_MANIFEST_VERSION,
manifest_version: DEFAULT_MANIFEST_VERSION,
name: "Test Executable Extension",
version: "1.0.0",
description: "A test extension with executable files",

View file

@ -10,7 +10,7 @@ import {
getDefaultRepositoryUrl,
readPackageJson,
} from "../src/cli/init.js";
import { LATEST_MANIFEST_VERSION } from "../src/schemas/index.js";
import { DEFAULT_MANIFEST_VERSION } from "../src/shared/constants.js";
// Mock the fs module
jest.mock("fs", () => ({
@ -220,7 +220,7 @@ describe("init functions", () => {
);
expect(manifest).toEqual({
manifest_version: LATEST_MANIFEST_VERSION,
manifest_version: DEFAULT_MANIFEST_VERSION,
name: "test-extension",
version: "1.0.0",
description: "Test description",
@ -322,7 +322,7 @@ describe("init functions", () => {
);
expect(manifest).toEqual({
manifest_version: LATEST_MANIFEST_VERSION,
manifest_version: DEFAULT_MANIFEST_VERSION,
name: "test-extension",
display_name: "Test Extension",
version: "1.0.0",