#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const proxyFetch_1 = require("./proxyFetch");
(0, proxyFetch_1.installProxyFetch)();
const commander_1 = require("commander");
const clientInfo_1 = require("./clientInfo");
const login_1 = require("./commands/login");
const whoami_1 = require("./commands/whoami");
const logout_1 = require("./commands/logout");
const accounts_1 = require("./commands/accounts");
const browse_1 = require("./commands/browse");
const search_1 = require("./commands/search");
const tags_1 = require("./commands/tags");
const detail_1 = require("./commands/detail");
const play_1 = require("./commands/play");
const ads_1 = require("./commands/ads");
const comments_1 = require("./commands/comments");
const versionsBrowse_1 = require("./commands/versionsBrowse");
const credits_1 = require("./commands/credits");
const boosts_1 = require("./commands/boosts");
const notifications_1 = require("./commands/notifications");
const creations_1 = require("./commands/creations");
const generation_1 = require("./commands/generation");
const init_1 = require("./commands/init");
const create_1 = require("./commands/create");
const createRemixContent_1 = require("./commands/createRemixContent");
const dev_1 = require("./commands/dev");
const devBrowser_1 = require("./commands/devBrowser");
const capture_1 = require("./commands/capture");
const devServer_1 = require("./commands/devServer");
const captureListing_1 = require("./commands/captureListing");
const captureRemote_1 = require("./commands/captureRemote");
const validate_1 = require("./commands/validate");
const build_1 = require("./commands/build");
const format_1 = require("./commands/format");
const upload_1 = require("./commands/upload");
const documentation_1 = require("./commands/documentation");
const feedback_1 = require("./commands/feedback");
const changelog_1 = require("./commands/changelog");
const publicPages_1 = require("./commands/publicPages");
const upgrade_1 = require("./commands/upgrade");
const messages_1 = require("./messages");
function resolveInitTarget(pathArg) {
    if (typeof pathArg === 'string' && pathArg.trim().length > 0) {
        return pathArg.trim();
    }
    return '.';
}
function printRemovedCommandHint(command) {
    const replacements = {
        list: 'playdrop browse',
        generate: 'playdrop ai create',
        generations: 'playdrop ai jobs browse',
        init: 'playdrop project init',
        create: 'playdrop project create app',
        dev: 'playdrop project dev',
        capture: 'playdrop project capture',
        validate: 'playdrop project validate',
        build: 'playdrop project build',
        format: 'playdrop project format',
        upload: 'playdrop project publish',
        upgrade: 'playdrop update',
        documentation: 'playdrop documentation browse',
        feedback: 'playdrop feedback send',
    };
    if (replacements[command]) {
        console.error(`"${command}" was removed from the clean-break CLI. Use "${replacements[command]}" instead.`);
        return;
    }
    if (command === 'assets') {
        console.error('"assets" was removed. Use "playdrop detail <creator>/asset/<name>", "playdrop versions browse <creator>/asset/<name>", or "playdrop creations assets ..." instead.');
        return;
    }
    if (command === 'asset-packs') {
        console.error('"asset-packs" was removed. Use "playdrop detail <creator>/asset-pack/<name>", "playdrop versions browse <creator>/asset-pack/<name>", or "playdrop creations asset-packs ..." instead.');
        return;
    }
    if (command === 'internal' || command === 'migrate-catalogue-v2' || command === 'download') {
        console.error(`"${command}" is not part of the redesigned CLI surface. Run "playdrop help" to see the supported commands.`);
        return;
    }
    console.error(`Unknown command "${command}". Run "playdrop help" for the current command tree.`);
}
const program = new commander_1.Command();
program
    .name('playdrop')
    .description('Playdrop CLI for creators and AI agents.')
    .usage('<command> [options]')
    .version((0, clientInfo_1.getCliVersionLabel)(), '-V, --version', 'Print CLI version')
    .addHelpCommand('help [command]', 'Show help for a command');
