@a5c-ai/extension-mux 5.0.1-staging.04ca6ab00d21

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 (116) hide show
  1. package/README.md +58 -0
  2. package/dist/binTemplates.d.ts +7 -0
  3. package/dist/binTemplates.d.ts.map +1 -0
  4. package/dist/binTemplates.js +292 -0
  5. package/dist/cli.d.ts +8 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +299 -0
  8. package/dist/compiler.d.ts +15 -0
  9. package/dist/compiler.d.ts.map +1 -0
  10. package/dist/compiler.js +118 -0
  11. package/dist/diff.d.ts +9 -0
  12. package/dist/diff.d.ts.map +1 -0
  13. package/dist/diff.js +183 -0
  14. package/dist/emit.d.ts +3 -0
  15. package/dist/emit.d.ts.map +1 -0
  16. package/dist/emit.js +42 -0
  17. package/dist/hookRegistration.d.ts +8 -0
  18. package/dist/hookRegistration.d.ts.map +1 -0
  19. package/dist/hookRegistration.js +9 -0
  20. package/dist/index.d.ts +13 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +13 -0
  23. package/dist/init.d.ts +17 -0
  24. package/dist/init.d.ts.map +1 -0
  25. package/dist/init.js +200 -0
  26. package/dist/installInstructions.d.ts +3 -0
  27. package/dist/installInstructions.d.ts.map +1 -0
  28. package/dist/installInstructions.js +150 -0
  29. package/dist/installSharedGenerator.d.ts +3 -0
  30. package/dist/installSharedGenerator.d.ts.map +1 -0
  31. package/dist/installSharedGenerator.js +229 -0
  32. package/dist/manifestGenerators.d.ts +10 -0
  33. package/dist/manifestGenerators.d.ts.map +1 -0
  34. package/dist/manifestGenerators.js +11 -0
  35. package/dist/marketplaceGenerator.d.ts +3 -0
  36. package/dist/marketplaceGenerator.d.ts.map +1 -0
  37. package/dist/marketplaceGenerator.js +46 -0
  38. package/dist/proxiedHookTemplates.d.ts +10 -0
  39. package/dist/proxiedHookTemplates.d.ts.map +1 -0
  40. package/dist/proxiedHookTemplates.js +122 -0
  41. package/dist/resolve.d.ts +3 -0
  42. package/dist/resolve.d.ts.map +1 -0
  43. package/dist/resolve.js +106 -0
  44. package/dist/schema.d.ts +231 -0
  45. package/dist/schema.d.ts.map +1 -0
  46. package/dist/schema.js +340 -0
  47. package/dist/sdkConfig.d.ts +20 -0
  48. package/dist/sdkConfig.d.ts.map +1 -0
  49. package/dist/sdkConfig.js +41 -0
  50. package/dist/targets/adapters/base.d.ts +10 -0
  51. package/dist/targets/adapters/base.d.ts.map +1 -0
  52. package/dist/targets/adapters/base.js +16 -0
  53. package/dist/targets/adapters/claude-code.d.ts +9 -0
  54. package/dist/targets/adapters/claude-code.d.ts.map +1 -0
  55. package/dist/targets/adapters/claude-code.js +83 -0
  56. package/dist/targets/adapters/codex.d.ts +13 -0
  57. package/dist/targets/adapters/codex.d.ts.map +1 -0
  58. package/dist/targets/adapters/codex.js +103 -0
  59. package/dist/targets/adapters/cursor.d.ts +9 -0
  60. package/dist/targets/adapters/cursor.d.ts.map +1 -0
  61. package/dist/targets/adapters/cursor.js +57 -0
  62. package/dist/targets/adapters/gemini.d.ts +9 -0
  63. package/dist/targets/adapters/gemini.d.ts.map +1 -0
  64. package/dist/targets/adapters/gemini.js +86 -0
  65. package/dist/targets/adapters/github-copilot.d.ts +9 -0
  66. package/dist/targets/adapters/github-copilot.d.ts.map +1 -0
  67. package/dist/targets/adapters/github-copilot.js +61 -0
  68. package/dist/targets/adapters/hermes.d.ts +13 -0
  69. package/dist/targets/adapters/hermes.d.ts.map +1 -0
  70. package/dist/targets/adapters/hermes.js +96 -0
  71. package/dist/targets/adapters/hooks-utils.d.ts +12 -0
  72. package/dist/targets/adapters/hooks-utils.d.ts.map +1 -0
  73. package/dist/targets/adapters/hooks-utils.js +60 -0
  74. package/dist/targets/adapters/index.d.ts +27 -0
  75. package/dist/targets/adapters/index.d.ts.map +1 -0
  76. package/dist/targets/adapters/index.js +64 -0
  77. package/dist/targets/adapters/interface.d.ts +8 -0
  78. package/dist/targets/adapters/interface.d.ts.map +1 -0
  79. package/dist/targets/adapters/interface.js +2 -0
  80. package/dist/targets/adapters/oh-my-pi.d.ts +11 -0
  81. package/dist/targets/adapters/oh-my-pi.d.ts.map +1 -0
  82. package/dist/targets/adapters/oh-my-pi.js +88 -0
  83. package/dist/targets/adapters/openclaw.d.ts +14 -0
  84. package/dist/targets/adapters/openclaw.d.ts.map +1 -0
  85. package/dist/targets/adapters/openclaw.js +165 -0
  86. package/dist/targets/adapters/opencode.d.ts +10 -0
  87. package/dist/targets/adapters/opencode.d.ts.map +1 -0
  88. package/dist/targets/adapters/opencode.js +93 -0
  89. package/dist/targets/adapters/pi.d.ts +11 -0
  90. package/dist/targets/adapters/pi.d.ts.map +1 -0
  91. package/dist/targets/adapters/pi.js +90 -0
  92. package/dist/targets/index.d.ts +7 -0
  93. package/dist/targets/index.d.ts.map +1 -0
  94. package/dist/targets/index.js +77 -0
  95. package/dist/transform.d.ts +4 -0
  96. package/dist/transform.d.ts.map +1 -0
  97. package/dist/transform.js +243 -0
  98. package/dist/transformEmitters.d.ts +8 -0
  99. package/dist/transformEmitters.d.ts.map +1 -0
  100. package/dist/transformEmitters.js +340 -0
  101. package/dist/transformHelpers.d.ts +13 -0
  102. package/dist/transformHelpers.d.ts.map +1 -0
  103. package/dist/transformHelpers.js +239 -0
  104. package/dist/types.d.ts +204 -0
  105. package/dist/types.d.ts.map +1 -0
  106. package/dist/types.js +2 -0
  107. package/dist/utils.d.ts +42 -0
  108. package/dist/utils.d.ts.map +1 -0
  109. package/dist/utils.js +187 -0
  110. package/dist/validate.d.ts +3 -0
  111. package/dist/validate.d.ts.map +1 -0
  112. package/dist/validate.js +188 -0
  113. package/dist/verify.d.ts +6 -0
  114. package/dist/verify.d.ts.map +1 -0
  115. package/dist/verify.js +294 -0
  116. package/package.json +68 -0
