@enconvo/dxt 0.2.6

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.
@@ -0,0 +1,98 @@
1
+ import * as z from "zod";
2
+ export const McpServerConfigSchema = z.strictObject({
3
+ command: z.string(),
4
+ args: z.array(z.string()).optional(),
5
+ env: z.record(z.string(), z.string()).optional(),
6
+ });
7
+ export const DxtManifestAuthorSchema = z.strictObject({
8
+ name: z.string(),
9
+ email: z.string().email().optional(),
10
+ url: z.string().url().optional(),
11
+ });
12
+ export const DxtManifestRepositorySchema = z.strictObject({
13
+ type: z.string(),
14
+ url: z.string().url(),
15
+ });
16
+ export const DxtManifestPlatformOverrideSchema = McpServerConfigSchema.partial();
17
+ export const DxtManifestMcpConfigSchema = McpServerConfigSchema.extend({
18
+ platform_overrides: z
19
+ .record(z.string(), DxtManifestPlatformOverrideSchema)
20
+ .optional(),
21
+ });
22
+ export const DxtManifestServerSchema = z.strictObject({
23
+ type: z.enum(["python", "node", "binary"]),
24
+ entry_point: z.string(),
25
+ mcp_config: DxtManifestMcpConfigSchema,
26
+ });
27
+ export const DxtManifestCompatibilitySchema = z
28
+ .strictObject({
29
+ claude_desktop: z.string().optional(),
30
+ platforms: z.array(z.enum(["darwin", "win32", "linux"])).optional(),
31
+ runtimes: z
32
+ .strictObject({
33
+ python: z.string().optional(),
34
+ node: z.string().optional(),
35
+ })
36
+ .optional(),
37
+ })
38
+ .passthrough();
39
+ export const DxtManifestToolSchema = z.strictObject({
40
+ name: z.string(),
41
+ description: z.string().optional(),
42
+ });
43
+ export const DxtManifestPromptSchema = z.strictObject({
44
+ name: z.string(),
45
+ description: z.string().optional(),
46
+ arguments: z.array(z.string()).optional(),
47
+ text: z.string(),
48
+ });
49
+ export const DxtUserConfigurationOptionSchema = z.strictObject({
50
+ type: z.enum(["string", "number", "boolean", "directory", "file"]),
51
+ title: z.string(),
52
+ description: z.string(),
53
+ required: z.boolean().optional(),
54
+ default: z
55
+ .union([z.string(), z.number(), z.boolean(), z.array(z.string())])
56
+ .optional(),
57
+ multiple: z.boolean().optional(),
58
+ sensitive: z.boolean().optional(),
59
+ min: z.number().optional(),
60
+ max: z.number().optional(),
61
+ credentials: z.array(z.string()).optional(),
62
+ });
63
+ export const DxtUserConfigValuesSchema = z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]));
64
+ export const DxtManifestSchema = z.strictObject({
65
+ $schema: z.string().optional(),
66
+ dxt_version: z.string(),
67
+ name: z.string(),
68
+ display_name: z.string().optional(),
69
+ version: z.string(),
70
+ description: z.string(),
71
+ long_description: z.string().optional(),
72
+ author: DxtManifestAuthorSchema,
73
+ repository: DxtManifestRepositorySchema.optional(),
74
+ homepage: z.string().url().optional(),
75
+ documentation: z.string().url().optional(),
76
+ support: z.string().url().optional(),
77
+ icon: z.string().optional(),
78
+ screenshots: z.array(z.string()).optional(),
79
+ server: DxtManifestServerSchema,
80
+ tools: z.array(DxtManifestToolSchema).optional(),
81
+ tools_generated: z.boolean().optional(),
82
+ prompts: z.array(DxtManifestPromptSchema).optional(),
83
+ prompts_generated: z.boolean().optional(),
84
+ keywords: z.array(z.string()).optional(),
85
+ license: z.string().optional(),
86
+ compatibility: DxtManifestCompatibilitySchema.optional(),
87
+ user_config: z
88
+ .record(z.string(), DxtUserConfigurationOptionSchema)
89
+ .optional(),
90
+ });
91
+ export const DxtSignatureInfoSchema = z.strictObject({
92
+ status: z.enum(["signed", "unsigned", "self-signed"]),
93
+ publisher: z.string().optional(),
94
+ issuer: z.string().optional(),
95
+ valid_from: z.string().optional(),
96
+ valid_to: z.string().optional(),
97
+ fingerprint: z.string().optional(),
98
+ });
@@ -0,0 +1,34 @@
1
+ import type { DxtManifest, DxtUserConfigValues, Logger, McpServerConfig } from "../types.js";
2
+ /**
3
+ * This file contains utility functions for handling DXT configuration,
4
+ * including variable replacement and MCP server configuration generation.
5
+ */
6
+ /**
7
+ * Recursively replaces variables in any value. Handles strings, arrays, and objects.
8
+ *
9
+ * @param value The value to process
10
+ * @param variables Object containing variable replacements
11
+ * @returns The processed value with all variables replaced
12
+ */
13
+ export declare function replaceVariables(value: unknown, variables: Record<string, string | string[]>): unknown;
14
+ interface GetMcpConfigForManifestOptions {
15
+ manifest: DxtManifest;
16
+ extensionPath: string;
17
+ systemDirs: Record<string, string>;
18
+ userConfig: DxtUserConfigValues;
19
+ pathSeparator: string;
20
+ logger?: Logger;
21
+ }
22
+ export declare function getMcpConfigForManifest(options: GetMcpConfigForManifestOptions): Promise<McpServerConfig | undefined>;
23
+ interface HasRequiredConfigMissingOptions {
24
+ manifest: DxtManifest;
25
+ userConfig?: DxtUserConfigValues;
26
+ }
27
+ /**
28
+ * Check if an extension has missing required configuration
29
+ * @param manifest The extension manifest
30
+ * @param userConfig The user configuration
31
+ * @returns true if required configuration is missing
32
+ */
33
+ export declare function hasRequiredConfigMissing({ manifest, userConfig, }: HasRequiredConfigMissingOptions): boolean;
34
+ export {};
@@ -0,0 +1,157 @@
1
+ /**
2
+ * This file contains utility functions for handling DXT configuration,
3
+ * including variable replacement and MCP server configuration generation.
4
+ */
5
+ /**
6
+ * Recursively replaces variables in any value. Handles strings, arrays, and objects.
7
+ *
8
+ * @param value The value to process
9
+ * @param variables Object containing variable replacements
10
+ * @returns The processed value with all variables replaced
11
+ */
12
+ export function replaceVariables(value, variables) {
13
+ if (typeof value === "string") {
14
+ let result = value;
15
+ // Replace all variables in the string
16
+ for (const [key, replacement] of Object.entries(variables)) {
17
+ const pattern = new RegExp(`\\$\\{${key}\\}`, "g");
18
+ // Check if this pattern actually exists in the string
19
+ if (result.match(pattern)) {
20
+ if (Array.isArray(replacement)) {
21
+ console.warn(`Cannot replace ${key} with array value in string context: "${value}"`, { key, replacement });
22
+ }
23
+ else {
24
+ result = result.replace(pattern, replacement);
25
+ }
26
+ }
27
+ }
28
+ return result;
29
+ }
30
+ else if (Array.isArray(value)) {
31
+ // For arrays, we need to handle special case of array expansion
32
+ const result = [];
33
+ for (const item of value) {
34
+ if (typeof item === "string" &&
35
+ item.match(/^\$\{user_config\.[^}]+\}$/)) {
36
+ // This is a user config variable that might expand to multiple values
37
+ const varName = item.match(/^\$\{([^}]+)\}$/)?.[1];
38
+ if (varName && variables[varName]) {
39
+ const replacement = variables[varName];
40
+ if (Array.isArray(replacement)) {
41
+ // Expand array inline
42
+ result.push(...replacement);
43
+ }
44
+ else {
45
+ result.push(replacement);
46
+ }
47
+ }
48
+ else {
49
+ // Variable not found, keep original
50
+ result.push(item);
51
+ }
52
+ }
53
+ else {
54
+ // Recursively process non-variable items
55
+ result.push(replaceVariables(item, variables));
56
+ }
57
+ }
58
+ return result;
59
+ }
60
+ else if (value && typeof value === "object") {
61
+ const result = {};
62
+ for (const [key, val] of Object.entries(value)) {
63
+ result[key] = replaceVariables(val, variables);
64
+ }
65
+ return result;
66
+ }
67
+ return value;
68
+ }
69
+ export async function getMcpConfigForManifest(options) {
70
+ const { manifest, extensionPath, systemDirs, userConfig, pathSeparator, logger, } = options;
71
+ const baseConfig = manifest.server?.mcp_config;
72
+ if (!baseConfig) {
73
+ return undefined;
74
+ }
75
+ let result = {
76
+ ...baseConfig,
77
+ };
78
+ if (baseConfig.platform_overrides) {
79
+ if (process.platform in baseConfig.platform_overrides) {
80
+ const platformConfig = baseConfig.platform_overrides[process.platform];
81
+ result.command = platformConfig.command || result.command;
82
+ result.args = platformConfig.args || result.args;
83
+ result.env = platformConfig.env || result.env;
84
+ }
85
+ }
86
+ // Check if required configuration is missing
87
+ if (hasRequiredConfigMissing({ manifest, userConfig })) {
88
+ logger?.warn(`Extension ${manifest.name} has missing required configuration, skipping MCP config`);
89
+ return undefined;
90
+ }
91
+ const variables = {
92
+ __dirname: extensionPath,
93
+ pathSeparator,
94
+ "/": pathSeparator,
95
+ ...systemDirs,
96
+ };
97
+ // Build merged configuration from defaults and user settings
98
+ const mergedConfig = {};
99
+ // First, add defaults from manifest
100
+ if (manifest.user_config) {
101
+ for (const [key, configOption] of Object.entries(manifest.user_config)) {
102
+ if (configOption.default !== undefined) {
103
+ mergedConfig[key] = configOption.default;
104
+ }
105
+ }
106
+ }
107
+ // Then, override with user settings
108
+ if (userConfig) {
109
+ Object.assign(mergedConfig, userConfig);
110
+ }
111
+ // Add merged configuration variables for substitution
112
+ for (const [key, value] of Object.entries(mergedConfig)) {
113
+ // Convert user config to the format expected by variable substitution
114
+ const userConfigKey = `user_config.${key}`;
115
+ if (Array.isArray(value)) {
116
+ // Keep arrays as arrays for proper expansion
117
+ variables[userConfigKey] = value.map(String);
118
+ }
119
+ else if (typeof value === "boolean") {
120
+ // Convert booleans to "true"/"false" strings as per spec
121
+ variables[userConfigKey] = value ? "true" : "false";
122
+ }
123
+ else {
124
+ // Convert other types to strings
125
+ variables[userConfigKey] = String(value);
126
+ }
127
+ }
128
+ // Replace all variables in the config
129
+ result = replaceVariables(result, variables);
130
+ return result;
131
+ }
132
+ function isInvalidSingleValue(value) {
133
+ return value === undefined || value === null || value === "";
134
+ }
135
+ /**
136
+ * Check if an extension has missing required configuration
137
+ * @param manifest The extension manifest
138
+ * @param userConfig The user configuration
139
+ * @returns true if required configuration is missing
140
+ */
141
+ export function hasRequiredConfigMissing({ manifest, userConfig, }) {
142
+ if (!manifest.user_config) {
143
+ return false;
144
+ }
145
+ const config = userConfig || {};
146
+ for (const [key, configOption] of Object.entries(manifest.user_config)) {
147
+ if (configOption.required) {
148
+ const value = config[key];
149
+ if (isInvalidSingleValue(value) ||
150
+ (Array.isArray(value) &&
151
+ (value.length === 0 || value.some(isInvalidSingleValue)))) {
152
+ return true;
153
+ }
154
+ }
155
+ }
156
+ return false;
157
+ }
@@ -0,0 +1,11 @@
1
+ interface LoggerOptions {
2
+ silent?: boolean;
3
+ }
4
+ export declare function getLogger({ silent }?: LoggerOptions): {
5
+ log: (...args: unknown[]) => void;
6
+ error: (...args: unknown[]) => void;
7
+ warn: (...args: unknown[]) => void;
8
+ info: (...args: unknown[]) => void;
9
+ debug: (...args: unknown[]) => void;
10
+ };
11
+ export {};
@@ -0,0 +1,29 @@
1
+ export function getLogger({ silent = false } = {}) {
2
+ return {
3
+ log: (...args) => {
4
+ if (!silent) {
5
+ console.log(...args);
6
+ }
7
+ },
8
+ error: (...args) => {
9
+ if (!silent) {
10
+ console.error(...args);
11
+ }
12
+ },
13
+ warn: (...args) => {
14
+ if (!silent) {
15
+ console.warn(...args);
16
+ }
17
+ },
18
+ info: (...args) => {
19
+ if (!silent) {
20
+ console.info(...args);
21
+ }
22
+ },
23
+ debug: (...args) => {
24
+ if (!silent) {
25
+ console.debug(...args);
26
+ }
27
+ },
28
+ };
29
+ }
@@ -0,0 +1,23 @@
1
+ import type * as z from "zod";
2
+ import type { DxtManifestAuthorSchema, DxtManifestCompatibilitySchema, DxtManifestMcpConfigSchema, DxtManifestPlatformOverrideSchema, DxtManifestPromptSchema, DxtManifestRepositorySchema, DxtManifestSchema, DxtManifestServerSchema, DxtManifestToolSchema, DxtSignatureInfoSchema, DxtUserConfigurationOptionSchema, DxtUserConfigValuesSchema, McpServerConfigSchema } from "./schemas.js";
3
+ export type McpServerConfig = z.infer<typeof McpServerConfigSchema>;
4
+ export type DxtManifestAuthor = z.infer<typeof DxtManifestAuthorSchema>;
5
+ export type DxtManifestRepository = z.infer<typeof DxtManifestRepositorySchema>;
6
+ export type DxtManifestPlatformOverride = z.infer<typeof DxtManifestPlatformOverrideSchema>;
7
+ export type DxtManifestMcpConfig = z.infer<typeof DxtManifestMcpConfigSchema>;
8
+ export type DxtManifestServer = z.infer<typeof DxtManifestServerSchema>;
9
+ export type DxtManifestCompatibility = z.infer<typeof DxtManifestCompatibilitySchema>;
10
+ export type DxtManifestTool = z.infer<typeof DxtManifestToolSchema>;
11
+ export type DxtManifestPrompt = z.infer<typeof DxtManifestPromptSchema>;
12
+ export type DxtUserConfigurationOption = z.infer<typeof DxtUserConfigurationOptionSchema>;
13
+ export type DxtUserConfigValues = z.infer<typeof DxtUserConfigValuesSchema>;
14
+ export type DxtManifest = z.infer<typeof DxtManifestSchema>;
15
+ /**
16
+ * Information about a DXT package signature
17
+ */
18
+ export type DxtSignatureInfo = z.infer<typeof DxtSignatureInfoSchema>;
19
+ export interface Logger {
20
+ log: (...args: unknown[]) => void;
21
+ error: (...args: unknown[]) => void;
22
+ warn: (...args: unknown[]) => void;
23
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,83 @@
1
+ {
2
+ "name": "@enconvo/dxt",
3
+ "description": "Tools for building Desktop Extensions",
4
+ "version": "0.2.6",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.js"
14
+ },
15
+ "./browser": {
16
+ "types": "./dist/browser.d.ts",
17
+ "import": "./dist/browser.js",
18
+ "require": "./dist/browser.js"
19
+ },
20
+ "./node": {
21
+ "types": "./dist/node.d.ts",
22
+ "import": "./dist/node.js",
23
+ "require": "./dist/node.js"
24
+ },
25
+ "./cli": {
26
+ "types": "./dist/cli.d.ts",
27
+ "import": "./dist/cli.js",
28
+ "require": "./dist/cli.js"
29
+ }
30
+ },
31
+ "bin": {
32
+ "dxt": "dist/cli/cli.js"
33
+ },
34
+ "files": [
35
+ "dist"
36
+ ],
37
+ "scripts": {
38
+ "build": "yarn run build:code",
39
+ "build:code": "tsc",
40
+ "build:schema": "node ./scripts/build-dxt-schema.js",
41
+ "dev": "tsc --watch",
42
+ "test": "jest",
43
+ "test:watch": "jest --watch",
44
+ "prepublishOnly": "npm run build",
45
+ "fix": "eslint --ext .ts . --fix && prettier -w .",
46
+ "lint": "tsc -p ./tsconfig.json && eslint --ext .ts .",
47
+ "dev-version": "./scripts/create-dev-version.js"
48
+ },
49
+ "author": "Anthropic <support@anthropic.com>",
50
+ "license": "MIT",
51
+ "devDependencies": {
52
+ "@types/jest": "^29.5.14",
53
+ "@types/node": "^22.15.3",
54
+ "@types/node-forge": "1.3.11",
55
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
56
+ "@typescript-eslint/parser": "^5.62.0",
57
+ "eslint": "^8.43.0",
58
+ "eslint-config-prettier": "^8.10.0",
59
+ "eslint-import-resolver-typescript": "^3.6.1",
60
+ "eslint-plugin-import": "^2.29.1",
61
+ "eslint-plugin-prettier": "^5.1.3",
62
+ "eslint-plugin-simple-import-sort": "^10.0.0",
63
+ "jest": "^29.7.0",
64
+ "prettier": "^3.3.3",
65
+ "ts-jest": "^29.3.2",
66
+ "typescript": "^5.6.3"
67
+ },
68
+ "dependencies": {
69
+ "@inquirer/prompts": "^6.0.1",
70
+ "commander": "^13.1.0",
71
+ "fflate": "^0.8.2",
72
+ "galactus": "^1.0.0",
73
+ "ignore": "^7.0.5",
74
+ "node-forge": "^1.3.1",
75
+ "pretty-bytes": "^5.6.0",
76
+ "zod": "^3.25.67"
77
+ },
78
+ "resolutions": {
79
+ "@babel/helpers": "7.27.1",
80
+ "@babel/parser": "7.27.3"
81
+ },
82
+ "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
83
+ }