frontmcp 1.0.4 → 1.1.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.
Files changed (100) hide show
  1. package/package.json +10 -4
  2. package/src/commands/build/adapters/cloudflare.d.ts +1 -1
  3. package/src/commands/build/adapters/cloudflare.js +1 -0
  4. package/src/commands/build/adapters/cloudflare.js.map +1 -1
  5. package/src/commands/build/adapters/distributed.d.ts +15 -0
  6. package/src/commands/build/adapters/distributed.js +30 -0
  7. package/src/commands/build/adapters/distributed.js.map +1 -0
  8. package/src/commands/build/adapters/index.d.ts +3 -2
  9. package/src/commands/build/adapters/index.js +4 -1
  10. package/src/commands/build/adapters/index.js.map +1 -1
  11. package/src/commands/build/adapters/lambda.d.ts +1 -1
  12. package/src/commands/build/adapters/lambda.js +1 -0
  13. package/src/commands/build/adapters/lambda.js.map +1 -1
  14. package/src/commands/build/adapters/vercel.d.ts +1 -1
  15. package/src/commands/build/adapters/vercel.js +1 -0
  16. package/src/commands/build/adapters/vercel.js.map +1 -1
  17. package/src/commands/build/exec/cli-runtime/generate-cli-entry.js +122 -34
  18. package/src/commands/build/exec/cli-runtime/generate-cli-entry.js.map +1 -1
  19. package/src/commands/build/exec/config.d.ts +2 -2
  20. package/src/commands/build/exec/config.js.map +1 -1
  21. package/src/commands/build/exec/esbuild-bundler.d.ts +1 -1
  22. package/src/commands/build/exec/esbuild-bundler.js +1 -1
  23. package/src/commands/build/exec/esbuild-bundler.js.map +1 -1
  24. package/src/commands/build/exec/index.d.ts +1 -1
  25. package/src/commands/build/exec/index.js +5 -38
  26. package/src/commands/build/exec/index.js.map +1 -1
  27. package/src/commands/build/exec/skill-assets.d.ts +27 -0
  28. package/src/commands/build/exec/skill-assets.js +60 -0
  29. package/src/commands/build/exec/skill-assets.js.map +1 -0
  30. package/src/commands/build/index.d.ts +1 -1
  31. package/src/commands/build/index.js +44 -5
  32. package/src/commands/build/index.js.map +1 -1
  33. package/src/commands/build/mcpb/binary.d.ts +37 -0
  34. package/src/commands/build/mcpb/binary.js +72 -0
  35. package/src/commands/build/mcpb/binary.js.map +1 -0
  36. package/src/commands/build/mcpb/constants.d.ts +21 -0
  37. package/src/commands/build/mcpb/constants.js +31 -0
  38. package/src/commands/build/mcpb/constants.js.map +1 -0
  39. package/src/commands/build/mcpb/index.d.ts +20 -0
  40. package/src/commands/build/mcpb/index.js +241 -0
  41. package/src/commands/build/mcpb/index.js.map +1 -0
  42. package/src/commands/build/mcpb/manifest.d.ts +183 -0
  43. package/src/commands/build/mcpb/manifest.js +252 -0
  44. package/src/commands/build/mcpb/manifest.js.map +1 -0
  45. package/src/commands/build/mcpb/stage.d.ts +50 -0
  46. package/src/commands/build/mcpb/stage.js +94 -0
  47. package/src/commands/build/mcpb/stage.js.map +1 -0
  48. package/src/commands/build/mcpb/user-config.d.ts +26 -0
  49. package/src/commands/build/mcpb/user-config.js +147 -0
  50. package/src/commands/build/mcpb/user-config.js.map +1 -0
  51. package/src/commands/build/mcpb/validate.d.ts +27 -0
  52. package/src/commands/build/mcpb/validate.js +218 -0
  53. package/src/commands/build/mcpb/validate.js.map +1 -0
  54. package/src/commands/build/mcpb/zip.d.ts +37 -0
  55. package/src/commands/build/mcpb/zip.js +85 -0
  56. package/src/commands/build/mcpb/zip.js.map +1 -0
  57. package/src/commands/build/register.d.ts +1 -1
  58. package/src/commands/build/register.js +7 -1
  59. package/src/commands/build/register.js.map +1 -1
  60. package/src/commands/build/sdk/index.d.ts +1 -1
  61. package/src/commands/build/sdk/index.js +1 -1
  62. package/src/commands/build/sdk/index.js.map +1 -1
  63. package/src/commands/build/types.d.ts +1 -1
  64. package/src/commands/build/types.js.map +1 -1
  65. package/src/commands/mcpb/register.d.ts +2 -0
  66. package/src/commands/mcpb/register.js +14 -0
  67. package/src/commands/mcpb/register.js.map +1 -0
  68. package/src/commands/mcpb/validate.d.ts +1 -0
  69. package/src/commands/mcpb/validate.js +28 -0
  70. package/src/commands/mcpb/validate.js.map +1 -0
  71. package/src/commands/scaffold/create.js +5 -7
  72. package/src/commands/scaffold/create.js.map +1 -1
  73. package/src/config/define-config.d.ts +26 -0
  74. package/src/config/define-config.js +31 -0
  75. package/src/config/define-config.js.map +1 -0
  76. package/src/config/frontmcp-config.loader.d.ts +32 -0
  77. package/src/config/frontmcp-config.loader.js +113 -0
  78. package/src/config/frontmcp-config.loader.js.map +1 -0
  79. package/src/config/frontmcp-config.schema.d.ts +1062 -0
  80. package/src/config/frontmcp-config.schema.js +313 -0
  81. package/src/config/frontmcp-config.schema.js.map +1 -0
  82. package/src/config/frontmcp-config.types.d.ts +287 -0
  83. package/src/config/frontmcp-config.types.js +14 -0
  84. package/src/config/frontmcp-config.types.js.map +1 -0
  85. package/src/config/index.d.ts +5 -0
  86. package/src/config/index.js +13 -0
  87. package/src/config/index.js.map +1 -0
  88. package/src/core/args.d.ts +7 -2
  89. package/src/core/args.js +12 -2
  90. package/src/core/args.js.map +1 -1
  91. package/src/core/bridge.d.ts +1 -1
  92. package/src/core/bridge.js +10 -0
  93. package/src/core/bridge.js.map +1 -1
  94. package/src/core/cli.js +3 -1
  95. package/src/core/cli.js.map +1 -1
  96. package/src/core/program.js +15 -13
  97. package/src/core/program.js.map +1 -1
  98. package/src/index.d.ts +2 -0
  99. package/src/index.js +7 -0
  100. package/src/index.js.map +1 -1