@@ -0,0 +1,106 @@
1
+ // Stage 2: RESOLVE - Load target profile and compute effective manifest
2
+ import { getAllTargets, getTargetProfile } from './targets/index.js';
3
+ import { deepMerge } from './utils.js';
4
+ export function resolve(manifest, targetName) {
5
+ const diagnostics = [];
6
+ // Load target profile
7
+ const targetProfile = getTargetProfile(targetName);
8
+ if (!targetProfile) {
9
+ diagnostics.push({
10
+ level: 'error',
11
+ category: 'compilation',
12
+ message: `Unknown target: ${targetName}`,
13
+ target: targetName,
14
+ suggestion: `Valid targets: ${getAllTargets().join(', ')}`,
15
+ });
16
+ // Return error result
17
+ return {
18
+ effectiveManifest: manifest,
19
+ targetProfile: {
20
+ name: targetName,
21
+ displayName: targetName,
22
+ adapterName: targetName,
23
+ pluginRootEnvVar: null,
24
+ supportedHooks: new Map(),
25
+ commandFormat: 'markdown',
26
+ skillHandling: 'native',
27
+ manifestFormat: 'plugin.json',
28
+ hookRegistrationFormat: null,
29
+ hookRegistrationOutputPath: null,
30
+ hookRegistrationAliasPaths: [],
31
+ harnessManifestPath: null,
32
+ requiredSurfaceFile: null,
33
+ scriptVariants: [],
34
+ npmPublishable: false,
35
+ adapterFamily: 'shell-hook',
36
+ distribution: 'marketplace',
37
+ componentSupport: { agents: 'unsupported', context: 'unsupported' },
38
+ },
39
+ componentSupport: {
40
+ hooks: {},
41
+ commands: 'unsupported',
42
+ skills: 'unsupported',
43
+ agents: 'unsupported',
44
+ context: 'unsupported',
45
+ },
46
+ diagnostics,
47
+ };
48
+ }
49
+ // Apply target overrides
50
+ let effectiveManifest = { ...manifest };
51
+ if (manifest.targets && manifest.targets[targetName]) {
52
+ const override = manifest.targets[targetName];
53
+ const { extraFileSets: _extraFileSets, harnessInstallSurfaceExportSets: _harnessInstallSurfaceExportSets, ...mergeableOverride } = override;
54
+ // Deep merge handles the override, but TypeScript needs to know that
55
+ // the result may include extended fields like npmPackageName and
56
+ // the skills field may temporarily hold the 'derive-from-commands' directive.
57
+ // deepMerge returns Record<string, unknown>, so we cast through unknown
58
+ // back to A5cPluginManifest, as we know the merge preserves required fields.
59
+ effectiveManifest = deepMerge(effectiveManifest, mergeableOverride);
60
+ }
61
+ // Compute component support
62
+ const componentSupport = {
63
+ hooks: {},
64
+ commands: targetProfile.commandFormat === 'none' ? 'unsupported' : targetProfile.commandFormat === 'toml' ? 'toml' : 'native',
65
+ skills: targetProfile.skillHandling === 'native' ? 'native' : targetProfile.skillHandling === 'derived-from-commands' ? 'derived' : 'unsupported',
66
+ agents: targetProfile.componentSupport?.agents ?? 'unsupported',
67
+ context: targetProfile.componentSupport?.context ?? 'unsupported',
68
+ };
69
+ // Determine hook support for each canonical hook
70
+ if (effectiveManifest.hooks) {
71
+ for (const canonicalHook of Object.keys(effectiveManifest.hooks)) {
72
+ const nativeHook = targetProfile.supportedHooks.get(canonicalHook);
73
+ if (nativeHook) {
74
+ componentSupport.hooks[canonicalHook] = 'native';
75
+ }
76
+ else {
77
+ componentSupport.hooks[canonicalHook] = 'unsupported';
78
+ diagnostics.push({
79
+ level: 'warning',
80
+ category: 'compatibility',
81
+ message: `Hook '${canonicalHook}' is not supported by target '${targetName}' — skipping`,
82
+ component: `hooks.${canonicalHook}`,
83
+ target: targetName,
84
+ });
85
+ }
86
+ }
87
+ }
88
+ // Check for skill derivation directive
89
+ if (targetProfile.skillHandling === 'derived-from-commands') {
90
+ const skillsDirective = effectiveManifest.skills;
91
+ if (typeof skillsDirective === 'string' && skillsDirective === 'derive-from-commands') {
92
+ diagnostics.push({
93
+ level: 'info',
94
+ category: 'compilation',
95
+ message: `Target '${targetName}' will derive skills from commands`,
96
+ target: targetName,
97
+ });
98
+ }
99
+ }
100
+ return {
101
+ effectiveManifest,
102
+ targetProfile,
103
+ componentSupport,
104
+ diagnostics,
105
+ };
106
+ }
@@ -0,0 +1,231 @@
1
+ import type { Diagnostic } from './types.js';
2
+ export declare const A5C_PLUGIN_SCHEMA: {
3
+ $schema: string;
4
+ $id: string;
5
+ title: string;
6
+ type: string;
7
+ required: string[];
8
+ properties: {
9
+ name: {
10
+ type: string;
11
+ pattern: string;
12
+ };
13
+ version: {
14
+ type: string;
15
+ };
16
+ description: {
17
+ type: string;
18
+ };
19
+ author: {
20
+ oneOf: ({
21
+ type: string;
22
+ required?: undefined;
23
+ properties?: undefined;
24
+ } | {
25
+ type: string;
26
+ required: string[];
27
+ properties: {
28
+ name: {
29
+ type: string;
30
+ };
31
+ email: {
32
+ type: string;
33
+ format: string;
34
+ };
35
+ };
36
+ })[];
37
+ };
38
+ license: {
39
+ type: string;
40
+ };
41
+ repository: {
42
+ type: string;
43
+ properties: {
44
+ type: {
45
+ type: string;
46
+ };
47
+ url: {
48
+ type: string;
49
+ format: string;
50
+ };
51
+ };
52
+ };
53
+ homepage: {
54
+ type: string;
55
+ format: string;
56
+ };
57
+ keywords: {
58
+ type: string;
59
+ items: {
60
+ type: string;
61
+ };
62
+ };
63
+ hooks: {
64
+ type: string;
65
+ additionalProperties: {
66
+ type: string[];
67
+ };
68
+ };
69
+ commands: {
70
+ oneOf: ({
71
+ type: string;
72
+ items?: undefined;
73
+ } | {
74
+ type: string;
75
+ items: {
76
+ type: string;
77
+ };
78
+ })[];
79
+ };
80
+ skills: {
81
+ type: string;
82
+ items: {
83
+ type: string;
84
+ required: string[];
85
+ properties: {
86
+ name: {
87
+ type: string;
88
+ };
89
+ file: {
90
+ type: string;
91
+ };
92
+ };
93
+ };
94
+ };
95
+ agents: {
96
+ oneOf: ({
97
+ type: string;
98
+ items?: undefined;
99
+ } | {
100
+ type: string;
101
+ items: {
102
+ type: string;
103
+ };
104
+ })[];
105
+ };
106
+ contextFiles: {
107
+ type: string;
108
+ additionalProperties: {
109
+ type: string;
110
+ };
111
+ };
112
+ extraFileSets: {
113
+ type: string;
114
+ additionalProperties: {
115
+ type: string;
116
+ additionalProperties: {
117
+ type: string;
118
+ };
119
+ };
120
+ };
121
+ harnessInstallSurfaceExportSets: {
122
+ type: string;
123
+ additionalProperties: {
124
+ type: string;
125
+ items: {
126
+ type: string;
127
+ };
128
+ };
129
+ };
130
+ targets: {
131
+ type: string;
132
+ additionalProperties: {
133
+ type: string;
134
+ properties: {
135
+ npmPackageName: {
136
+ type: string;
137
+ };
138
+ type: {
139
+ type: string;
140
+ enum: string[];
141
+ };
142
+ skills: {
143
+ oneOf: ({
144
+ type: string;
145
+ enum: string[];
146
+ } | {
147
+ type: string;
148
+ enum?: undefined;
149
+ })[];
150
+ };
151
+ hooks: {
152
+ type: string;
153
+ additionalProperties: {
154
+ type: string[];
155
+ };
156
+ };
157
+ extraFileSets: {
158
+ type: string;
159
+ items: {
160
+ type: string;
161
+ };
162
+ };
163
+ extraFiles: {
164
+ type: string;
165
+ additionalProperties: {
166
+ type: string;
167
+ };
168
+ };
169
+ templateVars: {
170
+ type: string;
171
+ additionalProperties: {
172
+ type: string;
173
+ };
174
+ };
175
+ harnessInstallSurfaceExportSets: {
176
+ type: string;
177
+ items: {
178
+ type: string;
179
+ };
180
+ };
181
+ };
182
+ additionalProperties: boolean;
183
+ };
184
+ };
185
+ include: {
186
+ type: string;
187
+ items: {
188
+ type: string;
189
+ };
190
+ description: string;
191
+ };
192
+ hookConfig: {
193
+ type: string;
194
+ properties: {
195
+ proxyAdapter: {
196
+ type: string;
197
+ };
198
+ matchers: {
199
+ type: string;
200
+ additionalProperties: {
201
+ type: string;
202
+ };
203
+ };
204
+ };
205
+ };
206
+ sdk: {
207
+ type: string;
208
+ };
209
+ hookFilePattern: {
210
+ type: string;
211
+ };
212
+ postInstall: {
213
+ type: string;
214
+ };
215
+ installSurface: {
216
+ type: string;
217
+ };
218
+ installSurfaceExports: {
219
+ type: string;
220
+ items: {
221
+ type: string;
222
+ };
223
+ };
224
+ };
225
+ additionalProperties: boolean;
226
+ };
227
+ export declare function validate(data: unknown): {
228
+ valid: boolean;
229
+ diagnostics: Diagnostic[];
230
+ };
231
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmI7B,CAAC;AAcF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,UAAU,EAAE,CAAA;CAAE,CAyMrF"}
package/dist/schema.js ADDED
@@ -0,0 +1,340 @@
1
+ // JSON Schema for plugin.json validation
2
+ // Manual validation implementation to avoid external dependencies
3
+ export const A5C_PLUGIN_SCHEMA = {
4
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
5
+ $id: 'https://extension-mux.dev/schemas/plugin.json',
6
+ title: 'Unified Plugin Format Manifest',
7
+ type: 'object',
8
+ required: ['name', 'version', 'description', 'author', 'license'],
9
+ properties: {
10
+ name: { type: 'string', pattern: '^[a-z0-9-]+$' },
11
+ version: { type: 'string' },
12
+ description: { type: 'string' },
13
+ author: {
14
+ oneOf: [
15
+ { type: 'string' },
16
+ {
17
+ type: 'object',
18
+ required: ['name'],
19
+ properties: {
20
+ name: { type: 'string' },
21
+ email: { type: 'string', format: 'email' },
22
+ },
23
+ },
24
+ ],
25
+ },
26
+ license: { type: 'string' },
27
+ repository: {
28
+ type: 'object',
29
+ properties: {
30
+ type: { type: 'string' },
31
+ url: { type: 'string', format: 'uri' },
32
+ },
33
+ },
34
+ homepage: { type: 'string', format: 'uri' },
35
+ keywords: { type: 'array', items: { type: 'string' } },
36
+ hooks: {
37
+ type: 'object',
38
+ additionalProperties: { type: ['string', 'boolean', 'null'] },
39
+ },
40
+ commands: {
41
+ oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }],
42
+ },
43
+ skills: {
44
+ type: 'array',
45
+ items: {
46
+ type: 'object',
47
+ required: ['name', 'file'],
48
+ properties: {
49
+ name: { type: 'string' },
50
+ file: { type: 'string' },
51
+ },
52
+ },
53
+ },
54
+ agents: {
55
+ oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }],
56
+ },
57
+ contextFiles: {
58
+ type: 'object',
59
+ additionalProperties: { type: 'string' },
60
+ },
61
+ extraFileSets: {
62
+ type: 'object',
63
+ additionalProperties: {
64
+ type: 'object',
65
+ additionalProperties: { type: 'string' },
66
+ },
67
+ },
68
+ harnessInstallSurfaceExportSets: {
69
+ type: 'object',
70
+ additionalProperties: {
71
+ type: 'array',
72
+ items: { type: 'string' },
73
+ },
74
+ },
75
+ targets: {
76
+ type: 'object',
77
+ additionalProperties: {
78
+ type: 'object',
79
+ properties: {
80
+ npmPackageName: { type: 'string' },
81
+ type: { type: 'string', enum: ['typescript-build'] },
82
+ skills: {
83
+ oneOf: [
84
+ { type: 'string', enum: ['derive-from-commands'] },
85
+ { type: 'array' },
86
+ ],
87
+ },
88
+ hooks: {
89
+ type: 'object',
90
+ additionalProperties: { type: ['string', 'null'] },
91
+ },
92
+ extraFileSets: {
93
+ type: 'array',
94
+ items: { type: 'string' },
95
+ },
96
+ extraFiles: {
97
+ type: 'object',
98
+ additionalProperties: { type: 'string' },
99
+ },
100
+ templateVars: {
101
+ type: 'object',
102
+ additionalProperties: { type: 'string' },
103
+ },
104
+ harnessInstallSurfaceExportSets: {
105
+ type: 'array',
106
+ items: { type: 'string' },
107
+ },
108
+ },
109
+ additionalProperties: true,
110
+ },
111
+ },
112
+ include: {
113
+ type: 'array',
114
+ items: { type: 'string' },
115
+ description: 'Extra files to copy to output (glob patterns relative to source dir)',
116
+ },
117
+ hookConfig: {
118
+ type: 'object',
119
+ properties: {
120
+ proxyAdapter: { type: 'boolean' },
121
+ matchers: {
122
+ type: 'object',
123
+ additionalProperties: { type: 'string' },
124
+ },
125
+ },
126
+ },
127
+ sdk: { type: 'object' },
128
+ hookFilePattern: { type: 'string' },
129
+ postInstall: { type: 'string' },
130
+ installSurface: { type: 'string' },
131
+ installSurfaceExports: { type: 'array', items: { type: 'string' } },
132
+ },
133
+ additionalProperties: false,
134
+ };
135
+ function isString(value) {
136
+ return typeof value === 'string';
137
+ }
138
+ function isObject(value) {
139
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
140
+ }
141
+ function isArray(value) {
142
+ return Array.isArray(value);
143
+ }
144
+ export function validate(data) {
145
+ const diagnostics = [];
146
+ if (!isObject(data)) {
147
+ diagnostics.push({
148
+ level: 'error',
149
+ category: 'validation',
150
+ message: 'Manifest must be a JSON object',
151
+ });
152
+ return { valid: false, diagnostics };
153
+ }
154
+ const manifest = data;
155
+ // Required fields
156
+ const required = ['name', 'version', 'description', 'author', 'license'];
157
+ for (const field of required) {
158
+ if (!(field in manifest)) {
159
+ diagnostics.push({
160
+ level: 'error',
161
+ category: 'validation',
162
+ message: `Required field '${field}' is missing`,
163
+ });
164
+ }
165
+ }
166
+ // name: string matching pattern
167
+ if ('name' in manifest) {
168
+ if (!isString(manifest.name)) {
169
+ diagnostics.push({
170
+ level: 'error',
171
+ category: 'validation',
172
+ message: "Field 'name' must be a string",
173
+ });
174
+ }
175
+ else if (!/^[a-z0-9-]+$/.test(manifest.name)) {
176
+ diagnostics.push({
177
+ level: 'error',
178
+ category: 'validation',
179
+ message: "Field 'name' must match pattern ^[a-z0-9-]+$",
180
+ });
181
+ }
182
+ }
183
+ // version, description, license: strings
184
+ for (const field of ['version', 'description', 'license']) {
185
+ if (field in manifest && !isString(manifest[field])) {
186
+ diagnostics.push({
187
+ level: 'error',
188
+ category: 'validation',
189
+ message: `Field '${field}' must be a string`,
190
+ });
191
+ }
192
+ }
193
+ // author: string or object with name
194
+ if ('author' in manifest) {
195
+ const author = manifest.author;
196
+ if (!isString(author) && !isObject(author)) {
197
+ diagnostics.push({
198
+ level: 'error',
199
+ category: 'validation',
200
+ message: "Field 'author' must be a string or object",
201
+ });
202
+ }
203
+ else if (isObject(author)) {
204
+ if (!('name' in author) || !isString(author.name)) {
205
+ diagnostics.push({
206
+ level: 'error',
207
+ category: 'validation',
208
+ message: "Field 'author.name' is required and must be a string",
209
+ });
210
+ }
211
+ if ('email' in author && !isString(author.email)) {
212
+ diagnostics.push({
213
+ level: 'error',
214
+ category: 'validation',
215
+ message: "Field 'author.email' must be a string",
216
+ });
217
+ }
218
+ }
219
+ }
220
+ // repository: object with type and url
221
+ if ('repository' in manifest) {
222
+ if (!isObject(manifest.repository)) {
223
+ diagnostics.push({
224
+ level: 'error',
225
+ category: 'validation',
226
+ message: "Field 'repository' must be an object",
227
+ });
228
+ }
229
+ else {
230
+ const repo = manifest.repository;
231
+ if ('type' in repo && !isString(repo.type)) {
232
+ diagnostics.push({
233
+ level: 'error',
234
+ category: 'validation',
235
+ message: "Field 'repository.type' must be a string",
236
+ });
237
+ }
238
+ if ('url' in repo && !isString(repo.url)) {
239
+ diagnostics.push({
240
+ level: 'error',
241
+ category: 'validation',
242
+ message: "Field 'repository.url' must be a string",
243
+ });
244
+ }
245
+ }
246
+ }
247
+ // hooks: object with string or null values
248
+ if ('hooks' in manifest) {
249
+ if (!isObject(manifest.hooks)) {
250
+ diagnostics.push({
251
+ level: 'error',
252
+ category: 'validation',
253
+ message: "Field 'hooks' must be an object",
254
+ });
255
+ }
256
+ else {
257
+ for (const [key, value] of Object.entries(manifest.hooks)) {
258
+ if (!isString(value) && typeof value !== 'boolean' && value !== null) {
259
+ diagnostics.push({
260
+ level: 'error',
261
+ category: 'validation',
262
+ message: `Hook '${key}' must be a string, boolean, or null`,
263
+ });
264
+ }
265
+ }
266
+ }
267
+ }
268
+ // commands: string or array of strings
269
+ if ('commands' in manifest) {
270
+ const commands = manifest.commands;
271
+ if (!isString(commands) && !isArray(commands)) {
272
+ diagnostics.push({
273
+ level: 'error',
274
+ category: 'validation',
275
+ message: "Field 'commands' must be a string or array",
276
+ });
277
+ }
278
+ else if (isArray(commands)) {
279
+ for (let i = 0; i < commands.length; i++) {
280
+ if (!isString(commands[i])) {
281
+ diagnostics.push({
282
+ level: 'error',
283
+ category: 'validation',
284
+ message: `commands[${i}] must be a string`,
285
+ });
286
+ }
287
+ }
288
+ }
289
+ }
290
+ // skills: array of objects with name and file
291
+ if ('skills' in manifest) {
292
+ if (!isArray(manifest.skills)) {
293
+ diagnostics.push({
294
+ level: 'error',
295
+ category: 'validation',
296
+ message: "Field 'skills' must be an array",
297
+ });
298
+ }
299
+ else {
300
+ for (let i = 0; i < manifest.skills.length; i++) {
301
+ const skill = manifest.skills[i];
302
+ if (!isObject(skill)) {
303
+ diagnostics.push({
304
+ level: 'error',
305
+ category: 'validation',
306
+ message: `skills[${i}] must be an object`,
307
+ });
308
+ }
309
+ else {
310
+ if (!('name' in skill) || !isString(skill.name)) {
311
+ diagnostics.push({
312
+ level: 'error',
313
+ category: 'validation',
314
+ message: `skills[${i}].name is required and must be a string`,
315
+ });
316
+ }
317
+ if (!('file' in skill) || !isString(skill.file)) {
318
+ diagnostics.push({
319
+ level: 'error',
320
+ category: 'validation',
321
+ message: `skills[${i}].file is required and must be a string`,
322
+ });
323
+ }
324
+ }
325
+ }
326
+ }
327
+ }
328
+ // targets: object with per-target overrides
329
+ if ('targets' in manifest && !isObject(manifest.targets)) {
330
+ diagnostics.push({
331
+ level: 'error',
332
+ category: 'validation',
333
+ message: "Field 'targets' must be an object",
334
+ });
335
+ }
336
+ return {
337
+ valid: diagnostics.filter((d) => d.level === 'error').length === 0,
338
+ diagnostics,
339
+ };
340
+ }
@@ -0,0 +1,20 @@
1
+ import type { A5cPluginManifest, TargetProfile } from './types.js';
2
+ export interface SdkConfig {
3
+ package: string;
4
+ cli: string;
5
+ proxyPackage: string;
6
+ proxyBinary: string;
7
+ scope: string;
8
+ envPrefix: string;
9
+ stateDir: string;
10
+ }
11
+ type PackageNamedManifest = A5cPluginManifest & {
12
+ npmPackageName?: string;
13
+ };
14
+ type TargetPackageProfile = Pick<TargetProfile, 'name' | 'npmPackageName'>;
15
+ export declare const BABYSITTER_DEFAULT_SDK_CONFIG: Readonly<SdkConfig>;
16
+ export declare function resolveSdkConfig(manifest: A5cPluginManifest): SdkConfig;
17
+ export declare function resolveTargetNpmPackageName(manifest: PackageNamedManifest, targetProfile: TargetPackageProfile): string;
18
+ export declare function resolveTargetCliName(manifest: PackageNamedManifest, targetProfile: TargetPackageProfile): string;
19
+ export {};
20
+ //# sourceMappingURL=sdkConfig.d.ts.map