@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.
- package/README.md +58 -0
- package/dist/binTemplates.d.ts +7 -0
- package/dist/binTemplates.d.ts.map +1 -0
- package/dist/binTemplates.js +292 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +299 -0
- package/dist/compiler.d.ts +15 -0
- package/dist/compiler.d.ts.map +1 -0
- package/dist/compiler.js +118 -0
- package/dist/diff.d.ts +9 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +183 -0
- package/dist/emit.d.ts +3 -0
- package/dist/emit.d.ts.map +1 -0
- package/dist/emit.js +42 -0
- package/dist/hookRegistration.d.ts +8 -0
- package/dist/hookRegistration.d.ts.map +1 -0
- package/dist/hookRegistration.js +9 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/init.d.ts +17 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +200 -0
- package/dist/installInstructions.d.ts +3 -0
- package/dist/installInstructions.d.ts.map +1 -0
- package/dist/installInstructions.js +150 -0
- package/dist/installSharedGenerator.d.ts +3 -0
- package/dist/installSharedGenerator.d.ts.map +1 -0
- package/dist/installSharedGenerator.js +229 -0
- package/dist/manifestGenerators.d.ts +10 -0
- package/dist/manifestGenerators.d.ts.map +1 -0
- package/dist/manifestGenerators.js +11 -0
- package/dist/marketplaceGenerator.d.ts +3 -0
- package/dist/marketplaceGenerator.d.ts.map +1 -0
- package/dist/marketplaceGenerator.js +46 -0
- package/dist/proxiedHookTemplates.d.ts +10 -0
- package/dist/proxiedHookTemplates.d.ts.map +1 -0
- package/dist/proxiedHookTemplates.js +122 -0
- package/dist/resolve.d.ts +3 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +106 -0
- package/dist/schema.d.ts +231 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +340 -0
- package/dist/sdkConfig.d.ts +20 -0
- package/dist/sdkConfig.d.ts.map +1 -0
- package/dist/sdkConfig.js +41 -0
- package/dist/targets/adapters/base.d.ts +10 -0
- package/dist/targets/adapters/base.d.ts.map +1 -0
- package/dist/targets/adapters/base.js +16 -0
- package/dist/targets/adapters/claude-code.d.ts +9 -0
- package/dist/targets/adapters/claude-code.d.ts.map +1 -0
- package/dist/targets/adapters/claude-code.js +83 -0
- package/dist/targets/adapters/codex.d.ts +13 -0
- package/dist/targets/adapters/codex.d.ts.map +1 -0
- package/dist/targets/adapters/codex.js +103 -0
- package/dist/targets/adapters/cursor.d.ts +9 -0
- package/dist/targets/adapters/cursor.d.ts.map +1 -0
- package/dist/targets/adapters/cursor.js +57 -0
- package/dist/targets/adapters/gemini.d.ts +9 -0
- package/dist/targets/adapters/gemini.d.ts.map +1 -0
- package/dist/targets/adapters/gemini.js +86 -0
- package/dist/targets/adapters/github-copilot.d.ts +9 -0
- package/dist/targets/adapters/github-copilot.d.ts.map +1 -0
- package/dist/targets/adapters/github-copilot.js +61 -0
- package/dist/targets/adapters/hermes.d.ts +13 -0
- package/dist/targets/adapters/hermes.d.ts.map +1 -0
- package/dist/targets/adapters/hermes.js +96 -0
- package/dist/targets/adapters/hooks-utils.d.ts +12 -0
- package/dist/targets/adapters/hooks-utils.d.ts.map +1 -0
- package/dist/targets/adapters/hooks-utils.js +60 -0
- package/dist/targets/adapters/index.d.ts +27 -0
- package/dist/targets/adapters/index.d.ts.map +1 -0
- package/dist/targets/adapters/index.js +64 -0
- package/dist/targets/adapters/interface.d.ts +8 -0
- package/dist/targets/adapters/interface.d.ts.map +1 -0
- package/dist/targets/adapters/interface.js +2 -0
- package/dist/targets/adapters/oh-my-pi.d.ts +11 -0
- package/dist/targets/adapters/oh-my-pi.d.ts.map +1 -0
- package/dist/targets/adapters/oh-my-pi.js +88 -0
- package/dist/targets/adapters/openclaw.d.ts +14 -0
- package/dist/targets/adapters/openclaw.d.ts.map +1 -0
- package/dist/targets/adapters/openclaw.js +165 -0
- package/dist/targets/adapters/opencode.d.ts +10 -0
- package/dist/targets/adapters/opencode.d.ts.map +1 -0
- package/dist/targets/adapters/opencode.js +93 -0
- package/dist/targets/adapters/pi.d.ts +11 -0
- package/dist/targets/adapters/pi.d.ts.map +1 -0
- package/dist/targets/adapters/pi.js +90 -0
- package/dist/targets/index.d.ts +7 -0
- package/dist/targets/index.d.ts.map +1 -0
- package/dist/targets/index.js +77 -0
- package/dist/transform.d.ts +4 -0
- package/dist/transform.d.ts.map +1 -0
- package/dist/transform.js +243 -0
- package/dist/transformEmitters.d.ts +8 -0
- package/dist/transformEmitters.d.ts.map +1 -0
- package/dist/transformEmitters.js +340 -0
- package/dist/transformHelpers.d.ts +13 -0
- package/dist/transformHelpers.d.ts.map +1 -0
- package/dist/transformHelpers.js +239 -0
- package/dist/types.d.ts +204 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/utils.d.ts +42 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +187 -0
- package/dist/validate.d.ts +3 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +188 -0
- package/dist/verify.d.ts +6 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +294 -0
- package/package.json +68 -0
package/dist/compiler.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Compiler pipeline orchestrator
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { validate } from './validate.js';
|
|
5
|
+
import { resolve } from './resolve.js';
|
|
6
|
+
import { transform } from './transform.js';
|
|
7
|
+
import { emit } from './emit.js';
|
|
8
|
+
import { verify } from './verify.js';
|
|
9
|
+
import { getAllTargets } from './targets/index.js';
|
|
10
|
+
import { generateMarketplaceJson } from './marketplaceGenerator.js';
|
|
11
|
+
export function compile(options) {
|
|
12
|
+
const { source, target, output, outputBaseDir, dryRun = false, verifyOutput = false } = options;
|
|
13
|
+
// Stage 1: VALIDATE
|
|
14
|
+
const validateResult = validate(source);
|
|
15
|
+
if (!validateResult.valid || !validateResult.manifest) {
|
|
16
|
+
return {
|
|
17
|
+
target,
|
|
18
|
+
status: 'error',
|
|
19
|
+
outputDir: output,
|
|
20
|
+
emittedFiles: [],
|
|
21
|
+
componentSupport: {
|
|
22
|
+
hooks: {},
|
|
23
|
+
commands: 'unsupported',
|
|
24
|
+
skills: 'unsupported',
|
|
25
|
+
agents: 'unsupported',
|
|
26
|
+
context: 'unsupported',
|
|
27
|
+
},
|
|
28
|
+
diagnostics: validateResult.diagnostics,
|
|
29
|
+
verificationChecklist: [],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const diagnostics = [...validateResult.diagnostics];
|
|
33
|
+
// Stage 2: RESOLVE
|
|
34
|
+
const resolveResult = resolve(validateResult.manifest, target);
|
|
35
|
+
diagnostics.push(...resolveResult.diagnostics);
|
|
36
|
+
if (resolveResult.diagnostics.some((d) => d.level === 'error')) {
|
|
37
|
+
return {
|
|
38
|
+
target,
|
|
39
|
+
status: 'error',
|
|
40
|
+
outputDir: output,
|
|
41
|
+
emittedFiles: [],
|
|
42
|
+
componentSupport: resolveResult.componentSupport,
|
|
43
|
+
diagnostics,
|
|
44
|
+
verificationChecklist: [],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Stage 3: TRANSFORM
|
|
48
|
+
const transformResult = transform(source, resolveResult.effectiveManifest, resolveResult.targetProfile);
|
|
49
|
+
diagnostics.push(...transformResult.diagnostics);
|
|
50
|
+
if (transformResult.diagnostics.some((d) => d.level === 'error')) {
|
|
51
|
+
return {
|
|
52
|
+
target,
|
|
53
|
+
status: 'error',
|
|
54
|
+
outputDir: output,
|
|
55
|
+
emittedFiles: [],
|
|
56
|
+
componentSupport: resolveResult.componentSupport,
|
|
57
|
+
diagnostics,
|
|
58
|
+
verificationChecklist: [],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// Stage 4: EMIT
|
|
62
|
+
const emitResult = emit(output, transformResult.files, dryRun);
|
|
63
|
+
diagnostics.push(...emitResult.diagnostics);
|
|
64
|
+
if (emitResult.diagnostics.some((d) => d.level === 'error')) {
|
|
65
|
+
return {
|
|
66
|
+
target,
|
|
67
|
+
status: 'error',
|
|
68
|
+
outputDir: output,
|
|
69
|
+
emittedFiles: emitResult.emittedFiles,
|
|
70
|
+
componentSupport: resolveResult.componentSupport,
|
|
71
|
+
diagnostics,
|
|
72
|
+
verificationChecklist: [],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// Generate marketplace manifest if target has a marketplace path
|
|
76
|
+
if (resolveResult.targetProfile.marketplacePath && !dryRun && outputBaseDir) {
|
|
77
|
+
const marketplaceContent = generateMarketplaceJson(resolveResult.effectiveManifest, resolveResult.targetProfile, output, outputBaseDir);
|
|
78
|
+
const marketplaceFullPath = path.join(outputBaseDir, resolveResult.targetProfile.marketplacePath);
|
|
79
|
+
fs.mkdirSync(path.dirname(marketplaceFullPath), { recursive: true });
|
|
80
|
+
fs.writeFileSync(marketplaceFullPath, marketplaceContent);
|
|
81
|
+
emitResult.emittedFiles.push(resolveResult.targetProfile.marketplacePath);
|
|
82
|
+
}
|
|
83
|
+
// Stage 5: VERIFY (optional)
|
|
84
|
+
let verificationChecklist = [];
|
|
85
|
+
if (verifyOutput && !dryRun) {
|
|
86
|
+
const verifyResult = verify(output, emitResult.emittedFiles, {
|
|
87
|
+
outputBaseDir,
|
|
88
|
+
});
|
|
89
|
+
diagnostics.push(...verifyResult.diagnostics);
|
|
90
|
+
verificationChecklist = verifyResult.verificationChecklist;
|
|
91
|
+
}
|
|
92
|
+
const hasErrors = diagnostics.some((d) => d.level === 'error');
|
|
93
|
+
const hasWarnings = diagnostics.some((d) => d.level === 'warning');
|
|
94
|
+
return {
|
|
95
|
+
target,
|
|
96
|
+
status: hasErrors ? 'error' : hasWarnings ? 'warning' : 'success',
|
|
97
|
+
outputDir: output,
|
|
98
|
+
emittedFiles: emitResult.emittedFiles,
|
|
99
|
+
componentSupport: resolveResult.componentSupport,
|
|
100
|
+
diagnostics,
|
|
101
|
+
verificationChecklist,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
export function compileAll(source, outputBaseDir, options = {}) {
|
|
105
|
+
const targets = getAllTargets();
|
|
106
|
+
const results = [];
|
|
107
|
+
for (const target of targets) {
|
|
108
|
+
const result = compile({
|
|
109
|
+
source,
|
|
110
|
+
target,
|
|
111
|
+
output: `${outputBaseDir}/${target}`,
|
|
112
|
+
outputBaseDir,
|
|
113
|
+
...options,
|
|
114
|
+
});
|
|
115
|
+
results.push(result);
|
|
116
|
+
}
|
|
117
|
+
return results;
|
|
118
|
+
}
|
package/dist/diff.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DiffResult } from './types.js';
|
|
2
|
+
export interface DiffOptions {
|
|
3
|
+
source: string;
|
|
4
|
+
target: string;
|
|
5
|
+
existing: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function diffTarget(options: DiffOptions): DiffResult;
|
|
8
|
+
export declare function formatDiffResult(result: DiffResult): string;
|
|
9
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAsB,UAAU,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAcD,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,CAoF3D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAoC3D"}
|
package/dist/diff.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as os from 'os';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { compile } from './compiler.js';
|
|
5
|
+
import { getTargetProfile } from './targets/index.js';
|
|
6
|
+
const IGNORED_EXISTING_FILES = new Set([
|
|
7
|
+
'package-lock.json',
|
|
8
|
+
'plugin.lock.json',
|
|
9
|
+
'.npmrc',
|
|
10
|
+
'.cursorrules',
|
|
11
|
+
'CHANGELOG.md',
|
|
12
|
+
'hooks/proxied-hooks.json',
|
|
13
|
+
'hooks/hooks.json',
|
|
14
|
+
'proxied-hooks.json',
|
|
15
|
+
'versions.json',
|
|
16
|
+
]);
|
|
17
|
+
export function diffTarget(options) {
|
|
18
|
+
const { source, target, existing } = options;
|
|
19
|
+
const targetProfile = getTargetProfile(target);
|
|
20
|
+
if (!targetProfile) {
|
|
21
|
+
throw new Error(`Unknown target: ${target}`);
|
|
22
|
+
}
|
|
23
|
+
if (!fs.existsSync(existing)) {
|
|
24
|
+
throw new Error(`Existing directory not found: ${existing}`);
|
|
25
|
+
}
|
|
26
|
+
if (!fs.statSync(existing).isDirectory()) {
|
|
27
|
+
throw new Error(`Existing path must be a directory: ${existing}`);
|
|
28
|
+
}
|
|
29
|
+
const tempBaseDir = fs.mkdtempSync(path.join(os.tmpdir(), 'extension-mux-diff-'));
|
|
30
|
+
const compiledDir = path.join(tempBaseDir, target);
|
|
31
|
+
try {
|
|
32
|
+
const compileResult = compile({
|
|
33
|
+
source,
|
|
34
|
+
target,
|
|
35
|
+
output: compiledDir,
|
|
36
|
+
});
|
|
37
|
+
if (compileResult.status === 'error') {
|
|
38
|
+
return {
|
|
39
|
+
target,
|
|
40
|
+
sourceDir: source,
|
|
41
|
+
existingDir: existing,
|
|
42
|
+
compilationStatus: compileResult.status,
|
|
43
|
+
diagnostics: compileResult.diagnostics,
|
|
44
|
+
status: 'error',
|
|
45
|
+
identical: false,
|
|
46
|
+
differenceCount: 0,
|
|
47
|
+
onlyInCompiled: [],
|
|
48
|
+
onlyInExisting: [],
|
|
49
|
+
differingFiles: [],
|
|
50
|
+
ignoredExistingFiles: [],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const compiledFiles = collectFiles(compiledDir);
|
|
54
|
+
const allExistingFiles = collectFiles(existing);
|
|
55
|
+
const ignoredExistingFiles = allExistingFiles.filter((file) => isIgnoredExistingFile(file));
|
|
56
|
+
const existingFiles = allExistingFiles;
|
|
57
|
+
const onlyInCompiled = compiledFiles.filter((file) => !existingFiles.includes(file)).sort();
|
|
58
|
+
const onlyInExisting = existingFiles
|
|
59
|
+
.filter((file) => !compiledFiles.includes(file) && !isIgnoredExistingFile(file))
|
|
60
|
+
.sort();
|
|
61
|
+
const differingFiles = compiledFiles
|
|
62
|
+
.filter((file) => existingFiles.includes(file) && !isIgnoredExistingFile(file))
|
|
63
|
+
.sort()
|
|
64
|
+
.flatMap((file) => {
|
|
65
|
+
const difference = compareFile(path.join(compiledDir, file), path.join(existing, file), file);
|
|
66
|
+
return difference ? [difference] : [];
|
|
67
|
+
});
|
|
68
|
+
const differenceCount = onlyInCompiled.length + onlyInExisting.length + differingFiles.length;
|
|
69
|
+
return {
|
|
70
|
+
target,
|
|
71
|
+
sourceDir: source,
|
|
72
|
+
existingDir: existing,
|
|
73
|
+
compilationStatus: compileResult.status,
|
|
74
|
+
diagnostics: compileResult.diagnostics,
|
|
75
|
+
status: differenceCount > 0 ? 'different' : 'match',
|
|
76
|
+
identical: differenceCount === 0,
|
|
77
|
+
differenceCount,
|
|
78
|
+
onlyInCompiled,
|
|
79
|
+
onlyInExisting,
|
|
80
|
+
differingFiles,
|
|
81
|
+
ignoredExistingFiles,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
fs.rmSync(tempBaseDir, { recursive: true, force: true });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export function formatDiffResult(result) {
|
|
89
|
+
if (result.status === 'error') {
|
|
90
|
+
return `Compilation failed for target ${result.target}.`;
|
|
91
|
+
}
|
|
92
|
+
if (result.identical) {
|
|
93
|
+
return `No differences found for target ${result.target}.`;
|
|
94
|
+
}
|
|
95
|
+
const lines = [];
|
|
96
|
+
if (result.onlyInCompiled.length > 0) {
|
|
97
|
+
lines.push('Files only in compiled:');
|
|
98
|
+
for (const file of result.onlyInCompiled) {
|
|
99
|
+
lines.push(` ${file}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (result.onlyInExisting.length > 0) {
|
|
103
|
+
lines.push('Files only in existing:');
|
|
104
|
+
for (const file of result.onlyInExisting) {
|
|
105
|
+
lines.push(` ${file}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (result.differingFiles.length > 0) {
|
|
109
|
+
lines.push('Files with differences:');
|
|
110
|
+
for (const file of result.differingFiles) {
|
|
111
|
+
lines.push(` ${file.path}`);
|
|
112
|
+
lines.push(` - compiled: ${formatLinePreview(file.compiledLine)}`);
|
|
113
|
+
lines.push(` + existing: ${formatLinePreview(file.existingLine)}`);
|
|
114
|
+
lines.push(` (content differs at line ${file.line})`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return lines.join('\n');
|
|
118
|
+
}
|
|
119
|
+
function compareFile(compiledPath, existingPath, relativePath) {
|
|
120
|
+
const compiledContent = fs.readFileSync(compiledPath, 'utf-8');
|
|
121
|
+
const existingContent = fs.readFileSync(existingPath, 'utf-8');
|
|
122
|
+
if (compiledContent === existingContent) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
const compiledLines = compiledContent.split(/\r?\n/);
|
|
126
|
+
const existingLines = existingContent.split(/\r?\n/);
|
|
127
|
+
const maxLines = Math.max(compiledLines.length, existingLines.length);
|
|
128
|
+
for (let index = 0; index < maxLines; index++) {
|
|
129
|
+
if (compiledLines[index] !== existingLines[index]) {
|
|
130
|
+
const difference = {
|
|
131
|
+
path: relativePath,
|
|
132
|
+
line: index + 1,
|
|
133
|
+
compiledLine: compiledLines[index] ?? null,
|
|
134
|
+
existingLine: existingLines[index] ?? null,
|
|
135
|
+
};
|
|
136
|
+
return difference;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
path: relativePath,
|
|
141
|
+
line: maxLines,
|
|
142
|
+
compiledLine: compiledLines[maxLines - 1] ?? null,
|
|
143
|
+
existingLine: existingLines[maxLines - 1] ?? null,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function collectFiles(dir, prefix = '') {
|
|
147
|
+
const results = [];
|
|
148
|
+
if (!fs.existsSync(dir)) {
|
|
149
|
+
return results;
|
|
150
|
+
}
|
|
151
|
+
for (const entry of fs.readdirSync(dir)) {
|
|
152
|
+
if (entry === 'node_modules' || entry === '.git' || entry === 'dist') {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const fullPath = path.join(dir, entry);
|
|
156
|
+
const relativePath = prefix ? `${prefix}/${entry}` : entry;
|
|
157
|
+
if (fs.statSync(fullPath).isDirectory()) {
|
|
158
|
+
results.push(...collectFiles(fullPath, relativePath));
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
results.push(relativePath);
|
|
162
|
+
}
|
|
163
|
+
return results.sort();
|
|
164
|
+
}
|
|
165
|
+
function isIgnoredExistingFile(file) {
|
|
166
|
+
return (file.startsWith('.a5c/') ||
|
|
167
|
+
file.startsWith('test/') ||
|
|
168
|
+
IGNORED_EXISTING_FILES.has(file) ||
|
|
169
|
+
file.endsWith('.legacy') ||
|
|
170
|
+
file.endsWith('.legacy.ts') ||
|
|
171
|
+
file.includes('sync-command') ||
|
|
172
|
+
file.endsWith('.png') ||
|
|
173
|
+
file.endsWith('.svg'));
|
|
174
|
+
}
|
|
175
|
+
function formatLinePreview(line) {
|
|
176
|
+
if (line === null) {
|
|
177
|
+
return '(missing)';
|
|
178
|
+
}
|
|
179
|
+
if (line.length === 0) {
|
|
180
|
+
return '(empty)';
|
|
181
|
+
}
|
|
182
|
+
return line;
|
|
183
|
+
}
|
package/dist/emit.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAc,MAAM,YAAY,CAAC;AAE1E,wBAAgB,IAAI,CAClB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,eAAe,EAAE,EACxB,MAAM,UAAQ,GACb,UAAU,CA2CZ"}
|
package/dist/emit.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Stage 4: EMIT - Write transformed files to output directory
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
export function emit(outputDir, files, dryRun = false) {
|
|
5
|
+
const diagnostics = [];
|
|
6
|
+
const emittedFiles = [];
|
|
7
|
+
if (!dryRun) {
|
|
8
|
+
// Create output directory
|
|
9
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
10
|
+
}
|
|
11
|
+
for (const file of files) {
|
|
12
|
+
const fullPath = path.join(outputDir, file.path);
|
|
13
|
+
const dir = path.dirname(fullPath);
|
|
14
|
+
if (!dryRun) {
|
|
15
|
+
// Create parent directories
|
|
16
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
17
|
+
// Write file
|
|
18
|
+
if (file.binaryContent) {
|
|
19
|
+
fs.writeFileSync(fullPath, file.binaryContent);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
fs.writeFileSync(fullPath, file.content, 'utf-8');
|
|
23
|
+
}
|
|
24
|
+
// Make executable if needed
|
|
25
|
+
if (file.executable) {
|
|
26
|
+
try {
|
|
27
|
+
fs.chmodSync(fullPath, 0o755);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
diagnostics.push({
|
|
31
|
+
level: 'warning',
|
|
32
|
+
category: 'compilation',
|
|
33
|
+
message: `Failed to make file executable: ${file.path}`,
|
|
34
|
+
source: fullPath,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
emittedFiles.push(file.path);
|
|
40
|
+
}
|
|
41
|
+
return { emittedFiles, diagnostics };
|
|
42
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { generateClaudeCodeHooksJson } from './targets/adapters/claude-code.js';
|
|
2
|
+
export { generateCodexHooksJson } from './targets/adapters/codex.js';
|
|
3
|
+
export { generateCursorHooksJson } from './targets/adapters/cursor.js';
|
|
4
|
+
export { generateGeminiHooksJson } from './targets/adapters/gemini.js';
|
|
5
|
+
export { generateGithubCopilotHooksJson } from './targets/adapters/github-copilot.js';
|
|
6
|
+
export { generateOpenCodeHooksJson } from './targets/adapters/opencode.js';
|
|
7
|
+
export { generateOpenClawHooksJson } from './targets/adapters/openclaw.js';
|
|
8
|
+
//# sourceMappingURL=hookRegistration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hookRegistration.d.ts","sourceRoot":"","sources":["../src/hookRegistration.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,2BAA2B,EAAE,MAAM,mCAAmC,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,8BAA8B,EAAE,MAAM,sCAAsC,CAAC;AACtF,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Hook registration file generators for all targets
|
|
2
|
+
// This is a thin re-export shell — actual implementations live in targets/adapters/
|
|
3
|
+
export { generateClaudeCodeHooksJson } from './targets/adapters/claude-code.js';
|
|
4
|
+
export { generateCodexHooksJson } from './targets/adapters/codex.js';
|
|
5
|
+
export { generateCursorHooksJson } from './targets/adapters/cursor.js';
|
|
6
|
+
export { generateGeminiHooksJson } from './targets/adapters/gemini.js';
|
|
7
|
+
export { generateGithubCopilotHooksJson } from './targets/adapters/github-copilot.js';
|
|
8
|
+
export { generateOpenCodeHooksJson } from './targets/adapters/opencode.js';
|
|
9
|
+
export { generateOpenClawHooksJson } from './targets/adapters/openclaw.js';
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export { A5C_PLUGIN_SCHEMA, validate as validateSchema } from './schema.js';
|
|
3
|
+
export * from './utils.js';
|
|
4
|
+
export { validate as validateDirectory } from './validate.js';
|
|
5
|
+
export * from './resolve.js';
|
|
6
|
+
export * from './transform.js';
|
|
7
|
+
export * from './emit.js';
|
|
8
|
+
export * from './verify.js';
|
|
9
|
+
export * from './compiler.js';
|
|
10
|
+
export * from './diff.js';
|
|
11
|
+
export * from './targets/index.js';
|
|
12
|
+
export * from './init.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,QAAQ,IAAI,cAAc,EAAE,MAAM,aAAa,CAAC;AAC5E,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC9D,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Public API for @a5c-ai/extension-mux
|
|
2
|
+
export * from './types.js';
|
|
3
|
+
export { A5C_PLUGIN_SCHEMA, validate as validateSchema } from './schema.js';
|
|
4
|
+
export * from './utils.js';
|
|
5
|
+
export { validate as validateDirectory } from './validate.js';
|
|
6
|
+
export * from './resolve.js';
|
|
7
|
+
export * from './transform.js';
|
|
8
|
+
export * from './emit.js';
|
|
9
|
+
export * from './verify.js';
|
|
10
|
+
export * from './compiler.js';
|
|
11
|
+
export * from './diff.js';
|
|
12
|
+
export * from './targets/index.js';
|
|
13
|
+
export * from './init.js';
|
package/dist/init.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const INIT_TEMPLATES: readonly ["minimal", "full", "hooks-only"];
|
|
2
|
+
export type InitTemplate = typeof INIT_TEMPLATES[number];
|
|
3
|
+
export interface InitOptions {
|
|
4
|
+
name: string;
|
|
5
|
+
output?: string;
|
|
6
|
+
template?: InitTemplate;
|
|
7
|
+
dryRun?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface InitResult {
|
|
10
|
+
name: string;
|
|
11
|
+
outputDir: string;
|
|
12
|
+
template: InitTemplate;
|
|
13
|
+
writtenFiles: string[];
|
|
14
|
+
dryRun: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function scaffoldPlugin(options: InitOptions): InitResult;
|
|
17
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AA8BA,eAAO,MAAM,cAAc,4CAA6C,CAAC;AAEzE,MAAM,MAAM,YAAY,GAAG,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,YAAY,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;CACjB;AAUD,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,CAsC/D"}
|
package/dist/init.js
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { listPluginTargetDescriptors } from '@a5c-ai/agent-catalog';
|
|
5
|
+
/**
|
|
6
|
+
* Build the contextFiles map from catalog data.
|
|
7
|
+
* Targets with a requiredSurfaceFile that is an AGENTS.md-style file
|
|
8
|
+
* get a context/ mapping.
|
|
9
|
+
*/
|
|
10
|
+
function buildContextFilesMap() {
|
|
11
|
+
const map = {};
|
|
12
|
+
for (const target of listPluginTargetDescriptors()) {
|
|
13
|
+
if (target.requiredSurfaceFile) {
|
|
14
|
+
map[target.targetId] = `context/${target.requiredSurfaceFile}`;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return map;
|
|
18
|
+
}
|
|
19
|
+
function buildContextSurfaceFiles(name, manifest) {
|
|
20
|
+
const contextFiles = manifest.contextFiles ?? {};
|
|
21
|
+
const uniquePaths = [...new Set(Object.values(contextFiles))];
|
|
22
|
+
return uniquePaths.map((contextPath) => ({
|
|
23
|
+
path: contextPath,
|
|
24
|
+
content: buildAgentsContext(name),
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
export const INIT_TEMPLATES = ['minimal', 'full', 'hooks-only'];
|
|
28
|
+
const NAME_PATTERN = /^[a-z0-9-]+$/;
|
|
29
|
+
export function scaffoldPlugin(options) {
|
|
30
|
+
const template = normalizeTemplate(options.template);
|
|
31
|
+
const outputDir = path.resolve(options.output ?? process.cwd());
|
|
32
|
+
const dryRun = options.dryRun ?? false;
|
|
33
|
+
if (!options.name) {
|
|
34
|
+
throw new Error('Plugin name is required');
|
|
35
|
+
}
|
|
36
|
+
if (!NAME_PATTERN.test(options.name)) {
|
|
37
|
+
throw new Error('Plugin name must match pattern ^[a-z0-9-]+$');
|
|
38
|
+
}
|
|
39
|
+
ensureScaffoldTarget(outputDir);
|
|
40
|
+
const files = buildTemplateFiles(options.name, template);
|
|
41
|
+
if (!dryRun) {
|
|
42
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
43
|
+
for (const file of files) {
|
|
44
|
+
const fullPath = path.join(outputDir, file.path);
|
|
45
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
46
|
+
fs.writeFileSync(fullPath, file.content, 'utf-8');
|
|
47
|
+
if (file.executable) {
|
|
48
|
+
fs.chmodSync(fullPath, 0o755);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
name: options.name,
|
|
54
|
+
outputDir,
|
|
55
|
+
template,
|
|
56
|
+
writtenFiles: files.map((file) => file.path),
|
|
57
|
+
dryRun,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function normalizeTemplate(template) {
|
|
61
|
+
if (!template) {
|
|
62
|
+
return 'minimal';
|
|
63
|
+
}
|
|
64
|
+
if (INIT_TEMPLATES.includes(template)) {
|
|
65
|
+
return template;
|
|
66
|
+
}
|
|
67
|
+
throw new Error(`Unsupported template: ${template}. Expected one of: ${INIT_TEMPLATES.join(', ')}`);
|
|
68
|
+
}
|
|
69
|
+
function ensureScaffoldTarget(outputDir) {
|
|
70
|
+
if (!fs.existsSync(outputDir)) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const stat = fs.statSync(outputDir);
|
|
74
|
+
if (!stat.isDirectory()) {
|
|
75
|
+
throw new Error(`Output path is not a directory: ${outputDir}`);
|
|
76
|
+
}
|
|
77
|
+
const entries = fs.readdirSync(outputDir);
|
|
78
|
+
if (entries.length > 0) {
|
|
79
|
+
throw new Error(`Output directory must be empty: ${outputDir}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function buildTemplateFiles(name, template) {
|
|
83
|
+
const manifest = buildManifest(name, template);
|
|
84
|
+
const files = [
|
|
85
|
+
{
|
|
86
|
+
path: 'plugin.json',
|
|
87
|
+
content: `${JSON.stringify(manifest, null, 2)}\n`,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
path: 'versions.json',
|
|
91
|
+
content: `${JSON.stringify({ sdkVersion: readPackageVersion() }, null, 2)}\n`,
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
switch (template) {
|
|
95
|
+
case 'minimal':
|
|
96
|
+
return files;
|
|
97
|
+
case 'full':
|
|
98
|
+
return files.concat([
|
|
99
|
+
{
|
|
100
|
+
path: 'commands/example.md',
|
|
101
|
+
content: buildExampleCommand(name),
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
path: 'skills/example/SKILL.md',
|
|
105
|
+
content: buildExampleSkill(name),
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
path: 'hooks/session-start.handler.sh',
|
|
109
|
+
content: buildSessionStartHook(),
|
|
110
|
+
executable: true,
|
|
111
|
+
},
|
|
112
|
+
...buildContextSurfaceFiles(name, manifest),
|
|
113
|
+
]);
|
|
114
|
+
case 'hooks-only':
|
|
115
|
+
return files.concat([
|
|
116
|
+
{
|
|
117
|
+
path: 'hooks/session-start.handler.sh',
|
|
118
|
+
content: buildSessionStartHook(),
|
|
119
|
+
executable: true,
|
|
120
|
+
},
|
|
121
|
+
]);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function buildManifest(name, template) {
|
|
125
|
+
const baseManifest = {
|
|
126
|
+
name,
|
|
127
|
+
version: '0.1.0',
|
|
128
|
+
description: `Starter unified plugin for ${name}`,
|
|
129
|
+
author: 'Your Name',
|
|
130
|
+
license: 'MIT',
|
|
131
|
+
};
|
|
132
|
+
if (template === 'full') {
|
|
133
|
+
return {
|
|
134
|
+
...baseManifest,
|
|
135
|
+
hooks: {
|
|
136
|
+
SessionStart: 'hooks/session-start.handler.sh',
|
|
137
|
+
},
|
|
138
|
+
commands: 'commands',
|
|
139
|
+
skills: [
|
|
140
|
+
{
|
|
141
|
+
name: 'example',
|
|
142
|
+
file: 'skills/example/SKILL.md',
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
contextFiles: buildContextFilesMap(),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
if (template === 'hooks-only') {
|
|
149
|
+
return {
|
|
150
|
+
...baseManifest,
|
|
151
|
+
hooks: {
|
|
152
|
+
SessionStart: 'hooks/session-start.handler.sh',
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return baseManifest;
|
|
157
|
+
}
|
|
158
|
+
function buildExampleCommand(name) {
|
|
159
|
+
return `# Example Command
|
|
160
|
+
|
|
161
|
+
This is the starter command for \`${name}\`.
|
|
162
|
+
|
|
163
|
+
- Replace this file with your real command docs.
|
|
164
|
+
- Keep commands in markdown so compatible targets can copy or adapt them.
|
|
165
|
+
`;
|
|
166
|
+
}
|
|
167
|
+
function buildExampleSkill(name) {
|
|
168
|
+
return `# Example Skill
|
|
169
|
+
|
|
170
|
+
Use this skill as the starter skill for \`${name}\`.
|
|
171
|
+
|
|
172
|
+
Update the content to describe when the skill should be used and what it should do.
|
|
173
|
+
`;
|
|
174
|
+
}
|
|
175
|
+
function buildSessionStartHook() {
|
|
176
|
+
return `#!/usr/bin/env bash
|
|
177
|
+
set -euo pipefail
|
|
178
|
+
|
|
179
|
+
# Starter hook for SessionStart. Emit JSON for the harness runtime.
|
|
180
|
+
printf '{}\n'
|
|
181
|
+
`;
|
|
182
|
+
}
|
|
183
|
+
function buildAgentsContext(name) {
|
|
184
|
+
return `# ${name}
|
|
185
|
+
|
|
186
|
+
Add harness-facing project guidance here for targets that support context files.
|
|
187
|
+
`;
|
|
188
|
+
}
|
|
189
|
+
function readPackageVersion() {
|
|
190
|
+
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
|
191
|
+
const packageJsonPath = path.resolve(moduleDir, '../package.json');
|
|
192
|
+
try {
|
|
193
|
+
const raw = fs.readFileSync(packageJsonPath, 'utf-8');
|
|
194
|
+
const parsed = JSON.parse(raw);
|
|
195
|
+
return parsed.version ?? '0.0.0';
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
return '0.0.0';
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installInstructions.d.ts","sourceRoot":"","sources":["../src/installInstructions.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAOnE,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,iBAAiB,EAC3B,aAAa,EAAE,aAAa,EAC5B,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAcR"}
|