@hi-man/himan 0.1.0 → 0.2.2

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.
@@ -0,0 +1,104 @@
1
+ import { HimanError, errorCodes } from "../utils/errors.js";
2
+ import { getSupportedAgentNames, normalizeAgent } from "../utils/agent-configs.js";
3
+ import { runAction } from "./shared.js";
4
+ export function registerResourceCommands(command, services) {
5
+ command
6
+ .command("list")
7
+ .argument("[type]", "resource type", "rule")
8
+ .option("--agent <list>", "agent list filter, comma separated")
9
+ .option("--json", "output json format")
10
+ .description("List resources from current default source")
11
+ .action(async (type, options) => {
12
+ await runAction(async () => {
13
+ const resourceType = ensureResourceType(type);
14
+ const resources = await services.list(resourceType, parseAgents(options.agent));
15
+ if (options.json) {
16
+ process.stdout.write(`${JSON.stringify(resources, null, 2)}\n`);
17
+ return;
18
+ }
19
+ if (resources.length === 0) {
20
+ process.stdout.write("No resources found.\n");
21
+ return;
22
+ }
23
+ for (const resource of resources) {
24
+ process.stdout.write(`- ${resource.type}/${resource.name}${resource.description ? `: ${resource.description}` : ""}\n`);
25
+ }
26
+ });
27
+ });
28
+ command
29
+ .command("history")
30
+ .argument("<type>", "resource type")
31
+ .argument("<name>", "resource name")
32
+ .option("--json", "output json format")
33
+ .description("Show resource history")
34
+ .action(async (type, name, options) => {
35
+ await runAction(async () => {
36
+ const resourceType = ensureResourceType(type);
37
+ const versions = await services.history(resourceType, name);
38
+ if (options.json) {
39
+ process.stdout.write(`${JSON.stringify(versions, null, 2)}\n`);
40
+ return;
41
+ }
42
+ if (versions.length === 0) {
43
+ process.stdout.write(`No history found for ${resourceType}/${name}.\n`);
44
+ return;
45
+ }
46
+ for (const version of versions) {
47
+ process.stdout.write(`- ${version.raw}\n`);
48
+ }
49
+ });
50
+ });
51
+ command
52
+ .command("create")
53
+ .argument("<type>", "resource type")
54
+ .argument("<name>", "resource name")
55
+ .option("--description <text>", "resource description")
56
+ .option("--agent <list>", "agent list, comma separated")
57
+ .option("--entry <file>", "entry file name")
58
+ .option("--template <name>", "template name", "basic")
59
+ .option("--force", "overwrite existing resource")
60
+ .option("--dry-run", "show files without writing")
61
+ .option("--json", "output json format")
62
+ .description("Create resource scaffold")
63
+ .action(async (type, name, options) => {
64
+ await runAction(async () => {
65
+ const resourceType = ensureResourceType(type);
66
+ const result = await services.create(resourceType, name, {
67
+ description: options.description,
68
+ agents: parseAgents(options.agent),
69
+ entry: options.entry,
70
+ template: options.template,
71
+ force: options.force,
72
+ dryRun: options.dryRun,
73
+ }, process.cwd());
74
+ if (options.json) {
75
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
76
+ return;
77
+ }
78
+ process.stdout.write(`Created ${result.type}/${result.name} at ${result.resourceDir}${result.dryRun ? " (dry-run)" : ""}\n`);
79
+ });
80
+ });
81
+ }
82
+ function ensureResourceType(type) {
83
+ if (type !== "rule" && type !== "command" && type !== "skill") {
84
+ throw new HimanError(errorCodes.UNSUPPORTED_RESOURCE_TYPE, `Unsupported resource type: ${type}`);
85
+ }
86
+ return type;
87
+ }
88
+ function parseAgents(input) {
89
+ if (!input)
90
+ return undefined;
91
+ const agents = input
92
+ .split(",")
93
+ .map((item) => item.trim())
94
+ .filter(Boolean);
95
+ if (agents.length === 0)
96
+ return undefined;
97
+ const supported = getSupportedAgentNames();
98
+ for (const agent of agents) {
99
+ if (!normalizeAgent(agent)) {
100
+ throw new HimanError(errorCodes.INVALID_INPUT, `Unsupported agent: ${agent}. Supported agents: ${supported.join(", ")}`);
101
+ }
102
+ }
103
+ return agents;
104
+ }
@@ -0,0 +1,69 @@
1
+ import { Command, CommanderError } from "commander";
2
+ import { errorCodes, HimanError } from "../utils/errors.js";
3
+ import { PACKAGE_VERSION } from "../utils/version.js";
4
+ export function createBaseProgram(name, description) {
5
+ const program = new Command();
6
+ program.exitOverride();
7
+ program.configureOutput({
8
+ writeOut: (str) => {
9
+ process.stdout.write(str);
10
+ },
11
+ writeErr: () => {
12
+ // Parse/usage errors are unified by writeCliError().
13
+ },
14
+ });
15
+ program.name(name).description(description).version(PACKAGE_VERSION);
16
+ return program;
17
+ }
18
+ export async function runAction(action) {
19
+ try {
20
+ await action();
21
+ }
22
+ catch (error) {
23
+ writeCliError(error);
24
+ process.exitCode = 1;
25
+ }
26
+ }
27
+ export function writeCliError(error) {
28
+ const payload = toCliErrorPayload(error);
29
+ if (shouldOutputJsonError()) {
30
+ process.stderr.write(`${JSON.stringify(payload, null, 2)}\n`);
31
+ return;
32
+ }
33
+ process.stderr.write(`[${payload.error.code}] ${payload.error.message}\n`);
34
+ }
35
+ function toCliErrorPayload(error) {
36
+ if (error instanceof CommanderError) {
37
+ return {
38
+ ok: false,
39
+ error: {
40
+ code: errorCodes.CLI_USAGE,
41
+ message: error.message,
42
+ details: {
43
+ commanderCode: error.code,
44
+ exitCode: error.exitCode,
45
+ },
46
+ },
47
+ };
48
+ }
49
+ if (error instanceof HimanError) {
50
+ return {
51
+ ok: false,
52
+ error: {
53
+ code: error.code,
54
+ message: error.message,
55
+ details: error.details,
56
+ },
57
+ };
58
+ }
59
+ return {
60
+ ok: false,
61
+ error: {
62
+ code: "E_UNKNOWN",
63
+ message: error instanceof Error ? error.message : String(error),
64
+ },
65
+ };
66
+ }
67
+ function shouldOutputJsonError() {
68
+ return process.argv.includes("--json");
69
+ }
@@ -0,0 +1,58 @@
1
+ import { runAction } from "./shared.js";
2
+ export function registerInitCommand(command, services) {
3
+ command
4
+ .command("init")
5
+ .argument("<git_repo>", "Git repository URL")
6
+ .action(async (gitRepo) => {
7
+ await runAction(async () => {
8
+ const result = await services.initSource("git", gitRepo);
9
+ process.stdout.write(`Initialized ${result.sourceType} source: ${result.repo}\n`);
10
+ });
11
+ });
12
+ }
13
+ export function registerSourceCommands(command, services, options) {
14
+ if (options?.includeInit) {
15
+ registerInitCommand(command, services);
16
+ }
17
+ command
18
+ .command("add")
19
+ .argument("<name>", "source name (kebab-case)")
20
+ .argument("<git_repo>", "Git repository URL")
21
+ .description("Add a named git source")
22
+ .action(async (name, gitRepo) => {
23
+ await runAction(async () => {
24
+ const result = await services.addSource(name, "git", gitRepo);
25
+ process.stdout.write(`Added source ${result.name}: ${result.type}${result.repo ? ` ${result.repo}` : ""}\n`);
26
+ });
27
+ });
28
+ command
29
+ .command("use")
30
+ .argument("<name>", "source name")
31
+ .description("Switch default source")
32
+ .action(async (name) => {
33
+ await runAction(async () => {
34
+ const result = await services.useSource(name);
35
+ process.stdout.write(`Using source: ${result.name}\n`);
36
+ });
37
+ });
38
+ command
39
+ .command("list")
40
+ .option("--json", "output json format")
41
+ .description("List configured sources and current default")
42
+ .action(async (options) => {
43
+ await runAction(async () => {
44
+ const sources = await services.listSources();
45
+ if (options.json) {
46
+ process.stdout.write(`${JSON.stringify(sources, null, 2)}\n`);
47
+ return;
48
+ }
49
+ if (sources.length === 0) {
50
+ process.stdout.write("No sources configured.\n");
51
+ return;
52
+ }
53
+ for (const source of sources) {
54
+ process.stdout.write(`- ${source.name}${source.isDefault ? " (default)" : ""}: ${source.type}${source.repo ? ` ${source.repo}` : ""}\n`);
55
+ }
56
+ });
57
+ });
58
+ }