@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,93 @@
1
+ // OpenCode harness output adapter
2
+ import { BaseHarnessOutputAdapter } from './base.js';
3
+ import { iterateHooks, slugify, applyPattern, resolveHookPath, getPattern, getJsPattern, resolveSdkConfig, } from './hooks-utils.js';
4
+ import { generateOpenCodeAccomplishSkill } from '../../transformHelpers.js';
5
+ export class OpenCodeAdapter extends BaseHarnessOutputAdapter {
6
+ generateHookRegistration(manifest, targetProfile, _diagnostics) {
7
+ const content = generateOpenCodeHooksJson(manifest, targetProfile);
8
+ return { path: targetProfile.hookRegistrationOutputPath || 'hooks/hooks.json', content };
9
+ }
10
+ generateManifestFiles(_sourceDir, manifest, _targetProfile, _diagnostics) {
11
+ const files = [];
12
+ files.push({
13
+ path: 'plugin.json',
14
+ content: generateOpenCodeManifest(manifest, this.targetName),
15
+ });
16
+ return files;
17
+ }
18
+ generateExtraTargetFiles(_sourceDir, manifest, _targetProfile, _diagnostics) {
19
+ const files = [];
20
+ const accomplishSkill = generateOpenCodeAccomplishSkill(manifest);
21
+ if (accomplishSkill) {
22
+ files.push({ path: `accomplish-skills/${manifest.name}/SKILL.md`, content: accomplishSkill });
23
+ }
24
+ return files;
25
+ }
26
+ }
27
+ export function generateOpenCodeManifest(manifest, targetName = 'opencode') {
28
+ const pluginJson = {
29
+ name: manifest.name,
30
+ version: manifest.version,
31
+ description: manifest.description,
32
+ author: manifest.author,
33
+ license: manifest.license,
34
+ harness: targetName,
35
+ hooks: 'hooks/',
36
+ commands: 'commands/',
37
+ skills: 'skills/',
38
+ };
39
+ if (manifest.repository) {
40
+ pluginJson.repository = manifest.repository;
41
+ }
42
+ if (manifest.keywords) {
43
+ pluginJson.keywords = manifest.keywords;
44
+ }
45
+ return JSON.stringify(pluginJson, null, 2) + '\n';
46
+ }
47
+ export function generateOpenCodeHooksJson(manifest, targetProfile) {
48
+ const hooks = {};
49
+ const pat = getPattern(manifest, targetProfile.name);
50
+ const sdk = resolveSdkConfig(manifest);
51
+ iterateHooks(manifest, targetProfile, (canonical, native, handler) => {
52
+ const slug = slugify(canonical);
53
+ const adapter = targetProfile.adapterName;
54
+ if (handler === 'proxy') {
55
+ hooks[native] = [{
56
+ type: 'command',
57
+ command: `${sdk.proxyBinary} invoke --adapter ${adapter} --json`,
58
+ description: `${manifest.name} ${canonical} hook`,
59
+ timeoutMs: canonical === 'ShellEnv' ? 5000 : 30000,
60
+ }];
61
+ }
62
+ else if (handler === true) {
63
+ hooks[native] = [{
64
+ type: 'command',
65
+ command: `echo '{}'`,
66
+ description: `${manifest.name} ${canonical} hook`,
67
+ timeoutMs: canonical === 'ShellEnv' ? 5000 : 30000,
68
+ }];
69
+ }
70
+ else {
71
+ const jsPat = getJsPattern(manifest, targetProfile.name);
72
+ let handlerScript;
73
+ if (jsPat) {
74
+ handlerScript = applyPattern(jsPat, manifest.name, slug, native);
75
+ }
76
+ else {
77
+ const p = resolveHookPath(handler, slug, manifest.name, native, pat);
78
+ handlerScript = p ? p.replace(/\.sh$/, '.js') : 'echo {}';
79
+ }
80
+ hooks[native] = [{
81
+ type: 'command',
82
+ script: `./${handlerScript}`,
83
+ description: `${manifest.name} ${canonical} hook`,
84
+ timeoutMs: canonical === 'ShellEnv' ? 5000 : 30000,
85
+ }];
86
+ }
87
+ });
88
+ return JSON.stringify({
89
+ version: 1,
90
+ description: `${manifest.name} hook registration for OpenCode.`,
91
+ hooks,
92
+ }, null, 2) + '\n';
93
+ }
@@ -0,0 +1,11 @@
1
+ import type { A5cPluginManifest, TargetProfile, TransformedFile, Diagnostic } from '../../types.js';
2
+ import { BaseHarnessOutputAdapter } from './base.js';
3
+ export declare class PiAdapter extends BaseHarnessOutputAdapter {
4
+ generateManifestFiles(_sourceDir: string, manifest: A5cPluginManifest, _targetProfile: TargetProfile, _diagnostics: Diagnostic[]): TransformedFile[];
5
+ }
6
+ type ResolvedManifest = A5cPluginManifest & {
7
+ npmPackageName?: string;
8
+ };
9
+ export declare function generatePiManifest(manifest: ResolvedManifest, targetName?: string): string;
10
+ export {};
11
+ //# sourceMappingURL=pi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.d.ts","sourceRoot":"","sources":["../../../src/targets/adapters/pi.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACpG,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAMrD,qBAAa,SAAU,SAAQ,wBAAwB;IAIrD,qBAAqB,CACnB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,iBAAiB,EAC3B,cAAc,EAAE,aAAa,EAC7B,YAAY,EAAE,UAAU,EAAE,GACzB,eAAe,EAAE;CAQrB;AAED,KAAK,gBAAgB,GAAG,iBAAiB,GAAG;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAwCF,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,UAAU,SAAO,GAAG,MAAM,CA8CxF"}
@@ -0,0 +1,90 @@
1
+ // Pi harness output adapter
2
+ import { BaseHarnessOutputAdapter } from './base.js';
3
+ import { resolveTargetCliName, resolveTargetNpmPackageName, } from '../../sdkConfig.js';
4
+ export class PiAdapter extends BaseHarnessOutputAdapter {
5
+ generateManifestFiles(_sourceDir, manifest, _targetProfile, _diagnostics) {
6
+ const files = [];
7
+ files.push({
8
+ path: 'package.json',
9
+ content: generatePiManifest(manifest, this.targetName),
10
+ });
11
+ return files;
12
+ }
13
+ }
14
+ function buildNpmRepository(manifest, npmPackageName) {
15
+ if (!manifest.repository)
16
+ return undefined;
17
+ let url = typeof manifest.repository === 'string'
18
+ ? manifest.repository
19
+ : manifest.repository.url;
20
+ if (!url.startsWith('git+'))
21
+ url = `git+${url}`;
22
+ if (!url.endsWith('.git'))
23
+ url = `${url}.git`;
24
+ const directory = `plugins/${npmPackageName.split('/').pop()}`;
25
+ return { type: 'git', url, directory };
26
+ }
27
+ function buildNpmHomepage(manifest, npmPackageName) {
28
+ if (!manifest.repository)
29
+ return undefined;
30
+ const url = typeof manifest.repository === 'string'
31
+ ? manifest.repository
32
+ : manifest.repository.url;
33
+ const base = url.replace(/\.git$/, '').replace(/^git\+/, '');
34
+ const directory = `plugins/${npmPackageName.split('/').pop()}`;
35
+ return `${base}/tree/main/${directory}#readme`;
36
+ }
37
+ function buildNpmBugs(manifest) {
38
+ if (!manifest.repository)
39
+ return undefined;
40
+ const url = typeof manifest.repository === 'string'
41
+ ? manifest.repository
42
+ : manifest.repository.url;
43
+ const base = url.replace(/\.git$/, '').replace(/^git\+/, '');
44
+ return { url: `${base}/issues` };
45
+ }
46
+ export function generatePiManifest(manifest, targetName = 'pi') {
47
+ const target = { name: targetName };
48
+ const packageJson = {
49
+ name: resolveTargetNpmPackageName(manifest, target),
50
+ version: manifest.version,
51
+ type: 'module',
52
+ description: `${manifest.description} — ${targetName}`,
53
+ keywords: [targetName, manifest.name, 'orchestration'],
54
+ [targetName]: {
55
+ extensions: ['./extensions'],
56
+ skills: ['./skills'],
57
+ },
58
+ peerDependencies: {
59
+ '@mariozechner/pi-coding-agent': '*',
60
+ },
61
+ scripts: {
62
+ test: 'npm run validate:ci',
63
+ 'test:integration': 'node --test test/integration.test.js',
64
+ 'test:packaged-install': 'node test/packaged-install.test.cjs',
65
+ 'validate:ci': 'npm run test:integration && npm run test:packaged-install',
66
+ deploy: 'npm publish --access public',
67
+ 'deploy:staging': 'npm publish --access public --tag staging',
68
+ },
69
+ bin: { [resolveTargetCliName(manifest, target)]: 'bin/cli.cjs' },
70
+ files: [
71
+ 'bin/',
72
+ 'package.json',
73
+ 'versions.json',
74
+ 'README.md',
75
+ 'AGENTS.md',
76
+ 'extensions/',
77
+ 'skills/',
78
+ 'commands/',
79
+ 'scripts/',
80
+ ],
81
+ author: typeof manifest.author === 'string' ? manifest.author : manifest.author.name,
82
+ license: manifest.license,
83
+ publishConfig: { access: 'public' },
84
+ };
85
+ const piPkgName = packageJson.name;
86
+ packageJson.repository = buildNpmRepository(manifest, piPkgName);
87
+ packageJson.homepage = buildNpmHomepage(manifest, piPkgName);
88
+ packageJson.bugs = buildNpmBugs(manifest);
89
+ return JSON.stringify(packageJson, null, 2) + '\n';
90
+ }
@@ -0,0 +1,7 @@
1
+ import type { TargetProfile } from '../types.js';
2
+ export declare const TARGET_REGISTRY: Record<string, TargetProfile>;
3
+ export declare const HOOK_NAME_MAP: Record<string, Record<string, string>>;
4
+ export declare function getTargetProfile(name: string): TargetProfile | null;
5
+ export declare function requireTargetProfile(name: string): TargetProfile;
6
+ export declare function getAllTargets(): string[];
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/targets/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAiEjD,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAEzD,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAoB,CAAC;AAEtF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAGnE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAMhE;AAED,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAExC"}
@@ -0,0 +1,77 @@
1
+ // Catalog-backed target registry and hook name mapping
2
+ import { getHookNameMap, getPluginTargetDescriptor, listPluginTargetDescriptors, } from '@a5c-ai/agent-catalog';
3
+ function toManifestFormat(format) {
4
+ if (format === 'plugin.json')
5
+ return 'plugin.json';
6
+ if (format === 'state-only' || format.includes('package.json'))
7
+ return 'package.json';
8
+ return 'multiple';
9
+ }
10
+ function toCommandFormat(format) {
11
+ if (format === 'extension-manifest')
12
+ return 'toml';
13
+ if (format === 'none' || format === 'package-json commands')
14
+ return 'none';
15
+ return 'markdown';
16
+ }
17
+ function toHookRegistrationFormat(format) {
18
+ return format || null;
19
+ }
20
+ function toScriptVariants(variants) {
21
+ return (variants ?? []).filter((variant) => variant === 'bash' ||
22
+ variant === 'powershell' ||
23
+ variant === 'javascript' ||
24
+ variant === 'typescript');
25
+ }
26
+ function canonicalTargetName(name) {
27
+ // Try exact match first; if not found, check if any target's adapterName or cliCommand matches
28
+ if (getPluginTargetDescriptor(name))
29
+ return name;
30
+ for (const target of listPluginTargetDescriptors()) {
31
+ if (target.adapterName === name || target.cliCommand === name)
32
+ return target.targetId;
33
+ }
34
+ return name;
35
+ }
36
+ function toTargetProfile(target) {
37
+ return {
38
+ name: target.targetId,
39
+ displayName: target.displayName,
40
+ adapterName: target.adapterName,
41
+ pluginRootEnvVar: target.pluginRootEnvVar ?? null,
42
+ supportedHooks: new Map(Object.entries(target.supportedHooks)),
43
+ commandFormat: toCommandFormat(target.commandFormat),
44
+ skillHandling: target.skillHandling ?? 'none',
45
+ manifestFormat: toManifestFormat(target.manifestFormat),
46
+ hookRegistrationFormat: toHookRegistrationFormat(target.hookRegistrationFormat),
47
+ hookRegistrationOutputPath: target.hookRegistrationOutputPath ?? null,
48
+ hookRegistrationAliasPaths: target.hookRegistrationAliasPaths ?? [],
49
+ harnessManifestPath: target.harnessManifestPath ?? null,
50
+ requiredSurfaceFile: target.requiredSurfaceFile ?? null,
51
+ scriptVariants: toScriptVariants(target.scriptVariants),
52
+ npmPublishable: target.npmPublishable,
53
+ adapterFamily: target.adapterFamily ?? 'shell-hook',
54
+ distribution: target.distribution ?? 'marketplace',
55
+ pluginRootEnvVarForExtension: target.pluginRootEnvVarForExtension ?? undefined,
56
+ marketplacePath: target.marketplacePath,
57
+ installLayout: target.installLayout,
58
+ packageMetadata: target.packageMetadata,
59
+ componentSupport: target.componentSupport,
60
+ };
61
+ }
62
+ export const TARGET_REGISTRY = Object.fromEntries(listPluginTargetDescriptors().map((target) => [target.targetId, toTargetProfile(target)]));
63
+ export const HOOK_NAME_MAP = getHookNameMap();
64
+ export function getTargetProfile(name) {
65
+ const descriptor = getPluginTargetDescriptor(canonicalTargetName(name));
66
+ return descriptor ? toTargetProfile(descriptor) : null;
67
+ }
68
+ export function requireTargetProfile(name) {
69
+ const profile = getTargetProfile(name);
70
+ if (!profile) {
71
+ throw new Error(`Unknown target profile: ${name}`);
72
+ }
73
+ return profile;
74
+ }
75
+ export function getAllTargets() {
76
+ return listPluginTargetDescriptors().map((target) => target.targetId);
77
+ }
@@ -0,0 +1,4 @@
1
+ import type { A5cPluginManifest, TargetProfile, TransformResult } from './types.js';
2
+ export declare function transform(sourceDir: string, manifest: A5cPluginManifest, targetProfile: TargetProfile): TransformResult;
3
+ export { getCommandPaths } from './utils.js';
4
+ //# sourceMappingURL=transform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EACb,eAAe,EAGhB,MAAM,YAAY,CAAC;AA2BpB,wBAAgB,SAAS,CACvB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,iBAAiB,EAC3B,aAAa,EAAE,aAAa,GAC3B,eAAe,CAqCjB;AA2HD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,243 @@
1
+ // Stage 3: TRANSFORM - Transform components to target format
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import { buildSkillFromCommand, getCommandPaths, markdownToToml, } from './utils.js';
5
+ import { getAdapter } from './targets/adapters/index.js';
6
+ import { generatePs1Wrapper, generateJsBridge, generateTsHookStub, } from './transformHelpers.js';
7
+ import { generateManifests, copyAgentFiles, copyContextFiles, copyIncludedFiles, generateExtraFiles, } from './transformEmitters.js';
8
+ function toOutputPath(value) {
9
+ return value.replace(/\\/g, '/');
10
+ }
11
+ export function transform(sourceDir, manifest, targetProfile) {
12
+ const files = [];
13
+ const diagnostics = [];
14
+ // Transform commands
15
+ const commandFiles = transformCommands(sourceDir, manifest, targetProfile, diagnostics);
16
+ files.push(...commandFiles);
17
+ // Transform skills
18
+ const skillFiles = transformSkills(sourceDir, manifest, targetProfile, diagnostics);
19
+ files.push(...skillFiles);
20
+ // Transform hooks
21
+ const hookFiles = transformHooks(sourceDir, manifest, targetProfile, diagnostics);
22
+ files.push(...hookFiles);
23
+ // Generate manifests
24
+ const manifestFiles = generateManifests(sourceDir, manifest, targetProfile, diagnostics);
25
+ files.push(...manifestFiles);
26
+ // Copy agent instruction files
27
+ const agentFiles = copyAgentFiles(sourceDir, manifest, targetProfile, diagnostics);
28
+ files.push(...agentFiles);
29
+ // Copy context files
30
+ const contextFiles = copyContextFiles(sourceDir, manifest, targetProfile, diagnostics);
31
+ files.push(...contextFiles);
32
+ // Copy included files (versions.json, assets, etc.) — skip hooks/ since transformHooks handles those
33
+ const includedFiles = copyIncludedFiles(sourceDir, manifest, ['hooks/', 'hooks']);
34
+ files.push(...includedFiles);
35
+ // Generate extra files (Pi/oh-my-pi extensions, etc.)
36
+ const extraFiles = generateExtraFiles(sourceDir, manifest, targetProfile, diagnostics);
37
+ files.push(...extraFiles);
38
+ return { files, diagnostics };
39
+ }
40
+ function transformCommands(sourceDir, manifest, targetProfile, _diagnostics) {
41
+ const files = [];
42
+ if (targetProfile.commandFormat === 'none') {
43
+ return files;
44
+ }
45
+ if (!manifest.commands) {
46
+ return files;
47
+ }
48
+ const commandPaths = [];
49
+ if (typeof manifest.commands === 'string') {
50
+ // Directory path - glob all .md files
51
+ const commandDir = path.join(sourceDir, manifest.commands);
52
+ if (fs.existsSync(commandDir)) {
53
+ const entries = fs.readdirSync(commandDir);
54
+ for (const entry of entries) {
55
+ if (entry.endsWith('.md')) {
56
+ commandPaths.push(toOutputPath(path.join(manifest.commands, entry)));
57
+ }
58
+ }
59
+ }
60
+ }
61
+ else {
62
+ commandPaths.push(...manifest.commands.map(toOutputPath));
63
+ }
64
+ for (const cmdPath of commandPaths) {
65
+ const fullPath = path.join(sourceDir, cmdPath);
66
+ if (!fs.existsSync(fullPath)) {
67
+ continue;
68
+ }
69
+ const content = fs.readFileSync(fullPath, 'utf-8');
70
+ if (targetProfile.commandFormat === 'toml') {
71
+ // Convert to TOML (Gemini)
72
+ const tomlContent = markdownToToml(content);
73
+ const basename = path.basename(cmdPath, '.md');
74
+ files.push({
75
+ path: `commands/${basename}.toml`,
76
+ content: tomlContent,
77
+ });
78
+ }
79
+ else {
80
+ // Copy as-is (Markdown)
81
+ files.push({
82
+ path: cmdPath,
83
+ content,
84
+ });
85
+ }
86
+ }
87
+ return files;
88
+ }
89
+ function transformSkills(sourceDir, manifest, targetProfile, _diagnostics) {
90
+ const files = [];
91
+ if (targetProfile.skillHandling === 'none') {
92
+ return files;
93
+ }
94
+ // Always copy standalone skills
95
+ if (manifest.skills && Array.isArray(manifest.skills)) {
96
+ for (const skill of manifest.skills) {
97
+ const fullPath = path.join(sourceDir, skill.file);
98
+ if (fs.existsSync(fullPath)) {
99
+ files.push({
100
+ path: skill.file,
101
+ content: fs.readFileSync(fullPath, 'utf-8'),
102
+ });
103
+ }
104
+ }
105
+ }
106
+ // Derive skills from commands if needed
107
+ if (targetProfile.skillHandling === 'derived-from-commands') {
108
+ const commandPaths = getCommandPaths(sourceDir, manifest);
109
+ // Build set of standalone skill names to avoid duplicating them
110
+ const standaloneSkillNames = new Set();
111
+ if (manifest.skills && Array.isArray(manifest.skills)) {
112
+ for (const skill of manifest.skills) {
113
+ standaloneSkillNames.add(skill.name);
114
+ }
115
+ }
116
+ for (const cmdPath of commandPaths) {
117
+ const fullPath = path.join(sourceDir, cmdPath);
118
+ if (!fs.existsSync(fullPath))
119
+ continue;
120
+ const basename = path.basename(cmdPath, '.md');
121
+ if (standaloneSkillNames.has(basename)) {
122
+ continue;
123
+ }
124
+ const content = fs.readFileSync(fullPath, 'utf-8');
125
+ const derivedSkill = buildSkillFromCommand(basename, content);
126
+ files.push({
127
+ path: `skills/${basename}/SKILL.md`,
128
+ content: derivedSkill,
129
+ });
130
+ }
131
+ }
132
+ return files;
133
+ }
134
+ // Re-export for backward compatibility
135
+ export { getCommandPaths } from './utils.js';
136
+ function transformHooks(sourceDir, manifest, targetProfile, diagnostics) {
137
+ const files = [];
138
+ if (!manifest.hooks || targetProfile.supportedHooks.size === 0) {
139
+ return files;
140
+ }
141
+ const isProgrammatic = targetProfile.adapterFamily === 'programmatic';
142
+ const override = manifest.targets?.[targetProfile.name];
143
+ const hookFilePattern = typeof override?.hookFilePattern === 'string'
144
+ ? override.hookFilePattern
145
+ : typeof manifest.hookFilePattern === 'string' ? manifest.hookFilePattern : undefined;
146
+ const hookJsPattern = typeof override?.hookJsPattern === 'string'
147
+ ? override.hookJsPattern
148
+ : hookFilePattern ? hookFilePattern.replace(/\.sh$/, '.js') : undefined;
149
+ const toSlug = (s) => s
150
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
151
+ .replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
152
+ const toNativeSlug = (s) => s.replace(/[._]/g, '-').replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
153
+ for (const [canonicalHook, handlerValue] of Object.entries(manifest.hooks)) {
154
+ if (handlerValue === null)
155
+ continue;
156
+ const nativeHook = targetProfile.supportedHooks.get(canonicalHook);
157
+ if (!nativeHook)
158
+ continue;
159
+ if (typeof handlerValue !== 'string' || handlerValue === 'proxy')
160
+ continue;
161
+ const hookSlug = toSlug(canonicalHook);
162
+ const nativeSlug = toNativeSlug(nativeHook);
163
+ const sourceScript = path.join(sourceDir, handlerValue);
164
+ if (!fs.existsSync(sourceScript))
165
+ continue;
166
+ const rawContent = fs.readFileSync(sourceScript, 'utf-8');
167
+ const content = rawContent.replace(/ADAPTER_NAME="\$\{ADAPTER_NAME:\?[^}]*\}"/, `ADAPTER_NAME="\${ADAPTER_NAME:-${targetProfile.adapterName}}"`);
168
+ // Determine bash output filename via hookFilePattern
169
+ let outName;
170
+ if (hookFilePattern) {
171
+ outName = hookFilePattern
172
+ .replace(/\{\{name\}\}/g, manifest.name)
173
+ .replace(/\{\{slug\}\}/g, hookSlug)
174
+ .replace(/\{\{native\}\}/g, nativeSlug);
175
+ }
176
+ else {
177
+ outName = path.basename(handlerValue);
178
+ }
179
+ files.push({ path: `hooks/${outName}`, content, executable: true });
180
+ if (targetProfile.scriptVariants.includes('powershell')) {
181
+ const ps1Name = outName.replace(/\.sh$/, '.ps1');
182
+ files.push({ path: `hooks/${ps1Name}`, content: generatePs1Wrapper(hookSlug, targetProfile.adapterName, handlerValue) });
183
+ }
184
+ // JS bridge for programmatic targets — uses hookJsPattern if available
185
+ if (isProgrammatic) {
186
+ let jsName;
187
+ if (hookJsPattern) {
188
+ jsName = hookJsPattern
189
+ .replace(/\{\{name\}\}/g, manifest.name)
190
+ .replace(/\{\{slug\}\}/g, hookSlug)
191
+ .replace(/\{\{native\}\}/g, nativeSlug);
192
+ }
193
+ else {
194
+ jsName = outName.replace(/\.sh$/, '.js');
195
+ }
196
+ files.push({ path: `hooks/${jsName}`, content: generateJsBridge(jsName.replace(/\.js$/, ''), handlerValue, targetProfile), executable: true });
197
+ }
198
+ // TS hook stubs for targets with typescript variant (openclaw)
199
+ if (targetProfile.scriptVariants.includes('typescript')) {
200
+ const tsName = `${nativeSlug}.ts`;
201
+ files.push({
202
+ path: `extensions/hooks/${tsName}`,
203
+ content: generateTsHookStub(nativeHook, nativeSlug, outName, targetProfile),
204
+ });
205
+ }
206
+ }
207
+ // Emit Stop hook script for programmatic targets that declare Stop in the
208
+ // manifest but don't list it in supportedHooks (e.g. openclaw).
209
+ if (targetProfile.adapterFamily === 'programmatic' && typeof manifest.hooks?.Stop === 'string' && !targetProfile.supportedHooks.has('Stop')) {
210
+ const stopSource = path.join(sourceDir, manifest.hooks.Stop);
211
+ if (fs.existsSync(stopSource)) {
212
+ const rawContent = fs.readFileSync(stopSource, 'utf-8');
213
+ const content = rawContent.replace(/ADAPTER_NAME="\$\{ADAPTER_NAME:\?[^}]*\}"/, `ADAPTER_NAME="\${ADAPTER_NAME:-${targetProfile.adapterName}}"`);
214
+ const stopOutName = hookFilePattern
215
+ ? hookFilePattern
216
+ .replace(/\{\{name\}\}/g, manifest.name)
217
+ .replace(/\{\{slug\}\}/g, toSlug('Stop'))
218
+ .replace(/\{\{native\}\}/g, 'stop-hook')
219
+ : path.basename(manifest.hooks.Stop);
220
+ const stopPath = `hooks/${stopOutName}`;
221
+ if (!files.some((file) => file.path === stopPath)) {
222
+ files.push({ path: stopPath, content, executable: true });
223
+ }
224
+ }
225
+ }
226
+ // Generate hook registration file for shell-hook targets
227
+ if (targetProfile.hookRegistrationFormat) {
228
+ const hookRegFile = generateHookRegistrationFile(manifest, targetProfile, diagnostics);
229
+ if (hookRegFile) {
230
+ files.push(hookRegFile);
231
+ for (const aliasPath of targetProfile.hookRegistrationAliasPaths) {
232
+ files.push({ path: aliasPath, content: hookRegFile.content });
233
+ }
234
+ }
235
+ }
236
+ return files;
237
+ }
238
+ function generateHookRegistrationFile(manifest, targetProfile, diagnostics) {
239
+ const adapter = getAdapter(targetProfile.name);
240
+ if (!adapter)
241
+ return null;
242
+ return adapter.generateHookRegistration(manifest, targetProfile, diagnostics);
243
+ }
@@ -0,0 +1,8 @@
1
+ import type { A5cPluginManifest, TargetProfile, TransformedFile, Diagnostic } from './types.js';
2
+ export declare function generateManifests(sourceDir: string, manifest: A5cPluginManifest, targetProfile: TargetProfile, _diagnostics: Diagnostic[]): TransformedFile[];
3
+ export declare function copyAgentFiles(sourceDir: string, manifest: A5cPluginManifest, targetProfile: TargetProfile, _diagnostics: Diagnostic[]): TransformedFile[];
4
+ export declare function copyContextFiles(sourceDir: string, manifest: A5cPluginManifest, targetProfile: TargetProfile, _diagnostics: Diagnostic[]): TransformedFile[];
5
+ export declare function copyIncludedFiles(sourceDir: string, manifest: A5cPluginManifest, excludePatterns?: string[]): TransformedFile[];
6
+ export declare function collectDir(sourceDir: string, relDir: string, files: TransformedFile[]): void;
7
+ export declare function generateExtraFiles(sourceDir: string, manifest: A5cPluginManifest, targetProfile: TargetProfile, _diagnostics: Diagnostic[]): TransformedFile[];
8
+ //# sourceMappingURL=transformEmitters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformEmitters.d.ts","sourceRoot":"","sources":["../src/transformEmitters.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA8EhG,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,iBAAiB,EAC3B,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,UAAU,EAAE,GACzB,eAAe,EAAE,CA2GnB;AAED,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,iBAAiB,EAC3B,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,UAAU,EAAE,GACzB,eAAe,EAAE,CAkBnB;AAED,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,iBAAiB,EAC3B,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,UAAU,EAAE,GACzB,eAAe,EAAE,CAkBnB;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,iBAAiB,EAC3B,eAAe,GAAE,MAAM,EAAO,GAC7B,eAAe,EAAE,CA8CnB;AAED,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,eAAe,EAAE,GACvB,IAAI,CAeN;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,iBAAiB,EAC3B,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,UAAU,EAAE,GACzB,eAAe,EAAE,CAmFnB"}