@nextclaw/aigen 0.1.0-beta.0 → 0.1.0-beta.1
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/dist/app/main.js +9 -2
- package/dist/app/main.js.map +1 -1
- package/package.json +1 -1
package/dist/app/main.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
2
3
|
import { Command, CommanderError, InvalidArgumentError } from "commander";
|
|
3
4
|
import { chmod, mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
4
5
|
import { basename, join, resolve } from "node:path";
|
|
@@ -882,12 +883,13 @@ const toCommandFailure = (error) => {
|
|
|
882
883
|
//#endregion
|
|
883
884
|
//#region src/app/aigen-app.ts
|
|
884
885
|
var AigenApp = class {
|
|
885
|
-
constructor(imageController, providersController, modelsController, secretsController, doctorController) {
|
|
886
|
+
constructor(imageController, providersController, modelsController, secretsController, doctorController, version = resolveAigenPackageVersion()) {
|
|
886
887
|
this.imageController = imageController;
|
|
887
888
|
this.providersController = providersController;
|
|
888
889
|
this.modelsController = modelsController;
|
|
889
890
|
this.secretsController = secretsController;
|
|
890
891
|
this.doctorController = doctorController;
|
|
892
|
+
this.version = version;
|
|
891
893
|
}
|
|
892
894
|
run = async (argv) => {
|
|
893
895
|
let commandOutput;
|
|
@@ -918,7 +920,7 @@ var AigenApp = class {
|
|
|
918
920
|
};
|
|
919
921
|
createProgram = (sink) => {
|
|
920
922
|
const program = new Command();
|
|
921
|
-
program.name("aigen").description("Stateless AI media generation CLI.").version(
|
|
923
|
+
program.name("aigen").description("Stateless AI media generation CLI.").version(this.version, "-v, --version");
|
|
922
924
|
program.exitOverride();
|
|
923
925
|
program.showHelpAfterError();
|
|
924
926
|
registerAigenCommands(program, {
|
|
@@ -952,6 +954,11 @@ const createAigenApp = (homeDir) => {
|
|
|
952
954
|
const providerRuntimeManager = new ProviderRuntimeManager([new OpenRouterProvider()]);
|
|
953
955
|
return new AigenApp(new ImageController(new ImageGenerationManager(configRepository, secretsRepository, providerRuntimeManager, new OutputFileManager())), new ProvidersController(configRepository), new ModelsController(configRepository, secretsRepository, providerRuntimeManager), new SecretsController(secretsRepository), new DoctorController(configRepository, secretsRepository, providerRuntimeManager));
|
|
954
956
|
};
|
|
957
|
+
const resolveAigenPackageVersion = () => {
|
|
958
|
+
const packageJsonUrl = new URL("../../package.json", import.meta.url);
|
|
959
|
+
const packageJson = JSON.parse(readFileSync(packageJsonUrl, "utf8"));
|
|
960
|
+
return typeof packageJson.version === "string" ? packageJson.version : "0.0.0";
|
|
961
|
+
};
|
|
955
962
|
//#endregion
|
|
956
963
|
//#region src/app/main.ts
|
|
957
964
|
const output = await createAigenApp().run(process.argv.slice(2));
|
package/dist/app/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","names":[],"sources":["../../src/types/cli-output.types.ts","../../src/utils/route.utils.ts","../../src/controllers/doctor.controller.ts","../../src/controllers/image.controller.ts","../../src/controllers/models.controller.ts","../../src/controllers/providers.controller.ts","../../src/controllers/secrets.controller.ts","../../src/app/register-aigen-commands.ts","../../src/managers/image-generation.manager.ts","../../src/utils/mime.utils.ts","../../src/managers/output-file.manager.ts","../../src/types/provider.types.ts","../../src/managers/provider-runtime.manager.ts","../../src/utils/data-url.utils.ts","../../src/providers/openrouter.provider.ts","../../src/types/config.types.ts","../../src/repositories/config.repository.ts","../../src/repositories/secrets.repository.ts","../../src/utils/error.utils.ts","../../src/app/aigen-app.ts","../../src/app/main.ts"],"sourcesContent":["export type AigenErrorCode =\n | \"CONFIG_NOT_FOUND\"\n | \"CONFIG_INVALID\"\n | \"PROVIDER_NOT_FOUND\"\n | \"MODEL_NOT_FOUND\"\n | \"SECRET_NOT_FOUND\"\n | \"MISSING_API_KEY\"\n | \"PROVIDER_RUNTIME_NOT_FOUND\"\n | \"PROVIDER_REQUEST_FAILED\"\n | \"UNSUPPORTED_PARAMETER\"\n | \"INVALID_ARGUMENT\"\n | \"FILE_WRITE_FAILED\";\n\nexport type AigenCommandError = {\n code: AigenErrorCode;\n message: string;\n retryable?: boolean;\n};\n\nexport type AigenCommandSuccess<TData extends Record<string, unknown> = Record<string, unknown>> = {\n ok: true;\n} & TData;\n\nexport type AigenCommandFailure = {\n ok: false;\n error: AigenCommandError;\n};\n\nexport type AigenCommandOutput<TData extends Record<string, unknown> = Record<string, unknown>> =\n | AigenCommandSuccess<TData>\n | AigenCommandFailure;\n\nexport class AigenError extends Error {\n readonly code: AigenErrorCode;\n readonly retryable: boolean;\n\n constructor(code: AigenErrorCode, message: string, options?: { retryable?: boolean }) {\n super(message);\n this.name = \"AigenError\";\n this.code = code;\n this.retryable = options?.retryable ?? false;\n }\n}\n","import { AigenError } from \"@/types/cli-output.types.js\";\n\nexport type AigenModelRoute = {\n providerId: string;\n providerLocalModel: string;\n};\n\nexport const parseModelRoute = (route: string): AigenModelRoute => {\n const slashIndex = route.indexOf(\"/\");\n\n if (slashIndex <= 0 || slashIndex === route.length - 1) {\n throw new AigenError(\n \"INVALID_ARGUMENT\",\n \"Model route must use <provider-id>/<provider-local-model>.\",\n );\n }\n\n return {\n providerId: route.slice(0, slashIndex),\n providerLocalModel: route.slice(slashIndex + 1)\n };\n};\n\nexport const assertResourceId = (id: string, label: string): void => {\n if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(id)) {\n throw new AigenError(\"INVALID_ARGUMENT\", `${label} must be a stable resource id.`);\n }\n};\n","import type { ConfigRepository } from \"@/repositories/config.repository.js\";\nimport type { SecretsRepository } from \"@/repositories/secrets.repository.js\";\nimport type { AigenCommandOutput } from \"@/types/cli-output.types.js\";\nimport { parseModelRoute } from \"@/utils/route.utils.js\";\nimport type { ProviderRuntimeManager } from \"@/managers/provider-runtime.manager.js\";\n\nexport type DoctorRunOptions = {\n provider?: string;\n model?: string;\n};\n\ntype DoctorCheck = {\n name: string;\n ok: boolean;\n};\n\nexport class DoctorController {\n constructor(\n private readonly configRepository: ConfigRepository,\n private readonly secretsRepository: SecretsRepository,\n private readonly providerRuntimeManager: ProviderRuntimeManager,\n ) {}\n\n run = async (options: DoctorRunOptions): Promise<AigenCommandOutput> => {\n const { provider, model } = options;\n const checks: DoctorCheck[] = [];\n const config = await this.configRepository.readConfig();\n\n checks.push({ name: \"config\", ok: true });\n\n if (provider) {\n await this.checkProvider(provider, checks);\n }\n\n if (model) {\n const route = parseModelRoute(model);\n await this.configRepository.getModel(route.providerId, route.providerLocalModel);\n await this.checkProvider(route.providerId, checks);\n checks.push({ name: \"model\", ok: true });\n }\n\n return {\n ok: true,\n providerCount: Object.keys(config.providers).length,\n checks\n };\n };\n\n private checkProvider = async (providerId: string, checks: DoctorCheck[]): Promise<void> => {\n const providerConfig = await this.configRepository.getProvider(providerId);\n this.providerRuntimeManager.getImageProvider(providerConfig.apiFormat);\n checks.push({ name: \"provider\", ok: true });\n await this.secretsRepository.getProviderSecret(providerId);\n checks.push({ name: \"secret\", ok: true });\n };\n}\n","import type { ImageGenerationManager } from \"@/managers/image-generation.manager.js\";\nimport type { AigenCommandOutput } from \"@/types/cli-output.types.js\";\nimport type { AigenImageInput } from \"@/types/image-generation.types.js\";\n\nexport type ImageGenerateOptions = AigenImageInput;\n\nexport class ImageController {\n constructor(private readonly imageGenerationManager: ImageGenerationManager) {}\n\n generate = async (options: ImageGenerateOptions): Promise<AigenCommandOutput> =>\n this.imageGenerationManager.generate(options);\n}\n","import type { ConfigRepository } from \"@/repositories/config.repository.js\";\nimport type { SecretsRepository } from \"@/repositories/secrets.repository.js\";\nimport { AigenError, type AigenCommandOutput } from \"@/types/cli-output.types.js\";\nimport type { AigenMediaKind, AigenModelCapabilities, AigenModelConfig } from \"@/types/config.types.js\";\nimport { parseModelRoute } from \"@/utils/route.utils.js\";\nimport type { ProviderRuntimeManager } from \"@/managers/provider-runtime.manager.js\";\n\nexport type ModelListOptions = {\n remote?: boolean;\n provider?: string;\n kind?: AigenMediaKind;\n};\n\nexport type ModelWriteOptions = {\n kind?: AigenMediaKind;\n displayName?: string;\n maxCount?: number;\n generate?: boolean;\n edit?: boolean;\n};\n\nexport class ModelsController {\n constructor(\n private readonly configRepository: ConfigRepository,\n private readonly secretsRepository: SecretsRepository,\n private readonly providerRuntimeManager: ProviderRuntimeManager,\n ) {}\n\n list = async (options: ModelListOptions): Promise<AigenCommandOutput> =>\n options.remote ? this.listRemote(options) : this.listLocal(options);\n\n private listLocal = async (options: ModelListOptions): Promise<AigenCommandOutput> => {\n const models = await this.configRepository.listModels(options.provider, options.kind);\n\n return {\n ok: true,\n models: models.map((model) => ({\n route: model.route,\n provider: model.providerId,\n providerLocalModel: model.providerLocalModel,\n kind: model.config.kind,\n displayName: model.config.displayName,\n capabilities: model.config.capabilities\n }))\n };\n };\n\n private listRemote = async (options: ModelListOptions): Promise<AigenCommandOutput> => {\n if (!options.provider) {\n throw new AigenError(\"INVALID_ARGUMENT\", \"Missing required --provider for remote model listing.\");\n }\n\n const providerId = options.provider;\n const providerConfig = await this.configRepository.getProvider(providerId);\n const provider = this.providerRuntimeManager.getRemoteModelListProvider(providerConfig.apiFormat);\n const apiKey = await this.secretsRepository.getProviderApiKey(providerId);\n const result = await provider.listRemoteModels(\n {\n kind: options.kind\n },\n {\n providerId,\n apiFormat: providerConfig.apiFormat,\n apiBase: providerConfig.apiBase,\n apiKey,\n headers: providerConfig.headers\n },\n );\n\n return {\n ok: true,\n models: result.models.map((model) => ({\n route: `${providerId}/${model.providerLocalModel}`,\n provider: providerId,\n apiFormat: providerConfig.apiFormat,\n providerLocalModel: model.providerLocalModel,\n kind: \"image\",\n displayName: model.displayName,\n inputModalities: model.inputModalities,\n outputModalities: model.outputModalities,\n pricing: model.pricing,\n metadata: model.metadata\n })),\n metadata: result.metadata\n };\n };\n\n get = async (modelRoute: string): Promise<AigenCommandOutput> => {\n const route = parseModelRoute(modelRoute);\n const modelConfig = await this.configRepository.getModel(route.providerId, route.providerLocalModel);\n\n return {\n ok: true,\n model: {\n route: modelRoute,\n provider: route.providerId,\n providerLocalModel: route.providerLocalModel,\n kind: modelConfig.kind,\n displayName: modelConfig.displayName,\n capabilities: modelConfig.capabilities\n }\n };\n };\n\n add = async (modelRoute: string, options: ModelWriteOptions): Promise<AigenCommandOutput> => {\n const route = parseModelRoute(modelRoute);\n const modelConfig = this.fullModelConfigFromOptions(options);\n await this.configRepository.addModel(route.providerId, route.providerLocalModel, modelConfig);\n\n return {\n ok: true,\n model: {\n route: modelRoute,\n provider: route.providerId,\n providerLocalModel: route.providerLocalModel,\n ...modelConfig\n }\n };\n };\n\n update = async (modelRoute: string, options: ModelWriteOptions): Promise<AigenCommandOutput> => {\n const route = parseModelRoute(modelRoute);\n const modelConfig = await this.configRepository.updateModel(\n route.providerId,\n route.providerLocalModel,\n this.modelConfigFromOptions(options),\n );\n\n return {\n ok: true,\n model: {\n route: modelRoute,\n provider: route.providerId,\n providerLocalModel: route.providerLocalModel,\n ...modelConfig\n }\n };\n };\n\n remove = async (modelRoute: string): Promise<AigenCommandOutput> => {\n const route = parseModelRoute(modelRoute);\n await this.configRepository.removeModel(route.providerId, route.providerLocalModel);\n\n return {\n ok: true,\n removed: true,\n model: modelRoute\n };\n };\n\n private fullModelConfigFromOptions = (options: ModelWriteOptions): AigenModelConfig => {\n return {\n kind: options.kind ?? \"image\",\n displayName: options.displayName,\n capabilities: this.capabilitiesFromOptions(options)\n };\n };\n\n private modelConfigFromOptions = (options: ModelWriteOptions): Partial<AigenModelConfig> => {\n return {\n kind: options.kind,\n displayName: options.displayName,\n capabilities: this.capabilitiesFromOptions(options)\n };\n };\n\n private capabilitiesFromOptions = (options: ModelWriteOptions): AigenModelCapabilities | undefined => {\n const maxCount = options.maxCount;\n const generate = options.generate ?? false;\n const edit = options.edit ?? false;\n\n if (maxCount === undefined && !generate && !edit) {\n return undefined;\n }\n\n return {\n generate: generate || undefined,\n edit: edit || undefined,\n maxCount\n };\n };\n}\n","import type { ConfigRepository } from \"@/repositories/config.repository.js\";\nimport type { AigenCommandOutput } from \"@/types/cli-output.types.js\";\nimport type { AigenProviderConfig } from \"@/types/config.types.js\";\n\nexport type ProviderAddOptions = {\n apiFormat: string;\n displayName?: string;\n apiBase?: string;\n};\n\nexport type ProviderUpdateOptions = Partial<ProviderAddOptions>;\n\nexport class ProvidersController {\n constructor(private readonly configRepository: ConfigRepository) {}\n\n list = async (): Promise<AigenCommandOutput> => {\n const providers = await this.configRepository.listProviders();\n return {\n ok: true,\n providers: providers.map(({ id, config }) => this.toProviderOutput(id, config))\n };\n };\n\n get = async (providerId: string): Promise<AigenCommandOutput> => ({\n ok: true,\n provider: this.toProviderOutput(providerId, await this.configRepository.getProvider(providerId))\n });\n\n add = async (providerId: string, options: ProviderAddOptions): Promise<AigenCommandOutput> => {\n const { apiFormat, displayName, apiBase } = options;\n const providerConfig: AigenProviderConfig = {\n apiFormat,\n displayName,\n apiKeyRef: `provider:${providerId}`,\n apiBase: apiBase ?? this.defaultApiBase(apiFormat),\n models: {}\n };\n\n await this.configRepository.addProvider(providerId, providerConfig);\n return {\n ok: true,\n provider: this.toProviderOutput(providerId, providerConfig)\n };\n };\n\n update = async (providerId: string, options: ProviderUpdateOptions): Promise<AigenCommandOutput> => {\n const { apiFormat, displayName, apiBase } = options;\n const providerConfig = await this.configRepository.updateProvider(providerId, {\n apiFormat,\n displayName,\n apiBase\n });\n\n return {\n ok: true,\n provider: this.toProviderOutput(providerId, providerConfig)\n };\n };\n\n remove = async (providerId: string): Promise<AigenCommandOutput> => {\n await this.configRepository.removeProvider(providerId);\n return {\n ok: true,\n removed: true,\n providerId\n };\n };\n\n private toProviderOutput = (providerId: string, config: AigenProviderConfig): Record<string, unknown> => ({\n id: providerId,\n apiFormat: config.apiFormat,\n displayName: config.displayName,\n apiBase: config.apiBase,\n apiKeyRef: config.apiKeyRef,\n modelCount: Object.keys(config.models).length\n });\n\n private defaultApiBase = (apiFormat: string): string => {\n if (apiFormat === \"openrouter\") {\n return \"https://openrouter.ai/api/v1\";\n }\n\n if (apiFormat === \"openai\") {\n return \"https://api.openai.com/v1\";\n }\n\n return \"\";\n };\n}\n","import type { SecretsRepository } from \"@/repositories/secrets.repository.js\";\nimport type { AigenCommandOutput } from \"@/types/cli-output.types.js\";\n\nexport class SecretsController {\n constructor(private readonly secretsRepository: SecretsRepository) {}\n\n list = async (): Promise<AigenCommandOutput> => ({\n ok: true,\n secrets: await this.secretsRepository.listSecrets()\n });\n\n get = async (providerId: string): Promise<AigenCommandOutput> => ({\n ok: true,\n secret: await this.secretsRepository.getProviderSecret(providerId)\n });\n\n set = async (providerId: string): Promise<AigenCommandOutput> => {\n const secret = await this.secretsRepository.setProviderApiKey(providerId, await this.readStdin());\n return {\n ok: true,\n secret\n };\n };\n\n remove = async (providerId: string): Promise<AigenCommandOutput> => {\n await this.secretsRepository.removeProviderSecret(providerId);\n return {\n ok: true,\n removed: true,\n providerId\n };\n };\n\n private readStdin = async (): Promise<string> =>\n new Promise((resolve, reject) => {\n let value = \"\";\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk) => {\n value += chunk;\n });\n process.stdin.on(\"end\", () => {\n resolve(value);\n });\n process.stdin.on(\"error\", reject);\n });\n}\n","import { InvalidArgumentError, type Command } from \"commander\";\nimport type { DoctorController } from \"@/controllers/doctor.controller.js\";\nimport type { ImageController } from \"@/controllers/image.controller.js\";\nimport type { ModelsController } from \"@/controllers/models.controller.js\";\nimport type { ProvidersController } from \"@/controllers/providers.controller.js\";\nimport type { SecretsController } from \"@/controllers/secrets.controller.js\";\nimport type { AigenCommandOutput } from \"@/types/cli-output.types.js\";\n\nexport type AigenCommandOutputSink = (output: AigenCommandOutput) => void;\n\nexport type AigenCommandControllers = {\n imageController: ImageController;\n providersController: ProvidersController;\n modelsController: ModelsController;\n secretsController: SecretsController;\n doctorController: DoctorController;\n};\n\nexport const registerAigenCommands = (\n program: Command,\n controllers: AigenCommandControllers,\n sink: AigenCommandOutputSink,\n): void => {\n registerImageCommand(program, controllers, sink);\n registerProvidersCommands(program, controllers, sink);\n registerModelsCommands(program, controllers, sink);\n registerSecretsCommands(program, controllers, sink);\n registerDoctorCommand(program, controllers, sink);\n};\n\nconst registerImageCommand = (\n program: Command,\n controllers: AigenCommandControllers,\n sink: AigenCommandOutputSink,\n): void => {\n withOutputOptions(\n program\n .command(\"image\")\n .description(\"Generate an image\")\n .requiredOption(\n \"--model <route>\",\n \"Model route in <provider-id>/<provider-local-model> format\",\n )\n .requiredOption(\"--prompt <text>\", \"Generation prompt\")\n .option(\"--size <size>\", \"Image size\")\n .option(\n \"--n <count>\",\n \"Number of images to generate\",\n parseNumberOption,\n 1,\n )\n .option(\"--quality <quality>\", \"Image quality\")\n .option(\"--background <background>\", \"Background mode\")\n .option(\"--output-format <format>\", \"Output format\")\n .option(\n \"--output-compression <value>\",\n \"Output compression\",\n parseNumberOption,\n )\n .option(\"--moderation <mode>\", \"Moderation mode\")\n .requiredOption(\"--output-dir <dir>\", \"Directory for generated assets\")\n .requiredOption(\"--output-name <name>\", \"Base output file name\"),\n ).action(async (options) => {\n sink(await controllers.imageController.generate(options));\n });\n};\n\nconst registerProvidersCommands = (\n program: Command,\n controllers: AigenCommandControllers,\n sink: AigenCommandOutputSink,\n): void => {\n const providers = program\n .command(\"providers\")\n .description(\"Manage image generation providers\");\n\n withOutputOptions(\n providers.command(\"list\").description(\"List configured providers\"),\n ).action(async () => {\n sink(await controllers.providersController.list());\n });\n\n withOutputOptions(\n providers\n .command(\"get <providerId>\")\n .description(\"Get a configured provider\"),\n ).action(async (providerId) => {\n sink(await controllers.providersController.get(providerId));\n });\n\n withOutputOptions(\n providers\n .command(\"add <providerId>\")\n .description(\"Add a provider\")\n .requiredOption(\n \"--api-format <format>\",\n \"Provider API format, for example openrouter or openai\",\n )\n .option(\"--display-name <name>\", \"Provider display name\")\n .option(\"--api-base <url>\", \"Provider API base URL\"),\n ).action(async (providerId, options) => {\n sink(await controllers.providersController.add(providerId, options));\n });\n\n withOutputOptions(\n providers\n .command(\"update <providerId>\")\n .description(\"Update a provider\")\n .option(\"--api-format <format>\", \"Provider API format\")\n .option(\"--display-name <name>\", \"Provider display name\")\n .option(\"--api-base <url>\", \"Provider API base URL\"),\n ).action(async (providerId, options) => {\n sink(await controllers.providersController.update(providerId, options));\n });\n\n withOutputOptions(\n providers.command(\"remove <providerId>\").description(\"Remove a provider\"),\n ).action(async (providerId) => {\n sink(await controllers.providersController.remove(providerId));\n });\n};\n\nconst registerModelsCommands = (\n program: Command,\n controllers: AigenCommandControllers,\n sink: AigenCommandOutputSink,\n): void => {\n const models = program\n .command(\"models\")\n .description(\"Manage provider models\");\n\n withOutputOptions(\n models\n .command(\"list\")\n .description(\n \"List configured models, or remote provider models with --remote\",\n )\n .option(\"--remote\", \"List remote models from a provider\", false)\n .option(\"--provider <providerId>\", \"Provider id\")\n .option(\"--kind <kind>\", \"Model kind\"),\n ).action(async (options) => {\n sink(await controllers.modelsController.list(options));\n });\n\n withOutputOptions(\n models.command(\"get <modelRoute>\").description(\"Get a configured model\"),\n ).action(async (modelRoute) => {\n sink(await controllers.modelsController.get(modelRoute));\n });\n\n withOutputOptions(\n models\n .command(\"add <modelRoute>\")\n .description(\"Add a model under a provider\")\n .option(\"--kind <kind>\", \"Model kind\", \"image\")\n .option(\"--display-name <name>\", \"Model display name\")\n .option(\"--generate\", \"Mark model as generation-capable\", false)\n .option(\"--edit\", \"Mark model as edit-capable\", false)\n .option(\n \"--max-count <count>\",\n \"Maximum generated asset count\",\n parseNumberOption,\n ),\n ).action(async (modelRoute, options) => {\n sink(await controllers.modelsController.add(modelRoute, options));\n });\n\n withOutputOptions(\n models\n .command(\"update <modelRoute>\")\n .description(\"Update a model\")\n .option(\"--kind <kind>\", \"Model kind\")\n .option(\"--display-name <name>\", \"Model display name\")\n .option(\"--generate\", \"Mark model as generation-capable\")\n .option(\"--edit\", \"Mark model as edit-capable\")\n .option(\n \"--max-count <count>\",\n \"Maximum generated asset count\",\n parseNumberOption,\n ),\n ).action(async (modelRoute, options) => {\n sink(await controllers.modelsController.update(modelRoute, options));\n });\n\n withOutputOptions(\n models.command(\"remove <modelRoute>\").description(\"Remove a model\"),\n ).action(async (modelRoute) => {\n sink(await controllers.modelsController.remove(modelRoute));\n });\n};\n\nconst registerSecretsCommands = (\n program: Command,\n controllers: AigenCommandControllers,\n sink: AigenCommandOutputSink,\n): void => {\n const secrets = program\n .command(\"secrets\")\n .description(\"Manage provider API keys\");\n\n withOutputOptions(\n secrets.command(\"list\").description(\"List masked provider secrets\"),\n ).action(async () => {\n sink(await controllers.secretsController.list());\n });\n\n withOutputOptions(\n secrets\n .command(\"get <providerId>\")\n .description(\"Get masked provider secret metadata\"),\n ).action(async (providerId) => {\n sink(await controllers.secretsController.get(providerId));\n });\n\n withOutputOptions(\n secrets\n .command(\"set <providerId>\")\n .description(\"Set provider API key from stdin\")\n .option(\"--stdin\", \"Read provider API key from stdin\", false),\n ).action(async (providerId) => {\n sink(await controllers.secretsController.set(providerId));\n });\n\n withOutputOptions(\n secrets\n .command(\"remove <providerId>\")\n .description(\"Remove provider API key\"),\n ).action(async (providerId) => {\n sink(await controllers.secretsController.remove(providerId));\n });\n};\n\nconst registerDoctorCommand = (\n program: Command,\n controllers: AigenCommandControllers,\n sink: AigenCommandOutputSink,\n): void => {\n withOutputOptions(\n program\n .command(\"doctor\")\n .description(\"Run local configuration diagnostics\")\n .option(\"--provider <providerId>\", \"Provider id to check\")\n .option(\"--model <modelRoute>\", \"Model route to check\"),\n ).action(async (options) => {\n sink(await controllers.doctorController.run(options));\n });\n};\n\nconst withOutputOptions = (command: Command): Command =>\n command\n .option(\"--json\", \"Output JSON\", false)\n .option(\"--debug\", \"Print debug diagnostics to stderr\", false);\n\nconst parseNumberOption = (value: string): number => {\n const parsed = Number(value);\n\n if (!Number.isFinite(parsed)) {\n throw new InvalidArgumentError(\"must be a number\");\n }\n\n return parsed;\n};\n","import type { ConfigRepository } from \"@/repositories/config.repository.js\";\nimport type { SecretsRepository } from \"@/repositories/secrets.repository.js\";\nimport type { AigenImageInput, AigenImageSuccessOutput } from \"@/types/image-generation.types.js\";\nimport type { OutputFileManager } from \"./output-file.manager.js\";\nimport type { ProviderRuntimeManager } from \"./provider-runtime.manager.js\";\nimport { parseModelRoute } from \"@/utils/route.utils.js\";\n\nexport class ImageGenerationManager {\n constructor(\n private readonly configRepository: ConfigRepository,\n private readonly secretsRepository: SecretsRepository,\n private readonly providerRuntimeManager: ProviderRuntimeManager,\n private readonly outputFileManager: OutputFileManager,\n ) {}\n\n generate = async (input: AigenImageInput): Promise<AigenImageSuccessOutput> => {\n const route = parseModelRoute(input.model);\n const providerConfig = await this.configRepository.getProvider(route.providerId);\n await this.configRepository.getModel(route.providerId, route.providerLocalModel);\n\n const provider = this.providerRuntimeManager.getImageProvider(providerConfig.apiFormat);\n const apiKey = await this.secretsRepository.getProviderApiKey(route.providerId);\n const result = await provider.generateImage(\n {\n providerLocalModel: route.providerLocalModel,\n prompt: input.prompt,\n size: input.size,\n n: input.n ?? 1,\n quality: input.quality,\n background: input.background,\n outputFormat: input.outputFormat,\n outputCompression: input.outputCompression,\n moderation: input.moderation\n },\n {\n providerId: route.providerId,\n apiFormat: providerConfig.apiFormat,\n apiBase: providerConfig.apiBase,\n apiKey,\n headers: providerConfig.headers\n },\n );\n const assets = await this.outputFileManager.writeImages(result.images, input.outputDir, input.outputName);\n\n return {\n ok: true,\n kind: \"image\",\n provider: route.providerId,\n apiFormat: providerConfig.apiFormat,\n model: input.model,\n providerLocalModel: route.providerLocalModel,\n assets,\n usage: result.usage,\n metadata: {\n ...result.metadata,\n upstreamRequestId: result.upstreamRequestId\n }\n };\n };\n}\n","export const mimeTypeToExtension = (mimeType: string): string => {\n switch (mimeType.toLowerCase()) {\n case \"image/jpeg\":\n case \"image/jpg\":\n return \"jpg\";\n case \"image/png\":\n return \"png\";\n case \"image/webp\":\n return \"webp\";\n case \"image/gif\":\n return \"gif\";\n default:\n return \"bin\";\n }\n};\n\nexport const extensionToMimeType = (extension: string): string => {\n switch (extension.toLowerCase()) {\n case \"jpg\":\n case \"jpeg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"webp\":\n return \"image/webp\";\n case \"gif\":\n return \"image/gif\";\n default:\n return \"application/octet-stream\";\n }\n};\n","import { mkdir, stat, writeFile } from \"node:fs/promises\";\nimport { basename, resolve } from \"node:path\";\n\nimport { AigenError } from \"@/types/cli-output.types.js\";\nimport type { AigenImageAsset } from \"@/types/image-generation.types.js\";\nimport type { AigenProviderImage } from \"@/types/provider.types.js\";\nimport { mimeTypeToExtension } from \"@/utils/mime.utils.js\";\n\nexport class OutputFileManager {\n writeImages = async (\n images: AigenProviderImage[],\n outputDir: string,\n outputName: string,\n ): Promise<AigenImageAsset[]> => {\n this.assertOutputName(outputName);\n await mkdir(outputDir, { recursive: true });\n\n const resolvedOutputDir = resolve(outputDir);\n const assets: AigenImageAsset[] = [];\n\n for (let index = 0; index < images.length; index += 1) {\n const image = images[index];\n const extension = image.format ?? mimeTypeToExtension(image.mimeType);\n const filename = this.createFilename(outputName, extension, images.length, index);\n const path = resolve(resolvedOutputDir, filename);\n\n this.assertContainedPath(resolvedOutputDir, path);\n await writeFile(path, image.bytes, { flag: \"wx\" });\n\n const fileStat = await stat(path);\n assets.push({\n path,\n filename,\n mimeType: image.mimeType,\n format: extension,\n width: image.width,\n height: image.height,\n sizeBytes: fileStat.size\n });\n }\n\n return assets;\n };\n\n private assertOutputName = (outputName: string): void => {\n if (!outputName || outputName !== basename(outputName) || outputName.includes(\"/\") || outputName.includes(\"\\\\\")) {\n throw new AigenError(\"INVALID_ARGUMENT\", \"output-name must be a basename without path separators.\");\n }\n };\n\n private assertContainedPath = (outputDir: string, path: string): void => {\n if (path !== outputDir && !path.startsWith(`${outputDir}/`)) {\n throw new AigenError(\"FILE_WRITE_FAILED\", \"Generated file path escaped output-dir.\");\n }\n };\n\n private createFilename = (outputName: string, extension: string, count: number, index: number): string => {\n const suffix = count === 1 ? \"\" : `-${index + 1}`;\n return `${outputName}${suffix}.${extension}`;\n };\n}\n","import type { AigenMediaKind } from \"./config.types.js\";\n\nexport type AigenProviderContext = {\n providerId: string;\n apiFormat: string;\n apiBase: string;\n apiKey: string;\n headers?: Record<string, string>;\n};\n\nexport type AigenProviderImageRequest = {\n providerLocalModel: string;\n prompt: string;\n size?: string;\n n: number;\n quality?: string;\n background?: string;\n outputFormat?: string;\n outputCompression?: number;\n moderation?: string;\n};\n\nexport type AigenProviderImage = {\n bytes: Uint8Array;\n mimeType: string;\n format?: string;\n width?: number;\n height?: number;\n revisedPrompt?: string;\n};\n\nexport type AigenProviderImageResult = {\n images: AigenProviderImage[];\n usage?: Record<string, unknown>;\n upstreamRequestId?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport interface AigenImageProvider {\n readonly apiFormat: string;\n\n generateImage(\n request: AigenProviderImageRequest,\n context: AigenProviderContext,\n ): Promise<AigenProviderImageResult>;\n}\n\nexport type AigenRemoteModelListRequest = {\n kind?: AigenMediaKind;\n};\n\nexport type AigenRemoteModel = {\n providerLocalModel: string;\n displayName?: string;\n inputModalities?: string[];\n outputModalities?: string[];\n pricing?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n};\n\nexport type AigenRemoteModelListResult = {\n models: AigenRemoteModel[];\n metadata?: Record<string, unknown>;\n};\n\nexport interface AigenRemoteModelListProvider {\n listRemoteModels(\n request: AigenRemoteModelListRequest,\n context: AigenProviderContext,\n ): Promise<AigenRemoteModelListResult>;\n}\n\nexport const isRemoteModelListProvider = (\n provider: AigenImageProvider,\n): provider is AigenImageProvider & AigenRemoteModelListProvider =>\n \"listRemoteModels\" in provider && typeof provider.listRemoteModels === \"function\";\n","import { AigenError } from \"@/types/cli-output.types.js\";\nimport {\n isRemoteModelListProvider,\n type AigenImageProvider,\n type AigenRemoteModelListProvider\n} from \"@/types/provider.types.js\";\n\nexport class ProviderRuntimeManager {\n private readonly providers = new Map<string, AigenImageProvider>();\n\n constructor(providers: AigenImageProvider[]) {\n providers.forEach((provider) => {\n this.providers.set(provider.apiFormat, provider);\n });\n }\n\n getImageProvider = (apiFormat: string): AigenImageProvider => {\n const provider = this.providers.get(apiFormat);\n\n if (!provider) {\n throw new AigenError(\"PROVIDER_RUNTIME_NOT_FOUND\", `API format '${apiFormat}' is not supported.`);\n }\n\n return provider;\n };\n\n getRemoteModelListProvider = (apiFormat: string): AigenImageProvider & AigenRemoteModelListProvider => {\n const provider = this.getImageProvider(apiFormat);\n\n if (!isRemoteModelListProvider(provider)) {\n throw new AigenError(\"UNSUPPORTED_PARAMETER\", `API format '${apiFormat}' does not support remote model list.`);\n }\n\n return provider;\n };\n}\n","import { AigenError } from \"@/types/cli-output.types.js\";\n\nexport type ParsedDataUrl = {\n mimeType: string;\n bytes: Uint8Array;\n};\n\nexport const parseImageDataUrl = (value: string): ParsedDataUrl => {\n const match = /^data:([^;,]+);base64,(.+)$/s.exec(value);\n\n if (!match) {\n throw new AigenError(\"PROVIDER_REQUEST_FAILED\", \"Provider returned an invalid image data URL.\");\n }\n\n return {\n mimeType: match[1] ?? \"application/octet-stream\",\n bytes: Uint8Array.from(Buffer.from(match[2] ?? \"\", \"base64\"))\n };\n};\n\nexport const isDataUrl = (value: string): boolean => value.startsWith(\"data:\");\n","import { AigenError } from \"@/types/cli-output.types.js\";\nimport type {\n AigenImageProvider,\n AigenProviderContext,\n AigenProviderImageResult,\n AigenProviderImageRequest,\n AigenRemoteModelListProvider,\n AigenRemoteModelListRequest,\n AigenRemoteModelListResult\n} from \"@/types/provider.types.js\";\nimport { isDataUrl, parseImageDataUrl } from \"@/utils/data-url.utils.js\";\nimport { extensionToMimeType } from \"@/utils/mime.utils.js\";\n\ntype JsonRecord = Record<string, unknown>;\n\nexport class OpenRouterProvider implements AigenImageProvider, AigenRemoteModelListProvider {\n readonly apiFormat = \"openrouter\";\n\n generateImage = async (\n request: AigenProviderImageRequest,\n context: AigenProviderContext,\n ): Promise<AigenProviderImageResult> => {\n const response = await fetch(this.url(context.apiBase, \"/chat/completions\"), {\n method: \"POST\",\n headers: this.headers(context),\n body: JSON.stringify(this.toChatCompletionsBody(request))\n });\n\n const payload = await this.readJson(response);\n\n if (!response.ok) {\n throw new AigenError(\"PROVIDER_REQUEST_FAILED\", \"OpenRouter image generation request failed.\", {\n retryable: response.status >= 500\n });\n }\n\n return {\n images: await this.extractImages(payload),\n usage: this.recordOrUndefined(payload.usage),\n upstreamRequestId: this.stringOrUndefined(payload.id),\n metadata: {\n model: this.stringOrUndefined(payload.model)\n }\n };\n };\n\n listRemoteModels = async (\n _request: AigenRemoteModelListRequest,\n context: AigenProviderContext,\n ): Promise<AigenRemoteModelListResult> => {\n const response = await fetch(this.url(context.apiBase, \"/models?output_modalities=image\"), {\n method: \"GET\",\n headers: this.headers(context)\n });\n const payload = await this.readJson(response);\n\n if (!response.ok) {\n throw new AigenError(\"PROVIDER_REQUEST_FAILED\", \"OpenRouter models request failed.\", {\n retryable: response.status >= 500\n });\n }\n\n const data = Array.isArray(payload.data) ? payload.data : [];\n\n return {\n models: data.flatMap((entry) => {\n const model = this.recordOrUndefined(entry);\n const id = this.stringOrUndefined(model?.id);\n\n if (!model || !id) {\n return [];\n }\n\n return [\n {\n providerLocalModel: id,\n displayName: this.stringOrUndefined(model.name),\n inputModalities: this.stringArrayOrUndefined(this.recordOrUndefined(model.architecture)?.input_modalities),\n outputModalities: this.stringArrayOrUndefined(this.recordOrUndefined(model.architecture)?.output_modalities),\n pricing: this.recordOrUndefined(model.pricing),\n metadata: model\n }\n ];\n })\n };\n };\n\n private toChatCompletionsBody = (request: AigenProviderImageRequest): JsonRecord => {\n const body: JsonRecord = {\n model: request.providerLocalModel,\n messages: [\n {\n role: \"user\",\n content: request.prompt\n }\n ],\n modalities: [\"image\"],\n stream: false\n };\n\n if (request.size) {\n body.image_config = {\n image_size: request.size\n };\n }\n\n return body;\n };\n\n private extractImages = async (payload: JsonRecord): Promise<AigenProviderImageResult[\"images\"]> => {\n const choices = Array.isArray(payload.choices) ? payload.choices : [];\n const urls = choices.flatMap((choice) => this.extractImageUrls(choice));\n\n if (urls.length === 0) {\n throw new AigenError(\"PROVIDER_REQUEST_FAILED\", \"OpenRouter response did not include generated images.\");\n }\n\n return Promise.all(urls.map((url) => this.loadImageUrl(url)));\n };\n\n private extractImageUrls = (choice: unknown): string[] => {\n const message = this.recordOrUndefined(this.recordOrUndefined(choice)?.message);\n const images = Array.isArray(message?.images) ? message.images : [];\n\n return images.flatMap((image) => {\n const url = this.stringOrUndefined(this.recordOrUndefined(this.recordOrUndefined(image)?.image_url)?.url);\n return url ? [url] : [];\n });\n };\n\n private loadImageUrl = async (url: string): Promise<AigenProviderImageResult[\"images\"][number]> => {\n if (isDataUrl(url)) {\n const dataUrl = parseImageDataUrl(url);\n return {\n bytes: dataUrl.bytes,\n mimeType: dataUrl.mimeType\n };\n }\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new AigenError(\"PROVIDER_REQUEST_FAILED\", \"Failed to download generated image.\", {\n retryable: response.status >= 500\n });\n }\n\n const contentType = response.headers.get(\"content-type\") ?? this.mimeTypeFromUrl(url);\n return {\n bytes: new Uint8Array(await response.arrayBuffer()),\n mimeType: contentType\n };\n };\n\n private readJson = async (response: Response): Promise<JsonRecord> => {\n const value = (await response.json()) as unknown;\n const record = this.recordOrUndefined(value);\n\n if (!record) {\n throw new AigenError(\"PROVIDER_REQUEST_FAILED\", \"Provider returned a non-object JSON response.\");\n }\n\n return record;\n };\n\n private headers = (context: AigenProviderContext): HeadersInit => ({\n authorization: `Bearer ${context.apiKey}`,\n \"content-type\": \"application/json\",\n ...context.headers\n });\n\n private url = (apiBase: string, path: string): string => `${apiBase.replace(/\\/$/, \"\")}${path}`;\n\n private recordOrUndefined = (value: unknown): JsonRecord | undefined =>\n value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonRecord) : undefined;\n\n private stringOrUndefined = (value: unknown): string | undefined => (typeof value === \"string\" ? value : undefined);\n\n private stringArrayOrUndefined = (value: unknown): string[] | undefined =>\n Array.isArray(value) && value.every((item) => typeof item === \"string\") ? value : undefined;\n\n private mimeTypeFromUrl = (url: string): string => {\n const extension = url.split(\"?\")[0]?.split(\".\").pop();\n return extension ? extensionToMimeType(extension) : \"application/octet-stream\";\n };\n}\n","export type AigenMediaKind = \"image\" | \"video\" | \"audio\";\n\nexport type AigenModelCapabilities = {\n generate?: boolean;\n edit?: boolean;\n maxCount?: number;\n sizes?: string[];\n outputFormats?: string[];\n qualities?: string[];\n supportsTransparentBackground?: boolean;\n};\n\nexport type AigenModelConfig = {\n kind: AigenMediaKind;\n displayName?: string;\n capabilities?: AigenModelCapabilities;\n};\n\nexport type AigenProviderConfig = {\n apiFormat: string;\n displayName?: string;\n apiBase: string;\n apiKeyRef: string;\n headers?: Record<string, string>;\n models: Record<string, AigenModelConfig>;\n};\n\nexport type AigenConfig = {\n version: 1;\n providers: Record<string, AigenProviderConfig>;\n};\n\nexport const createEmptyAigenConfig = (): AigenConfig => ({\n version: 1,\n providers: {}\n});\n","import { mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { AigenError } from \"@/types/cli-output.types.js\";\nimport {\n createEmptyAigenConfig,\n type AigenConfig,\n type AigenModelConfig,\n type AigenProviderConfig\n} from \"@/types/config.types.js\";\nimport { assertResourceId } from \"@/utils/route.utils.js\";\n\nexport class ConfigRepository {\n readonly homeDir: string;\n readonly configPath: string;\n\n constructor(homeDir = process.env.AIGEN_HOME ?? join(homedir(), \".aigen\")) {\n this.homeDir = homeDir;\n this.configPath = join(homeDir, \"config.json\");\n }\n\n readConfig = async (): Promise<AigenConfig> => {\n try {\n const text = await readFile(this.configPath, \"utf8\");\n return this.parseConfig(text);\n } catch (error) {\n if (this.isNotFoundError(error)) {\n throw new AigenError(\"CONFIG_NOT_FOUND\", \"aigen config.json does not exist.\");\n }\n\n throw error;\n }\n };\n\n readConfigOrCreate = async (): Promise<AigenConfig> => {\n try {\n return await this.readConfig();\n } catch (error) {\n if (error instanceof AigenError && error.code === \"CONFIG_NOT_FOUND\") {\n return createEmptyAigenConfig();\n }\n\n throw error;\n }\n };\n\n writeConfig = async (config: AigenConfig): Promise<void> => {\n await mkdir(this.homeDir, { recursive: true });\n await writeFile(this.configPath, `${JSON.stringify(config, null, 2)}\\n`, { mode: 0o600 });\n };\n\n listProviders = async (): Promise<Array<{ id: string; config: AigenProviderConfig }>> => {\n const config = await this.readConfig();\n return Object.entries(config.providers).map(([id, providerConfig]) => ({\n id,\n config: providerConfig\n }));\n };\n\n getProvider = async (providerId: string): Promise<AigenProviderConfig> => {\n const config = await this.readConfig();\n const providerConfig = config.providers[providerId];\n\n if (!providerConfig) {\n throw new AigenError(\"PROVIDER_NOT_FOUND\", `Provider '${providerId}' does not exist.`);\n }\n\n return providerConfig;\n };\n\n addProvider = async (providerId: string, providerConfig: AigenProviderConfig): Promise<void> => {\n assertResourceId(providerId, \"Provider id\");\n const config = await this.readConfigOrCreate();\n\n if (config.providers[providerId]) {\n throw new AigenError(\"INVALID_ARGUMENT\", `Provider '${providerId}' already exists.`);\n }\n\n config.providers[providerId] = providerConfig;\n await this.writeConfig(config);\n };\n\n updateProvider = async (\n providerId: string,\n patch: Partial<Omit<AigenProviderConfig, \"models\">>,\n ): Promise<AigenProviderConfig> => {\n const config = await this.readConfig();\n const current = config.providers[providerId];\n\n if (!current) {\n throw new AigenError(\"PROVIDER_NOT_FOUND\", `Provider '${providerId}' does not exist.`);\n }\n\n const next: AigenProviderConfig = {\n ...current,\n apiFormat: patch.apiFormat ?? current.apiFormat,\n displayName: patch.displayName ?? current.displayName,\n apiBase: patch.apiBase ?? current.apiBase,\n apiKeyRef: patch.apiKeyRef ?? current.apiKeyRef,\n headers: patch.headers ?? current.headers\n };\n\n config.providers[providerId] = next;\n await this.writeConfig(config);\n return next;\n };\n\n removeProvider = async (providerId: string): Promise<void> => {\n const config = await this.readConfig();\n\n if (!config.providers[providerId]) {\n throw new AigenError(\"PROVIDER_NOT_FOUND\", `Provider '${providerId}' does not exist.`);\n }\n\n delete config.providers[providerId];\n await this.writeConfig(config);\n };\n\n listModels = async (\n providerId?: string,\n kind?: string,\n ): Promise<\n Array<{ route: string; providerId: string; providerLocalModel: string; config: AigenModelConfig }>\n > => {\n const config = await this.readConfig();\n const providers = providerId\n ? [[providerId, await this.getProvider(providerId)] as const]\n : Object.entries(config.providers);\n\n return providers.flatMap(([id, providerConfig]) =>\n Object.entries(providerConfig.models)\n .filter(([, modelConfig]) => !kind || modelConfig.kind === kind)\n .map(([providerLocalModel, modelConfig]) => ({\n route: `${id}/${providerLocalModel}`,\n providerId: id,\n providerLocalModel,\n config: modelConfig\n })),\n );\n };\n\n getModel = async (providerId: string, providerLocalModel: string): Promise<AigenModelConfig> => {\n const providerConfig = await this.getProvider(providerId);\n const modelConfig = providerConfig.models[providerLocalModel];\n\n if (!modelConfig) {\n throw new AigenError(\"MODEL_NOT_FOUND\", `Model '${providerId}/${providerLocalModel}' does not exist.`);\n }\n\n return modelConfig;\n };\n\n addModel = async (\n providerId: string,\n providerLocalModel: string,\n modelConfig: AigenModelConfig,\n ): Promise<void> => {\n const config = await this.readConfig();\n const providerConfig = config.providers[providerId];\n\n if (!providerConfig) {\n throw new AigenError(\"PROVIDER_NOT_FOUND\", `Provider '${providerId}' does not exist.`);\n }\n\n if (providerConfig.models[providerLocalModel]) {\n throw new AigenError(\"INVALID_ARGUMENT\", `Model '${providerId}/${providerLocalModel}' already exists.`);\n }\n\n providerConfig.models[providerLocalModel] = modelConfig;\n await this.writeConfig(config);\n };\n\n updateModel = async (\n providerId: string,\n providerLocalModel: string,\n patch: Partial<AigenModelConfig>,\n ): Promise<AigenModelConfig> => {\n const config = await this.readConfig();\n const providerConfig = config.providers[providerId];\n\n if (!providerConfig) {\n throw new AigenError(\"PROVIDER_NOT_FOUND\", `Provider '${providerId}' does not exist.`);\n }\n\n const current = providerConfig.models[providerLocalModel];\n\n if (!current) {\n throw new AigenError(\"MODEL_NOT_FOUND\", `Model '${providerId}/${providerLocalModel}' does not exist.`);\n }\n\n const next: AigenModelConfig = {\n ...current,\n kind: patch.kind ?? current.kind,\n displayName: patch.displayName ?? current.displayName,\n capabilities: patch.capabilities ?? current.capabilities\n };\n\n providerConfig.models[providerLocalModel] = next;\n await this.writeConfig(config);\n return next;\n };\n\n removeModel = async (providerId: string, providerLocalModel: string): Promise<void> => {\n const config = await this.readConfig();\n const providerConfig = config.providers[providerId];\n\n if (!providerConfig) {\n throw new AigenError(\"PROVIDER_NOT_FOUND\", `Provider '${providerId}' does not exist.`);\n }\n\n if (!providerConfig.models[providerLocalModel]) {\n throw new AigenError(\"MODEL_NOT_FOUND\", `Model '${providerId}/${providerLocalModel}' does not exist.`);\n }\n\n delete providerConfig.models[providerLocalModel];\n await this.writeConfig(config);\n };\n\n clear = async (): Promise<void> => {\n await rm(this.configPath, { force: true });\n };\n\n private parseConfig = (text: string): AigenConfig => {\n const value = JSON.parse(text) as Partial<AigenConfig>;\n\n if (value.version !== 1 || !value.providers || typeof value.providers !== \"object\") {\n throw new AigenError(\"CONFIG_INVALID\", \"aigen config.json is invalid.\");\n }\n\n return {\n version: 1,\n providers: value.providers\n };\n };\n\n private isNotFoundError = (error: unknown): boolean =>\n error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n","import { createHash } from \"node:crypto\";\nimport { chmod, mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { AigenError } from \"@/types/cli-output.types.js\";\n\ntype AigenSecretEntry = {\n kind: \"apiKey\";\n value: string;\n updatedAt: string;\n};\n\ntype AigenSecretsFile = {\n version: 1;\n secrets: Record<string, AigenSecretEntry>;\n};\n\nexport type AigenSecretMetadata = {\n ref: string;\n kind: \"apiKey\";\n exists: true;\n maskedValue: string;\n fingerprint: string;\n updatedAt: string;\n};\n\nexport class SecretsRepository {\n readonly homeDir: string;\n readonly secretsPath: string;\n\n constructor(homeDir = process.env.AIGEN_HOME ?? join(homedir(), \".aigen\")) {\n this.homeDir = homeDir;\n this.secretsPath = join(homeDir, \"secrets.json\");\n }\n\n setProviderApiKey = async (providerId: string, value: string): Promise<AigenSecretMetadata> => {\n const trimmedValue = value.trim();\n\n if (!trimmedValue) {\n throw new AigenError(\"INVALID_ARGUMENT\", \"API key cannot be empty.\");\n }\n\n const secretsFile = await this.readSecretsOrCreate();\n const ref = this.providerRef(providerId);\n\n secretsFile.secrets[ref] = {\n kind: \"apiKey\",\n value: trimmedValue,\n updatedAt: new Date().toISOString()\n };\n\n await this.writeSecrets(secretsFile);\n return this.toMetadata(ref, secretsFile.secrets[ref]);\n };\n\n getProviderApiKey = async (providerId: string): Promise<string> => {\n const ref = this.providerRef(providerId);\n const entry = await this.getSecretEntry(ref);\n return entry.value;\n };\n\n getProviderSecret = async (providerId: string): Promise<AigenSecretMetadata> => {\n const ref = this.providerRef(providerId);\n const entry = await this.getSecretEntry(ref);\n return this.toMetadata(ref, entry);\n };\n\n listSecrets = async (): Promise<AigenSecretMetadata[]> => {\n const secretsFile = await this.readSecretsOrCreate();\n return Object.entries(secretsFile.secrets).map(([ref, entry]) => this.toMetadata(ref, entry));\n };\n\n removeProviderSecret = async (providerId: string): Promise<void> => {\n const secretsFile = await this.readSecretsOrCreate();\n const ref = this.providerRef(providerId);\n\n if (!secretsFile.secrets[ref]) {\n throw new AigenError(\"SECRET_NOT_FOUND\", `Secret '${ref}' does not exist.`);\n }\n\n delete secretsFile.secrets[ref];\n await this.writeSecrets(secretsFile);\n };\n\n clear = async (): Promise<void> => {\n await rm(this.secretsPath, { force: true });\n };\n\n private getSecretEntry = async (ref: string): Promise<AigenSecretEntry> => {\n const secretsFile = await this.readSecretsOrCreate();\n const entry = secretsFile.secrets[ref];\n\n if (!entry) {\n throw new AigenError(\"MISSING_API_KEY\", `Secret '${ref}' does not exist.`);\n }\n\n return entry;\n };\n\n private readSecretsOrCreate = async (): Promise<AigenSecretsFile> => {\n try {\n const text = await readFile(this.secretsPath, \"utf8\");\n const value = JSON.parse(text) as Partial<AigenSecretsFile>;\n\n if (value.version !== 1 || !value.secrets || typeof value.secrets !== \"object\") {\n throw new AigenError(\"CONFIG_INVALID\", \"aigen secrets.json is invalid.\");\n }\n\n return {\n version: 1,\n secrets: value.secrets as Record<string, AigenSecretEntry>\n };\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return {\n version: 1,\n secrets: {}\n };\n }\n\n throw error;\n }\n };\n\n private writeSecrets = async (secretsFile: AigenSecretsFile): Promise<void> => {\n await mkdir(this.homeDir, { recursive: true });\n await writeFile(this.secretsPath, `${JSON.stringify(secretsFile, null, 2)}\\n`, { mode: 0o600 });\n await chmod(this.secretsPath, 0o600);\n };\n\n private providerRef = (providerId: string): string => `provider:${providerId}`;\n\n private toMetadata = (ref: string, entry: AigenSecretEntry): AigenSecretMetadata => ({\n ref,\n kind: entry.kind,\n exists: true,\n maskedValue: this.maskValue(entry.value),\n fingerprint: this.fingerprint(entry.value),\n updatedAt: entry.updatedAt\n });\n\n private maskValue = (value: string): string => {\n if (value.length <= 8) {\n return \"********\";\n }\n\n return `${value.slice(0, 3)}...${value.slice(-4)}`;\n };\n\n private fingerprint = (value: string): string =>\n `sha256:${createHash(\"sha256\").update(value).digest(\"hex\").slice(0, 12)}`;\n}\n","import { AigenError, type AigenCommandFailure } from \"@/types/cli-output.types.js\";\n\nexport const toCommandFailure = (error: unknown): AigenCommandFailure => {\n if (error instanceof AigenError) {\n return {\n ok: false,\n error: {\n code: error.code,\n message: error.message,\n retryable: error.retryable\n }\n };\n }\n\n return {\n ok: false,\n error: {\n code: \"PROVIDER_REQUEST_FAILED\",\n message: error instanceof Error ? error.message : \"Unknown aigen failure.\",\n retryable: false\n }\n };\n};\n\nexport const assertNever = (value: never): never => {\n throw new AigenError(\"INVALID_ARGUMENT\", `Unsupported command: ${String(value)}`);\n};\n","import { Command, CommanderError } from \"commander\";\nimport { DoctorController } from \"@/controllers/doctor.controller.js\";\nimport { ImageController } from \"@/controllers/image.controller.js\";\nimport { ModelsController } from \"@/controllers/models.controller.js\";\nimport { ProvidersController } from \"@/controllers/providers.controller.js\";\nimport { SecretsController } from \"@/controllers/secrets.controller.js\";\nimport {\n registerAigenCommands,\n type AigenCommandOutputSink,\n} from \"@/app/register-aigen-commands.js\";\nimport { ImageGenerationManager } from \"@/managers/image-generation.manager.js\";\nimport { OutputFileManager } from \"@/managers/output-file.manager.js\";\nimport { ProviderRuntimeManager } from \"@/managers/provider-runtime.manager.js\";\nimport { OpenRouterProvider } from \"@/providers/openrouter.provider.js\";\nimport { ConfigRepository } from \"@/repositories/config.repository.js\";\nimport { SecretsRepository } from \"@/repositories/secrets.repository.js\";\nimport {\n AigenError,\n type AigenCommandOutput,\n} from \"@/types/cli-output.types.js\";\nimport { toCommandFailure } from \"@/utils/error.utils.js\";\n\nexport class AigenApp {\n constructor(\n private readonly imageController: ImageController,\n private readonly providersController: ProvidersController,\n private readonly modelsController: ModelsController,\n private readonly secretsController: SecretsController,\n private readonly doctorController: DoctorController,\n ) {}\n\n run = async (argv: string[]): Promise<AigenCommandOutput> => {\n let commandOutput: AigenCommandOutput | undefined;\n let commanderOut = \"\";\n let commanderErr = \"\";\n const program = this.createProgram((output) => {\n commandOutput = output;\n });\n\n program.configureOutput({\n writeOut: (value) => {\n commanderOut += value;\n },\n writeErr: (value) => {\n commanderErr += value;\n },\n });\n\n try {\n if (argv.length === 0) {\n throw new AigenError(\"INVALID_ARGUMENT\", \"Missing command.\");\n }\n\n await program.parseAsync(argv, { from: \"user\" });\n return (\n commandOutput ?? {\n ok: true,\n output: commanderOut.trim(),\n }\n );\n } catch (error) {\n if (error instanceof CommanderError) {\n return this.commanderFailure(error, commanderOut, commanderErr);\n }\n\n return toCommandFailure(error);\n }\n };\n\n private createProgram = (sink: AigenCommandOutputSink): Command => {\n const program = new Command();\n program\n .name(\"aigen\")\n .description(\"Stateless AI media generation CLI.\")\n .version(\"0.0.0\", \"-v, --version\");\n program.exitOverride();\n program.showHelpAfterError();\n\n registerAigenCommands(\n program,\n {\n imageController: this.imageController,\n providersController: this.providersController,\n modelsController: this.modelsController,\n secretsController: this.secretsController,\n doctorController: this.doctorController,\n },\n sink,\n );\n\n return program;\n };\n\n private commanderFailure = (\n error: CommanderError,\n capturedOutput: string,\n capturedError: string,\n ): AigenCommandOutput => {\n const output = capturedOutput.trim();\n\n if (error.exitCode === 0) {\n return {\n ok: true,\n output,\n };\n }\n\n return {\n ok: false,\n error: {\n code: \"INVALID_ARGUMENT\",\n message: capturedError.trim() || error.message,\n retryable: false,\n },\n };\n };\n}\n\nexport const createAigenApp = (homeDir?: string): AigenApp => {\n const configRepository = new ConfigRepository(homeDir);\n const secretsRepository = new SecretsRepository(homeDir);\n const providerRuntimeManager = new ProviderRuntimeManager([\n new OpenRouterProvider(),\n ]);\n const outputFileManager = new OutputFileManager();\n const imageGenerationManager = new ImageGenerationManager(\n configRepository,\n secretsRepository,\n providerRuntimeManager,\n outputFileManager,\n );\n\n return new AigenApp(\n new ImageController(imageGenerationManager),\n new ProvidersController(configRepository),\n new ModelsController(\n configRepository,\n secretsRepository,\n providerRuntimeManager,\n ),\n new SecretsController(secretsRepository),\n new DoctorController(\n configRepository,\n secretsRepository,\n providerRuntimeManager,\n ),\n );\n};\n","#!/usr/bin/env node\nimport { createAigenApp } from \"./aigen-app.js\";\n\nconst app = createAigenApp();\nconst output = await app.run(process.argv.slice(2));\n\nprocess.stdout.write(`${JSON.stringify(output, null, 2)}\\n`);\nprocess.exitCode = output.ok ? 0 : 1;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"main.js","names":[],"sources":["../../src/types/cli-output.types.ts","../../src/utils/route.utils.ts","../../src/controllers/doctor.controller.ts","../../src/controllers/image.controller.ts","../../src/controllers/models.controller.ts","../../src/controllers/providers.controller.ts","../../src/controllers/secrets.controller.ts","../../src/app/register-aigen-commands.ts","../../src/managers/image-generation.manager.ts","../../src/utils/mime.utils.ts","../../src/managers/output-file.manager.ts","../../src/types/provider.types.ts","../../src/managers/provider-runtime.manager.ts","../../src/utils/data-url.utils.ts","../../src/providers/openrouter.provider.ts","../../src/types/config.types.ts","../../src/repositories/config.repository.ts","../../src/repositories/secrets.repository.ts","../../src/utils/error.utils.ts","../../src/app/aigen-app.ts","../../src/app/main.ts"],"sourcesContent":["export type AigenErrorCode =\n | \"CONFIG_NOT_FOUND\"\n | \"CONFIG_INVALID\"\n | \"PROVIDER_NOT_FOUND\"\n | \"MODEL_NOT_FOUND\"\n | \"SECRET_NOT_FOUND\"\n | \"MISSING_API_KEY\"\n | \"PROVIDER_RUNTIME_NOT_FOUND\"\n | \"PROVIDER_REQUEST_FAILED\"\n | \"UNSUPPORTED_PARAMETER\"\n | \"INVALID_ARGUMENT\"\n | \"FILE_WRITE_FAILED\";\n\nexport type AigenCommandError = {\n code: AigenErrorCode;\n message: string;\n retryable?: boolean;\n};\n\nexport type AigenCommandSuccess<TData extends Record<string, unknown> = Record<string, unknown>> = {\n ok: true;\n} & TData;\n\nexport type AigenCommandFailure = {\n ok: false;\n error: AigenCommandError;\n};\n\nexport type AigenCommandOutput<TData extends Record<string, unknown> = Record<string, unknown>> =\n | AigenCommandSuccess<TData>\n | AigenCommandFailure;\n\nexport class AigenError extends Error {\n readonly code: AigenErrorCode;\n readonly retryable: boolean;\n\n constructor(code: AigenErrorCode, message: string, options?: { retryable?: boolean }) {\n super(message);\n this.name = \"AigenError\";\n this.code = code;\n this.retryable = options?.retryable ?? false;\n }\n}\n","import { AigenError } from \"@/types/cli-output.types.js\";\n\nexport type AigenModelRoute = {\n providerId: string;\n providerLocalModel: string;\n};\n\nexport const parseModelRoute = (route: string): AigenModelRoute => {\n const slashIndex = route.indexOf(\"/\");\n\n if (slashIndex <= 0 || slashIndex === route.length - 1) {\n throw new AigenError(\n \"INVALID_ARGUMENT\",\n \"Model route must use <provider-id>/<provider-local-model>.\",\n );\n }\n\n return {\n providerId: route.slice(0, slashIndex),\n providerLocalModel: route.slice(slashIndex + 1)\n };\n};\n\nexport const assertResourceId = (id: string, label: string): void => {\n if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(id)) {\n throw new AigenError(\"INVALID_ARGUMENT\", `${label} must be a stable resource id.`);\n }\n};\n","import type { ConfigRepository } from \"@/repositories/config.repository.js\";\nimport type { SecretsRepository } from \"@/repositories/secrets.repository.js\";\nimport type { AigenCommandOutput } from \"@/types/cli-output.types.js\";\nimport { parseModelRoute } from \"@/utils/route.utils.js\";\nimport type { ProviderRuntimeManager } from \"@/managers/provider-runtime.manager.js\";\n\nexport type DoctorRunOptions = {\n provider?: string;\n model?: string;\n};\n\ntype DoctorCheck = {\n name: string;\n ok: boolean;\n};\n\nexport class DoctorController {\n constructor(\n private readonly configRepository: ConfigRepository,\n private readonly secretsRepository: SecretsRepository,\n private readonly providerRuntimeManager: ProviderRuntimeManager,\n ) {}\n\n run = async (options: DoctorRunOptions): Promise<AigenCommandOutput> => {\n const { provider, model } = options;\n const checks: DoctorCheck[] = [];\n const config = await this.configRepository.readConfig();\n\n checks.push({ name: \"config\", ok: true });\n\n if (provider) {\n await this.checkProvider(provider, checks);\n }\n\n if (model) {\n const route = parseModelRoute(model);\n await this.configRepository.getModel(route.providerId, route.providerLocalModel);\n await this.checkProvider(route.providerId, checks);\n checks.push({ name: \"model\", ok: true });\n }\n\n return {\n ok: true,\n providerCount: Object.keys(config.providers).length,\n checks\n };\n };\n\n private checkProvider = async (providerId: string, checks: DoctorCheck[]): Promise<void> => {\n const providerConfig = await this.configRepository.getProvider(providerId);\n this.providerRuntimeManager.getImageProvider(providerConfig.apiFormat);\n checks.push({ name: \"provider\", ok: true });\n await this.secretsRepository.getProviderSecret(providerId);\n checks.push({ name: \"secret\", ok: true });\n };\n}\n","import type { ImageGenerationManager } from \"@/managers/image-generation.manager.js\";\nimport type { AigenCommandOutput } from \"@/types/cli-output.types.js\";\nimport type { AigenImageInput } from \"@/types/image-generation.types.js\";\n\nexport type ImageGenerateOptions = AigenImageInput;\n\nexport class ImageController {\n constructor(private readonly imageGenerationManager: ImageGenerationManager) {}\n\n generate = async (options: ImageGenerateOptions): Promise<AigenCommandOutput> =>\n this.imageGenerationManager.generate(options);\n}\n","import type { ConfigRepository } from \"@/repositories/config.repository.js\";\nimport type { SecretsRepository } from \"@/repositories/secrets.repository.js\";\nimport { AigenError, type AigenCommandOutput } from \"@/types/cli-output.types.js\";\nimport type { AigenMediaKind, AigenModelCapabilities, AigenModelConfig } from \"@/types/config.types.js\";\nimport { parseModelRoute } from \"@/utils/route.utils.js\";\nimport type { ProviderRuntimeManager } from \"@/managers/provider-runtime.manager.js\";\n\nexport type ModelListOptions = {\n remote?: boolean;\n provider?: string;\n kind?: AigenMediaKind;\n};\n\nexport type ModelWriteOptions = {\n kind?: AigenMediaKind;\n displayName?: string;\n maxCount?: number;\n generate?: boolean;\n edit?: boolean;\n};\n\nexport class ModelsController {\n constructor(\n private readonly configRepository: ConfigRepository,\n private readonly secretsRepository: SecretsRepository,\n private readonly providerRuntimeManager: ProviderRuntimeManager,\n ) {}\n\n list = async (options: ModelListOptions): Promise<AigenCommandOutput> =>\n options.remote ? this.listRemote(options) : this.listLocal(options);\n\n private listLocal = async (options: ModelListOptions): Promise<AigenCommandOutput> => {\n const models = await this.configRepository.listModels(options.provider, options.kind);\n\n return {\n ok: true,\n models: models.map((model) => ({\n route: model.route,\n provider: model.providerId,\n providerLocalModel: model.providerLocalModel,\n kind: model.config.kind,\n displayName: model.config.displayName,\n capabilities: model.config.capabilities\n }))\n };\n };\n\n private listRemote = async (options: ModelListOptions): Promise<AigenCommandOutput> => {\n if (!options.provider) {\n throw new AigenError(\"INVALID_ARGUMENT\", \"Missing required --provider for remote model listing.\");\n }\n\n const providerId = options.provider;\n const providerConfig = await this.configRepository.getProvider(providerId);\n const provider = this.providerRuntimeManager.getRemoteModelListProvider(providerConfig.apiFormat);\n const apiKey = await this.secretsRepository.getProviderApiKey(providerId);\n const result = await provider.listRemoteModels(\n {\n kind: options.kind\n },\n {\n providerId,\n apiFormat: providerConfig.apiFormat,\n apiBase: providerConfig.apiBase,\n apiKey,\n headers: providerConfig.headers\n },\n );\n\n return {\n ok: true,\n models: result.models.map((model) => ({\n route: `${providerId}/${model.providerLocalModel}`,\n provider: providerId,\n apiFormat: providerConfig.apiFormat,\n providerLocalModel: model.providerLocalModel,\n kind: \"image\",\n displayName: model.displayName,\n inputModalities: model.inputModalities,\n outputModalities: model.outputModalities,\n pricing: model.pricing,\n metadata: model.metadata\n })),\n metadata: result.metadata\n };\n };\n\n get = async (modelRoute: string): Promise<AigenCommandOutput> => {\n const route = parseModelRoute(modelRoute);\n const modelConfig = await this.configRepository.getModel(route.providerId, route.providerLocalModel);\n\n return {\n ok: true,\n model: {\n route: modelRoute,\n provider: route.providerId,\n providerLocalModel: route.providerLocalModel,\n kind: modelConfig.kind,\n displayName: modelConfig.displayName,\n capabilities: modelConfig.capabilities\n }\n };\n };\n\n add = async (modelRoute: string, options: ModelWriteOptions): Promise<AigenCommandOutput> => {\n const route = parseModelRoute(modelRoute);\n const modelConfig = this.fullModelConfigFromOptions(options);\n await this.configRepository.addModel(route.providerId, route.providerLocalModel, modelConfig);\n\n return {\n ok: true,\n model: {\n route: modelRoute,\n provider: route.providerId,\n providerLocalModel: route.providerLocalModel,\n ...modelConfig\n }\n };\n };\n\n update = async (modelRoute: string, options: ModelWriteOptions): Promise<AigenCommandOutput> => {\n const route = parseModelRoute(modelRoute);\n const modelConfig = await this.configRepository.updateModel(\n route.providerId,\n route.providerLocalModel,\n this.modelConfigFromOptions(options),\n );\n\n return {\n ok: true,\n model: {\n route: modelRoute,\n provider: route.providerId,\n providerLocalModel: route.providerLocalModel,\n ...modelConfig\n }\n };\n };\n\n remove = async (modelRoute: string): Promise<AigenCommandOutput> => {\n const route = parseModelRoute(modelRoute);\n await this.configRepository.removeModel(route.providerId, route.providerLocalModel);\n\n return {\n ok: true,\n removed: true,\n model: modelRoute\n };\n };\n\n private fullModelConfigFromOptions = (options: ModelWriteOptions): AigenModelConfig => {\n return {\n kind: options.kind ?? \"image\",\n displayName: options.displayName,\n capabilities: this.capabilitiesFromOptions(options)\n };\n };\n\n private modelConfigFromOptions = (options: ModelWriteOptions): Partial<AigenModelConfig> => {\n return {\n kind: options.kind,\n displayName: options.displayName,\n capabilities: this.capabilitiesFromOptions(options)\n };\n };\n\n private capabilitiesFromOptions = (options: ModelWriteOptions): AigenModelCapabilities | undefined => {\n const maxCount = options.maxCount;\n const generate = options.generate ?? false;\n const edit = options.edit ?? false;\n\n if (maxCount === undefined && !generate && !edit) {\n return undefined;\n }\n\n return {\n generate: generate || undefined,\n edit: edit || undefined,\n maxCount\n };\n };\n}\n","import type { ConfigRepository } from \"@/repositories/config.repository.js\";\nimport type { AigenCommandOutput } from \"@/types/cli-output.types.js\";\nimport type { AigenProviderConfig } from \"@/types/config.types.js\";\n\nexport type ProviderAddOptions = {\n apiFormat: string;\n displayName?: string;\n apiBase?: string;\n};\n\nexport type ProviderUpdateOptions = Partial<ProviderAddOptions>;\n\nexport class ProvidersController {\n constructor(private readonly configRepository: ConfigRepository) {}\n\n list = async (): Promise<AigenCommandOutput> => {\n const providers = await this.configRepository.listProviders();\n return {\n ok: true,\n providers: providers.map(({ id, config }) => this.toProviderOutput(id, config))\n };\n };\n\n get = async (providerId: string): Promise<AigenCommandOutput> => ({\n ok: true,\n provider: this.toProviderOutput(providerId, await this.configRepository.getProvider(providerId))\n });\n\n add = async (providerId: string, options: ProviderAddOptions): Promise<AigenCommandOutput> => {\n const { apiFormat, displayName, apiBase } = options;\n const providerConfig: AigenProviderConfig = {\n apiFormat,\n displayName,\n apiKeyRef: `provider:${providerId}`,\n apiBase: apiBase ?? this.defaultApiBase(apiFormat),\n models: {}\n };\n\n await this.configRepository.addProvider(providerId, providerConfig);\n return {\n ok: true,\n provider: this.toProviderOutput(providerId, providerConfig)\n };\n };\n\n update = async (providerId: string, options: ProviderUpdateOptions): Promise<AigenCommandOutput> => {\n const { apiFormat, displayName, apiBase } = options;\n const providerConfig = await this.configRepository.updateProvider(providerId, {\n apiFormat,\n displayName,\n apiBase\n });\n\n return {\n ok: true,\n provider: this.toProviderOutput(providerId, providerConfig)\n };\n };\n\n remove = async (providerId: string): Promise<AigenCommandOutput> => {\n await this.configRepository.removeProvider(providerId);\n return {\n ok: true,\n removed: true,\n providerId\n };\n };\n\n private toProviderOutput = (providerId: string, config: AigenProviderConfig): Record<string, unknown> => ({\n id: providerId,\n apiFormat: config.apiFormat,\n displayName: config.displayName,\n apiBase: config.apiBase,\n apiKeyRef: config.apiKeyRef,\n modelCount: Object.keys(config.models).length\n });\n\n private defaultApiBase = (apiFormat: string): string => {\n if (apiFormat === \"openrouter\") {\n return \"https://openrouter.ai/api/v1\";\n }\n\n if (apiFormat === \"openai\") {\n return \"https://api.openai.com/v1\";\n }\n\n return \"\";\n };\n}\n","import type { SecretsRepository } from \"@/repositories/secrets.repository.js\";\nimport type { AigenCommandOutput } from \"@/types/cli-output.types.js\";\n\nexport class SecretsController {\n constructor(private readonly secretsRepository: SecretsRepository) {}\n\n list = async (): Promise<AigenCommandOutput> => ({\n ok: true,\n secrets: await this.secretsRepository.listSecrets()\n });\n\n get = async (providerId: string): Promise<AigenCommandOutput> => ({\n ok: true,\n secret: await this.secretsRepository.getProviderSecret(providerId)\n });\n\n set = async (providerId: string): Promise<AigenCommandOutput> => {\n const secret = await this.secretsRepository.setProviderApiKey(providerId, await this.readStdin());\n return {\n ok: true,\n secret\n };\n };\n\n remove = async (providerId: string): Promise<AigenCommandOutput> => {\n await this.secretsRepository.removeProviderSecret(providerId);\n return {\n ok: true,\n removed: true,\n providerId\n };\n };\n\n private readStdin = async (): Promise<string> =>\n new Promise((resolve, reject) => {\n let value = \"\";\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk) => {\n value += chunk;\n });\n process.stdin.on(\"end\", () => {\n resolve(value);\n });\n process.stdin.on(\"error\", reject);\n });\n}\n","import { InvalidArgumentError, type Command } from \"commander\";\nimport type { DoctorController } from \"@/controllers/doctor.controller.js\";\nimport type { ImageController } from \"@/controllers/image.controller.js\";\nimport type { ModelsController } from \"@/controllers/models.controller.js\";\nimport type { ProvidersController } from \"@/controllers/providers.controller.js\";\nimport type { SecretsController } from \"@/controllers/secrets.controller.js\";\nimport type { AigenCommandOutput } from \"@/types/cli-output.types.js\";\n\nexport type AigenCommandOutputSink = (output: AigenCommandOutput) => void;\n\nexport type AigenCommandControllers = {\n imageController: ImageController;\n providersController: ProvidersController;\n modelsController: ModelsController;\n secretsController: SecretsController;\n doctorController: DoctorController;\n};\n\nexport const registerAigenCommands = (\n program: Command,\n controllers: AigenCommandControllers,\n sink: AigenCommandOutputSink,\n): void => {\n registerImageCommand(program, controllers, sink);\n registerProvidersCommands(program, controllers, sink);\n registerModelsCommands(program, controllers, sink);\n registerSecretsCommands(program, controllers, sink);\n registerDoctorCommand(program, controllers, sink);\n};\n\nconst registerImageCommand = (\n program: Command,\n controllers: AigenCommandControllers,\n sink: AigenCommandOutputSink,\n): void => {\n withOutputOptions(\n program\n .command(\"image\")\n .description(\"Generate an image\")\n .requiredOption(\n \"--model <route>\",\n \"Model route in <provider-id>/<provider-local-model> format\",\n )\n .requiredOption(\"--prompt <text>\", \"Generation prompt\")\n .option(\"--size <size>\", \"Image size\")\n .option(\n \"--n <count>\",\n \"Number of images to generate\",\n parseNumberOption,\n 1,\n )\n .option(\"--quality <quality>\", \"Image quality\")\n .option(\"--background <background>\", \"Background mode\")\n .option(\"--output-format <format>\", \"Output format\")\n .option(\n \"--output-compression <value>\",\n \"Output compression\",\n parseNumberOption,\n )\n .option(\"--moderation <mode>\", \"Moderation mode\")\n .requiredOption(\"--output-dir <dir>\", \"Directory for generated assets\")\n .requiredOption(\"--output-name <name>\", \"Base output file name\"),\n ).action(async (options) => {\n sink(await controllers.imageController.generate(options));\n });\n};\n\nconst registerProvidersCommands = (\n program: Command,\n controllers: AigenCommandControllers,\n sink: AigenCommandOutputSink,\n): void => {\n const providers = program\n .command(\"providers\")\n .description(\"Manage image generation providers\");\n\n withOutputOptions(\n providers.command(\"list\").description(\"List configured providers\"),\n ).action(async () => {\n sink(await controllers.providersController.list());\n });\n\n withOutputOptions(\n providers\n .command(\"get <providerId>\")\n .description(\"Get a configured provider\"),\n ).action(async (providerId) => {\n sink(await controllers.providersController.get(providerId));\n });\n\n withOutputOptions(\n providers\n .command(\"add <providerId>\")\n .description(\"Add a provider\")\n .requiredOption(\n \"--api-format <format>\",\n \"Provider API format, for example openrouter or openai\",\n )\n .option(\"--display-name <name>\", \"Provider display name\")\n .option(\"--api-base <url>\", \"Provider API base URL\"),\n ).action(async (providerId, options) => {\n sink(await controllers.providersController.add(providerId, options));\n });\n\n withOutputOptions(\n providers\n .command(\"update <providerId>\")\n .description(\"Update a provider\")\n .option(\"--api-format <format>\", \"Provider API format\")\n .option(\"--display-name <name>\", \"Provider display name\")\n .option(\"--api-base <url>\", \"Provider API base URL\"),\n ).action(async (providerId, options) => {\n sink(await controllers.providersController.update(providerId, options));\n });\n\n withOutputOptions(\n providers.command(\"remove <providerId>\").description(\"Remove a provider\"),\n ).action(async (providerId) => {\n sink(await controllers.providersController.remove(providerId));\n });\n};\n\nconst registerModelsCommands = (\n program: Command,\n controllers: AigenCommandControllers,\n sink: AigenCommandOutputSink,\n): void => {\n const models = program\n .command(\"models\")\n .description(\"Manage provider models\");\n\n withOutputOptions(\n models\n .command(\"list\")\n .description(\n \"List configured models, or remote provider models with --remote\",\n )\n .option(\"--remote\", \"List remote models from a provider\", false)\n .option(\"--provider <providerId>\", \"Provider id\")\n .option(\"--kind <kind>\", \"Model kind\"),\n ).action(async (options) => {\n sink(await controllers.modelsController.list(options));\n });\n\n withOutputOptions(\n models.command(\"get <modelRoute>\").description(\"Get a configured model\"),\n ).action(async (modelRoute) => {\n sink(await controllers.modelsController.get(modelRoute));\n });\n\n withOutputOptions(\n models\n .command(\"add <modelRoute>\")\n .description(\"Add a model under a provider\")\n .option(\"--kind <kind>\", \"Model kind\", \"image\")\n .option(\"--display-name <name>\", \"Model display name\")\n .option(\"--generate\", \"Mark model as generation-capable\", false)\n .option(\"--edit\", \"Mark model as edit-capable\", false)\n .option(\n \"--max-count <count>\",\n \"Maximum generated asset count\",\n parseNumberOption,\n ),\n ).action(async (modelRoute, options) => {\n sink(await controllers.modelsController.add(modelRoute, options));\n });\n\n withOutputOptions(\n models\n .command(\"update <modelRoute>\")\n .description(\"Update a model\")\n .option(\"--kind <kind>\", \"Model kind\")\n .option(\"--display-name <name>\", \"Model display name\")\n .option(\"--generate\", \"Mark model as generation-capable\")\n .option(\"--edit\", \"Mark model as edit-capable\")\n .option(\n \"--max-count <count>\",\n \"Maximum generated asset count\",\n parseNumberOption,\n ),\n ).action(async (modelRoute, options) => {\n sink(await controllers.modelsController.update(modelRoute, options));\n });\n\n withOutputOptions(\n models.command(\"remove <modelRoute>\").description(\"Remove a model\"),\n ).action(async (modelRoute) => {\n sink(await controllers.modelsController.remove(modelRoute));\n });\n};\n\nconst registerSecretsCommands = (\n program: Command,\n controllers: AigenCommandControllers,\n sink: AigenCommandOutputSink,\n): void => {\n const secrets = program\n .command(\"secrets\")\n .description(\"Manage provider API keys\");\n\n withOutputOptions(\n secrets.command(\"list\").description(\"List masked provider secrets\"),\n ).action(async () => {\n sink(await controllers.secretsController.list());\n });\n\n withOutputOptions(\n secrets\n .command(\"get <providerId>\")\n .description(\"Get masked provider secret metadata\"),\n ).action(async (providerId) => {\n sink(await controllers.secretsController.get(providerId));\n });\n\n withOutputOptions(\n secrets\n .command(\"set <providerId>\")\n .description(\"Set provider API key from stdin\")\n .option(\"--stdin\", \"Read provider API key from stdin\", false),\n ).action(async (providerId) => {\n sink(await controllers.secretsController.set(providerId));\n });\n\n withOutputOptions(\n secrets\n .command(\"remove <providerId>\")\n .description(\"Remove provider API key\"),\n ).action(async (providerId) => {\n sink(await controllers.secretsController.remove(providerId));\n });\n};\n\nconst registerDoctorCommand = (\n program: Command,\n controllers: AigenCommandControllers,\n sink: AigenCommandOutputSink,\n): void => {\n withOutputOptions(\n program\n .command(\"doctor\")\n .description(\"Run local configuration diagnostics\")\n .option(\"--provider <providerId>\", \"Provider id to check\")\n .option(\"--model <modelRoute>\", \"Model route to check\"),\n ).action(async (options) => {\n sink(await controllers.doctorController.run(options));\n });\n};\n\nconst withOutputOptions = (command: Command): Command =>\n command\n .option(\"--json\", \"Output JSON\", false)\n .option(\"--debug\", \"Print debug diagnostics to stderr\", false);\n\nconst parseNumberOption = (value: string): number => {\n const parsed = Number(value);\n\n if (!Number.isFinite(parsed)) {\n throw new InvalidArgumentError(\"must be a number\");\n }\n\n return parsed;\n};\n","import type { ConfigRepository } from \"@/repositories/config.repository.js\";\nimport type { SecretsRepository } from \"@/repositories/secrets.repository.js\";\nimport type { AigenImageInput, AigenImageSuccessOutput } from \"@/types/image-generation.types.js\";\nimport type { OutputFileManager } from \"./output-file.manager.js\";\nimport type { ProviderRuntimeManager } from \"./provider-runtime.manager.js\";\nimport { parseModelRoute } from \"@/utils/route.utils.js\";\n\nexport class ImageGenerationManager {\n constructor(\n private readonly configRepository: ConfigRepository,\n private readonly secretsRepository: SecretsRepository,\n private readonly providerRuntimeManager: ProviderRuntimeManager,\n private readonly outputFileManager: OutputFileManager,\n ) {}\n\n generate = async (input: AigenImageInput): Promise<AigenImageSuccessOutput> => {\n const route = parseModelRoute(input.model);\n const providerConfig = await this.configRepository.getProvider(route.providerId);\n await this.configRepository.getModel(route.providerId, route.providerLocalModel);\n\n const provider = this.providerRuntimeManager.getImageProvider(providerConfig.apiFormat);\n const apiKey = await this.secretsRepository.getProviderApiKey(route.providerId);\n const result = await provider.generateImage(\n {\n providerLocalModel: route.providerLocalModel,\n prompt: input.prompt,\n size: input.size,\n n: input.n ?? 1,\n quality: input.quality,\n background: input.background,\n outputFormat: input.outputFormat,\n outputCompression: input.outputCompression,\n moderation: input.moderation\n },\n {\n providerId: route.providerId,\n apiFormat: providerConfig.apiFormat,\n apiBase: providerConfig.apiBase,\n apiKey,\n headers: providerConfig.headers\n },\n );\n const assets = await this.outputFileManager.writeImages(result.images, input.outputDir, input.outputName);\n\n return {\n ok: true,\n kind: \"image\",\n provider: route.providerId,\n apiFormat: providerConfig.apiFormat,\n model: input.model,\n providerLocalModel: route.providerLocalModel,\n assets,\n usage: result.usage,\n metadata: {\n ...result.metadata,\n upstreamRequestId: result.upstreamRequestId\n }\n };\n };\n}\n","export const mimeTypeToExtension = (mimeType: string): string => {\n switch (mimeType.toLowerCase()) {\n case \"image/jpeg\":\n case \"image/jpg\":\n return \"jpg\";\n case \"image/png\":\n return \"png\";\n case \"image/webp\":\n return \"webp\";\n case \"image/gif\":\n return \"gif\";\n default:\n return \"bin\";\n }\n};\n\nexport const extensionToMimeType = (extension: string): string => {\n switch (extension.toLowerCase()) {\n case \"jpg\":\n case \"jpeg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"webp\":\n return \"image/webp\";\n case \"gif\":\n return \"image/gif\";\n default:\n return \"application/octet-stream\";\n }\n};\n","import { mkdir, stat, writeFile } from \"node:fs/promises\";\nimport { basename, resolve } from \"node:path\";\n\nimport { AigenError } from \"@/types/cli-output.types.js\";\nimport type { AigenImageAsset } from \"@/types/image-generation.types.js\";\nimport type { AigenProviderImage } from \"@/types/provider.types.js\";\nimport { mimeTypeToExtension } from \"@/utils/mime.utils.js\";\n\nexport class OutputFileManager {\n writeImages = async (\n images: AigenProviderImage[],\n outputDir: string,\n outputName: string,\n ): Promise<AigenImageAsset[]> => {\n this.assertOutputName(outputName);\n await mkdir(outputDir, { recursive: true });\n\n const resolvedOutputDir = resolve(outputDir);\n const assets: AigenImageAsset[] = [];\n\n for (let index = 0; index < images.length; index += 1) {\n const image = images[index];\n const extension = image.format ?? mimeTypeToExtension(image.mimeType);\n const filename = this.createFilename(outputName, extension, images.length, index);\n const path = resolve(resolvedOutputDir, filename);\n\n this.assertContainedPath(resolvedOutputDir, path);\n await writeFile(path, image.bytes, { flag: \"wx\" });\n\n const fileStat = await stat(path);\n assets.push({\n path,\n filename,\n mimeType: image.mimeType,\n format: extension,\n width: image.width,\n height: image.height,\n sizeBytes: fileStat.size\n });\n }\n\n return assets;\n };\n\n private assertOutputName = (outputName: string): void => {\n if (!outputName || outputName !== basename(outputName) || outputName.includes(\"/\") || outputName.includes(\"\\\\\")) {\n throw new AigenError(\"INVALID_ARGUMENT\", \"output-name must be a basename without path separators.\");\n }\n };\n\n private assertContainedPath = (outputDir: string, path: string): void => {\n if (path !== outputDir && !path.startsWith(`${outputDir}/`)) {\n throw new AigenError(\"FILE_WRITE_FAILED\", \"Generated file path escaped output-dir.\");\n }\n };\n\n private createFilename = (outputName: string, extension: string, count: number, index: number): string => {\n const suffix = count === 1 ? \"\" : `-${index + 1}`;\n return `${outputName}${suffix}.${extension}`;\n };\n}\n","import type { AigenMediaKind } from \"./config.types.js\";\n\nexport type AigenProviderContext = {\n providerId: string;\n apiFormat: string;\n apiBase: string;\n apiKey: string;\n headers?: Record<string, string>;\n};\n\nexport type AigenProviderImageRequest = {\n providerLocalModel: string;\n prompt: string;\n size?: string;\n n: number;\n quality?: string;\n background?: string;\n outputFormat?: string;\n outputCompression?: number;\n moderation?: string;\n};\n\nexport type AigenProviderImage = {\n bytes: Uint8Array;\n mimeType: string;\n format?: string;\n width?: number;\n height?: number;\n revisedPrompt?: string;\n};\n\nexport type AigenProviderImageResult = {\n images: AigenProviderImage[];\n usage?: Record<string, unknown>;\n upstreamRequestId?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport interface AigenImageProvider {\n readonly apiFormat: string;\n\n generateImage(\n request: AigenProviderImageRequest,\n context: AigenProviderContext,\n ): Promise<AigenProviderImageResult>;\n}\n\nexport type AigenRemoteModelListRequest = {\n kind?: AigenMediaKind;\n};\n\nexport type AigenRemoteModel = {\n providerLocalModel: string;\n displayName?: string;\n inputModalities?: string[];\n outputModalities?: string[];\n pricing?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n};\n\nexport type AigenRemoteModelListResult = {\n models: AigenRemoteModel[];\n metadata?: Record<string, unknown>;\n};\n\nexport interface AigenRemoteModelListProvider {\n listRemoteModels(\n request: AigenRemoteModelListRequest,\n context: AigenProviderContext,\n ): Promise<AigenRemoteModelListResult>;\n}\n\nexport const isRemoteModelListProvider = (\n provider: AigenImageProvider,\n): provider is AigenImageProvider & AigenRemoteModelListProvider =>\n \"listRemoteModels\" in provider && typeof provider.listRemoteModels === \"function\";\n","import { AigenError } from \"@/types/cli-output.types.js\";\nimport {\n isRemoteModelListProvider,\n type AigenImageProvider,\n type AigenRemoteModelListProvider\n} from \"@/types/provider.types.js\";\n\nexport class ProviderRuntimeManager {\n private readonly providers = new Map<string, AigenImageProvider>();\n\n constructor(providers: AigenImageProvider[]) {\n providers.forEach((provider) => {\n this.providers.set(provider.apiFormat, provider);\n });\n }\n\n getImageProvider = (apiFormat: string): AigenImageProvider => {\n const provider = this.providers.get(apiFormat);\n\n if (!provider) {\n throw new AigenError(\"PROVIDER_RUNTIME_NOT_FOUND\", `API format '${apiFormat}' is not supported.`);\n }\n\n return provider;\n };\n\n getRemoteModelListProvider = (apiFormat: string): AigenImageProvider & AigenRemoteModelListProvider => {\n const provider = this.getImageProvider(apiFormat);\n\n if (!isRemoteModelListProvider(provider)) {\n throw new AigenError(\"UNSUPPORTED_PARAMETER\", `API format '${apiFormat}' does not support remote model list.`);\n }\n\n return provider;\n };\n}\n","import { AigenError } from \"@/types/cli-output.types.js\";\n\nexport type ParsedDataUrl = {\n mimeType: string;\n bytes: Uint8Array;\n};\n\nexport const parseImageDataUrl = (value: string): ParsedDataUrl => {\n const match = /^data:([^;,]+);base64,(.+)$/s.exec(value);\n\n if (!match) {\n throw new AigenError(\"PROVIDER_REQUEST_FAILED\", \"Provider returned an invalid image data URL.\");\n }\n\n return {\n mimeType: match[1] ?? \"application/octet-stream\",\n bytes: Uint8Array.from(Buffer.from(match[2] ?? \"\", \"base64\"))\n };\n};\n\nexport const isDataUrl = (value: string): boolean => value.startsWith(\"data:\");\n","import { AigenError } from \"@/types/cli-output.types.js\";\nimport type {\n AigenImageProvider,\n AigenProviderContext,\n AigenProviderImageResult,\n AigenProviderImageRequest,\n AigenRemoteModelListProvider,\n AigenRemoteModelListRequest,\n AigenRemoteModelListResult\n} from \"@/types/provider.types.js\";\nimport { isDataUrl, parseImageDataUrl } from \"@/utils/data-url.utils.js\";\nimport { extensionToMimeType } from \"@/utils/mime.utils.js\";\n\ntype JsonRecord = Record<string, unknown>;\n\nexport class OpenRouterProvider implements AigenImageProvider, AigenRemoteModelListProvider {\n readonly apiFormat = \"openrouter\";\n\n generateImage = async (\n request: AigenProviderImageRequest,\n context: AigenProviderContext,\n ): Promise<AigenProviderImageResult> => {\n const response = await fetch(this.url(context.apiBase, \"/chat/completions\"), {\n method: \"POST\",\n headers: this.headers(context),\n body: JSON.stringify(this.toChatCompletionsBody(request))\n });\n\n const payload = await this.readJson(response);\n\n if (!response.ok) {\n throw new AigenError(\"PROVIDER_REQUEST_FAILED\", \"OpenRouter image generation request failed.\", {\n retryable: response.status >= 500\n });\n }\n\n return {\n images: await this.extractImages(payload),\n usage: this.recordOrUndefined(payload.usage),\n upstreamRequestId: this.stringOrUndefined(payload.id),\n metadata: {\n model: this.stringOrUndefined(payload.model)\n }\n };\n };\n\n listRemoteModels = async (\n _request: AigenRemoteModelListRequest,\n context: AigenProviderContext,\n ): Promise<AigenRemoteModelListResult> => {\n const response = await fetch(this.url(context.apiBase, \"/models?output_modalities=image\"), {\n method: \"GET\",\n headers: this.headers(context)\n });\n const payload = await this.readJson(response);\n\n if (!response.ok) {\n throw new AigenError(\"PROVIDER_REQUEST_FAILED\", \"OpenRouter models request failed.\", {\n retryable: response.status >= 500\n });\n }\n\n const data = Array.isArray(payload.data) ? payload.data : [];\n\n return {\n models: data.flatMap((entry) => {\n const model = this.recordOrUndefined(entry);\n const id = this.stringOrUndefined(model?.id);\n\n if (!model || !id) {\n return [];\n }\n\n return [\n {\n providerLocalModel: id,\n displayName: this.stringOrUndefined(model.name),\n inputModalities: this.stringArrayOrUndefined(this.recordOrUndefined(model.architecture)?.input_modalities),\n outputModalities: this.stringArrayOrUndefined(this.recordOrUndefined(model.architecture)?.output_modalities),\n pricing: this.recordOrUndefined(model.pricing),\n metadata: model\n }\n ];\n })\n };\n };\n\n private toChatCompletionsBody = (request: AigenProviderImageRequest): JsonRecord => {\n const body: JsonRecord = {\n model: request.providerLocalModel,\n messages: [\n {\n role: \"user\",\n content: request.prompt\n }\n ],\n modalities: [\"image\"],\n stream: false\n };\n\n if (request.size) {\n body.image_config = {\n image_size: request.size\n };\n }\n\n return body;\n };\n\n private extractImages = async (payload: JsonRecord): Promise<AigenProviderImageResult[\"images\"]> => {\n const choices = Array.isArray(payload.choices) ? payload.choices : [];\n const urls = choices.flatMap((choice) => this.extractImageUrls(choice));\n\n if (urls.length === 0) {\n throw new AigenError(\"PROVIDER_REQUEST_FAILED\", \"OpenRouter response did not include generated images.\");\n }\n\n return Promise.all(urls.map((url) => this.loadImageUrl(url)));\n };\n\n private extractImageUrls = (choice: unknown): string[] => {\n const message = this.recordOrUndefined(this.recordOrUndefined(choice)?.message);\n const images = Array.isArray(message?.images) ? message.images : [];\n\n return images.flatMap((image) => {\n const url = this.stringOrUndefined(this.recordOrUndefined(this.recordOrUndefined(image)?.image_url)?.url);\n return url ? [url] : [];\n });\n };\n\n private loadImageUrl = async (url: string): Promise<AigenProviderImageResult[\"images\"][number]> => {\n if (isDataUrl(url)) {\n const dataUrl = parseImageDataUrl(url);\n return {\n bytes: dataUrl.bytes,\n mimeType: dataUrl.mimeType\n };\n }\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new AigenError(\"PROVIDER_REQUEST_FAILED\", \"Failed to download generated image.\", {\n retryable: response.status >= 500\n });\n }\n\n const contentType = response.headers.get(\"content-type\") ?? this.mimeTypeFromUrl(url);\n return {\n bytes: new Uint8Array(await response.arrayBuffer()),\n mimeType: contentType\n };\n };\n\n private readJson = async (response: Response): Promise<JsonRecord> => {\n const value = (await response.json()) as unknown;\n const record = this.recordOrUndefined(value);\n\n if (!record) {\n throw new AigenError(\"PROVIDER_REQUEST_FAILED\", \"Provider returned a non-object JSON response.\");\n }\n\n return record;\n };\n\n private headers = (context: AigenProviderContext): HeadersInit => ({\n authorization: `Bearer ${context.apiKey}`,\n \"content-type\": \"application/json\",\n ...context.headers\n });\n\n private url = (apiBase: string, path: string): string => `${apiBase.replace(/\\/$/, \"\")}${path}`;\n\n private recordOrUndefined = (value: unknown): JsonRecord | undefined =>\n value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonRecord) : undefined;\n\n private stringOrUndefined = (value: unknown): string | undefined => (typeof value === \"string\" ? value : undefined);\n\n private stringArrayOrUndefined = (value: unknown): string[] | undefined =>\n Array.isArray(value) && value.every((item) => typeof item === \"string\") ? value : undefined;\n\n private mimeTypeFromUrl = (url: string): string => {\n const extension = url.split(\"?\")[0]?.split(\".\").pop();\n return extension ? extensionToMimeType(extension) : \"application/octet-stream\";\n };\n}\n","export type AigenMediaKind = \"image\" | \"video\" | \"audio\";\n\nexport type AigenModelCapabilities = {\n generate?: boolean;\n edit?: boolean;\n maxCount?: number;\n sizes?: string[];\n outputFormats?: string[];\n qualities?: string[];\n supportsTransparentBackground?: boolean;\n};\n\nexport type AigenModelConfig = {\n kind: AigenMediaKind;\n displayName?: string;\n capabilities?: AigenModelCapabilities;\n};\n\nexport type AigenProviderConfig = {\n apiFormat: string;\n displayName?: string;\n apiBase: string;\n apiKeyRef: string;\n headers?: Record<string, string>;\n models: Record<string, AigenModelConfig>;\n};\n\nexport type AigenConfig = {\n version: 1;\n providers: Record<string, AigenProviderConfig>;\n};\n\nexport const createEmptyAigenConfig = (): AigenConfig => ({\n version: 1,\n providers: {}\n});\n","import { mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { AigenError } from \"@/types/cli-output.types.js\";\nimport {\n createEmptyAigenConfig,\n type AigenConfig,\n type AigenModelConfig,\n type AigenProviderConfig\n} from \"@/types/config.types.js\";\nimport { assertResourceId } from \"@/utils/route.utils.js\";\n\nexport class ConfigRepository {\n readonly homeDir: string;\n readonly configPath: string;\n\n constructor(homeDir = process.env.AIGEN_HOME ?? join(homedir(), \".aigen\")) {\n this.homeDir = homeDir;\n this.configPath = join(homeDir, \"config.json\");\n }\n\n readConfig = async (): Promise<AigenConfig> => {\n try {\n const text = await readFile(this.configPath, \"utf8\");\n return this.parseConfig(text);\n } catch (error) {\n if (this.isNotFoundError(error)) {\n throw new AigenError(\"CONFIG_NOT_FOUND\", \"aigen config.json does not exist.\");\n }\n\n throw error;\n }\n };\n\n readConfigOrCreate = async (): Promise<AigenConfig> => {\n try {\n return await this.readConfig();\n } catch (error) {\n if (error instanceof AigenError && error.code === \"CONFIG_NOT_FOUND\") {\n return createEmptyAigenConfig();\n }\n\n throw error;\n }\n };\n\n writeConfig = async (config: AigenConfig): Promise<void> => {\n await mkdir(this.homeDir, { recursive: true });\n await writeFile(this.configPath, `${JSON.stringify(config, null, 2)}\\n`, { mode: 0o600 });\n };\n\n listProviders = async (): Promise<Array<{ id: string; config: AigenProviderConfig }>> => {\n const config = await this.readConfig();\n return Object.entries(config.providers).map(([id, providerConfig]) => ({\n id,\n config: providerConfig\n }));\n };\n\n getProvider = async (providerId: string): Promise<AigenProviderConfig> => {\n const config = await this.readConfig();\n const providerConfig = config.providers[providerId];\n\n if (!providerConfig) {\n throw new AigenError(\"PROVIDER_NOT_FOUND\", `Provider '${providerId}' does not exist.`);\n }\n\n return providerConfig;\n };\n\n addProvider = async (providerId: string, providerConfig: AigenProviderConfig): Promise<void> => {\n assertResourceId(providerId, \"Provider id\");\n const config = await this.readConfigOrCreate();\n\n if (config.providers[providerId]) {\n throw new AigenError(\"INVALID_ARGUMENT\", `Provider '${providerId}' already exists.`);\n }\n\n config.providers[providerId] = providerConfig;\n await this.writeConfig(config);\n };\n\n updateProvider = async (\n providerId: string,\n patch: Partial<Omit<AigenProviderConfig, \"models\">>,\n ): Promise<AigenProviderConfig> => {\n const config = await this.readConfig();\n const current = config.providers[providerId];\n\n if (!current) {\n throw new AigenError(\"PROVIDER_NOT_FOUND\", `Provider '${providerId}' does not exist.`);\n }\n\n const next: AigenProviderConfig = {\n ...current,\n apiFormat: patch.apiFormat ?? current.apiFormat,\n displayName: patch.displayName ?? current.displayName,\n apiBase: patch.apiBase ?? current.apiBase,\n apiKeyRef: patch.apiKeyRef ?? current.apiKeyRef,\n headers: patch.headers ?? current.headers\n };\n\n config.providers[providerId] = next;\n await this.writeConfig(config);\n return next;\n };\n\n removeProvider = async (providerId: string): Promise<void> => {\n const config = await this.readConfig();\n\n if (!config.providers[providerId]) {\n throw new AigenError(\"PROVIDER_NOT_FOUND\", `Provider '${providerId}' does not exist.`);\n }\n\n delete config.providers[providerId];\n await this.writeConfig(config);\n };\n\n listModels = async (\n providerId?: string,\n kind?: string,\n ): Promise<\n Array<{ route: string; providerId: string; providerLocalModel: string; config: AigenModelConfig }>\n > => {\n const config = await this.readConfig();\n const providers = providerId\n ? [[providerId, await this.getProvider(providerId)] as const]\n : Object.entries(config.providers);\n\n return providers.flatMap(([id, providerConfig]) =>\n Object.entries(providerConfig.models)\n .filter(([, modelConfig]) => !kind || modelConfig.kind === kind)\n .map(([providerLocalModel, modelConfig]) => ({\n route: `${id}/${providerLocalModel}`,\n providerId: id,\n providerLocalModel,\n config: modelConfig\n })),\n );\n };\n\n getModel = async (providerId: string, providerLocalModel: string): Promise<AigenModelConfig> => {\n const providerConfig = await this.getProvider(providerId);\n const modelConfig = providerConfig.models[providerLocalModel];\n\n if (!modelConfig) {\n throw new AigenError(\"MODEL_NOT_FOUND\", `Model '${providerId}/${providerLocalModel}' does not exist.`);\n }\n\n return modelConfig;\n };\n\n addModel = async (\n providerId: string,\n providerLocalModel: string,\n modelConfig: AigenModelConfig,\n ): Promise<void> => {\n const config = await this.readConfig();\n const providerConfig = config.providers[providerId];\n\n if (!providerConfig) {\n throw new AigenError(\"PROVIDER_NOT_FOUND\", `Provider '${providerId}' does not exist.`);\n }\n\n if (providerConfig.models[providerLocalModel]) {\n throw new AigenError(\"INVALID_ARGUMENT\", `Model '${providerId}/${providerLocalModel}' already exists.`);\n }\n\n providerConfig.models[providerLocalModel] = modelConfig;\n await this.writeConfig(config);\n };\n\n updateModel = async (\n providerId: string,\n providerLocalModel: string,\n patch: Partial<AigenModelConfig>,\n ): Promise<AigenModelConfig> => {\n const config = await this.readConfig();\n const providerConfig = config.providers[providerId];\n\n if (!providerConfig) {\n throw new AigenError(\"PROVIDER_NOT_FOUND\", `Provider '${providerId}' does not exist.`);\n }\n\n const current = providerConfig.models[providerLocalModel];\n\n if (!current) {\n throw new AigenError(\"MODEL_NOT_FOUND\", `Model '${providerId}/${providerLocalModel}' does not exist.`);\n }\n\n const next: AigenModelConfig = {\n ...current,\n kind: patch.kind ?? current.kind,\n displayName: patch.displayName ?? current.displayName,\n capabilities: patch.capabilities ?? current.capabilities\n };\n\n providerConfig.models[providerLocalModel] = next;\n await this.writeConfig(config);\n return next;\n };\n\n removeModel = async (providerId: string, providerLocalModel: string): Promise<void> => {\n const config = await this.readConfig();\n const providerConfig = config.providers[providerId];\n\n if (!providerConfig) {\n throw new AigenError(\"PROVIDER_NOT_FOUND\", `Provider '${providerId}' does not exist.`);\n }\n\n if (!providerConfig.models[providerLocalModel]) {\n throw new AigenError(\"MODEL_NOT_FOUND\", `Model '${providerId}/${providerLocalModel}' does not exist.`);\n }\n\n delete providerConfig.models[providerLocalModel];\n await this.writeConfig(config);\n };\n\n clear = async (): Promise<void> => {\n await rm(this.configPath, { force: true });\n };\n\n private parseConfig = (text: string): AigenConfig => {\n const value = JSON.parse(text) as Partial<AigenConfig>;\n\n if (value.version !== 1 || !value.providers || typeof value.providers !== \"object\") {\n throw new AigenError(\"CONFIG_INVALID\", \"aigen config.json is invalid.\");\n }\n\n return {\n version: 1,\n providers: value.providers\n };\n };\n\n private isNotFoundError = (error: unknown): boolean =>\n error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n","import { createHash } from \"node:crypto\";\nimport { chmod, mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { AigenError } from \"@/types/cli-output.types.js\";\n\ntype AigenSecretEntry = {\n kind: \"apiKey\";\n value: string;\n updatedAt: string;\n};\n\ntype AigenSecretsFile = {\n version: 1;\n secrets: Record<string, AigenSecretEntry>;\n};\n\nexport type AigenSecretMetadata = {\n ref: string;\n kind: \"apiKey\";\n exists: true;\n maskedValue: string;\n fingerprint: string;\n updatedAt: string;\n};\n\nexport class SecretsRepository {\n readonly homeDir: string;\n readonly secretsPath: string;\n\n constructor(homeDir = process.env.AIGEN_HOME ?? join(homedir(), \".aigen\")) {\n this.homeDir = homeDir;\n this.secretsPath = join(homeDir, \"secrets.json\");\n }\n\n setProviderApiKey = async (providerId: string, value: string): Promise<AigenSecretMetadata> => {\n const trimmedValue = value.trim();\n\n if (!trimmedValue) {\n throw new AigenError(\"INVALID_ARGUMENT\", \"API key cannot be empty.\");\n }\n\n const secretsFile = await this.readSecretsOrCreate();\n const ref = this.providerRef(providerId);\n\n secretsFile.secrets[ref] = {\n kind: \"apiKey\",\n value: trimmedValue,\n updatedAt: new Date().toISOString()\n };\n\n await this.writeSecrets(secretsFile);\n return this.toMetadata(ref, secretsFile.secrets[ref]);\n };\n\n getProviderApiKey = async (providerId: string): Promise<string> => {\n const ref = this.providerRef(providerId);\n const entry = await this.getSecretEntry(ref);\n return entry.value;\n };\n\n getProviderSecret = async (providerId: string): Promise<AigenSecretMetadata> => {\n const ref = this.providerRef(providerId);\n const entry = await this.getSecretEntry(ref);\n return this.toMetadata(ref, entry);\n };\n\n listSecrets = async (): Promise<AigenSecretMetadata[]> => {\n const secretsFile = await this.readSecretsOrCreate();\n return Object.entries(secretsFile.secrets).map(([ref, entry]) => this.toMetadata(ref, entry));\n };\n\n removeProviderSecret = async (providerId: string): Promise<void> => {\n const secretsFile = await this.readSecretsOrCreate();\n const ref = this.providerRef(providerId);\n\n if (!secretsFile.secrets[ref]) {\n throw new AigenError(\"SECRET_NOT_FOUND\", `Secret '${ref}' does not exist.`);\n }\n\n delete secretsFile.secrets[ref];\n await this.writeSecrets(secretsFile);\n };\n\n clear = async (): Promise<void> => {\n await rm(this.secretsPath, { force: true });\n };\n\n private getSecretEntry = async (ref: string): Promise<AigenSecretEntry> => {\n const secretsFile = await this.readSecretsOrCreate();\n const entry = secretsFile.secrets[ref];\n\n if (!entry) {\n throw new AigenError(\"MISSING_API_KEY\", `Secret '${ref}' does not exist.`);\n }\n\n return entry;\n };\n\n private readSecretsOrCreate = async (): Promise<AigenSecretsFile> => {\n try {\n const text = await readFile(this.secretsPath, \"utf8\");\n const value = JSON.parse(text) as Partial<AigenSecretsFile>;\n\n if (value.version !== 1 || !value.secrets || typeof value.secrets !== \"object\") {\n throw new AigenError(\"CONFIG_INVALID\", \"aigen secrets.json is invalid.\");\n }\n\n return {\n version: 1,\n secrets: value.secrets as Record<string, AigenSecretEntry>\n };\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return {\n version: 1,\n secrets: {}\n };\n }\n\n throw error;\n }\n };\n\n private writeSecrets = async (secretsFile: AigenSecretsFile): Promise<void> => {\n await mkdir(this.homeDir, { recursive: true });\n await writeFile(this.secretsPath, `${JSON.stringify(secretsFile, null, 2)}\\n`, { mode: 0o600 });\n await chmod(this.secretsPath, 0o600);\n };\n\n private providerRef = (providerId: string): string => `provider:${providerId}`;\n\n private toMetadata = (ref: string, entry: AigenSecretEntry): AigenSecretMetadata => ({\n ref,\n kind: entry.kind,\n exists: true,\n maskedValue: this.maskValue(entry.value),\n fingerprint: this.fingerprint(entry.value),\n updatedAt: entry.updatedAt\n });\n\n private maskValue = (value: string): string => {\n if (value.length <= 8) {\n return \"********\";\n }\n\n return `${value.slice(0, 3)}...${value.slice(-4)}`;\n };\n\n private fingerprint = (value: string): string =>\n `sha256:${createHash(\"sha256\").update(value).digest(\"hex\").slice(0, 12)}`;\n}\n","import { AigenError, type AigenCommandFailure } from \"@/types/cli-output.types.js\";\n\nexport const toCommandFailure = (error: unknown): AigenCommandFailure => {\n if (error instanceof AigenError) {\n return {\n ok: false,\n error: {\n code: error.code,\n message: error.message,\n retryable: error.retryable\n }\n };\n }\n\n return {\n ok: false,\n error: {\n code: \"PROVIDER_REQUEST_FAILED\",\n message: error instanceof Error ? error.message : \"Unknown aigen failure.\",\n retryable: false\n }\n };\n};\n\nexport const assertNever = (value: never): never => {\n throw new AigenError(\"INVALID_ARGUMENT\", `Unsupported command: ${String(value)}`);\n};\n","import { readFileSync } from \"node:fs\";\nimport { Command, CommanderError } from \"commander\";\nimport { DoctorController } from \"@/controllers/doctor.controller.js\";\nimport { ImageController } from \"@/controllers/image.controller.js\";\nimport { ModelsController } from \"@/controllers/models.controller.js\";\nimport { ProvidersController } from \"@/controllers/providers.controller.js\";\nimport { SecretsController } from \"@/controllers/secrets.controller.js\";\nimport {\n registerAigenCommands,\n type AigenCommandOutputSink,\n} from \"@/app/register-aigen-commands.js\";\nimport { ImageGenerationManager } from \"@/managers/image-generation.manager.js\";\nimport { OutputFileManager } from \"@/managers/output-file.manager.js\";\nimport { ProviderRuntimeManager } from \"@/managers/provider-runtime.manager.js\";\nimport { OpenRouterProvider } from \"@/providers/openrouter.provider.js\";\nimport { ConfigRepository } from \"@/repositories/config.repository.js\";\nimport { SecretsRepository } from \"@/repositories/secrets.repository.js\";\nimport {\n AigenError,\n type AigenCommandOutput,\n} from \"@/types/cli-output.types.js\";\nimport { toCommandFailure } from \"@/utils/error.utils.js\";\n\nexport class AigenApp {\n constructor(\n private readonly imageController: ImageController,\n private readonly providersController: ProvidersController,\n private readonly modelsController: ModelsController,\n private readonly secretsController: SecretsController,\n private readonly doctorController: DoctorController,\n private readonly version = resolveAigenPackageVersion(),\n ) {}\n\n run = async (argv: string[]): Promise<AigenCommandOutput> => {\n let commandOutput: AigenCommandOutput | undefined;\n let commanderOut = \"\";\n let commanderErr = \"\";\n const program = this.createProgram((output) => {\n commandOutput = output;\n });\n\n program.configureOutput({\n writeOut: (value) => {\n commanderOut += value;\n },\n writeErr: (value) => {\n commanderErr += value;\n },\n });\n\n try {\n if (argv.length === 0) {\n throw new AigenError(\"INVALID_ARGUMENT\", \"Missing command.\");\n }\n\n await program.parseAsync(argv, { from: \"user\" });\n return (\n commandOutput ?? {\n ok: true,\n output: commanderOut.trim(),\n }\n );\n } catch (error) {\n if (error instanceof CommanderError) {\n return this.commanderFailure(error, commanderOut, commanderErr);\n }\n\n return toCommandFailure(error);\n }\n };\n\n private createProgram = (sink: AigenCommandOutputSink): Command => {\n const program = new Command();\n program\n .name(\"aigen\")\n .description(\"Stateless AI media generation CLI.\")\n .version(this.version, \"-v, --version\");\n program.exitOverride();\n program.showHelpAfterError();\n\n registerAigenCommands(\n program,\n {\n imageController: this.imageController,\n providersController: this.providersController,\n modelsController: this.modelsController,\n secretsController: this.secretsController,\n doctorController: this.doctorController,\n },\n sink,\n );\n\n return program;\n };\n\n private commanderFailure = (\n error: CommanderError,\n capturedOutput: string,\n capturedError: string,\n ): AigenCommandOutput => {\n const output = capturedOutput.trim();\n\n if (error.exitCode === 0) {\n return {\n ok: true,\n output,\n };\n }\n\n return {\n ok: false,\n error: {\n code: \"INVALID_ARGUMENT\",\n message: capturedError.trim() || error.message,\n retryable: false,\n },\n };\n };\n}\n\nexport const createAigenApp = (homeDir?: string): AigenApp => {\n const configRepository = new ConfigRepository(homeDir);\n const secretsRepository = new SecretsRepository(homeDir);\n const providerRuntimeManager = new ProviderRuntimeManager([\n new OpenRouterProvider(),\n ]);\n const outputFileManager = new OutputFileManager();\n const imageGenerationManager = new ImageGenerationManager(\n configRepository,\n secretsRepository,\n providerRuntimeManager,\n outputFileManager,\n );\n\n return new AigenApp(\n new ImageController(imageGenerationManager),\n new ProvidersController(configRepository),\n new ModelsController(\n configRepository,\n secretsRepository,\n providerRuntimeManager,\n ),\n new SecretsController(secretsRepository),\n new DoctorController(\n configRepository,\n secretsRepository,\n providerRuntimeManager,\n ),\n );\n};\n\nconst resolveAigenPackageVersion = (): string => {\n const packageJsonUrl = new URL(\"../../package.json\", import.meta.url);\n const packageJson = JSON.parse(readFileSync(packageJsonUrl, \"utf8\")) as {\n version?: unknown;\n };\n\n return typeof packageJson.version === \"string\" ? packageJson.version : \"0.0.0\";\n};\n","#!/usr/bin/env node\nimport { createAigenApp } from \"./aigen-app.js\";\n\nconst app = createAigenApp();\nconst output = await app.run(process.argv.slice(2));\n\nprocess.stdout.write(`${JSON.stringify(output, null, 2)}\\n`);\nprocess.exitCode = output.ok ? 0 : 1;\n"],"mappings":"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"}
|