program.showHelpAfterError();
program.showSuggestionAfterError();
program.addHelpText('afterAll', '\nStart here: run `playdrop getting-started`, `playdrop faq`, or `playdrop changelog`.\n');
program.on('command:*', (unknownCommands) => {
    const [unknownCommand] = unknownCommands;
    if (unknownCommand) {
        printRemovedCommandHint(unknownCommand);
    }
    process.exitCode = 1;
});
function createEnvOption() {
    return new commander_1.Option('--env <env>', 'Environment (dev|local|prod|preview)').default('prod');
}
function collectRepeatedOption(value, previous = []) {
    return [...previous, value];
}
function registerLoginCommand(parent) {
    parent
        .command('login')
        .description('Log in to Playdrop')
        .addOption(createEnvOption())
        .option('--username <username>', 'Username for direct login')
        .option('--password <password>', 'Password for direct login')
        .option('--key <apiKey>', 'API key for direct login')
        .action(async (opts) => {
        await (0, login_1.login)(opts.env, {
            username: opts.username,
            password: opts.password,
            key: opts.key,
        });
    });
}
function registerLogoutCommand(parent) {
    parent
        .command('logout')
        .description('Log out of Playdrop')
        .argument('[username]', 'Username to log out')
        .option('--env <env>', 'Environment for targeted logout')
        .action((username, opts) => {
        (0, logout_1.logout)({ username, env: opts.env });
    });
}
function registerWhoamiCommand(parent) {
    parent
        .command('whoami')
        .description('Show the resolved account for this workspace')
        .option('--env <env>', 'Resolve this command against one logged-in environment')
        .action(async (opts) => {
        await (0, whoami_1.whoami)({ env: opts.env });
    });
}
function registerAccountsCommand(parent) {
    parent
        .command('accounts')
        .description('List stored Playdrop accounts')
        .action(() => {
        (0, accounts_1.listAccounts)();
    });
}
function registerUseAccountCommand(parent) {
    parent
        .command('use <username>')
        .description('Switch the default Playdrop account')
        .option('--env <env>', 'Environment for the selected account')
        .action((username, opts) => {
        (0, accounts_1.useAccount)(username, opts.env);
    });
}
registerLoginCommand(program);
registerLogoutCommand(program);
registerWhoamiCommand(program);
const auth = program.command('auth').description('Authentication commands');
registerLoginCommand(auth);
registerLogoutCommand(auth);
registerWhoamiCommand(auth);
registerAccountsCommand(auth);
registerUseAccountCommand(auth);
const browseCommand = program.command('browse').description('Browse public content');
browseCommand
    .option('--kind <kind>', 'app, asset, asset-pack, asset-spec, or all')
    .option('--creator <creator>', 'all, me, or a creator slug')
    .option('--app-type <type>', 'game, demo, tool, or template')
    .option('--auth <value>', 'App auth filter: required, optional, or none')
    .option('--surface <value>', 'App surface filter: desktop, mobile-portrait, or mobile-landscape')
    .option('--controller <value>', 'App controller filter: required, optional, or none')
    .option('--asset-category <category>', 'Asset category filter')
    .option('--asset-subcategory <subcategory>', 'Asset subcategory filter')
    .option('--asset-spec <ref>', 'Asset spec family or version filter for assets')
    .option('--asset-spec-owner <creator>', 'Asset spec owner filter for assets')
    .option('--asset-spec-name <name>', 'Asset spec name filter for assets')
    .option('--sort <sort>', 'Sort app, asset, or asset-spec browse results')
    .option('--limit <number>', 'Maximum number of results to return')
    .option('--offset <number>', 'Result offset')
    .option('--tag <ref>', 'Filter by canonical tag ref', collectRepeatedOption, [])
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, browse_1.browse)(opts);
});
browseCommand
    .command('categories')
    .description('Browse asset category definitions')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, browse_1.browseCategories)(opts);
});
program
    .command('search [query]')
    .description('Search public content')
    .option('--kind <kind>', 'app, asset, asset-pack, asset-spec, or all')
    .option('--creator <creator>', 'creator username filter')
    .option('--app-type <type>', 'game, demo, tool, or template')
    .option('--auth <value>', 'App auth filter: required, optional, or none')
    .option('--surface <value>', 'App surface filter: desktop, mobile-portrait, or mobile-landscape')
    .option('--controller <value>', 'App controller filter: required, optional, or none')
    .option('--asset-category <category>', 'Asset category filter')
    .option('--asset-subcategory <subcategory>', 'Asset subcategory filter')
    .option('--asset-spec <ref>', 'Asset spec family or version filter for assets')
    .option('--asset-spec-owner <creator>', 'Asset spec owner filter for assets')
    .option('--asset-spec-name <name>', 'Asset spec name filter for assets')
    .option('--sort <sort>', 'Sort search results')
    .option('--pack-contains-category <category>', 'Asset pack category filter')
    .option('--pack-contains-subcategory <subcategory>', 'Asset pack subcategory filter')
    .option('--limit <number>', 'Maximum number of results to return')
    .option('--offset <number>', 'Result offset')
    .option('--tag <ref>', 'Filter by canonical tag ref', collectRepeatedOption, [])
    .option('--json', 'Output JSON')
    .action(async (query, opts) => {
    await (0, search_1.search)(query, opts);
});
const tags = program.command('tags').description('Browse and inspect tags');
tags
    .command('browse')
    .description('Browse public tags')
    .option('--group <slug>', 'Filter to one tag group')
    .option('--kind <kind>', 'Filter to one target kind')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, tags_1.browseTags)(opts);
});
program
    .command('detail <ref>')
    .description('Show one app, asset, or asset pack')
    .option('--json', 'Output JSON')
    .action(async (ref, opts) => {
    await (0, detail_1.detail)(ref, opts);
});
program
    .command('play <ref>')
    .description('Open one published app in your browser with your current session')
    .option('--json', 'Output JSON')
    .action(async (ref, opts) => {
    await (0, play_1.play)(ref, opts);
});
const comments = program.command('comments').description('Comments for apps, assets, and asset packs');
comments
    .command('browse <ref>')
    .description('Browse comments for one item')
    .option('--json', 'Output JSON')
    .action(async (ref, opts) => {
    await (0, comments_1.browseComments)(ref, opts);
});
comments
    .command('add <ref>')
    .description('Add a comment to one item')
    .requiredOption('--body <text>', 'Comment text')
    .option('--reply-to <commentId>', 'Parent comment id')
    .option('--json', 'Output JSON')
    .action(async (ref, opts) => {
    await (0, comments_1.addComment)(ref, opts);
});
comments
    .command('delete <commentId>')
    .description('Delete a comment')
    .option('--json', 'Output JSON')
    .action(async (commentId, opts) => {
    await (0, comments_1.deleteComment)(commentId, opts);
});
const versions = program.command('versions').description('Version history');
versions
    .command('browse <ref>')
    .description('Browse versions or revisions for one item')
    .option('--limit <number>', 'Maximum number of results to return')
    .option('--offset <number>', 'Result offset')
    .option('--json', 'Output JSON')
    .action(async (ref, opts) => {
    await (0, versionsBrowse_1.browseVersions)(ref, opts);
});
const credits = program.command('credits').description('Credit balance and history');
credits
    .command('balance')
    .description('Show your credit balance')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, credits_1.showCreditBalance)(opts);
});
credits
    .command('transactions')
    .description('Browse your credit transactions')
    .option('--limit <number>', 'Maximum number of results to return')
    .option('--offset <number>', 'Result offset')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, credits_1.browseCreditTransactions)(opts);
});
credits
    .command('earnings')
    .description('Show creator ad earnings and boost spend summary')
    .option('--days <number>', 'Number of days to include')
    .option('--app-id <number>', 'Filter to one app id')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, credits_1.showCreatorEarnings)(opts);
});
const ads = program.command('ads').description('Creator ad earnings and reporting');
ads
    .command('earnings')
    .description('Show ad earnings grouped by app and format')
    .option('--app <ref>', 'Filter to one app ref')
    .option('--days <number>', 'Number of days to include')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, ads_1.showAdsEarnings)(opts);
});
ads
    .command('report')
    .description('Show daily ad reporting buckets')
    .option('--app <ref>', 'Filter to one app ref')
    .option('--days <number>', 'Number of days to include')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, ads_1.showAdsReport)(opts);
});
const boosts = program.command('boosts').description('Buy, activate, and inspect game boosts');
boosts
    .command('balance')
    .description('Show your available boost inventory')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, boosts_1.showBoostBalance)(opts);
});
boosts
    .command('offers')
    .description('List available boost packs')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, boosts_1.browseBoostOffers)(opts);
});
boosts
    .command('buy <sku>')
    .description('Buy one boost pack')
    .option('--quantity <number>', 'Number of packs to buy')
    .option('--json', 'Output JSON')
    .action(async (sku, opts) => {
    await (0, boosts_1.buyBoostPack)(sku, opts);
});
boosts
    .command('activate <ref>')
    .description('Activate one or more boosts for an app')
    .option('--units <number>', 'Number of boosts to consume')
    .option('--json', 'Output JSON')
    .action(async (ref, opts) => {
    await (0, boosts_1.activateBoost)(ref, opts);
});
boosts
    .command('status <ref>')
    .description('Show the current boost status for an app')
    .option('--json', 'Output JSON')
    .action(async (ref, opts) => {
    await (0, boosts_1.showBoostStatus)(ref, opts);
});
boosts
    .command('history <ref>')
    .description('Show past boost runs for an app')
    .option('--limit <number>', 'Maximum number of boost runs to include')
    .option('--json', 'Output JSON')
    .action(async (ref, opts) => {
    await (0, boosts_1.showBoostHistory)(ref, opts);
});
boosts
    .command('report <ref>')
    .description('Show daily boost performance for an app')
    .option('--days <number>', 'Number of days to include')
    .option('--json', 'Output JSON')
    .action(async (ref, opts) => {
    await (0, boosts_1.showBoostReport)(ref, opts);
});
const notifications = program.command('notifications').description('Notification inbox');
notifications
    .command('browse')
    .description('Browse notifications')
    .option('--status <status>', 'unread, read, or all')
    .option('--limit <number>', 'Maximum number of results to return')
    .option('--offset <number>', 'Result offset')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, notifications_1.browseNotifications)(opts);
});
notifications
    .command('read <id>')
    .description('Mark one notification as read')
    .option('--json', 'Output JSON')
    .action(async (id, opts) => {
    await (0, notifications_1.readNotification)(id, opts);
});
notifications
    .command('read-all')
    .description('Mark all notifications as read')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, notifications_1.readAllNotifications)(opts);
});
const creations = program.command('creations').description('Manage your creations');
creations
    .command('browse')
    .description('Browse your apps, assets, and asset packs')
    .option('--kind <kind>', 'app, asset, asset-pack, or all')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--limit <number>', 'Maximum number of results to return')
    .option('--offset <number>', 'Result offset')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, creations_1.browseCreations)(opts);
});
const creationApps = creations.command('apps').description('Manage app creations');
creationApps
    .command('update <name>')
    .description('Update app metadata')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--display-name <text>', 'Display name')
    .option('--type <type>', 'game, demo, tool, or template')
    .option('--json', 'Output JSON')
    .action(async (name, opts) => {
    await (0, creations_1.updateCreationApp)(name, opts);
});
creationApps
    .command('delete <name>')
    .description('Delete an app')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, opts) => {
    await (0, creations_1.deleteCreationApp)(name, opts);
});
const creationAppVersions = creationApps.command('versions').description('Manage app versions');
creationAppVersions
    .command('set-current <name> <version>')
    .description('Set the current app version')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, version, opts) => {
    await (0, creations_1.setCurrentCreationAppVersion)(name, version, opts);
});
creationAppVersions
    .command('publish <name> <version>')
    .description('Publish an app version')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, version, opts) => {
    await (0, creations_1.publishCreationAppVersion)(name, version, opts);
});
creationAppVersions
    .command('unpublish <name> <version>')
    .description('Unpublish an app version')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, version, opts) => {
    await (0, creations_1.unpublishCreationAppVersion)(name, version, opts);
});
creationAppVersions
    .command('delete <name> <version>')
    .description('Delete an app version')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, version, opts) => {
    await (0, creations_1.deleteCreationAppVersion)(name, version, opts);
});
const creationAssets = creations.command('assets').description('Manage asset creations');
creationAssets
    .command('update <name>')
    .description('Update asset metadata')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--name <slug>', 'New asset slug')
    .option('--display-name <text>', 'Display name')
    .option('--description <text>', 'Description')
    .option('--clear-description', 'Clear description')
    .option('--json', 'Output JSON')
    .action(async (name, opts) => {
    await (0, creations_1.updateCreationAsset)(name, opts);
});
creationAssets
    .command('delete <name>')
    .description('Delete an asset')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, opts) => {
    await (0, creations_1.deleteCreationAsset)(name, opts);
});
const creationAssetVersions = creationAssets.command('versions').description('Manage asset revisions');
creationAssetVersions
    .command('set-current <name> <revision>')
    .description('Set the current asset revision')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, revision, opts) => {
    await (0, creations_1.setCurrentCreationAssetVersion)(name, revision, opts);
});
creationAssetVersions
    .command('publish <name> <revision>')
    .description('Publish an asset revision')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, revision, opts) => {
    await (0, creations_1.publishCreationAssetVersion)(name, revision, opts);
});
creationAssetVersions
    .command('unpublish <name> <revision>')
    .description('Unpublish an asset revision')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, revision, opts) => {
    await (0, creations_1.unpublishCreationAssetVersion)(name, revision, opts);
});
creationAssetVersions
    .command('delete <name> <revision>')
    .description('Delete an asset revision')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, revision, opts) => {
    await (0, creations_1.deleteCreationAssetVersion)(name, revision, opts);
});
const creationAssetPacks = creations.command('asset-packs').description('Manage asset pack creations');
creationAssetPacks
    .command('update <name>')
    .description('Update asset pack metadata')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--name <slug>', 'New asset pack slug')
    .option('--display-name <text>', 'Display name')
    .option('--description <text>', 'Description')
    .option('--clear-description', 'Clear description')
    .option('--preview-app-version-id <id>', 'Preview app version id')
    .option('--clear-preview-app-version-id', 'Clear preview app version id')
    .option('--json', 'Output JSON')
    .action(async (name, opts) => {
    await (0, creations_1.updateCreationAssetPack)(name, opts);
});
creationAssetPacks
    .command('delete <name>')
    .description('Delete an asset pack')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, opts) => {
    await (0, creations_1.deleteCreationAssetPack)(name, opts);
});
const creationAssetPackVersions = creationAssetPacks.command('versions').description('Manage asset pack versions');
creationAssetPackVersions
    .command('set-current <name> <version>')
    .description('Set the current asset pack version')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, version, opts) => {
    await (0, creations_1.setCurrentCreationAssetPackVersion)(name, version, opts);
});
creationAssetPackVersions
    .command('publish <name> <version>')
    .description('Publish an asset pack version')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, version, opts) => {
    await (0, creations_1.publishCreationAssetPackVersion)(name, version, opts);
});
creationAssetPackVersions
    .command('unpublish <name> <version>')
    .description('Unpublish an asset pack version')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, version, opts) => {
    await (0, creations_1.unpublishCreationAssetPackVersion)(name, version, opts);
});
creationAssetPackVersions
    .command('delete <name> <version>')
    .description('Delete an asset pack version')
    .option('--creator <creator>', 'me or a creator slug')
    .option('--json', 'Output JSON')
    .action(async (name, version, opts) => {
    await (0, creations_1.deleteCreationAssetPackVersion)(name, version, opts);
});
const ai = program.command('ai').description('AI asset creation');
ai
    .command('create <type> <prompt>')
    .description('Create a new AI-generated asset')
    .option('--asset-name <slug>', 'Generated asset slug')
    .option('--asset-display-name <text>', 'Generated asset display name')
    .option('--asset-description <text>', 'Generated asset description')
    .option('--subcategory <slug>', 'Generated asset subcategory')
    .option('--visibility <visibility>', 'private or public')
    .option('--attach-app-version-id <id>', 'Attach generated asset to an app version')
    .option('--image1 <pathOrUrl>', 'Reference image one')
    .option('--image2 <pathOrUrl>', 'Reference image two')
    .option('--duration <value>', 'Duration value')
    .option('--instrumental', 'Force instrumental music generation')
    .option('--loop', 'Create a looping SFX')
    .option('--cover-prompt <text>', 'Cover prompt for music generation')
    .option('--voice <alias>', 'Speech voice alias')
    .option('--provider-voice-id <id>', 'Custom ElevenLabs speech voice id')
    .option('--ratio <ratio>', 'Aspect ratio')
    .option('--size <size>', 'Image size (image only)')
    .option('--resolution <resolution>', 'Resolution')
    .option('--source-mode <mode>', '3D source mode')
    .option('--topology <mode>', '3D topology mode')
    .option('--polycount <count>', '3D target polycount')
    .option('--remesh', 'Enable remeshing')
    .option('--texture', 'Enable texturing')
    .option('--timeout <seconds>', 'Wait timeout in seconds')
    .option('--poll <milliseconds>', 'Polling interval in milliseconds')
    .option('--json', 'Output JSON')
    .action(async (type, prompt, opts) => {
    await (0, generation_1.generate)(type, prompt, {
        subcategory: opts.subcategory,
        assetName: opts.assetName,
        assetDisplayName: opts.assetDisplayName,
        assetDescription: opts.assetDescription,
        visibility: opts.visibility,
        attachAppVersionId: opts.attachAppVersionId,
        image1: opts.image1,
        image2: opts.image2,
        duration: opts.duration,
        instrumental: opts.instrumental,
        loop: opts.loop,
        coverPrompt: opts.coverPrompt,
        voice: opts.voice,
        providerVoiceId: opts.providerVoiceId,
        ratio: opts.ratio,
        size: opts.size,
        resolution: opts.resolution,
        sourceMode: opts.sourceMode,
        topology: opts.topology,
        polycount: opts.polycount,
        remesh: opts.remesh,
        texture: opts.texture,
        timeoutSeconds: opts.timeout,
        pollIntervalMs: opts.poll,
        json: opts.json,
    });
});
const aiJobs = ai.command('jobs').description('Browse AI generation jobs');
aiJobs
    .command('browse')
    .description('Browse AI jobs')
    .option('--type <type>', 'image, music, sfx, speech, video, model_3d, or all')
    .option('--limit <number>', 'Maximum number of results to return')
    .option('--offset <number>', 'Result offset')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, generation_1.browseGenerationJobs)(opts);
});
ai
    .command('generations')
    .description('Browse AI generation history')
    .option('--type <type>', 'text, json, image, music, sfx, speech, video, model_3d, or all')
    .option('--limit <number>', 'Maximum number of results to return')
    .option('--offset <number>', 'Result offset')
    .option('--format <format>', 'text or json')
    .action(async (opts) => {
    await (0, generation_1.generations)(opts);
});
aiJobs
    .command('detail <id>')
    .description('Show one AI job')
    .option('--json', 'Output JSON')
    .action(async (id, opts) => {
    await (0, generation_1.showGenerationJob)(id, opts);
});
const project = program.command('project').description('Local workspace tooling');
const internalDevRouter = project.command('_dev-router').description('Internal shared dev router');
internalDevRouter
    .command('serve')
    .description('Run the internal shared dev router')
    .action(async () => {
    await (0, devServer_1.runDevRouterServer)();
});
project
    .command('init [path]')
    .description('Initialize a Playdrop workspace')
    .action(async (pathArg) => {
    await (0, init_1.init)(resolveInitTarget(pathArg));
});
const projectCreate = project.command('create').description('Create project resources');
projectCreate
    .command('app <name>')
    .description('Create a new app from a template or exact remix version')
    .option('--template <ref>', 'Template ref')
    .option('--remix <ref>', 'Canonical app version ref')
    .action(async (name, opts) => {
    await (0, create_1.create)(name, opts);
});
projectCreate
    .command('asset-spec <name>')
    .description('Create a new custom asset spec scaffold')
    .action(async (name) => {
    await (0, create_1.createAssetSpecProject)(name);
});
projectCreate
    .command('asset <name>')
    .description('Create a new asset remix from an exact asset version')
    .requiredOption('--remix <ref>', 'Canonical asset version ref')
    .action(async (name, opts) => {
    await (0, createRemixContent_1.createRemixContent)('asset', name, opts.remix);
});
projectCreate
    .command('pack <name>')
    .description('Create a new asset pack remix from an exact pack version')
    .requiredOption('--remix <ref>', 'Canonical pack version ref')
    .action(async (name, opts) => {
    await (0, createRemixContent_1.createRemixContent)('pack', name, opts.remix);
});
project
    .command('dev [target]')
    .description('Run an app locally')
    .option('--app <name>', 'App name when the target is a workspace')
    .option('--dev-auth <mode>', 'prompt, anonymous, viewer, or player')
    .option('--player <slot>', '1, 2, 3, or 4 when --dev-auth player is selected')
    .action(async (target, opts = {}) => {
    await (0, dev_1.dev)(target, undefined, opts.app, {
        devAuth: opts.devAuth,
        player: opts.player,
    });
});
project
    .command('dev-browser [target]')
    .description('Open the hosted /dev route in an isolated Chromium window')
    .option('--app <name>', 'App name when the target is a workspace')
    .option('--dev-auth <mode>', 'prompt, anonymous, viewer, or player')
    .option('--player <slot>', '1, 2, 3, or 4 when --dev-auth player is selected')
    .action(async (target, opts = {}) => {
    await (0, devBrowser_1.devBrowser)(target, {
        app: opts.app,
        devAuth: opts.devAuth,
        player: opts.player,
    });
});
const projectCapture = project.command('capture').description('Run a Playwright capture');
projectCapture
    .argument('[target]')
    .option('--app <name>', 'App name when the target is a workspace')
    .option('--timeout <seconds>', 'Capture timeout in seconds')
    .option('--log-level <level>', 'debug, info, warn, or error')
    .option('--screenshot <path>', 'Screenshot output path')
    .option('--surface <surface>', 'desktop, mobile-landscape, or mobile-portrait')
    .option('--dev-auth <mode>', 'anonymous, viewer, or player')
    .option('--player <slot>', '1, 2, 3, or 4 when --dev-auth player is selected')
    .option('--reset-dev-player <mode>', 'before, after, before-and-after, or never')
    .option('--username <username>', 'Override saved login username for this run')
    .option('--password <password>', 'Override saved login password for this run')
    .action(async (target, opts) => {
    const timeoutSeconds = opts.timeout !== undefined ? Number.parseFloat(String(opts.timeout)) : undefined;
    await (0, capture_1.capture)(target, {
        timeoutSeconds,
        appName: opts.app,
        logLevel: opts.logLevel,
        screenshotPath: opts.screenshot,
        surfaceTarget: opts.surface,
        devAuth: opts.devAuth,
        player: opts.player,
        resetDevPlayer: opts.resetDevPlayer,
        username: opts.username,
        password: opts.password,
    });
});
projectCapture
    .command('listing [target]', { hidden: true })
    .description('Record private listing video for a hosted app')
    .option('--app <name>', 'App name when the target is a workspace')
    .option('--duration <seconds>', 'Recording duration in seconds')
    .option('--width <pixels>', 'Final gameplay width in pixels')
    .option('--height <pixels>', 'Final gameplay height in pixels')
    .option('--fps <number>', 'Final output frame rate')
    .option('--poster-at <seconds>', 'Poster frame offset in seconds')
    .option('--audio', 'Capture gameplay audio')
    .option('--output-dir <path>', 'Output directory for the capture artifacts')
    .option('--keep-raw', 'Keep the raw intermediate recording')
    .action(async (target, opts) => {
    await (0, captureListing_1.captureListing)(target, {
        app: opts.app,
        duration: opts.duration,
        width: opts.width,
        height: opts.height,
        fps: opts.fps,
        posterAt: opts.posterAt,
        audio: opts.audio,
        outputDir: opts.outputDir,
        keepRaw: opts.keepRaw,
    });
});
projectCapture
    .command('remote <url>')
    .description('Run a Playwright capture against a published URL')
    .option('--timeout <seconds>', 'Capture timeout in seconds')
    .option('--screenshot <path>', 'Screenshot output path')
    .option('--log <path>', 'Log output path')
    .option('--expected-url <url>', 'Expected final URL after redirects')
    .option('--username <username>', 'Login username')
    .option('--password <password>', 'Login password')
    .option('--login-url <url>', 'Explicit login URL')
    .action(async (url, _opts, command) => {
    await (0, captureRemote_1.captureRemote)(url, {
        ...(command.parent?.opts() ?? {}),
        ...command.opts(),
    });
});
project
    .command('validate [target]')
    .description('Validate catalogue content')
    .option('--env <env>', 'Resolve this command against one logged-in environment')
    .action(async (target, opts) => {
    await (0, validate_1.validate)(target ?? '.', { env: opts.env });
});
project
    .command('build [target]')
    .description('Build local content')
    .action(async (target) => {
    await (0, build_1.build)(target ?? '.');
});
project
    .command('format [target]')
    .description('Run local formatting')
    .action(async (target) => {
    await (0, format_1.format)(target ?? '.');
});
project
    .command('publish [target]')
    .description('Publish local content to Playdrop')
    .option('--env <env>', 'Resolve this command against one logged-in environment')
    .option('--skip-ecs', 'Skip ecs.json and server.js during publish')
    .option('--clear-tags', 'Confirm clearing existing live tags when this publish removes them')
    .addOption(new commander_1.Option('--skip-review', 'Mark uploaded app versions as NOT_REQUIRED review. Admin-only.').hideHelp())
    .action(async (target, opts) => {
    await (0, upload_1.upload)(target ?? '.', {
        env: opts.env,
        skipEcs: opts.skipEcs,
        skipReview: opts.skipReview,
        clearTags: opts.clearTags,
    });
});
const documentation = program.command('documentation').description('Public Playdrop documentation');
documentation
    .command('browse')
    .description('Browse documentation entries')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, documentation_1.browseDocumentation)(opts);
});
documentation
    .command('read <path>')
    .description('Read one documentation entry')
    .action(async (pathArg) => {
    await (0, documentation_1.readDocumentation)(pathArg);
});
const feedback = program.command('feedback').description('Send or review feedback');
feedback
    .command('send')
    .description('Send feedback to the Playdrop team')
    .requiredOption('--title <title>', 'Feedback title')
    .option('--comment <text>', 'Feedback text')
    .option('--category <category>', 'Feedback category')
    .option('--file <path>', 'Load feedback text from a file')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, feedback_1.sendFeedback)(opts);
});
feedback
    .command('browse')
    .description('Browse feedback entries')
    .option('--limit <number>', 'Maximum number of results to return')
    .option('--offset <number>', 'Result offset')
    .option('--client <client>', 'Client filter')
    .option('--user-id <id>', 'User id filter')
    .option('--json', 'Output JSON')
    .action(async (opts) => {
    await (0, feedback_1.browseFeedback)(opts);
});
feedback
    .command('delete <id>', { hidden: true })
    .description('Delete one feedback entry')
    .option('--json', 'Output JSON')
    .action(async (id, opts) => {
    await (0, feedback_1.deleteFeedbackEntry)(id, opts);
});
program
    .command('getting-started')
    .description('Show the recommended first steps')
    .action(async () => {
    await (0, publicPages_1.showPublicPage)('getting-started', 'app-pages/getting-started.md');
});
program
    .command('faq')
    .description('Show creator-focused platform questions and answers')
    .action(async () => {
    await (0, publicPages_1.showPublicPage)('faq', 'app-pages/faq.md');
});
program
    .command('changelog')
    .description('Read the latest public Playdrop changelog')
    .action(async () => {
    await (0, changelog_1.showChangelog)();
});
program
    .command('start')
    .description('Alias of getting-started')
    .action(async () => {
    await (0, publicPages_1.showPublicPage)('getting-started', 'app-pages/getting-started.md');
});
program
    .command('update')
    .description('Update the Playdrop CLI')
    .option('--dry-run', 'Print the update command without running it')
    .action(async (opts) => {
    await (0, upgrade_1.upgrade)(Boolean(opts.dryRun));
});
program
    .command('version')
    .description('Print the Playdrop CLI version')
    .action(() => {
    console.log((0, clientInfo_1.getCliVersionLabel)());
});
if (process.argv.length <= 2) {
    program.outputHelp();
}
else {
    program.parseAsync(process.argv).catch((error) => {
        const message = error instanceof Error ? error.message : String(error);
        (0, messages_1.printErrorWithHelp)(message, [], {});
        process.exitCode = 1;
    });
}