@@ -0,0 +1,252 @@
1
+ "use strict";
2
+ /**
3
+ * MCPB manifest generator + Zod schema for the emitted manifest.
4
+ *
5
+ * Source priority when resolving fields:
6
+ * deployment.* (frontmcp.config) > package.json > hard defaults
7
+ *
8
+ * See https://github.com/modelcontextprotocol/mcpb/blob/main/MANIFEST.md
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.mcpbManifestSchema = void 0;
12
+ exports.loadPackageJsonMeta = loadPackageJsonMeta;
13
+ exports.parseAuthor = parseAuthor;
14
+ exports.normalizeRepository = normalizeRepository;
15
+ exports.resolveIconPath = resolveIconPath;
16
+ exports.generateMcpbManifest = generateMcpbManifest;
17
+ const tslib_1 = require("tslib");
18
+ const fs = tslib_1.__importStar(require("fs"));
19
+ const path = tslib_1.__importStar(require("path"));
20
+ const lazy_zod_1 = require("@frontmcp/lazy-zod");
21
+ const schema_extractor_1 = require("../exec/cli-runtime/schema-extractor");
22
+ const constants_1 = require("./constants");
23
+ // ============================================
24
+ // Zod schema (used by validate.ts)
25
+ // ============================================
26
+ const authorSchema = lazy_zod_1.z
27
+ .object({
28
+ name: lazy_zod_1.z.string(),
29
+ email: lazy_zod_1.z.string().optional(),
30
+ url: lazy_zod_1.z.string().optional(),
31
+ })
32
+ .strict();
33
+ const userConfigEntrySchema = lazy_zod_1.z
34
+ .object({
35
+ type: lazy_zod_1.z.enum(['string', 'number', 'boolean', 'directory', 'file']),
36
+ title: lazy_zod_1.z.string(),
37
+ description: lazy_zod_1.z.string().optional(),
38
+ required: lazy_zod_1.z.boolean().optional(),
39
+ default: lazy_zod_1.z.union([lazy_zod_1.z.string(), lazy_zod_1.z.number(), lazy_zod_1.z.boolean()]).optional(),
40
+ multiple: lazy_zod_1.z.boolean().optional(),
41
+ sensitive: lazy_zod_1.z.boolean().optional(),
42
+ min: lazy_zod_1.z.number().optional(),
43
+ max: lazy_zod_1.z.number().optional(),
44
+ })
45
+ .strict();
46
+ const mcpConfigSchema = lazy_zod_1.z.lazy(() => lazy_zod_1.z
47
+ .object({
48
+ command: lazy_zod_1.z.string(),
49
+ args: lazy_zod_1.z.array(lazy_zod_1.z.string()).optional(),
50
+ env: lazy_zod_1.z.record(lazy_zod_1.z.string(), lazy_zod_1.z.string()).optional(),
51
+ platform_overrides: lazy_zod_1.z.record(lazy_zod_1.z.string(), mcpConfigSchema).optional(),
52
+ })
53
+ .strict());
54
+ exports.mcpbManifestSchema = lazy_zod_1.z
55
+ .object({
56
+ manifest_version: lazy_zod_1.z.string(),
57
+ name: lazy_zod_1.z.string().min(1),
58
+ version: lazy_zod_1.z.string().min(1),
59
+ description: lazy_zod_1.z.string(),
60
+ display_name: lazy_zod_1.z.string().optional(),
61
+ long_description: lazy_zod_1.z.string().optional(),
62
+ author: authorSchema,
63
+ license: lazy_zod_1.z.string().optional(),
64
+ homepage: lazy_zod_1.z.string().optional(),
65
+ repository: lazy_zod_1.z
66
+ .object({ type: lazy_zod_1.z.string(), url: lazy_zod_1.z.string() })
67
+ .strict()
68
+ .optional(),
69
+ documentation: lazy_zod_1.z.string().optional(),
70
+ support: lazy_zod_1.z.string().optional(),
71
+ icon: lazy_zod_1.z.string().optional(),
72
+ keywords: lazy_zod_1.z.array(lazy_zod_1.z.string()).optional(),
73
+ privacy_policies: lazy_zod_1.z.array(lazy_zod_1.z.string()).optional(),
74
+ compatibility: lazy_zod_1.z
75
+ .object({
76
+ claude_desktop: lazy_zod_1.z.string().optional(),
77
+ platforms: lazy_zod_1.z.array(lazy_zod_1.z.enum(['darwin', 'win32', 'linux'])).optional(),
78
+ runtimes: lazy_zod_1.z
79
+ .object({ node: lazy_zod_1.z.string().optional(), python: lazy_zod_1.z.string().optional() })
80
+ .strict()
81
+ .optional(),
82
+ })
83
+ .strict()
84
+ .optional(),
85
+ server: lazy_zod_1.z
86
+ .object({
87
+ type: lazy_zod_1.z.enum(['node', 'python', 'binary', 'uv']),
88
+ entry_point: lazy_zod_1.z.string(),
89
+ mcp_config: mcpConfigSchema,
90
+ })
91
+ .strict(),
92
+ tools: lazy_zod_1.z
93
+ .array(lazy_zod_1.z.object({ name: lazy_zod_1.z.string(), description: lazy_zod_1.z.string() }).strict())
94
+ .optional(),
95
+ tools_generated: lazy_zod_1.z.boolean().optional(),
96
+ prompts: lazy_zod_1.z
97
+ .array(lazy_zod_1.z
98
+ .object({ name: lazy_zod_1.z.string(), description: lazy_zod_1.z.string().optional() })
99
+ .strict())
100
+ .optional(),
101
+ prompts_generated: lazy_zod_1.z.boolean().optional(),
102
+ user_config: lazy_zod_1.z.record(lazy_zod_1.z.string(), userConfigEntrySchema).optional(),
103
+ _meta: lazy_zod_1.z.record(lazy_zod_1.z.string(), lazy_zod_1.z.unknown()).optional(),
104
+ })
105
+ .strict();
106
+ /** Read and parse package.json from the given directory. Returns {} if absent. */
107
+ function loadPackageJsonMeta(cwd) {
108
+ const pkgPath = path.join(cwd, 'package.json');
109
+ if (!fs.existsSync(pkgPath))
110
+ return {};
111
+ try {
112
+ return JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
113
+ }
114
+ catch {
115
+ return {};
116
+ }
117
+ }
118
+ /**
119
+ * Parse npm-style "Name <email> (url)" into an McpbAuthor.
120
+ * Falls back to `{ name: <raw> }` when parsing fails.
121
+ */
122
+ function parseAuthor(author) {
123
+ if (!author)
124
+ return { name: 'unknown' };
125
+ if (typeof author === 'object' && 'name' in author) {
126
+ const a = author;
127
+ return {
128
+ name: a.name,
129
+ ...(a.email ? { email: a.email } : {}),
130
+ ...(a.url ? { url: a.url } : {}),
131
+ };
132
+ }
133
+ if (typeof author !== 'string') {
134
+ return { name: String(author) };
135
+ }
136
+ const match = author.match(/^([^<(]+?)(?:\s*<([^>]+)>)?(?:\s*\(([^)]+)\))?$/);
137
+ if (!match || !match[1])
138
+ return { name: author };
139
+ const [, name, email, url] = match;
140
+ return {
141
+ name: name.trim(),
142
+ ...(email ? { email: email.trim() } : {}),
143
+ ...(url ? { url: url.trim() } : {}),
144
+ };
145
+ }
146
+ /** Normalize repository field (string → {type, url}). */
147
+ function normalizeRepository(repo) {
148
+ if (!repo)
149
+ return undefined;
150
+ if (typeof repo === 'string') {
151
+ return { type: 'git', url: repo };
152
+ }
153
+ if (typeof repo === 'object' && repo.url) {
154
+ return { type: repo.type || 'git', url: repo.url };
155
+ }
156
+ return undefined;
157
+ }
158
+ /** Resolve first-existing icon path. */
159
+ function resolveIconPath(cwd, deploymentIcon, pkgIcon) {
160
+ const candidates = [deploymentIcon, pkgIcon, 'icon.png', 'assets/icon.png'].filter((x) => !!x);
161
+ for (const rel of candidates) {
162
+ if (fs.existsSync(path.resolve(cwd, rel))) {
163
+ return rel;
164
+ }
165
+ }
166
+ return undefined;
167
+ }
168
+ /** Produce the final MCPB manifest object. */
169
+ function generateMcpbManifest(input) {
170
+ const { name, version, cwd, deployment, schema, userConfig, userConfigEnv, platformOverrides, hasIcon, cliVersion, } = input;
171
+ const pkg = loadPackageJsonMeta(cwd);
172
+ const description = deployment?.longDescription?.split('\n')[0]?.trim()
173
+ || pkg.description
174
+ || '';
175
+ const author = deployment?.author || parseAuthor(pkg.author);
176
+ const license = deployment?.license ?? pkg.license;
177
+ const homepage = deployment?.homepage ?? pkg.homepage;
178
+ const repository = normalizeRepository(deployment?.repository ?? pkg.repository);
179
+ const keywords = deployment?.keywords ?? pkg.keywords;
180
+ const icon = hasIcon ? 'icon.png' : undefined;
181
+ const nodeVersion = deployment?.compatibility?.runtimes?.node
182
+ ?? input.nodeVersion
183
+ ?? constants_1.DEFAULT_NODE_COMPAT;
184
+ const compatibility = {
185
+ ...(deployment?.compatibility?.claude_desktop
186
+ ? { claude_desktop: deployment.compatibility.claude_desktop }
187
+ : {}),
188
+ platforms: deployment?.compatibility?.platforms ?? [...constants_1.DEFAULT_PLATFORMS],
189
+ runtimes: {
190
+ ...(deployment?.compatibility?.runtimes?.python
191
+ ? { python: deployment.compatibility.runtimes.python }
192
+ : {}),
193
+ node: nodeVersion,
194
+ },
195
+ };
196
+ const tools = schema.tools
197
+ .filter((t) => !schema_extractor_1.SYSTEM_TOOL_NAMES.has(t.name))
198
+ .map((t) => ({ name: t.name, description: t.description || '' }));
199
+ const prompts = schema.prompts.map((p) => ({
200
+ name: p.name,
201
+ ...(p.description ? { description: p.description } : {}),
202
+ }));
203
+ const mcpConfig = {
204
+ command: 'node',
205
+ args: ['${__dirname}/server/index.js'],
206
+ ...(Object.keys(userConfigEnv).length > 0 ? { env: userConfigEnv } : {}),
207
+ ...(platformOverrides && Object.keys(platformOverrides).length > 0
208
+ ? { platform_overrides: platformOverrides }
209
+ : {}),
210
+ };
211
+ const manifest = {
212
+ manifest_version: constants_1.MCPB_MANIFEST_VERSION,
213
+ name,
214
+ version,
215
+ description,
216
+ ...(deployment?.displayName ? { display_name: deployment.displayName } : {}),
217
+ ...(deployment?.longDescription
218
+ ? { long_description: deployment.longDescription }
219
+ : {}),
220
+ author,
221
+ ...(license ? { license } : {}),
222
+ ...(homepage ? { homepage } : {}),
223
+ ...(repository ? { repository } : {}),
224
+ ...(deployment?.documentation ? { documentation: deployment.documentation } : {}),
225
+ ...(deployment?.support ? { support: deployment.support } : {}),
226
+ ...(icon ? { icon } : {}),
227
+ ...(keywords && keywords.length > 0 ? { keywords } : {}),
228
+ ...(deployment?.privacyPolicies && deployment.privacyPolicies.length > 0
229
+ ? { privacy_policies: deployment.privacyPolicies }
230
+ : {}),
231
+ compatibility,
232
+ server: {
233
+ type: 'node',
234
+ entry_point: 'server/index.js',
235
+ mcp_config: mcpConfig,
236
+ },
237
+ tools,
238
+ tools_generated: false,
239
+ prompts,
240
+ // FrontMCP prompts resolve dynamically via execute() — MCPB's static `text`
241
+ // template cannot represent JS logic. Set generated:true so consumers query
242
+ // the server at runtime while still getting name/description hints here.
243
+ prompts_generated: true,
244
+ ...(Object.keys(userConfig).length > 0 ? { user_config: userConfig } : {}),
245
+ _meta: {
246
+ 'dev.frontmcp.generator': cliVersion ? `frontmcp@${cliVersion}` : 'frontmcp',
247
+ 'dev.frontmcp.capabilities': schema.capabilities,
248
+ },
249
+ };
250
+ return manifest;
251
+ }
252
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../../../src/commands/build/mcpb/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCPB manifest generator + Zod schema for the emitted manifest.\n *\n * Source priority when resolving fields:\n * deployment.* (frontmcp.config) > package.json > hard defaults\n *\n * See https://github.com/modelcontextprotocol/mcpb/blob/main/MANIFEST.md\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { z } from '@frontmcp/lazy-zod';\nimport { type ExtractedSchema, SYSTEM_TOOL_NAMES } from '../exec/cli-runtime/schema-extractor';\nimport type {\n McpbAuthor,\n McpbCompatibility,\n McpbDeployment,\n McpbRepository,\n McpbUserConfigEntry,\n} from '../../../config/frontmcp-config.types';\nimport {\n DEFAULT_NODE_COMPAT,\n DEFAULT_PLATFORMS,\n MCPB_MANIFEST_VERSION,\n} from './constants';\n\n// ============================================\n// Emitted manifest shape (MCPB v0.3 subset we produce)\n// ============================================\n\nexport interface McpbMcpConfig {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n platform_overrides?: Record<string, McpbMcpConfig>;\n}\n\nexport interface McpbManifest {\n manifest_version: string;\n name: string;\n version: string;\n description: string;\n display_name?: string;\n long_description?: string;\n author: McpbAuthor;\n license?: string;\n homepage?: string;\n repository?: { type: string; url: string };\n documentation?: string;\n support?: string;\n icon?: string;\n keywords?: string[];\n privacy_policies?: string[];\n compatibility?: McpbCompatibility;\n server: {\n type: 'node' | 'python' | 'binary' | 'uv';\n entry_point: string;\n mcp_config: McpbMcpConfig;\n };\n tools?: Array<{ name: string; description: string }>;\n tools_generated?: boolean;\n prompts?: Array<{ name: string; description?: string }>;\n prompts_generated?: boolean;\n user_config?: Record<string, McpbUserConfigEntry>;\n _meta?: Record<string, unknown>;\n}\n\n// ============================================\n// Zod schema (used by validate.ts)\n// ============================================\n\nconst authorSchema = z\n .object({\n name: z.string(),\n email: z.string().optional(),\n url: z.string().optional(),\n })\n .strict();\n\nconst userConfigEntrySchema = z\n .object({\n type: z.enum(['string', 'number', 'boolean', 'directory', 'file']),\n title: z.string(),\n description: z.string().optional(),\n required: z.boolean().optional(),\n default: z.union([z.string(), z.number(), z.boolean()]).optional(),\n multiple: z.boolean().optional(),\n sensitive: z.boolean().optional(),\n min: z.number().optional(),\n max: z.number().optional(),\n })\n .strict();\n\nconst mcpConfigSchema: z.ZodType<McpbMcpConfig> = z.lazy(() =>\n z\n .object({\n command: z.string(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n platform_overrides: z.record(z.string(), mcpConfigSchema).optional(),\n })\n .strict(),\n);\n\nexport const mcpbManifestSchema = z\n .object({\n manifest_version: z.string(),\n name: z.string().min(1),\n version: z.string().min(1),\n description: z.string(),\n display_name: z.string().optional(),\n long_description: z.string().optional(),\n author: authorSchema,\n license: z.string().optional(),\n homepage: z.string().optional(),\n repository: z\n .object({ type: z.string(), url: z.string() })\n .strict()\n .optional(),\n documentation: z.string().optional(),\n support: z.string().optional(),\n icon: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n privacy_policies: z.array(z.string()).optional(),\n compatibility: z\n .object({\n claude_desktop: z.string().optional(),\n platforms: z.array(z.enum(['darwin', 'win32', 'linux'])).optional(),\n runtimes: z\n .object({ node: z.string().optional(), python: z.string().optional() })\n .strict()\n .optional(),\n })\n .strict()\n .optional(),\n server: z\n .object({\n type: z.enum(['node', 'python', 'binary', 'uv']),\n entry_point: z.string(),\n mcp_config: mcpConfigSchema,\n })\n .strict(),\n tools: z\n .array(z.object({ name: z.string(), description: z.string() }).strict())\n .optional(),\n tools_generated: z.boolean().optional(),\n prompts: z\n .array(\n z\n .object({ name: z.string(), description: z.string().optional() })\n .strict(),\n )\n .optional(),\n prompts_generated: z.boolean().optional(),\n user_config: z.record(z.string(), userConfigEntrySchema).optional(),\n _meta: z.record(z.string(), z.unknown()).optional(),\n })\n .strict();\n\n// ============================================\n// Sources + helpers\n// ============================================\n\nexport interface PackageJsonMeta {\n name?: string;\n version?: string;\n description?: string;\n author?: string | McpbAuthor;\n license?: string;\n homepage?: string;\n repository?: string | { type?: string; url?: string };\n keywords?: string[];\n icon?: string;\n}\n\n/** Read and parse package.json from the given directory. Returns {} if absent. */\nexport function loadPackageJsonMeta(cwd: string): PackageJsonMeta {\n const pkgPath = path.join(cwd, 'package.json');\n if (!fs.existsSync(pkgPath)) return {};\n try {\n return JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as PackageJsonMeta;\n } catch {\n return {};\n }\n}\n\n/**\n * Parse npm-style \"Name <email> (url)\" into an McpbAuthor.\n * Falls back to `{ name: <raw> }` when parsing fails.\n */\nexport function parseAuthor(author: unknown): McpbAuthor {\n if (!author) return { name: 'unknown' };\n if (typeof author === 'object' && 'name' in author) {\n const a = author as McpbAuthor;\n return {\n name: a.name,\n ...(a.email ? { email: a.email } : {}),\n ...(a.url ? { url: a.url } : {}),\n };\n }\n if (typeof author !== 'string') {\n return { name: String(author) };\n }\n const match = author.match(/^([^<(]+?)(?:\\s*<([^>]+)>)?(?:\\s*\\(([^)]+)\\))?$/);\n if (!match || !match[1]) return { name: author };\n const [, name, email, url] = match;\n return {\n name: name.trim(),\n ...(email ? { email: email.trim() } : {}),\n ...(url ? { url: url.trim() } : {}),\n };\n}\n\n/** Normalize repository field (string → {type, url}). */\nexport function normalizeRepository(\n repo: McpbRepository | PackageJsonMeta['repository'] | undefined,\n): { type: string; url: string } | undefined {\n if (!repo) return undefined;\n if (typeof repo === 'string') {\n return { type: 'git', url: repo };\n }\n if (typeof repo === 'object' && repo.url) {\n return { type: repo.type || 'git', url: repo.url };\n }\n return undefined;\n}\n\n/** Resolve first-existing icon path. */\nexport function resolveIconPath(cwd: string, deploymentIcon?: string, pkgIcon?: string): string | undefined {\n const candidates = [deploymentIcon, pkgIcon, 'icon.png', 'assets/icon.png'].filter(\n (x): x is string => !!x,\n );\n for (const rel of candidates) {\n if (fs.existsSync(path.resolve(cwd, rel))) {\n return rel;\n }\n }\n return undefined;\n}\n\n// ============================================\n// Generator input + output\n// ============================================\n\nexport interface GenerateMcpbManifestInput {\n /** Resolved server name. */\n name: string;\n /** Resolved server version. */\n version: string;\n /** Optional resolved node version range (e.g., \">=22.0.0\"). */\n nodeVersion?: string;\n /** Project root. Used for icon resolution and package.json fallback. */\n cwd: string;\n /** Deployment config from frontmcp.config (may be undefined). */\n deployment?: McpbDeployment;\n /** Schema extracted from the compiled server bundle. */\n schema: ExtractedSchema;\n /** env → user_config reference map built by user-config.ts. */\n userConfigEnv: Record<string, string>;\n /** user_config entries built by user-config.ts. */\n userConfig: Record<string, McpbUserConfigEntry>;\n /** platform_overrides from binary.ts (may be empty). */\n platformOverrides?: Record<string, McpbMcpConfig>;\n /** Whether an icon was copied into the staged archive root. */\n hasIcon?: boolean;\n /** Tool name of the CLI version emitting this manifest (for _meta). */\n cliVersion?: string;\n}\n\n/** Produce the final MCPB manifest object. */\nexport function generateMcpbManifest(input: GenerateMcpbManifestInput): McpbManifest {\n const {\n name,\n version,\n cwd,\n deployment,\n schema,\n userConfig,\n userConfigEnv,\n platformOverrides,\n hasIcon,\n cliVersion,\n } = input;\n\n const pkg = loadPackageJsonMeta(cwd);\n\n const description = deployment?.longDescription?.split('\\n')[0]?.trim()\n || pkg.description\n || '';\n\n const author = deployment?.author || parseAuthor(pkg.author);\n const license = deployment?.license ?? pkg.license;\n const homepage = deployment?.homepage ?? pkg.homepage;\n const repository = normalizeRepository(deployment?.repository ?? pkg.repository);\n const keywords = deployment?.keywords ?? pkg.keywords;\n const icon = hasIcon ? 'icon.png' : undefined;\n\n const nodeVersion = deployment?.compatibility?.runtimes?.node\n ?? input.nodeVersion\n ?? DEFAULT_NODE_COMPAT;\n\n const compatibility: McpbCompatibility = {\n ...(deployment?.compatibility?.claude_desktop\n ? { claude_desktop: deployment.compatibility.claude_desktop }\n : {}),\n platforms: deployment?.compatibility?.platforms ?? [...DEFAULT_PLATFORMS],\n runtimes: {\n ...(deployment?.compatibility?.runtimes?.python\n ? { python: deployment.compatibility.runtimes.python }\n : {}),\n node: nodeVersion,\n },\n };\n\n const tools = schema.tools\n .filter((t) => !SYSTEM_TOOL_NAMES.has(t.name))\n .map((t) => ({ name: t.name, description: t.description || '' }));\n\n const prompts = schema.prompts.map((p) => ({\n name: p.name,\n ...(p.description ? { description: p.description } : {}),\n }));\n\n const mcpConfig: McpbMcpConfig = {\n command: 'node',\n args: ['${__dirname}/server/index.js'],\n ...(Object.keys(userConfigEnv).length > 0 ? { env: userConfigEnv } : {}),\n ...(platformOverrides && Object.keys(platformOverrides).length > 0\n ? { platform_overrides: platformOverrides }\n : {}),\n };\n\n const manifest: McpbManifest = {\n manifest_version: MCPB_MANIFEST_VERSION,\n name,\n version,\n description,\n ...(deployment?.displayName ? { display_name: deployment.displayName } : {}),\n ...(deployment?.longDescription\n ? { long_description: deployment.longDescription }\n : {}),\n author,\n ...(license ? { license } : {}),\n ...(homepage ? { homepage } : {}),\n ...(repository ? { repository } : {}),\n ...(deployment?.documentation ? { documentation: deployment.documentation } : {}),\n ...(deployment?.support ? { support: deployment.support } : {}),\n ...(icon ? { icon } : {}),\n ...(keywords && keywords.length > 0 ? { keywords } : {}),\n ...(deployment?.privacyPolicies && deployment.privacyPolicies.length > 0\n ? { privacy_policies: deployment.privacyPolicies }\n : {}),\n compatibility,\n server: {\n type: 'node',\n entry_point: 'server/index.js',\n mcp_config: mcpConfig,\n },\n tools,\n tools_generated: false,\n prompts,\n // FrontMCP prompts resolve dynamically via execute() — MCPB's static `text`\n // template cannot represent JS logic. Set generated:true so consumers query\n // the server at runtime while still getting name/description hints here.\n prompts_generated: true,\n ...(Object.keys(userConfig).length > 0 ? { user_config: userConfig } : {}),\n _meta: {\n 'dev.frontmcp.generator': cliVersion ? `frontmcp@${cliVersion}` : 'frontmcp',\n 'dev.frontmcp.capabilities': schema.capabilities,\n },\n };\n\n return manifest;\n}\n"]}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Stage the MCPB archive layout on disk before zipping.
3
+ *
4
+ * Layout produced:
5
+ *
6
+ * __stage/
7
+ * manifest.json
8
+ * server/
9
+ * index.js (esbuild bundle, renamed from {name}.bundle.js)
10
+ * package.json (minimal CJS manifest so Node resolves index.js)
11
+ * _skills/ (optional — when the server ships skills)
12
+ * bin/ (optional — when SEA is enabled)
13
+ * {platform}/{name}[.exe]
14
+ * icon.png (optional)
15
+ * README.md (optional)
16
+ */
17
+ import type { BinaryEntry } from './binary';
18
+ import type { ExtractedSchema } from '../exec/cli-runtime/schema-extractor';
19
+ export interface StageInput {
20
+ stageDir: string;
21
+ /** Project root (for reading README, icon, etc.). */
22
+ cwd: string;
23
+ /** Absolute path to the esbuild server bundle. */
24
+ serverBundlePath: string;
25
+ /** App name — written into server/package.json. */
26
+ name: string;
27
+ /** App version — written into server/package.json. */
28
+ version: string;
29
+ /** Schema extracted from the bundle (drives skill asset copy). */
30
+ schema: ExtractedSchema;
31
+ /** Absolute path of a resolved icon file (optional). */
32
+ iconPath?: string;
33
+ /** Binaries to stage under bin/{platform}/. */
34
+ binaries?: BinaryEntry[];
35
+ /** When true, copy README.md from cwd if present. @default true */
36
+ includeReadme?: boolean;
37
+ }
38
+ export interface StageResult {
39
+ stageDir: string;
40
+ /** Relative paths written into the stage (for logging). */
41
+ written: string[];
42
+ /** Whether an icon was actually staged (drives manifest.icon field). */
43
+ hasIcon: boolean;
44
+ /** Number of skill asset files copied (zero when no skills). */
45
+ skillAssetCount: number;
46
+ }
47
+ /** Build the staged `__stage/` tree on disk. */
48
+ export declare function stageMcpbDirectory(input: StageInput): StageResult;
49
+ /** Write the final manifest.json to the stage root. */
50
+ export declare function writeManifest(stageDir: string, manifest: unknown): string;
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ /**
3
+ * Stage the MCPB archive layout on disk before zipping.
4
+ *
5
+ * Layout produced:
6
+ *
7
+ * __stage/
8
+ * manifest.json
9
+ * server/
10
+ * index.js (esbuild bundle, renamed from {name}.bundle.js)
11
+ * package.json (minimal CJS manifest so Node resolves index.js)
12
+ * _skills/ (optional — when the server ships skills)
13
+ * bin/ (optional — when SEA is enabled)
14
+ * {platform}/{name}[.exe]
15
+ * icon.png (optional)
16
+ * README.md (optional)
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.stageMcpbDirectory = stageMcpbDirectory;
20
+ exports.writeManifest = writeManifest;
21
+ const tslib_1 = require("tslib");
22
+ const fs = tslib_1.__importStar(require("fs"));
23
+ const path = tslib_1.__importStar(require("path"));
24
+ const skill_assets_1 = require("../exec/skill-assets");
25
+ /** Build the staged `__stage/` tree on disk. */
26
+ function stageMcpbDirectory(input) {
27
+ const { stageDir, cwd, serverBundlePath, name, version, schema, iconPath, binaries = [], includeReadme = true, } = input;
28
+ const written = [];
29
+ fs.mkdirSync(stageDir, { recursive: true });
30
+ // 1. server/
31
+ const serverDir = path.join(stageDir, 'server');
32
+ fs.mkdirSync(serverDir, { recursive: true });
33
+ const serverIndex = path.join(serverDir, 'index.js');
34
+ fs.copyFileSync(serverBundlePath, serverIndex);
35
+ written.push('server/index.js');
36
+ // Minimal server/package.json so Node resolves index.js as CJS.
37
+ const serverPkg = {
38
+ name,
39
+ version,
40
+ main: 'index.js',
41
+ type: 'commonjs',
42
+ private: true,
43
+ };
44
+ fs.writeFileSync(path.join(serverDir, 'package.json'), `${JSON.stringify(serverPkg, null, 2)}\n`);
45
+ written.push('server/package.json');
46
+ // 2. server/_skills/ (if the bundle exposes skills)
47
+ const skillsResult = (0, skill_assets_1.copySkillAssets)(serverDir, schema.skillAssets);
48
+ if (skillsResult.copiedCount > 0) {
49
+ written.push('server/_skills/');
50
+ }
51
+ // 3. bin/{platform}/{file}
52
+ for (const bin of binaries) {
53
+ const destDir = path.join(stageDir, 'bin', bin.platform);
54
+ fs.mkdirSync(destDir, { recursive: true });
55
+ const destFile = path.join(destDir, bin.fileName);
56
+ fs.copyFileSync(bin.srcPath, destFile);
57
+ try {
58
+ fs.chmodSync(destFile, 0o755);
59
+ }
60
+ catch {
61
+ // Windows or a filesystem that rejects chmod — safe to ignore.
62
+ }
63
+ written.push(`bin/${bin.platform}/${bin.fileName}`);
64
+ }
65
+ // 4. icon.png
66
+ let hasIcon = false;
67
+ if (iconPath && fs.existsSync(iconPath)) {
68
+ const destIcon = path.join(stageDir, 'icon.png');
69
+ fs.copyFileSync(iconPath, destIcon);
70
+ written.push('icon.png');
71
+ hasIcon = true;
72
+ }
73
+ // 5. README.md
74
+ if (includeReadme) {
75
+ const readmePath = path.join(cwd, 'README.md');
76
+ if (fs.existsSync(readmePath)) {
77
+ fs.copyFileSync(readmePath, path.join(stageDir, 'README.md'));
78
+ written.push('README.md');
79
+ }
80
+ }
81
+ return {
82
+ stageDir,
83
+ written,
84
+ hasIcon,
85
+ skillAssetCount: skillsResult.copiedCount,
86
+ };
87
+ }
88
+ /** Write the final manifest.json to the stage root. */
89
+ function writeManifest(stageDir, manifest) {
90
+ const manifestPath = path.join(stageDir, 'manifest.json');
91
+ fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
92
+ return manifestPath;
93
+ }
94
+ //# sourceMappingURL=stage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stage.js","sourceRoot":"","sources":["../../../../../src/commands/build/mcpb/stage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Stage the MCPB archive layout on disk before zipping.\n *\n * Layout produced:\n *\n * __stage/\n * manifest.json\n * server/\n * index.js (esbuild bundle, renamed from {name}.bundle.js)\n * package.json (minimal CJS manifest so Node resolves index.js)\n * _skills/ (optional — when the server ships skills)\n * bin/ (optional — when SEA is enabled)\n * {platform}/{name}[.exe]\n * icon.png (optional)\n * README.md (optional)\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { BinaryEntry } from './binary';\nimport type { ExtractedSchema } from '../exec/cli-runtime/schema-extractor';\nimport { copySkillAssets } from '../exec/skill-assets';\n\nexport interface StageInput {\n stageDir: string;\n /** Project root (for reading README, icon, etc.). */\n cwd: string;\n /** Absolute path to the esbuild server bundle. */\n serverBundlePath: string;\n /** App name — written into server/package.json. */\n name: string;\n /** App version — written into server/package.json. */\n version: string;\n /** Schema extracted from the bundle (drives skill asset copy). */\n schema: ExtractedSchema;\n /** Absolute path of a resolved icon file (optional). */\n iconPath?: string;\n /** Binaries to stage under bin/{platform}/. */\n binaries?: BinaryEntry[];\n /** When true, copy README.md from cwd if present. @default true */\n includeReadme?: boolean;\n}\n\nexport interface StageResult {\n stageDir: string;\n /** Relative paths written into the stage (for logging). */\n written: string[];\n /** Whether an icon was actually staged (drives manifest.icon field). */\n hasIcon: boolean;\n /** Number of skill asset files copied (zero when no skills). */\n skillAssetCount: number;\n}\n\n/** Build the staged `__stage/` tree on disk. */\nexport function stageMcpbDirectory(input: StageInput): StageResult {\n const {\n stageDir,\n cwd,\n serverBundlePath,\n name,\n version,\n schema,\n iconPath,\n binaries = [],\n includeReadme = true,\n } = input;\n\n const written: string[] = [];\n fs.mkdirSync(stageDir, { recursive: true });\n\n // 1. server/\n const serverDir = path.join(stageDir, 'server');\n fs.mkdirSync(serverDir, { recursive: true });\n\n const serverIndex = path.join(serverDir, 'index.js');\n fs.copyFileSync(serverBundlePath, serverIndex);\n written.push('server/index.js');\n\n // Minimal server/package.json so Node resolves index.js as CJS.\n const serverPkg = {\n name,\n version,\n main: 'index.js',\n type: 'commonjs',\n private: true,\n };\n fs.writeFileSync(\n path.join(serverDir, 'package.json'),\n `${JSON.stringify(serverPkg, null, 2)}\\n`,\n );\n written.push('server/package.json');\n\n // 2. server/_skills/ (if the bundle exposes skills)\n const skillsResult = copySkillAssets(serverDir, schema.skillAssets);\n if (skillsResult.copiedCount > 0) {\n written.push('server/_skills/');\n }\n\n // 3. bin/{platform}/{file}\n for (const bin of binaries) {\n const destDir = path.join(stageDir, 'bin', bin.platform);\n fs.mkdirSync(destDir, { recursive: true });\n const destFile = path.join(destDir, bin.fileName);\n fs.copyFileSync(bin.srcPath, destFile);\n try {\n fs.chmodSync(destFile, 0o755);\n } catch {\n // Windows or a filesystem that rejects chmod — safe to ignore.\n }\n written.push(`bin/${bin.platform}/${bin.fileName}`);\n }\n\n // 4. icon.png\n let hasIcon = false;\n if (iconPath && fs.existsSync(iconPath)) {\n const destIcon = path.join(stageDir, 'icon.png');\n fs.copyFileSync(iconPath, destIcon);\n written.push('icon.png');\n hasIcon = true;\n }\n\n // 5. README.md\n if (includeReadme) {\n const readmePath = path.join(cwd, 'README.md');\n if (fs.existsSync(readmePath)) {\n fs.copyFileSync(readmePath, path.join(stageDir, 'README.md'));\n written.push('README.md');\n }\n }\n\n return {\n stageDir,\n written,\n hasIcon,\n skillAssetCount: skillsResult.copiedCount,\n };\n}\n\n/** Write the final manifest.json to the stage root. */\nexport function writeManifest(stageDir: string, manifest: unknown): string {\n const manifestPath = path.join(stageDir, 'manifest.json');\n fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`);\n return manifestPath;\n}\n"]}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Translate FrontMCP `setup.steps` into MCPB `user_config` + `mcp_config.env`.
3
+ *
4
+ * MCPB's user_config is a flat key/value form. FrontMCP's setup graph supports
5
+ * branching (`step.next`) and conditional visibility (`step.showWhen`). Those
6
+ * features have no MCPB equivalent — we emit a warning and render every step
7
+ * unconditionally.
8
+ */
9
+ import { type SetupStep } from '../exec/setup';
10
+ import type { McpbDeployment, McpbUserConfigEntry } from '../../../config/frontmcp-config.types';
11
+ export interface UserConfigTranslationResult {
12
+ /** MCPB user_config block. */
13
+ userConfig: Record<string, McpbUserConfigEntry>;
14
+ /** mcp_config.env map: ENV_NAME → ${user_config.key}. */
15
+ env: Record<string, string>;
16
+ /** Warnings to surface to the CLI log. */
17
+ warnings: string[];
18
+ }
19
+ /** Convert kebab/snake/SCREAMING_SNAKE id to camelCase for the MCPB key. */
20
+ export declare function idToCamelKey(id: string): string;
21
+ /**
22
+ * Produce MCPB user_config + env mapping from FrontMCP setup steps.
23
+ * Also applies any per-key `deployment.userConfig` overrides (e.g., to change
24
+ * type to `file` or `directory`).
25
+ */
26
+ export declare function setupStepsToUserConfig(steps: SetupStep[] | undefined, deployment?: McpbDeployment): UserConfigTranslationResult;
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ /**
3
+ * Translate FrontMCP `setup.steps` into MCPB `user_config` + `mcp_config.env`.
4
+ *
5
+ * MCPB's user_config is a flat key/value form. FrontMCP's setup graph supports
6
+ * branching (`step.next`) and conditional visibility (`step.showWhen`). Those
7
+ * features have no MCPB equivalent — we emit a warning and render every step
8
+ * unconditionally.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.idToCamelKey = idToCamelKey;
12
+ exports.setupStepsToUserConfig = setupStepsToUserConfig;
13
+ const setup_1 = require("../exec/setup");
14
+ const constants_1 = require("./constants");
15
+ /** Convert kebab/snake/SCREAMING_SNAKE id to camelCase for the MCPB key. */
16
+ function idToCamelKey(id) {
17
+ const normalized = id.replace(/[^a-zA-Z0-9]+/g, ' ').trim().toLowerCase();
18
+ const parts = normalized.split(/\s+/).filter(Boolean);
19
+ if (parts.length === 0)
20
+ return 'value';
21
+ return parts
22
+ .map((part, idx) => (idx === 0 ? part : part[0].toUpperCase() + part.slice(1)))
23
+ .join('');
24
+ }
25
+ /** Resolve the user_config.type for a setup step. */
26
+ function resolveType(jsonSchema, override) {
27
+ if (override) {
28
+ return { type: override, multiple: false };
29
+ }
30
+ const schemaType = jsonSchema['type'];
31
+ if (schemaType === 'boolean')
32
+ return { type: 'boolean', multiple: false };
33
+ if (schemaType === 'number' || schemaType === 'integer') {
34
+ return { type: 'number', multiple: false };
35
+ }
36
+ if (schemaType === 'array') {
37
+ const items = jsonSchema['items'];
38
+ const itemType = items && typeof items === 'object' && 'type' in items
39
+ ? items.type
40
+ : 'string';
41
+ if (itemType === 'number' || itemType === 'integer') {
42
+ return { type: 'number', multiple: true };
43
+ }
44
+ if (itemType === 'boolean') {
45
+ return { type: 'boolean', multiple: true };
46
+ }
47
+ return { type: 'string', multiple: true };
48
+ }
49
+ return { type: 'string', multiple: false };
50
+ }
51
+ /**
52
+ * Produce MCPB user_config + env mapping from FrontMCP setup steps.
53
+ * Also applies any per-key `deployment.userConfig` overrides (e.g., to change
54
+ * type to `file` or `directory`).
55
+ */
56
+ function setupStepsToUserConfig(steps, deployment) {
57
+ const userConfig = {};
58
+ const env = {};
59
+ const warnings = [];
60
+ if (!steps || steps.length === 0) {
61
+ // Allow deployment.userConfig to stand alone (no setup graph).
62
+ if (deployment?.userConfig) {
63
+ for (const [key, entry] of Object.entries(deployment.userConfig)) {
64
+ userConfig[key] = entry;
65
+ }
66
+ }
67
+ return { userConfig, env, warnings };
68
+ }
69
+ for (const step of steps) {
70
+ if (step.showWhen || step.next) {
71
+ warnings.push(`Step "${step.id}" uses showWhen/next — MCPB has no equivalent; rendered unconditionally`);
72
+ }
73
+ const jsonSchema = step.jsonSchema ?? (step.schema ? (0, setup_1.zodSchemaToJsonSchema)(step.schema) : { type: 'string' });
74
+ const key = idToCamelKey(step.id);
75
+ const override = deployment?.userConfig?.[key];
76
+ const { type, multiple } = resolveType(jsonSchema, override?.type);
77
+ const entry = {
78
+ type,
79
+ title: override?.title ?? step.prompt,
80
+ ...(step.description || override?.description
81
+ ? { description: override?.description ?? step.description }
82
+ : {}),
83
+ ...(step.sensitive || override?.sensitive ? { sensitive: true } : {}),
84
+ ...(multiple || override?.multiple ? { multiple: true } : {}),
85
+ };
86
+ const required = inferRequired(jsonSchema, override?.required);
87
+ if (required)
88
+ entry.required = true;
89
+ const defaultVal = jsonSchema['default'] ?? override?.default;
90
+ if (defaultVal !== undefined && !entry.sensitive) {
91
+ if ((entry.type === 'string' || entry.type === 'directory' || entry.type === 'file') &&
92
+ typeof defaultVal === 'string') {
93
+ entry.default = defaultVal;
94
+ }
95
+ else if (entry.type === 'number' && typeof defaultVal === 'number') {
96
+ entry.default = defaultVal;
97
+ }
98
+ else if (entry.type === 'boolean' && typeof defaultVal === 'boolean') {
99
+ entry.default = defaultVal;
100
+ }
101
+ }
102
+ const min = pickNumber(jsonSchema['minimum'] ?? jsonSchema['minLength']) ?? override?.min;
103
+ const max = pickNumber(jsonSchema['maximum'] ?? jsonSchema['maxLength']) ?? override?.max;
104
+ if (min !== undefined)
105
+ entry.min = min;
106
+ if (max !== undefined)
107
+ entry.max = max;
108
+ // Merge explicit deployment.userConfig fields that weren't captured above.
109
+ if (override) {
110
+ for (const prop of ['title', 'description', 'required', 'multiple', 'sensitive', 'min', 'max', 'default']) {
111
+ if (override[prop] !== undefined && entry[prop] === undefined) {
112
+ entry[prop] = override[prop];
113
+ }
114
+ }
115
+ }
116
+ userConfig[key] = entry;
117
+ const envName = step.env ?? (0, setup_1.idToEnvName)(step.id);
118
+ env[envName] = `\${${constants_1.USER_CONFIG_PREFIX}${key}}`;
119
+ }
120
+ // Any deployment.userConfig entries not derived from a setup step are merged verbatim.
121
+ if (deployment?.userConfig) {
122
+ for (const [key, entry] of Object.entries(deployment.userConfig)) {
123
+ if (!userConfig[key]) {
124
+ userConfig[key] = entry;
125
+ }
126
+ }
127
+ }
128
+ return { userConfig, env, warnings };
129
+ }
130
+ function inferRequired(jsonSchema, override) {
131
+ if (override !== undefined)
132
+ return override;
133
+ // JSON Schema 'required' arrays apply at the parent level; for a single-value
134
+ // schema, treat missing default + no `.optional()` marker as required.
135
+ if (jsonSchema['default'] !== undefined)
136
+ return false;
137
+ // Best-effort: Zod/v4 encodes optional as a union with undefined or nullable.
138
+ const anyOf = jsonSchema['anyOf'];
139
+ if (Array.isArray(anyOf) && anyOf.some((s) => s && typeof s === 'object' && s.type === 'null')) {
140
+ return false;
141
+ }
142
+ return true;
143
+ }
144
+ function pickNumber(value) {
145
+ return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
146
+ }
147
+ //# sourceMappingURL=user-config.js.map