@agenticflow/cli 0.0.1-beta.13
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 +125 -0
- package/TECHNICAL_DEBT.md +121 -0
- package/dist/builder/bundler.d.ts +17 -0
- package/dist/builder/bundler.d.ts.map +1 -0
- package/dist/builder/bundler.js +170 -0
- package/dist/builder/bundler.js.map +1 -0
- package/dist/builder/index.d.ts +6 -0
- package/dist/builder/index.d.ts.map +1 -0
- package/dist/builder/index.js +6 -0
- package/dist/builder/index.js.map +1 -0
- package/dist/builder/packager.d.ts +41 -0
- package/dist/builder/packager.d.ts.map +1 -0
- package/dist/builder/packager.js +145 -0
- package/dist/builder/packager.js.map +1 -0
- package/dist/builder/security.d.ts +26 -0
- package/dist/builder/security.d.ts.map +1 -0
- package/dist/builder/security.js +204 -0
- package/dist/builder/security.js.map +1 -0
- package/dist/builder/stripper.d.ts +19 -0
- package/dist/builder/stripper.d.ts.map +1 -0
- package/dist/builder/stripper.js +100 -0
- package/dist/builder/stripper.js.map +1 -0
- package/dist/builder/validator.d.ts +33 -0
- package/dist/builder/validator.d.ts.map +1 -0
- package/dist/builder/validator.js +150 -0
- package/dist/builder/validator.js.map +1 -0
- package/dist/cli/build.d.ts +3 -0
- package/dist/cli/build.d.ts.map +1 -0
- package/dist/cli/build.js +167 -0
- package/dist/cli/build.js.map +1 -0
- package/dist/cli/categories.d.ts +40 -0
- package/dist/cli/categories.d.ts.map +1 -0
- package/dist/cli/categories.js +101 -0
- package/dist/cli/categories.js.map +1 -0
- package/dist/cli/dev.d.ts +3 -0
- package/dist/cli/dev.d.ts.map +1 -0
- package/dist/cli/dev.js +226 -0
- package/dist/cli/dev.js.map +1 -0
- package/dist/cli/handler-types.d.ts +34 -0
- package/dist/cli/handler-types.d.ts.map +1 -0
- package/dist/cli/handler-types.js +67 -0
- package/dist/cli/handler-types.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +24 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +3 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +264 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/login.d.ts +3 -0
- package/dist/cli/login.d.ts.map +1 -0
- package/dist/cli/login.js +10 -0
- package/dist/cli/login.js.map +1 -0
- package/dist/cli/publish.d.ts +5 -0
- package/dist/cli/publish.d.ts.map +1 -0
- package/dist/cli/publish.js +120 -0
- package/dist/cli/publish.js.map +1 -0
- package/dist/cli/template-processor.d.ts +35 -0
- package/dist/cli/template-processor.d.ts.map +1 -0
- package/dist/cli/template-processor.js +82 -0
- package/dist/cli/template-processor.js.map +1 -0
- package/dist/cli/test.d.ts +3 -0
- package/dist/cli/test.d.ts.map +1 -0
- package/dist/cli/test.js +12 -0
- package/dist/cli/test.js.map +1 -0
- package/dist/dev/decorators.d.ts +10 -0
- package/dist/dev/decorators.d.ts.map +1 -0
- package/dist/dev/decorators.js +26 -0
- package/dist/dev/decorators.js.map +1 -0
- package/dist/dev/executor.d.ts +22 -0
- package/dist/dev/executor.d.ts.map +1 -0
- package/dist/dev/executor.js +243 -0
- package/dist/dev/executor.js.map +1 -0
- package/dist/dev/extractor.d.ts +15 -0
- package/dist/dev/extractor.d.ts.map +1 -0
- package/dist/dev/extractor.js +224 -0
- package/dist/dev/extractor.js.map +1 -0
- package/dist/dev/index.d.ts +3 -0
- package/dist/dev/index.d.ts.map +1 -0
- package/dist/dev/index.js +4 -0
- package/dist/dev/index.js.map +1 -0
- package/dist/dev/server.d.ts +91 -0
- package/dist/dev/server.d.ts.map +1 -0
- package/dist/dev/server.js +507 -0
- package/dist/dev/server.js.map +1 -0
- package/dist/dev/ui-dist/assets/index-BkKxvzfq.js +246 -0
- package/dist/dev/ui-dist/assets/index-DTO1qt7B.css +1 -0
- package/dist/dev/ui-dist/index.html +14 -0
- package/dist/dev/ui-dist/monkey.svg +3 -0
- package/dist/dev/ui-dist/package.json +27 -0
- package/dist/templates/_shared/.env.template +16 -0
- package/dist/templates/_shared/.gitignore.template +46 -0
- package/dist/templates/_shared/LICENSE.template +21 -0
- package/dist/templates/_shared/src/utils.ts.template +29 -0
- package/dist/templates/_shared/tsconfig.json.template +23 -0
- package/dist/templates/stateful/manifest.json.template +63 -0
- package/dist/templates/stateful/package.json.template +23 -0
- package/dist/templates/stateful/src/index.ts.template +147 -0
- package/dist/templates/stateless/docs/README.md.template +102 -0
- package/dist/templates/stateless/manifest.json.template +63 -0
- package/dist/templates/stateless/package.json.template +23 -0
- package/dist/templates/stateless/src/index.ts.template +103 -0
- package/package.json +51 -0
- package/vitest.config.ts +15 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { getCategoryColor, getCategoryApiValue } from './categories.js';
|
|
4
|
+
/**
|
|
5
|
+
* Process template context with derived values
|
|
6
|
+
*/
|
|
7
|
+
export function processTemplateContext(context) {
|
|
8
|
+
return {
|
|
9
|
+
...context,
|
|
10
|
+
handlerClassName: toPascalCase(context.handlerType),
|
|
11
|
+
handlerTypeFirstWord: context.handlerType.split('-')[0],
|
|
12
|
+
categoryColor: getCategoryColor(context.category),
|
|
13
|
+
categoryApi: getCategoryApiValue(context.category),
|
|
14
|
+
authorGitHub: context.authorName.toLowerCase().replace(/\s+/g, ''),
|
|
15
|
+
currentYear: new Date().getFullYear()
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Replace template variables in content
|
|
20
|
+
*/
|
|
21
|
+
export function replaceTemplateVariables(content, context) {
|
|
22
|
+
let result = content;
|
|
23
|
+
// Replace all template variables
|
|
24
|
+
Object.entries(context).forEach(([key, value]) => {
|
|
25
|
+
const placeholder = `{{${key}}}`;
|
|
26
|
+
result = result.replace(new RegExp(placeholder, 'g'), String(value));
|
|
27
|
+
});
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Copy and process a template file
|
|
32
|
+
*/
|
|
33
|
+
export async function processTemplateFile(templatePath, outputPath, context) {
|
|
34
|
+
const content = fs.readFileSync(templatePath, 'utf-8');
|
|
35
|
+
const processedContent = replaceTemplateVariables(content, context);
|
|
36
|
+
// Ensure output directory exists
|
|
37
|
+
const outputDir = path.dirname(outputPath);
|
|
38
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
39
|
+
fs.writeFileSync(outputPath, processedContent, 'utf-8');
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Copy and process an entire template directory
|
|
43
|
+
*/
|
|
44
|
+
export async function processTemplateDirectory(templateDir, outputDir, context) {
|
|
45
|
+
const files = await getTemplateFiles(templateDir);
|
|
46
|
+
for (const file of files) {
|
|
47
|
+
const templatePath = path.join(templateDir, file);
|
|
48
|
+
const outputPath = path.join(outputDir, file.replace('.template', ''));
|
|
49
|
+
await processTemplateFile(templatePath, outputPath, context);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get all template files recursively
|
|
54
|
+
*/
|
|
55
|
+
async function getTemplateFiles(dir) {
|
|
56
|
+
const files = [];
|
|
57
|
+
function walk(currentDir, relativePath = '') {
|
|
58
|
+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
59
|
+
for (const entry of entries) {
|
|
60
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
61
|
+
const relPath = path.join(relativePath, entry.name);
|
|
62
|
+
if (entry.isDirectory()) {
|
|
63
|
+
walk(fullPath, relPath);
|
|
64
|
+
}
|
|
65
|
+
else if (entry.name.endsWith('.template')) {
|
|
66
|
+
files.push(relPath);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
walk(dir);
|
|
71
|
+
return files;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Convert kebab-case to PascalCase
|
|
75
|
+
*/
|
|
76
|
+
function toPascalCase(str) {
|
|
77
|
+
return str
|
|
78
|
+
.split('-')
|
|
79
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
80
|
+
.join('');
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=template-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-processor.js","sourceRoot":"","sources":["../../src/cli/template-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/cli/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,eAAO,MAAM,WAAW,SAQpB,CAAC"}
|
package/dist/cli/test.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
export const testCommand = new Command('test')
|
|
4
|
+
.description('Run unit tests for the handler')
|
|
5
|
+
.option('--watch', 'Watch mode')
|
|
6
|
+
.option('--coverage', 'Generate coverage report')
|
|
7
|
+
.action(async (options) => {
|
|
8
|
+
console.log(chalk.blue('\n🧪 Running tests\n'));
|
|
9
|
+
console.log(chalk.yellow('⚠ Test runner not yet implemented'));
|
|
10
|
+
console.log(chalk.dim('Coming soon...\n'));
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/cli/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,gCAAgC,CAAC;KAC7C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC;KAC/B,MAAM,CAAC,YAAY,EAAE,0BAA0B,CAAC;KAChD,MAAM,CAAC,KAAK,EAAE,OAAgD,EAAE,EAAE;IACjE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,mCAAmC,CAAC,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev-time decorator for providing test values.
|
|
3
|
+
* STRIPPED DURING BUILD - Never ships to production.
|
|
4
|
+
*/
|
|
5
|
+
export declare function TestValue(value: any): PropertyDecorator;
|
|
6
|
+
/**
|
|
7
|
+
* Extract test values from a handler class
|
|
8
|
+
*/
|
|
9
|
+
export declare function extractTestValues(handlerClass: any): Record<string, any>;
|
|
10
|
+
//# sourceMappingURL=decorators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/dev/decorators.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,GAAG,GAAG,iBAAiB,CAOvD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAYxE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev-time decorator for providing test values.
|
|
3
|
+
* STRIPPED DURING BUILD - Never ships to production.
|
|
4
|
+
*/
|
|
5
|
+
export function TestValue(value) {
|
|
6
|
+
return (target, propertyKey) => {
|
|
7
|
+
if (!target.constructor.__testValues) {
|
|
8
|
+
target.constructor.__testValues = {};
|
|
9
|
+
}
|
|
10
|
+
target.constructor.__testValues[propertyKey] = value;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Extract test values from a handler class
|
|
15
|
+
*/
|
|
16
|
+
export function extractTestValues(handlerClass) {
|
|
17
|
+
const testValues = handlerClass.__testValues || {};
|
|
18
|
+
return Object.fromEntries(Object.entries(testValues).map(([key, value]) => {
|
|
19
|
+
// Resolve functions
|
|
20
|
+
if (typeof value === 'function') {
|
|
21
|
+
return [key, value()];
|
|
22
|
+
}
|
|
23
|
+
return [key, value];
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=decorators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/dev/decorators.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAU;IAClC,OAAO,CAAC,MAAW,EAAE,WAA4B,EAAE,EAAE;QACnD,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;YACrC,MAAM,CAAC,WAAW,CAAC,YAAY,GAAG,EAAE,CAAC;QACvC,CAAC;QACD,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC;IACvD,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,YAAiB;IACjD,MAAM,UAAU,GAAG,YAAY,CAAC,YAAY,IAAI,EAAE,CAAC;IAEnD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QAC9C,oBAAoB;QACpB,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACtB,CAAC,CAAC,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ExecutionResult {
|
|
2
|
+
success: boolean;
|
|
3
|
+
duration: number;
|
|
4
|
+
output?: any;
|
|
5
|
+
error?: {
|
|
6
|
+
message: string;
|
|
7
|
+
stack?: string;
|
|
8
|
+
code?: string;
|
|
9
|
+
};
|
|
10
|
+
logs: string[];
|
|
11
|
+
timestamp: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ExecutionOptions {
|
|
14
|
+
inputs: Record<string, any>;
|
|
15
|
+
testValues: Record<string, any>;
|
|
16
|
+
timeout?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Execute a handler in a child process using tsx
|
|
20
|
+
*/
|
|
21
|
+
export declare function executeHandler(projectDir: string, options: ExecutionOptions): Promise<ExecutionResult>;
|
|
22
|
+
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/dev/executor.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,KAAK,CAAC,EAAE;QACN,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,CA0I1B"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as os from 'os';
|
|
5
|
+
/**
|
|
6
|
+
* Execute a handler in a child process using tsx
|
|
7
|
+
*/
|
|
8
|
+
export async function executeHandler(projectDir, options) {
|
|
9
|
+
const startTime = Date.now();
|
|
10
|
+
const logs = [];
|
|
11
|
+
// Create a temporary runner script
|
|
12
|
+
const runnerCode = generateRunnerScript(projectDir, options);
|
|
13
|
+
const tempDir = path.join(os.tmpdir(), 'afh-runner');
|
|
14
|
+
if (!fs.existsSync(tempDir)) {
|
|
15
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
const runnerId = `runner-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
18
|
+
const runnerPath = path.join(tempDir, `${runnerId}.ts`);
|
|
19
|
+
fs.writeFileSync(runnerPath, runnerCode);
|
|
20
|
+
return new Promise((resolve) => {
|
|
21
|
+
let stdout = '';
|
|
22
|
+
let stderr = '';
|
|
23
|
+
let timedOut = false;
|
|
24
|
+
const timeout = options.timeout || 30000;
|
|
25
|
+
// Run with tsx
|
|
26
|
+
const child = spawn('npx', ['tsx', runnerPath], {
|
|
27
|
+
cwd: projectDir,
|
|
28
|
+
env: {
|
|
29
|
+
...process.env,
|
|
30
|
+
// Pass test values as env vars
|
|
31
|
+
AFH_TEST_VALUES: JSON.stringify(options.testValues),
|
|
32
|
+
AFH_INPUTS: JSON.stringify(options.inputs),
|
|
33
|
+
},
|
|
34
|
+
shell: true,
|
|
35
|
+
});
|
|
36
|
+
const timeoutId = setTimeout(() => {
|
|
37
|
+
timedOut = true;
|
|
38
|
+
child.kill('SIGTERM');
|
|
39
|
+
}, timeout);
|
|
40
|
+
child.stdout?.on('data', (data) => {
|
|
41
|
+
const text = data.toString();
|
|
42
|
+
stdout += text;
|
|
43
|
+
// Collect console.log output
|
|
44
|
+
text.split('\n').filter(Boolean).forEach(line => {
|
|
45
|
+
if (!line.startsWith('__AFH_RESULT__:')) {
|
|
46
|
+
logs.push(line);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
child.stderr?.on('data', (data) => {
|
|
51
|
+
stderr += data.toString();
|
|
52
|
+
});
|
|
53
|
+
child.on('close', (code) => {
|
|
54
|
+
clearTimeout(timeoutId);
|
|
55
|
+
// Clean up temp file
|
|
56
|
+
try {
|
|
57
|
+
fs.unlinkSync(runnerPath);
|
|
58
|
+
}
|
|
59
|
+
catch { }
|
|
60
|
+
const duration = Date.now() - startTime;
|
|
61
|
+
if (timedOut) {
|
|
62
|
+
resolve({
|
|
63
|
+
success: false,
|
|
64
|
+
duration,
|
|
65
|
+
error: {
|
|
66
|
+
message: `Execution timed out after ${timeout}ms`,
|
|
67
|
+
code: 'TIMEOUT'
|
|
68
|
+
},
|
|
69
|
+
logs,
|
|
70
|
+
timestamp: new Date().toISOString()
|
|
71
|
+
});
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Parse the result from stdout
|
|
75
|
+
const resultMatch = stdout.match(/__AFH_RESULT__:(.+)$/m);
|
|
76
|
+
if (resultMatch) {
|
|
77
|
+
try {
|
|
78
|
+
const result = JSON.parse(resultMatch[1]);
|
|
79
|
+
resolve({
|
|
80
|
+
success: result.success !== false,
|
|
81
|
+
duration,
|
|
82
|
+
output: result.output || result,
|
|
83
|
+
error: result.error,
|
|
84
|
+
logs,
|
|
85
|
+
timestamp: new Date().toISOString()
|
|
86
|
+
});
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
// Fall through to error handling
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (code !== 0 || stderr) {
|
|
94
|
+
resolve({
|
|
95
|
+
success: false,
|
|
96
|
+
duration,
|
|
97
|
+
error: {
|
|
98
|
+
message: stderr || `Process exited with code ${code}`,
|
|
99
|
+
code: code?.toString()
|
|
100
|
+
},
|
|
101
|
+
logs,
|
|
102
|
+
timestamp: new Date().toISOString()
|
|
103
|
+
});
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
resolve({
|
|
107
|
+
success: true,
|
|
108
|
+
duration,
|
|
109
|
+
output: { raw: stdout },
|
|
110
|
+
logs,
|
|
111
|
+
timestamp: new Date().toISOString()
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
child.on('error', (err) => {
|
|
115
|
+
clearTimeout(timeoutId);
|
|
116
|
+
resolve({
|
|
117
|
+
success: false,
|
|
118
|
+
duration: Date.now() - startTime,
|
|
119
|
+
error: {
|
|
120
|
+
message: err.message,
|
|
121
|
+
stack: err.stack
|
|
122
|
+
},
|
|
123
|
+
logs,
|
|
124
|
+
timestamp: new Date().toISOString()
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Generate a runner script that executes the handler
|
|
131
|
+
*/
|
|
132
|
+
function generateRunnerScript(projectDir, options) {
|
|
133
|
+
const srcPath = path.join(projectDir, 'src', 'index.ts');
|
|
134
|
+
// Use forward slashes for imports even on Windows
|
|
135
|
+
const importPath = srcPath.replace(/\\/g, '/');
|
|
136
|
+
return `
|
|
137
|
+
// Auto-generated runner script for AFH dev server
|
|
138
|
+
import handler from '${importPath}';
|
|
139
|
+
|
|
140
|
+
const testValues = JSON.parse(process.env.AFH_TEST_VALUES || '{}');
|
|
141
|
+
const inputs = JSON.parse(process.env.AFH_INPUTS || '{}');
|
|
142
|
+
|
|
143
|
+
// Mock CheckpointManager for stateful handlers
|
|
144
|
+
class MockCheckpointManager {
|
|
145
|
+
private data: any = null;
|
|
146
|
+
|
|
147
|
+
async save(instanceId: string, data: any): Promise<void> {
|
|
148
|
+
this.data = { data, savedAt: Date.now(), instanceId };
|
|
149
|
+
console.log('[checkpoint:save]', JSON.stringify(data));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async load(jobId: string): Promise<any> {
|
|
153
|
+
return this.data;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async clear(jobId: string): Promise<void> {
|
|
157
|
+
this.data = null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Mock StatefulHandlerContext
|
|
162
|
+
function createMockContext() {
|
|
163
|
+
const checkpointManager = new MockCheckpointManager();
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
// Base HandlerContext properties
|
|
167
|
+
executionId: 'dev-execution-' + Date.now(),
|
|
168
|
+
stepId: 'dev-step-1',
|
|
169
|
+
flowId: 'dev-flow',
|
|
170
|
+
attempt: 1,
|
|
171
|
+
maxAttempts: 3,
|
|
172
|
+
context: {},
|
|
173
|
+
vault: {
|
|
174
|
+
get: async (path: string) => {
|
|
175
|
+
console.log('[vault:get]', path);
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
// StatefulHandlerContext properties
|
|
181
|
+
checkpoints: checkpointManager,
|
|
182
|
+
instanceId: 'dev-instance-' + Date.now(),
|
|
183
|
+
jobId: 'dev-job-' + Date.now(),
|
|
184
|
+
isActive: async () => true,
|
|
185
|
+
updateProgress: async (percent: number, message?: string) => {
|
|
186
|
+
console.log('[progress]', percent + '%', message || '');
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async function run() {
|
|
192
|
+
try {
|
|
193
|
+
const instance = handler as any;
|
|
194
|
+
|
|
195
|
+
// Inject mock _context for stateful handlers
|
|
196
|
+
// This is what the engine would normally do
|
|
197
|
+
instance._context = createMockContext();
|
|
198
|
+
|
|
199
|
+
// Apply test values first (as defaults)
|
|
200
|
+
for (const [key, value] of Object.entries(testValues)) {
|
|
201
|
+
if (key in instance) {
|
|
202
|
+
instance[key] = value;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Apply inputs (override test values)
|
|
207
|
+
for (const [key, value] of Object.entries(inputs)) {
|
|
208
|
+
if (value !== undefined && value !== '') {
|
|
209
|
+
instance[key] = value;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Execute the handler
|
|
214
|
+
const result = await instance.execute();
|
|
215
|
+
|
|
216
|
+
// Output the result in a parseable format
|
|
217
|
+
console.log('__AFH_RESULT__:' + JSON.stringify({
|
|
218
|
+
success: result?.outcome !== 'failure',
|
|
219
|
+
output: result?.output || result,
|
|
220
|
+
error: result?.outcome === 'failure' ? {
|
|
221
|
+
code: result.error?.code,
|
|
222
|
+
message: result.error?.message,
|
|
223
|
+
details: result.error?.details
|
|
224
|
+
} : undefined
|
|
225
|
+
}));
|
|
226
|
+
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.log('__AFH_RESULT__:' + JSON.stringify({
|
|
229
|
+
success: false,
|
|
230
|
+
error: {
|
|
231
|
+
code: 'EXECUTION_ERROR',
|
|
232
|
+
message: error instanceof Error ? error.message : String(error),
|
|
233
|
+
details: { stack: error instanceof Error ? error.stack : undefined }
|
|
234
|
+
}
|
|
235
|
+
}));
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
run();
|
|
241
|
+
`;
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/dev/executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAqBzB;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,UAAkB,EAClB,OAAyB;IAEzB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,mCAAmC;IACnC,MAAM,UAAU,GAAG,oBAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC;IAErD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,QAAQ,KAAK,CAAC,CAAC;IAExD,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAEzC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC;QAEzC,eAAe;QACf,MAAM,KAAK,GAAiB,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE;YAC5D,GAAG,EAAE,UAAU;YACf,GAAG,EAAE;gBACH,GAAG,OAAO,CAAC,GAAG;gBACd,+BAA+B;gBAC/B,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC;gBACnD,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC;aAC3C;YACD,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAChC,QAAQ,GAAG,IAAI,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC,EAAE,OAAO,CAAC,CAAC;QAEZ,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YACxC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC7B,MAAM,IAAI,IAAI,CAAC;YACf,6BAA6B;YAC7B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;gBAC9C,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;oBACxC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClB,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YACxC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAmB,EAAE,EAAE;YACxC,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,qBAAqB;YACrB,IAAI,CAAC;gBACH,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;YAC5B,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YAEV,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAExC,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC;oBACN,OAAO,EAAE,KAAK;oBACd,QAAQ;oBACR,KAAK,EAAE;wBACL,OAAO,EAAE,6BAA6B,OAAO,IAAI;wBACjD,IAAI,EAAE,SAAS;qBAChB;oBACD,IAAI;oBACJ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACpC,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,+BAA+B;YAC/B,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAE1D,IAAI,WAAW,EAAE,CAAC;gBAChB,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC1C,OAAO,CAAC;wBACN,OAAO,EAAE,MAAM,CAAC,OAAO,KAAK,KAAK;wBACjC,QAAQ;wBACR,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM;wBAC/B,KAAK,EAAE,MAAM,CAAC,KAAK;wBACnB,IAAI;wBACJ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;qBACpC,CAAC,CAAC;oBACH,OAAO;gBACT,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,iCAAiC;gBACnC,CAAC;YACH,CAAC;YAED,IAAI,IAAI,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;gBACzB,OAAO,CAAC;oBACN,OAAO,EAAE,KAAK;oBACd,QAAQ;oBACR,KAAK,EAAE;wBACL,OAAO,EAAE,MAAM,IAAI,4BAA4B,IAAI,EAAE;wBACrD,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE;qBACvB;oBACD,IAAI;oBACJ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACpC,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,OAAO,CAAC;gBACN,OAAO,EAAE,IAAI;gBACb,QAAQ;gBACR,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE;gBACvB,IAAI;gBACJ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;YAC/B,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,OAAO,CAAC;gBACN,OAAO,EAAE,KAAK;gBACd,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;gBAChC,KAAK,EAAE;oBACL,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,KAAK,EAAE,GAAG,CAAC,KAAK;iBACjB;gBACD,IAAI;gBACJ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,UAAkB,EAAE,OAAyB;IACzE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IAEzD,kDAAkD;IAClD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAE/C,OAAO;;uBAEc,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuGhC,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract @TestValue decorator values from handler source code
|
|
3
|
+
* This uses regex-based parsing for simplicity - a proper implementation
|
|
4
|
+
* would use TypeScript Compiler API
|
|
5
|
+
*/
|
|
6
|
+
export declare function extractTestValuesFromSource(sourcePath: string): Record<string, any>;
|
|
7
|
+
/**
|
|
8
|
+
* Extract handler metadata from source
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractHandlerMetadata(sourcePath: string): Record<string, any>;
|
|
11
|
+
/**
|
|
12
|
+
* Extract @Input decorator metadata
|
|
13
|
+
*/
|
|
14
|
+
export declare function extractInputMetadata(sourcePath: string): Record<string, Record<string, any>>;
|
|
15
|
+
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/dev/extractor.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA4BnF;AAqED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAiC9E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAkG5F"}
|