@a5c-ai/extensions-adapter 6.0.1-staging.f8aae93c2dbc → 6.0.1

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 (127) hide show
  1. package/dist/binTemplates.d.ts +7 -0
  2. package/dist/binTemplates.d.ts.map +1 -0
  3. package/dist/binTemplates.js +292 -0
  4. package/dist/cli.d.ts +8 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +299 -0
  7. package/dist/compiler.d.ts +15 -0
  8. package/dist/compiler.d.ts.map +1 -0
  9. package/dist/compiler.js +118 -0
  10. package/dist/diff.d.ts +9 -0
  11. package/dist/diff.d.ts.map +1 -0
  12. package/dist/diff.js +183 -0
  13. package/dist/emit.d.ts +3 -0
  14. package/dist/emit.d.ts.map +1 -0
  15. package/dist/emit.js +42 -0
  16. package/dist/extension-adapter.d.ts +3 -0
  17. package/dist/extension-adapter.d.ts.map +1 -0
  18. package/dist/extension-adapter.js +4 -0
  19. package/dist/hookRegistration.d.ts +8 -0
  20. package/dist/hookRegistration.d.ts.map +1 -0
  21. package/dist/hookRegistration.js +9 -0
  22. package/dist/index.d.ts +13 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +13 -0
  25. package/dist/init.d.ts +17 -0
  26. package/dist/init.d.ts.map +1 -0
  27. package/dist/init.js +200 -0
  28. package/dist/installInstructions.d.ts +3 -0
  29. package/dist/installInstructions.d.ts.map +1 -0
  30. package/dist/installInstructions.js +150 -0
  31. package/dist/installSharedGenerator.d.ts +3 -0
  32. package/dist/installSharedGenerator.d.ts.map +1 -0
  33. package/dist/installSharedGenerator.js +229 -0
  34. package/dist/manifestGenerators.d.ts +10 -0
  35. package/dist/manifestGenerators.d.ts.map +1 -0
  36. package/dist/manifestGenerators.js +11 -0
  37. package/dist/marketplaceGenerator.d.ts +3 -0
  38. package/dist/marketplaceGenerator.d.ts.map +1 -0
  39. package/dist/marketplaceGenerator.js +47 -0
  40. package/dist/mcpConfig.d.ts +69 -0
  41. package/dist/mcpConfig.d.ts.map +1 -0
  42. package/dist/mcpConfig.js +115 -0
  43. package/dist/proxiedHookTemplates.d.ts +10 -0
  44. package/dist/proxiedHookTemplates.d.ts.map +1 -0
  45. package/dist/proxiedHookTemplates.js +123 -0
  46. package/dist/resolve.d.ts +3 -0
  47. package/dist/resolve.d.ts.map +1 -0
  48. package/dist/resolve.js +106 -0
  49. package/dist/schema.d.ts +231 -0
  50. package/dist/schema.d.ts.map +1 -0
  51. package/dist/schema.js +340 -0
  52. package/dist/sdkConfig.d.ts +20 -0
  53. package/dist/sdkConfig.d.ts.map +1 -0
  54. package/dist/sdkConfig.js +41 -0
  55. package/dist/targets/adapters/antigravity.d.ts +33 -0
  56. package/dist/targets/adapters/antigravity.d.ts.map +1 -0
  57. package/dist/targets/adapters/antigravity.js +173 -0
  58. package/dist/targets/adapters/base.d.ts +11 -0
  59. package/dist/targets/adapters/base.d.ts.map +1 -0
  60. package/dist/targets/adapters/base.js +19 -0
  61. package/dist/targets/adapters/claude-code.d.ts +10 -0
  62. package/dist/targets/adapters/claude-code.d.ts.map +1 -0
  63. package/dist/targets/adapters/claude-code.js +87 -0
  64. package/dist/targets/adapters/codex.d.ts +14 -0
  65. package/dist/targets/adapters/codex.d.ts.map +1 -0
  66. package/dist/targets/adapters/codex.js +136 -0
  67. package/dist/targets/adapters/cursor.d.ts +10 -0
  68. package/dist/targets/adapters/cursor.d.ts.map +1 -0
  69. package/dist/targets/adapters/cursor.js +63 -0
  70. package/dist/targets/adapters/gemini.d.ts +10 -0
  71. package/dist/targets/adapters/gemini.d.ts.map +1 -0
  72. package/dist/targets/adapters/gemini.js +103 -0
  73. package/dist/targets/adapters/genty.d.ts +12 -0
  74. package/dist/targets/adapters/genty.d.ts.map +1 -0
  75. package/dist/targets/adapters/genty.js +94 -0
  76. package/dist/targets/adapters/github-copilot.d.ts +10 -0
  77. package/dist/targets/adapters/github-copilot.d.ts.map +1 -0
  78. package/dist/targets/adapters/github-copilot.js +66 -0
  79. package/dist/targets/adapters/hermes.d.ts +13 -0
  80. package/dist/targets/adapters/hermes.d.ts.map +1 -0
  81. package/dist/targets/adapters/hermes.js +99 -0
  82. package/dist/targets/adapters/hooks-utils.d.ts +12 -0
  83. package/dist/targets/adapters/hooks-utils.d.ts.map +1 -0
  84. package/dist/targets/adapters/hooks-utils.js +60 -0
  85. package/dist/targets/adapters/index.d.ts +31 -0
  86. package/dist/targets/adapters/index.d.ts.map +1 -0
  87. package/dist/targets/adapters/index.js +75 -0
  88. package/dist/targets/adapters/interface.d.ts +9 -0
  89. package/dist/targets/adapters/interface.d.ts.map +1 -0
  90. package/dist/targets/adapters/interface.js +2 -0
  91. package/dist/targets/adapters/oh-my-pi.d.ts +12 -0
  92. package/dist/targets/adapters/oh-my-pi.d.ts.map +1 -0
  93. package/dist/targets/adapters/oh-my-pi.js +97 -0
  94. package/dist/targets/adapters/openclaw.d.ts +15 -0
  95. package/dist/targets/adapters/openclaw.d.ts.map +1 -0
  96. package/dist/targets/adapters/openclaw.js +170 -0
  97. package/dist/targets/adapters/opencode.d.ts +11 -0
  98. package/dist/targets/adapters/opencode.d.ts.map +1 -0
  99. package/dist/targets/adapters/opencode.js +101 -0
  100. package/dist/targets/adapters/pi.d.ts +12 -0
  101. package/dist/targets/adapters/pi.d.ts.map +1 -0
  102. package/dist/targets/adapters/pi.js +98 -0
  103. package/dist/targets/index.d.ts +7 -0
  104. package/dist/targets/index.d.ts.map +1 -0
  105. package/dist/targets/index.js +79 -0
  106. package/dist/transform.d.ts +4 -0
  107. package/dist/transform.d.ts.map +1 -0
  108. package/dist/transform.js +301 -0
  109. package/dist/transformEmitters.d.ts +8 -0
  110. package/dist/transformEmitters.d.ts.map +1 -0
  111. package/dist/transformEmitters.js +350 -0
  112. package/dist/transformHelpers.d.ts +15 -0
  113. package/dist/transformHelpers.d.ts.map +1 -0
  114. package/dist/transformHelpers.js +246 -0
  115. package/dist/types.d.ts +214 -0
  116. package/dist/types.d.ts.map +1 -0
  117. package/dist/types.js +2 -0
  118. package/dist/utils.d.ts +42 -0
  119. package/dist/utils.d.ts.map +1 -0
  120. package/dist/utils.js +187 -0
  121. package/dist/validate.d.ts +3 -0
  122. package/dist/validate.d.ts.map +1 -0
  123. package/dist/validate.js +188 -0
  124. package/dist/verify.d.ts +6 -0
  125. package/dist/verify.d.ts.map +1 -0
  126. package/dist/verify.js +294 -0
  127. package/package.json +2 -2
