feat: introduce archify skill for generating architecture diagrams

- Added a new Archify skill, enabling users to create polished architecture, workflow, sequence, data-flow, and lifecycle diagrams.
- Implemented comprehensive functionality including rendering, validation, and delivery of diagrams in various formats.
- Integrated a user-friendly command-line interface for generating and previewing diagrams.
- Developed supporting files including package.json, LICENSE, and SKILL.md for documentation and licensing.
- Added unit tests to ensure reliability and functionality of the new skill.

These changes enhance the application by providing a structured approach to visualizing system architecture and workflows, improving user experience and data representation.
This commit is contained in:
shancheas
2026-08-31 11:31:29 +07:00
parent 050fafd731
commit 166e0d40ac
221 changed files with 191228 additions and 1 deletions
@@ -0,0 +1,86 @@
import { spawnSync } from 'node:child_process';
import path from 'node:path';
const OPENERS = {
darwin: {
command: 'open',
method: 'open',
args: (target) => [target],
},
linux: {
command: 'xdg-open',
method: 'xdg-open',
args: (target) => [target],
},
win32: {
command: 'powershell.exe',
method: 'powershell',
// Keep the command constant and pass the target through PowerShell's
// argument array. Paths are never interpolated into executable source.
args: (target) => [
'-NoProfile',
'-NonInteractive',
'-Command',
'Start-Process -FilePath $args[0]',
target,
],
},
};
function launchTarget(target, options = {}) {
const platform = options.platform || process.platform;
const opener = OPENERS[platform];
if (!opener) {
return {
requested: true,
status: 'unsupported',
target,
method: null,
};
}
const spawn = options.spawn || spawnSync;
let result;
try {
result = spawn(opener.command, opener.args(target), {
encoding: 'utf8',
shell: false,
stdio: 'ignore',
timeout: options.timeoutMs || 5000,
windowsHide: true,
});
} catch {
result = { error: new Error('opener threw') };
}
let status = 'opened';
if (result?.error?.code === 'ENOENT') status = 'unsupported';
else if (result?.error || result?.signal || result?.status !== 0) status = 'failed';
return {
requested: true,
status,
target,
method: opener.method,
};
}
export function openArtifact(target, options = {}) {
return launchTarget(path.resolve(target), options);
}
export function openLoopbackUrl(target, options = {}) {
let url;
try {
url = new URL(target);
} catch {
throw new TypeError('Preview URL must be a valid loopback HTTP URL.');
}
if (url.protocol !== 'http:' || url.hostname !== '127.0.0.1' || !url.port) {
throw new TypeError('Preview URL must be a loopback URL using http://127.0.0.1:<port>.');
}
if (url.username || url.password || url.pathname !== '/' || url.search || url.hash) {
throw new TypeError('Preview URL must target the loopback preview root.');
}
return launchTarget(url.href, options);
}