@@ -0,0 +1,150 @@
1
+ // Unified installation instructions generator for all targets
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import { resolveSdkConfig, resolveTargetCliName, resolveTargetNpmPackageName, } from './sdkConfig.js';
5
+ export function generateInstallInstructions(manifest, targetProfile, sourceDir) {
6
+ // If a README.template.md exists in the source dir, use it
7
+ if (sourceDir) {
8
+ const templatePath = path.join(sourceDir, 'README.template.md');
9
+ if (fs.existsSync(templatePath)) {
10
+ return renderTemplate(fs.readFileSync(templatePath, 'utf-8'), manifest, targetProfile);
11
+ }
12
+ }
13
+ return renderDefault(manifest, targetProfile);
14
+ }
15
+ function renderTemplate(template, manifest, targetProfile) {
16
+ const sdk = resolveSdkConfig(manifest);
17
+ const npmPkg = resolveTargetNpmPackageName(manifest, targetProfile);
18
+ const cliName = resolveTargetCliName(manifest, targetProfile);
19
+ const skillNames = manifest.skills
20
+ ? manifest.skills.map(s => s.name).join(', ')
21
+ : 'none';
22
+ const hookNames = manifest.hooks
23
+ ? Object.keys(manifest.hooks)
24
+ .filter(h => {
25
+ const val = manifest.hooks[h];
26
+ if (val === null)
27
+ return false;
28
+ return targetProfile.supportedHooks.has(h);
29
+ })
30
+ .join(', ')
31
+ : 'none';
32
+ const commandList = getCommandNames(manifest).join(', ') || 'none';
33
+ const hasBinScripts = targetProfile.distribution === 'npm-cli' || targetProfile.distribution === 'both';
34
+ const hasExtension = targetProfile.adapterFamily === 'programmatic';
35
+ let installInstructions;
36
+ switch (targetProfile.distribution) {
37
+ case 'marketplace':
38
+ installInstructions = generateMarketplaceBlock(targetProfile, sdk.cli);
39
+ break;
40
+ case 'npm-cli':
41
+ installInstructions = generateNpmCliBlock(targetProfile, npmPkg, cliName);
42
+ break;
43
+ case 'both':
44
+ installInstructions = `### Option 1: Marketplace (Recommended)\n\n${generateMarketplaceBlock(targetProfile, sdk.cli)}\n\n### Option 2: npm Install\n\n${generateNpmCliBlock(targetProfile, npmPkg, cliName)}`;
45
+ break;
46
+ }
47
+ let verifyCommands = '';
48
+ if (targetProfile.npmPublishable) {
49
+ verifyCommands += `npm ls -g ${npmPkg} --depth=0\n`;
50
+ }
51
+ verifyCommands += `${sdk.cli} harness:discover --json | grep ${targetProfile.adapterName}`;
52
+ let result = template;
53
+ result = result.replace(/\{\{name\}\}/g, manifest.name);
54
+ result = result.replace(/\{\{description\}\}/g, manifest.description);
55
+ result = result.replace(/\{\{targetDisplayName\}\}/g, targetProfile.displayName);
56
+ result = result.replace(/\{\{installInstructions\}\}/g, installInstructions);
57
+ result = result.replace(/\{\{skillNames\}\}/g, skillNames);
58
+ result = result.replace(/\{\{hookNames\}\}/g, hookNames);
59
+ result = result.replace(/\{\{commandList\}\}/g, commandList);
60
+ result = result.replace(/\{\{verifyCommands\}\}/g, verifyCommands);
61
+ // Conditional blocks: {{#if flag}}...{{/if}}
62
+ result = replaceConditional(result, 'hasBinScripts', hasBinScripts);
63
+ result = replaceConditional(result, 'hasExtension', hasExtension);
64
+ return result;
65
+ }
66
+ function replaceConditional(text, flag, value) {
67
+ const pattern = new RegExp(`\\{\\{#if ${flag}\\}\\}([\\s\\S]*?)\\{\\{/if\\}\\}`, 'g');
68
+ return text.replace(pattern, value ? '$1' : '');
69
+ }
70
+ function getCommandNames(manifest) {
71
+ if (!manifest.commands)
72
+ return [];
73
+ if (typeof manifest.commands === 'string')
74
+ return ['(directory)'];
75
+ return manifest.commands.map(c => c.replace(/\.md$/, ''));
76
+ }
77
+ function generateMarketplaceBlock(targetProfile, sdkCli) {
78
+ return `\`\`\`bash\n${sdkCli} harness:install-plugin ${targetProfile.name}\n\`\`\``;
79
+ }
80
+ function generateNpmCliBlock(targetProfile, npmPkg, cliName) {
81
+ const lines = [
82
+ '```bash',
83
+ `npm install -g ${npmPkg}`,
84
+ `${cliName} install --global`,
85
+ '```',
86
+ '',
87
+ ];
88
+ if (targetProfile.packageMetadata?.activationMessage === 'codex-open-plugins') {
89
+ lines.push('Then open Codex and navigate to `/plugins` to activate the plugin.');
90
+ }
91
+ else {
92
+ lines.push(`Restart ${targetProfile.displayName} to pick up the installed plugin.`);
93
+ }
94
+ return lines.join('\n');
95
+ }
96
+ function renderDefault(manifest, targetProfile) {
97
+ const sdk = resolveSdkConfig(manifest);
98
+ const npmPkg = resolveTargetNpmPackageName(manifest, targetProfile);
99
+ const cliName = resolveTargetCliName(manifest, targetProfile);
100
+ const sections = [];
101
+ sections.push(`# ${manifest.name} — ${targetProfile.displayName} Plugin`);
102
+ sections.push('');
103
+ sections.push(manifest.description);
104
+ sections.push('');
105
+ sections.push('## Prerequisites');
106
+ sections.push('');
107
+ sections.push('Install the SDK CLI:');
108
+ sections.push('');
109
+ sections.push('```bash');
110
+ sections.push(`npm install -g ${sdk.package}`);
111
+ sections.push('```');
112
+ sections.push('');
113
+ sections.push('## Installation');
114
+ sections.push('');
115
+ switch (targetProfile.distribution) {
116
+ case 'marketplace':
117
+ sections.push(generateMarketplaceBlock(targetProfile, sdk.cli));
118
+ break;
119
+ case 'npm-cli':
120
+ sections.push(generateNpmCliBlock(targetProfile, npmPkg, cliName));
121
+ break;
122
+ case 'both':
123
+ sections.push('### Option 1: Marketplace (Recommended)');
124
+ sections.push('');
125
+ sections.push(generateMarketplaceBlock(targetProfile, sdk.cli));
126
+ sections.push('');
127
+ sections.push('### Option 2: npm Install');
128
+ sections.push('');
129
+ sections.push(generateNpmCliBlock(targetProfile, npmPkg, cliName));
130
+ break;
131
+ }
132
+ sections.push('');
133
+ if (targetProfile.npmPublishable) {
134
+ sections.push('### Workspace Install');
135
+ sections.push('');
136
+ sections.push('```bash');
137
+ sections.push(`npx -y ${npmPkg} install --workspace .`);
138
+ sections.push('```');
139
+ sections.push('');
140
+ }
141
+ sections.push('## Verification');
142
+ sections.push('');
143
+ sections.push('```bash');
144
+ if (targetProfile.npmPublishable) {
145
+ sections.push(`npm ls -g ${npmPkg} --depth=0`);
146
+ }
147
+ sections.push(`${sdk.cli} harness:discover --json | grep ${targetProfile.adapterName}`);
148
+ sections.push('```');
149
+ return sections.join('\n');
150
+ }
@@ -0,0 +1,3 @@
1
+ import type { A5cPluginManifest, TargetProfile } from './types.js';
2
+ export declare function generateInstallShared(manifest: A5cPluginManifest, targetProfile: TargetProfile, sourceDir?: string): string;
3
+ //# sourceMappingURL=installSharedGenerator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installSharedGenerator.d.ts","sourceRoot":"","sources":["../src/installSharedGenerator.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA4BnE,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,iBAAiB,EAC3B,aAAa,EAAE,aAAa,EAC5B,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CA4MR"}
@@ -0,0 +1,229 @@
1
+ // Generator for install-shared — generic plugin installation infrastructure.
2
+ // Only contains utilities any plugin would need: file ops, marketplace
3
+ // management, per-harness plugin paths.
4
+ // SDK-specific concepts (global state dirs, CLI resolution, process libraries)
5
+ // are provided by the plugin author via the manifest's `installSurface` field.
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ import { resolveSdkConfig } from './sdkConfig.js';
9
+ import { resolveHarnessInstallSurfaceExports } from './transformHelpers.js';
10
+ function getHomeDirCode(targetProfile, stateDir) {
11
+ const harnessHomeRelative = targetProfile.installLayout?.harnessHomeRelative;
12
+ if (!harnessHomeRelative) {
13
+ return `path.join(os.homedir(), '${stateDir}')`;
14
+ }
15
+ return `path.join(os.homedir(), ${JSON.stringify(harnessHomeRelative)})`;
16
+ }
17
+ function getPluginsDirCode(targetProfile) {
18
+ const pluginsDirRelative = targetProfile.installLayout?.pluginsDirRelative;
19
+ if (!pluginsDirRelative) {
20
+ return `path.join(getHarnessHome(), 'plugins')`;
21
+ }
22
+ return `path.join(os.homedir(), ${JSON.stringify(pluginsDirRelative)})`;
23
+ }
24
+ function getMarketplacePathCode(targetProfile) {
25
+ const marketplacePathRelative = targetProfile.installLayout?.marketplacePathRelative;
26
+ if (!marketplacePathRelative) {
27
+ return `path.join(getHarnessHome(), 'plugins', 'marketplace.json')`;
28
+ }
29
+ return `path.join(os.homedir(), ${JSON.stringify(marketplacePathRelative)})`;
30
+ }
31
+ export function generateInstallShared(manifest, targetProfile, sourceDir) {
32
+ const pluginName = manifest.name;
33
+ const sdk = resolveSdkConfig(manifest);
34
+ const authorName = typeof manifest.author === 'string' ? manifest.author : manifest.author.name;
35
+ const homeDirCode = getHomeDirCode(targetProfile, sdk.stateDir);
36
+ const pluginsDirCode = getPluginsDirCode(targetProfile);
37
+ const marketplacePathCode = getMarketplacePathCode(targetProfile);
38
+ const base = `'use strict';
39
+
40
+ const fs = require('fs');
41
+ const os = require('os');
42
+ const path = require('path');
43
+ const { spawnSync } = require('child_process');
44
+
45
+ const PLUGIN_NAME = ${JSON.stringify(pluginName)};
46
+ const PLUGIN_CATEGORY = 'Coding';
47
+
48
+ function getUserHome() {
49
+ return os.homedir();
50
+ }
51
+
52
+ function getHarnessHome() {
53
+ return ${homeDirCode};
54
+ }
55
+
56
+ function getHomePluginRoot(scope) {
57
+ if (scope === 'workspace') return path.join(process.cwd(), '${sdk.stateDir}', 'plugins', PLUGIN_NAME);
58
+ return path.join(${pluginsDirCode}, PLUGIN_NAME);
59
+ }
60
+
61
+ function getHomeMarketplacePath() {
62
+ return ${marketplacePathCode};
63
+ }
64
+
65
+ function writeFileIfChanged(filePath, contents) {
66
+ try {
67
+ const existing = fs.readFileSync(filePath, 'utf8');
68
+ if (existing === contents) return false;
69
+ } catch (e) { process.stderr.write('[extensions-adapter] file read failed for ' + filePath + ', overwriting: ' + (e instanceof Error ? e.message : String(e)) + '\\n'); }
70
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
71
+ fs.writeFileSync(filePath, contents);
72
+ return true;
73
+ }
74
+
75
+ function copyRecursive(src, dest) {
76
+ fs.mkdirSync(dest, { recursive: true });
77
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
78
+ if (entry.name === 'node_modules' || entry.name === '.git') continue;
79
+ const s = path.join(src, entry.name);
80
+ const d = path.join(dest, entry.name);
81
+ if (entry.isDirectory()) {
82
+ copyRecursive(s, d);
83
+ } else {
84
+ fs.copyFileSync(s, d);
85
+ }
86
+ }
87
+ }
88
+
89
+ function copyPluginBundle(packageRoot, pluginRoot) {
90
+ const bundleEntries = fs.readdirSync(packageRoot).filter(
91
+ e => !['node_modules', '.git', 'test', 'dist'].includes(e)
92
+ );
93
+ fs.mkdirSync(pluginRoot, { recursive: true });
94
+ for (const entry of bundleEntries) {
95
+ const src = path.join(packageRoot, entry);
96
+ const dest = path.join(pluginRoot, entry);
97
+ const stat = fs.statSync(src);
98
+ if (stat.isDirectory()) {
99
+ copyRecursive(src, dest);
100
+ } else {
101
+ fs.copyFileSync(src, dest);
102
+ }
103
+ }
104
+ }
105
+
106
+ function readJson(filePath) {
107
+ try {
108
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
109
+ } catch {
110
+ return null;
111
+ }
112
+ }
113
+
114
+ function writeJson(filePath, value) {
115
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
116
+ fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + '\\n');
117
+ }
118
+
119
+ function ensureExecutable(filePath) {
120
+ try {
121
+ fs.chmodSync(filePath, 0o755);
122
+ } catch (e) { process.stderr.write('[extensions-adapter] chmod failed for ' + filePath + ': ' + (e instanceof Error ? e.message : String(e)) + '\\n'); }
123
+ }
124
+
125
+ function normalizeMarketplaceSourcePath(source, marketplacePath) {
126
+ if (typeof source === 'string') {
127
+ return path.relative(path.dirname(marketplacePath), source).replace(/\\\\/g, '/');
128
+ }
129
+ return source;
130
+ }
131
+
132
+ function ensureMarketplaceEntry(marketplacePath, pluginRoot) {
133
+ let marketplace = readJson(marketplacePath) || {
134
+ name: ${JSON.stringify(authorName)},
135
+ plugins: [],
136
+ };
137
+ if (!Array.isArray(marketplace.plugins)) marketplace.plugins = [];
138
+ const idx = marketplace.plugins.findIndex(p => p.name === PLUGIN_NAME);
139
+ const relSource = './' + normalizeMarketplaceSourcePath(pluginRoot, marketplacePath);
140
+ const entry = {
141
+ name: PLUGIN_NAME,
142
+ source: relSource,
143
+ description: ${JSON.stringify(manifest.description)},
144
+ version: ${JSON.stringify(manifest.version)},
145
+ author: { name: ${JSON.stringify(authorName)} },
146
+ };
147
+ if (idx >= 0) marketplace.plugins[idx] = entry;
148
+ else marketplace.plugins.push(entry);
149
+ writeJson(marketplacePath, marketplace);
150
+ }
151
+
152
+ function removeMarketplaceEntry(marketplacePath) {
153
+ const marketplace = readJson(marketplacePath);
154
+ if (!marketplace || !Array.isArray(marketplace.plugins)) return;
155
+ marketplace.plugins = marketplace.plugins.filter(p => p.name !== PLUGIN_NAME);
156
+ writeJson(marketplacePath, marketplace);
157
+ }
158
+
159
+ function warnWindowsHooks() {
160
+ if (process.platform === 'win32') {
161
+ console.warn('[' + PLUGIN_NAME + '] Windows detected — shell hooks (.sh) require Git Bash or WSL.');
162
+ }
163
+ }
164
+
165
+ function runPostInstall(pluginRoot) {
166
+ const postInstall = path.join(pluginRoot, 'scripts', 'post-install.js');
167
+ if (fs.existsSync(postInstall)) {
168
+ spawnSync(process.execPath, [postInstall], {
169
+ cwd: pluginRoot, stdio: 'inherit',
170
+ env: { ...process.env, PLUGIN_ROOT: pluginRoot, CLAUDE_PLUGIN_ROOT: pluginRoot },
171
+ });
172
+ }
173
+ }
174
+ `;
175
+ const baseExports = [
176
+ 'PLUGIN_NAME',
177
+ 'PLUGIN_CATEGORY',
178
+ 'getUserHome',
179
+ 'getHarnessHome',
180
+ 'getHomePluginRoot',
181
+ 'getHomeMarketplacePath',
182
+ 'writeFileIfChanged',
183
+ 'copyRecursive',
184
+ 'copyPluginBundle',
185
+ 'readJson',
186
+ 'writeJson',
187
+ 'ensureExecutable',
188
+ 'normalizeMarketplaceSourcePath',
189
+ 'ensureMarketplaceEntry',
190
+ 'removeMarketplaceEntry',
191
+ 'warnWindowsHooks',
192
+ 'runPostInstall',
193
+ ];
194
+ // Read plugin-specific surface (SDK concepts: global state, CLI resolution, etc.)
195
+ let sdkSurface = '';
196
+ const surfaceExports = [];
197
+ if (sourceDir && manifest.installSurface) {
198
+ const surfacePath = path.join(sourceDir, manifest.installSurface);
199
+ if (fs.existsSync(surfacePath)) {
200
+ sdkSurface = fs.readFileSync(surfacePath, 'utf-8');
201
+ }
202
+ if (manifest.installSurfaceExports) {
203
+ surfaceExports.push(...manifest.installSurfaceExports);
204
+ }
205
+ }
206
+ // Read per-harness surface (harness-specific installation logic)
207
+ let harnessSurface = '';
208
+ const harnessSurfaceExports = resolveHarnessInstallSurfaceExports(manifest, targetProfile);
209
+ const override = manifest.targets?.[targetProfile.name];
210
+ if (sourceDir && override?.harnessInstallSurface) {
211
+ const surfacePath = path.join(sourceDir, override.harnessInstallSurface);
212
+ if (fs.existsSync(surfacePath)) {
213
+ harnessSurface = fs.readFileSync(surfacePath, 'utf-8');
214
+ }
215
+ }
216
+ // Deduplicate: per-harness exports override base/SDK exports of the same name
217
+ const overrideSet = new Set([...surfaceExports, ...harnessSurfaceExports]);
218
+ const dedupedBase = baseExports.filter(e => !overrideSet.has(e));
219
+ const allExports = [...dedupedBase, ...surfaceExports, ...harnessSurfaceExports];
220
+ const exportsBlock = `\nmodule.exports = {\n ${allExports.join(',\n ')},\n};\n`;
221
+ let result = base;
222
+ if (sdkSurface) {
223
+ result += '\n' + sdkSurface + '\n';
224
+ }
225
+ if (harnessSurface) {
226
+ result += '\n' + harnessSurface + '\n';
227
+ }
228
+ return result + exportsBlock;
229
+ }
@@ -0,0 +1,10 @@
1
+ export { generateClaudeCodeManifest } from './targets/adapters/claude-code.js';
2
+ export { generateCodexManifest } from './targets/adapters/codex.js';
3
+ export { generateCursorManifest } from './targets/adapters/cursor.js';
4
+ export { generateGeminiManifest } from './targets/adapters/gemini.js';
5
+ export { generateGithubCopilotManifest } from './targets/adapters/github-copilot.js';
6
+ export { generatePiManifest } from './targets/adapters/pi.js';
7
+ export { generateOhMyPiManifest } from './targets/adapters/oh-my-pi.js';
8
+ export { generateOpenCodeManifest } from './targets/adapters/opencode.js';
9
+ export { generateOpenClawPackageManifest, generateOpenClawManifest } from './targets/adapters/openclaw.js';
10
+ //# sourceMappingURL=manifestGenerators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifestGenerators.d.ts","sourceRoot":"","sources":["../src/manifestGenerators.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,EAAE,+BAA+B,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,11 @@
1
+ // Manifest generators for all targets
2
+ // This is a thin re-export shell — actual implementations live in targets/adapters/
3
+ export { generateClaudeCodeManifest } from './targets/adapters/claude-code.js';
4
+ export { generateCodexManifest } from './targets/adapters/codex.js';
5
+ export { generateCursorManifest } from './targets/adapters/cursor.js';
6
+ export { generateGeminiManifest } from './targets/adapters/gemini.js';
7
+ export { generateGithubCopilotManifest } from './targets/adapters/github-copilot.js';
8
+ export { generatePiManifest } from './targets/adapters/pi.js';
9
+ export { generateOhMyPiManifest } from './targets/adapters/oh-my-pi.js';
10
+ export { generateOpenCodeManifest } from './targets/adapters/opencode.js';
11
+ export { generateOpenClawPackageManifest, generateOpenClawManifest } from './targets/adapters/openclaw.js';
@@ -0,0 +1,3 @@
1
+ import type { A5cPluginManifest, TargetProfile } from './types.js';
2
+ export declare function generateMarketplaceJson(manifest: A5cPluginManifest, targetProfile: TargetProfile, pluginOutputDir: string, outputBaseDir: string): string;
3
+ //# sourceMappingURL=marketplaceGenerator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketplaceGenerator.d.ts","sourceRoot":"","sources":["../src/marketplaceGenerator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEnE,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,iBAAiB,EAC3B,aAAa,EAAE,aAAa,EAC5B,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,GACpB,MAAM,CA6CR"}
@@ -0,0 +1,47 @@
1
+ // Marketplace file generator
2
+ // Generates marketplace.json for targets that use marketplace distribution
3
+ import * as path from 'path';
4
+ export function generateMarketplaceJson(manifest, targetProfile, pluginOutputDir, outputBaseDir) {
5
+ const authorName = typeof manifest.author === 'string'
6
+ ? manifest.author
7
+ : manifest.author.name;
8
+ const relativePluginPath = path.relative(outputBaseDir, pluginOutputDir).replace(/\\/g, '/');
9
+ const pluginSourcePath = relativePluginPath.startsWith('.')
10
+ ? relativePluginPath
11
+ : `./${relativePluginPath}`;
12
+ if (targetProfile.packageMetadata?.activationMessage === 'codex-open-plugins') {
13
+ return JSON.stringify({
14
+ name: `${manifest.name}-local`,
15
+ interface: {
16
+ displayName: `${manifest.name.charAt(0).toUpperCase() + manifest.name.slice(1)} Local`,
17
+ },
18
+ plugins: [{
19
+ name: manifest.name,
20
+ source: {
21
+ source: 'local',
22
+ path: pluginSourcePath,
23
+ },
24
+ version: manifest.version,
25
+ policy: {
26
+ installation: 'AVAILABLE',
27
+ authentication: 'ON_INSTALL',
28
+ },
29
+ category: 'Coding',
30
+ }],
31
+ }, null, 2) + '\n';
32
+ }
33
+ return JSON.stringify({
34
+ name: authorName,
35
+ owner: {
36
+ name: authorName,
37
+ email: `support@${authorName}`,
38
+ },
39
+ plugins: [{
40
+ name: manifest.name,
41
+ source: pluginSourcePath,
42
+ description: manifest.description,
43
+ version: manifest.version,
44
+ author: { name: authorName },
45
+ }],
46
+ }, null, 2) + '\n';
47
+ }
@@ -0,0 +1,69 @@
1
+ import type { A5cPluginManifest, McpServerSpec, TransformedFile } from './types.js';
2
+ /** Default Atlas MCP server URL (SPEC §4.2 / spec.json mcp.url). */
3
+ export declare const DEFAULT_ATLAS_MCP_URL = "https://atlas-staging.a5c.ai/api/mcp";
4
+ /**
5
+ * Emission-time URL for a server spec: the literal `spec.url`, falling back to
6
+ * the default Atlas URL when unset.
7
+ */
8
+ export declare function resolveMcpUrl(spec: McpServerSpec): string;
9
+ /**
10
+ * The env-override default token emitted verbatim into command/args for the
11
+ * JSON + TOML targets, e.g. `${ATLAS_MCP_URL:-https://atlas-staging.a5c.ai/api/mcp}`.
12
+ * Falls back to the literal default URL when no env var is declared.
13
+ */
14
+ export declare function buildEnvOverrideUrl(spec: McpServerSpec): string;
15
+ /**
16
+ * The `mcp-remote` bridge args carrying the env-override default token:
17
+ * ["-y", "mcp-remote", "${ATLAS_MCP_URL:-<default>}"]
18
+ */
19
+ export declare function buildRemoteCommandArgs(spec: McpServerSpec): string[];
20
+ /**
21
+ * (A) JSON `mcpServers` map: { "mcpServers": { "<name>": { command, args } } }.
22
+ * Used by claude-code, cursor, github-copilot, antigravity, pi, oh-my-pi,
23
+ * openclaw, genty. Each server emits the `mcp-remote` bridge form.
24
+ */
25
+ export declare function buildJsonMcpServers(servers: Record<string, McpServerSpec>): {
26
+ mcpServers: Record<string, {
27
+ command: string;
28
+ args: string[];
29
+ }>;
30
+ };
31
+ /**
32
+ * (B) opencode merge fragment: { "mcp": { "<name>": { type:"local",
33
+ * command:[...array...], enabled:true } } }. opencode uses `mcp` (not
34
+ * `mcpServers`) and the command is an array.
35
+ */
36
+ export declare function buildOpencodeMcp(servers: Record<string, McpServerSpec>): {
37
+ mcp: Record<string, {
38
+ type: string;
39
+ command: string[];
40
+ enabled: boolean;
41
+ }>;
42
+ };
43
+ /**
44
+ * (B) codex TOML merge fragment: a `[mcp_servers.<name>]` table with
45
+ * command="npx" and args carrying the env-override token. Folded into
46
+ * ~/.codex/config.toml by the install surface.
47
+ */
48
+ export declare function buildCodexMcpToml(servers: Record<string, McpServerSpec>): string;
49
+ /**
50
+ * (B) gemini extension manifest fragment: { "mcpServers": { "<name>": {
51
+ * httpUrl:"<default>", command:"npx", args:[...token...] } } }. gemini
52
+ * extensions declare MCP in the extension manifest; prefer `httpUrl` for the
53
+ * remote URL while still carrying the `mcp-remote` command/args.
54
+ */
55
+ export declare function buildGeminiMcpServers(servers: Record<string, McpServerSpec>): {
56
+ mcpServers: Record<string, {
57
+ httpUrl: string;
58
+ command: string;
59
+ args: string[];
60
+ }>;
61
+ };
62
+ /** Serialize a JSON object as the file content (trailing newline, like siblings). */
63
+ export declare function toJsonContent(value: unknown): string;
64
+ /**
65
+ * Shared emitter for the (A) JSON `mcpServers` map targets. Returns the native
66
+ * MCP config file at `path`, or null when the manifest declares no MCP servers.
67
+ */
68
+ export declare function emitJsonMcpConfig(manifest: A5cPluginManifest, path: string): TransformedFile | null;
69
+ //# sourceMappingURL=mcpConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpConfig.d.ts","sourceRoot":"","sources":["../src/mcpConfig.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEpF,oEAAoE;AACpE,eAAO,MAAM,qBAAqB,yCAAyC,CAAC;AAE5E;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAG/D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,EAAE,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GACrC;IAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAA;CAAE,CASrE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GACrC;IAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;CAAE,CAUhF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,MAAM,CAShF;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GACrC;IACD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAClF,CAUA;AAED,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,MAAM,GACX,eAAe,GAAG,IAAI,CAKxB"}
@@ -0,0 +1,115 @@
1
+ // Shared MCP-config builders for the per-harness emit step.
2
+ //
3
+ // A new top-level `mcpServers` field on the unified plugin.json declares native
4
+ // MCP servers to wire into every target in its native config format. These
5
+ // helpers translate an McpServerSpec into the two canonical shapes:
6
+ // (A) JSON `mcpServers` map — claude-code, cursor, github-copilot,
7
+ // antigravity, pi, oh-my-pi, openclaw, genty
8
+ // (B) harness merge fragment — opencode (`mcp` array form), codex (TOML
9
+ // `mcp_servers`), gemini (`mcpServers` with `httpUrl`)
10
+ //
11
+ // The env-override happens at the harness' runtime via the `mcp-remote` bridge,
12
+ // mirroring the repo root `.mcp.json` shape:
13
+ // command: "npx", args: ["-y","mcp-remote","${ATLAS_MCP_URL:-<default>}"]
14
+ /** Default Atlas MCP server URL (SPEC §4.2 / spec.json mcp.url). */
15
+ export const DEFAULT_ATLAS_MCP_URL = 'https://atlas-staging.a5c.ai/api/mcp';
16
+ /**
17
+ * Emission-time URL for a server spec: the literal `spec.url`, falling back to
18
+ * the default Atlas URL when unset.
19
+ */
20
+ export function resolveMcpUrl(spec) {
21
+ return spec.url ?? DEFAULT_ATLAS_MCP_URL;
22
+ }
23
+ /**
24
+ * The env-override default token emitted verbatim into command/args for the
25
+ * JSON + TOML targets, e.g. `${ATLAS_MCP_URL:-https://atlas-staging.a5c.ai/api/mcp}`.
26
+ * Falls back to the literal default URL when no env var is declared.
27
+ */
28
+ export function buildEnvOverrideUrl(spec) {
29
+ const url = resolveMcpUrl(spec);
30
+ return spec.urlEnvVar ? `\${${spec.urlEnvVar}:-${url}}` : url;
31
+ }
32
+ /**
33
+ * The `mcp-remote` bridge args carrying the env-override default token:
34
+ * ["-y", "mcp-remote", "${ATLAS_MCP_URL:-<default>}"]
35
+ */
36
+ export function buildRemoteCommandArgs(spec) {
37
+ return ['-y', 'mcp-remote', buildEnvOverrideUrl(spec)];
38
+ }
39
+ /**
40
+ * (A) JSON `mcpServers` map: { "mcpServers": { "<name>": { command, args } } }.
41
+ * Used by claude-code, cursor, github-copilot, antigravity, pi, oh-my-pi,
42
+ * openclaw, genty. Each server emits the `mcp-remote` bridge form.
43
+ */
44
+ export function buildJsonMcpServers(servers) {
45
+ const mcpServers = {};
46
+ for (const [name, spec] of Object.entries(servers)) {
47
+ mcpServers[name] = {
48
+ command: 'npx',
49
+ args: buildRemoteCommandArgs(spec),
50
+ };
51
+ }
52
+ return { mcpServers };
53
+ }
54
+ /**
55
+ * (B) opencode merge fragment: { "mcp": { "<name>": { type:"local",
56
+ * command:[...array...], enabled:true } } }. opencode uses `mcp` (not
57
+ * `mcpServers`) and the command is an array.
58
+ */
59
+ export function buildOpencodeMcp(servers) {
60
+ const mcp = {};
61
+ for (const [name, spec] of Object.entries(servers)) {
62
+ mcp[name] = {
63
+ type: 'local',
64
+ command: ['npx', ...buildRemoteCommandArgs(spec)],
65
+ enabled: true,
66
+ };
67
+ }
68
+ return { mcp };
69
+ }
70
+ /**
71
+ * (B) codex TOML merge fragment: a `[mcp_servers.<name>]` table with
72
+ * command="npx" and args carrying the env-override token. Folded into
73
+ * ~/.codex/config.toml by the install surface.
74
+ */
75
+ export function buildCodexMcpToml(servers) {
76
+ const blocks = [];
77
+ for (const [name, spec] of Object.entries(servers)) {
78
+ const args = buildRemoteCommandArgs(spec)
79
+ .map((a) => JSON.stringify(a))
80
+ .join(', ');
81
+ blocks.push(`[mcp_servers.${name}]\ncommand = "npx"\nargs = [${args}]\n`);
82
+ }
83
+ return blocks.join('\n');
84
+ }
85
+ /**
86
+ * (B) gemini extension manifest fragment: { "mcpServers": { "<name>": {
87
+ * httpUrl:"<default>", command:"npx", args:[...token...] } } }. gemini
88
+ * extensions declare MCP in the extension manifest; prefer `httpUrl` for the
89
+ * remote URL while still carrying the `mcp-remote` command/args.
90
+ */
91
+ export function buildGeminiMcpServers(servers) {
92
+ const mcpServers = {};
93
+ for (const [name, spec] of Object.entries(servers)) {
94
+ mcpServers[name] = {
95
+ httpUrl: resolveMcpUrl(spec),
96
+ command: 'npx',
97
+ args: buildRemoteCommandArgs(spec),
98
+ };
99
+ }
100
+ return { mcpServers };
101
+ }
102
+ /** Serialize a JSON object as the file content (trailing newline, like siblings). */
103
+ export function toJsonContent(value) {
104
+ return JSON.stringify(value, null, 2) + '\n';
105
+ }
106
+ /**
107
+ * Shared emitter for the (A) JSON `mcpServers` map targets. Returns the native
108
+ * MCP config file at `path`, or null when the manifest declares no MCP servers.
109
+ */
110
+ export function emitJsonMcpConfig(manifest, path) {
111
+ if (!manifest.mcpServers || Object.keys(manifest.mcpServers).length === 0) {
112
+ return null;
113
+ }
114
+ return { path, content: toJsonContent(buildJsonMcpServers(manifest.mcpServers)) };
115
+ }
@@ -0,0 +1,10 @@
1
+ import type { TargetProfile } from './types.js';
2
+ export declare function generateProgrammaticExtension(manifest: {
3
+ name: string;
4
+ skills?: Array<{
5
+ name: string;
6
+ }>;
7
+ commands?: string[] | string;
8
+ hooks?: Record<string, string | boolean | null>;
9
+ }, targetProfile: TargetProfile, commandPaths?: string[]): string;
10
+ //# sourceMappingURL=proxiedHookTemplates.d.ts.map