UNPKG

@agentled/cli

Version:

CLI for Agentled — manage workflows, apps, and knowledge from the command line. Zero context-window cost for AI agents.

638 lines 33.4 kB
import { readFileSync } from 'node:fs'; import { randomUUID } from 'node:crypto'; import { AgentledClient } from '../client.js'; import { printError, printOutput } from '../utils/output.js'; function readJson(opts, label) { if (!opts.input && !opts.file) throw new Error(`Provide ${label} via --input '<json>' or --file <path>`); if (opts.input && opts.file) throw new Error(`Provide ${label} with either --input or --file, not both`); const raw = opts.file ? readFileSync(opts.file, 'utf8') : opts.input; return JSON.parse(raw); } function parseCsvList(value) { if (value === undefined) return undefined; return value .split(',') .map((item) => item.trim()) .filter(Boolean); } function parseJsonOption(value, label) { if (value === undefined) return undefined; try { const parsed = JSON.parse(value); if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { throw new Error(`${label} must be a JSON object`); } return parsed; } catch (error) { const message = error instanceof Error ? error.message : String(error); throw new Error(`Invalid ${label}: ${message}`); } } function parseJsonArrayOption(value, label) { if (value === undefined) return undefined; try { const parsed = JSON.parse(value); if (!Array.isArray(parsed) || parsed.some((item) => !item || typeof item !== 'object' || Array.isArray(item))) { throw new Error(`${label} must be a JSON array of objects`); } return parsed; } catch (error) { const message = error instanceof Error ? error.message : String(error); throw new Error(`Invalid ${label}: ${message}`); } } function parseGoalBinding(opts) { if (opts.kind === 'workflow-step') { if (!opts.workflowId || !opts.stepId) { throw new Error('workflow-step binding requires --workflow-id and --step-id'); } return { kind: opts.kind, workflowId: opts.workflowId, stepId: opts.stepId }; } if (opts.kind === 'agent-action') { if (!opts.agentId || !opts.appId || !opts.actionId) { throw new Error('agent-action binding requires --agent-id, --app-id, and --action-id'); } return { kind: opts.kind, agentId: opts.agentId, appId: opts.appId, actionId: opts.actionId }; } if (opts.kind === 'workspace-channel') { if (opts.channel !== 'email' && opts.channel !== 'linkedin' && opts.channel !== 'whatsapp') { throw new Error('workspace-channel binding requires --channel email, linkedin, or whatsapp'); } return { kind: opts.kind, channel: opts.channel }; } if (opts.kind === 'routine-action') { if (!opts.routineId || !opts.appId || !opts.actionId) { throw new Error('routine-action binding requires --routine-id, --app-id, and --action-id'); } return { kind: opts.kind, routineId: opts.routineId, appId: opts.appId, actionId: opts.actionId }; } throw new Error('kind must be workflow-step, agent-action, workspace-channel, or routine-action'); } function addGoalBindingOptions(command) { return command .requiredOption('--requirement <id>', 'Onboarding-goal approval requirement ID') .requiredOption('--kind <kind>', 'workflow-step, agent-action, workspace-channel, or routine-action') .option('--workflow-id <id>', 'Workflow ID for workflow-step bindings') .option('--step-id <id>', 'Step ID for workflow-step bindings') .option('--agent-id <id>', 'Agent ID for agent-action bindings') .option('--app-id <id>', 'App ID for agent-action or routine-action bindings') .option('--action-id <id>', 'Action ID for agent-action or routine-action bindings') .option('--channel <channel>', 'email, linkedin, or whatsapp for workspace-channel bindings') .option('--routine-id <id>', 'Routine ID for routine-action bindings') .option('--format <fmt>', 'Output format', 'json'); } export function registerUseCaseCommands(program) { const useCases = program .command('use-cases') .description('Manage workspace use cases, operating guides, and linked workflows, agents, routines, and knowledge refs'); useCases .command('list') .description('List workspace use cases, including operating-guide refs and missing-guide warnings') .option('--status <status>', 'Filter by status: selected, draft, active, paused, archived') .option('--limit <n>', 'Maximum rows to return', parseInt) .option('--format <fmt>', 'Output format', 'json') .action(async (opts) => { try { const result = await new AgentledClient().listWorkspaceUseCases({ status: opts.status, limit: opts.limit, }); printOutput(result, opts.format); } catch (error) { const message = error instanceof Error ? error.message : String(error); printError(message); } }); useCases .command('create') .description('Create a workspace use case record without provisioning workflows or running anything') .requiredOption('--name <name>', 'Use-case display name') .option('--key <key>', 'Stable workspace-local key, e.g. business-intro') .option('--workspace-slug <slug>', 'Optional workspace slug for readable IDs') .option('--description <text>', 'Use-case description') .option('--setup-hint <text>', 'Setup hint shown in the UI') .option('--status <status>', 'selected, draft, active, paused, or archived') .option('--source <source>', 'onboarding, catalog, custom, or imported') .option('--template-id <id>', 'Catalog template/source ID') .option('--workflow-graph-id <id>', 'Runtime workflowGraphId bridge') .option('--owner-user-id <id>', 'Owner user ID') .option('--collaborator-user-ids <ids>', 'Comma-separated collaborator user IDs') .option('--workflow-ids <ids>', 'Comma-separated linked workflow IDs') .option('--agent-ids <ids>', 'Comma-separated linked agent IDs') .option('--routine-ids <ids>', 'Comma-separated linked routine IDs') .option('--agent-file-ids <ids>', 'Comma-separated linked AgentFile IDs') .option('--knowledge-text-keys <keys>', 'Comma-separated linked KG text keys') .option('--knowledge-list-keys <keys>', 'Comma-separated linked KG list keys') .option('--data-source-ids <ids>', 'Comma-separated linked data source IDs') .option('--config <json>', 'Use-case config JSON; onboarding-goal approval policy must be edited in Use case > Safeguards') .option('--validation <json>', 'Validation metadata JSON object') .option('--metadata <json>', 'Additional metadata JSON object') .option('--input <json>', 'Full create payload JSON (overrides CLI flags)') .option('--file <path>', 'Path to JSON create payload file') .option('--format <fmt>', 'Output format', 'json') .action(async (opts) => { try { const payload = opts.input || opts.file ? readJson(opts, 'workspace use-case payload') : { name: opts.name, key: opts.key, workspaceSlug: opts.workspaceSlug, description: opts.description, setupHint: opts.setupHint, status: opts.status, source: opts.source, templateId: opts.templateId, workflowGraphId: opts.workflowGraphId, ownerUserId: opts.ownerUserId, collaboratorUserIds: parseCsvList(opts.collaboratorUserIds), workflowIds: parseCsvList(opts.workflowIds), agentIds: parseCsvList(opts.agentIds), routineIds: parseCsvList(opts.routineIds), agentFileIds: parseCsvList(opts.agentFileIds), knowledgeTextKeys: parseCsvList(opts.knowledgeTextKeys), knowledgeListKeys: parseCsvList(opts.knowledgeListKeys), dataSourceIds: parseCsvList(opts.dataSourceIds), config: parseJsonOption(opts.config, 'config'), validation: parseJsonOption(opts.validation, 'validation'), metadata: parseJsonOption(opts.metadata, 'metadata'), }; const result = await new AgentledClient().createWorkspaceUseCase(payload); printOutput(result, opts.format); } catch (error) { const message = error instanceof Error ? error.message : String(error); printError(message); } }); useCases .command('preview-kit') .description('Preview a Source -> KG -> Process use-case kit plan without creating records or running anything') .option('--name <name>', 'Use-case display name') .option('--key <key>', 'Stable workspace-local key, e.g. business-intro') .option('--workspace-slug <slug>', 'Optional workspace slug for readable preview IDs') .option('--locale <locale>', 'Workflow-agent locale bound into the exact preview; defaults to en') .option('--description <text>', 'Use-case description') .option('--setup-hint <text>', 'Setup hint shown in the UI') .option('--status <status>', 'selected, draft, active, paused, or archived') .option('--source <source>', 'onboarding, catalog, custom, or imported') .option('--workflow-graph-id <id>', 'Runtime workflowGraphId bridge') .option('--owner-user-id <id>', 'Owner user ID') .option('--collaborator-user-ids <ids>', 'Comma-separated collaborator user IDs') .option('--list <json>', 'Shared knowledge list spec JSON object') .option('--sources <json>', 'Source workflow specs JSON array; each source may include a concrete pipeline payload') .option('--tail <json>', 'Shared tail workflow spec JSON object; may include a concrete pipeline payload') .option('--orchestrator <json>', 'Orchestrator workflow spec JSON object; may include a concrete pipeline payload') .option('--receiver <json>', 'One receiver workflow spec for shared-assistant sourcing previews') .option('--install-profile <json>', 'Shared-assistant sourcing install profile JSON for atomic preview') .option('--config <json>', 'Use-case config JSON; onboarding-goal approval policy must be edited in Use case > Safeguards') .option('--metadata <json>', 'Additional metadata JSON object') .option('--input <json>', 'Full kit preview payload JSON (overrides CLI flags)') .option('--file <path>', 'Path to JSON kit preview payload file') .option('--format <fmt>', 'Output format', 'json') .action(async (opts) => { try { const payload = opts.input || opts.file ? readJson(opts, 'workspace use-case kit preview payload') : { name: opts.name, key: opts.key, workspaceSlug: opts.workspaceSlug, locale: opts.locale, description: opts.description, setupHint: opts.setupHint, status: opts.status, source: opts.source, workflowGraphId: opts.workflowGraphId, ownerUserId: opts.ownerUserId, collaboratorUserIds: parseCsvList(opts.collaboratorUserIds), list: parseJsonOption(opts.list, 'list'), sources: parseJsonArrayOption(opts.sources, 'sources'), tail: parseJsonOption(opts.tail, 'tail'), orchestrator: parseJsonOption(opts.orchestrator, 'orchestrator'), receiver: parseJsonOption(opts.receiver, 'receiver'), installProfile: parseJsonOption(opts.installProfile, 'install-profile'), config: parseJsonOption(opts.config, 'config'), metadata: parseJsonOption(opts.metadata, 'metadata'), }; if (!payload.name) { throw new Error('Provide a use-case name via --name, --input, or --file'); } const result = await new AgentledClient().previewWorkspaceUseCaseKit(payload); printOutput(result, opts.format); } catch (error) { const message = error instanceof Error ? error.message : String(error); printError(message); } }); useCases .command('provision-kit') .description('Apply a reviewed Source -> KG -> Process compatibility package through the shared paused lifecycle') .requiredOption('--confirm-token <token>', 'Required confirmation token: PROVISION_USE_CASE_KIT') .requiredOption('--preview <json>', 'Exact signed preview JSON returned by use-cases preview-kit') .option('--name <name>', 'Use-case display name') .option('--key <key>', 'Stable workspace-local key, e.g. business-intro') .option('--workspace-slug <slug>', 'Optional workspace slug for readable IDs') .option('--description <text>', 'Use-case description') .option('--setup-hint <text>', 'Setup hint shown in the UI') .option('--status <status>', 'selected, draft, active, paused, or archived') .option('--source <source>', 'onboarding, catalog, custom, or imported') .option('--workflow-graph-id <id>', 'Runtime workflowGraphId bridge') .option('--owner-user-id <id>', 'Owner user ID') .option('--collaborator-user-ids <ids>', 'Comma-separated collaborator user IDs') .option('--list <json>', 'Shared knowledge list spec JSON object') .option('--sources <json>', 'Source workflow specs JSON array; every workflow spec must include a concrete pipeline payload') .option('--tail <json>', 'Shared tail workflow spec JSON object; must include a concrete pipeline payload when present') .option('--orchestrator <json>', 'Orchestrator workflow spec JSON object; must include a concrete pipeline payload when present') .option('--receiver <json>', 'One receiver workflow spec; shared-assistant sourcing remains preview-only') .option('--install-profile <json>', 'Shared-assistant sourcing install profile JSON for atomic provisioning') .option('--config <json>', 'Use-case config JSON; onboarding-goal approval policy must be edited in Use case > Safeguards') .option('--metadata <json>', 'Additional metadata JSON object') .option('--locale <locale>', 'Locale used when assigning workflow agent language; defaults to en') .option('--input <json>', 'Full kit provision payload JSON (confirm token still comes from --confirm-token)') .option('--file <path>', 'Path to JSON kit provision payload file (confirm token still comes from --confirm-token)') .option('--format <fmt>', 'Output format', 'json') .action(async (opts) => { try { const payload = opts.input || opts.file ? readJson(opts, 'workspace use-case kit provision payload') : { name: opts.name, key: opts.key, workspaceSlug: opts.workspaceSlug, description: opts.description, setupHint: opts.setupHint, status: opts.status, source: opts.source, workflowGraphId: opts.workflowGraphId, ownerUserId: opts.ownerUserId, collaboratorUserIds: parseCsvList(opts.collaboratorUserIds), list: parseJsonOption(opts.list, 'list'), sources: parseJsonArrayOption(opts.sources, 'sources'), tail: parseJsonOption(opts.tail, 'tail'), orchestrator: parseJsonOption(opts.orchestrator, 'orchestrator'), receiver: parseJsonOption(opts.receiver, 'receiver'), installProfile: parseJsonOption(opts.installProfile, 'install-profile'), config: parseJsonOption(opts.config, 'config'), metadata: parseJsonOption(opts.metadata, 'metadata'), locale: opts.locale, }; if (!payload.name) { throw new Error('Provide a use-case name via --name, --input, or --file'); } const result = await new AgentledClient().provisionWorkspaceUseCaseKit({ ...payload, confirmToken: opts.confirmToken, preview: parseJsonOption(opts.preview, 'preview') || {}, }); printOutput(result, opts.format); } catch (error) { const message = error instanceof Error ? error.message : String(error); printError(message); } }); useCases .command('get <id>') .description('Get a workspace use case by stored id, key, or workflowGraphId, including operating-guide read commands') .option('--format <fmt>', 'Output format', 'json') .action(async (id, opts) => { try { const result = await new AgentledClient().getWorkspaceUseCase(id); printOutput(result, opts.format); } catch (error) { const message = error instanceof Error ? error.message : String(error); printError(message); } }); const goal = useCases .command('goal') .description('Read or mutate the typed onboarding-goal contract without raw config JSON'); goal .command('get <id>') .description('Get normalized onboarding-goal config and freshly resolved approval enforcement') .option('--format <fmt>', 'Output format', 'json') .action(async (id, opts) => { try { printOutput(await new AgentledClient().getWorkspaceUseCaseGoal(id), opts.format); } catch (error) { printError(error instanceof Error ? error.message : String(error)); } }); goal .command('set-policy <id>') .description('Set one desired approval policy; weakening sensitive safeguards requires --confirm') .requiredOption('--requirement <id>', 'Onboarding-goal approval requirement ID') .requiredOption('--desired <policy>', 'automatic, approval_required, or disabled') .option('--confirm', 'Explicitly confirm weakening a send, write, or delete safeguard', false) .option('--format <fmt>', 'Output format', 'json') .action(async (id, opts) => { try { if (!['automatic', 'approval_required', 'disabled'].includes(opts.desired)) { throw new Error('desired must be automatic, approval_required, or disabled'); } const result = await new AgentledClient().mutateWorkspaceUseCaseGoal(id, { action: 'set-policy', requirementId: opts.requirement, desired: opts.desired, ...(opts.confirm ? { confirm: true } : {}), }); printOutput(result, opts.format); } catch (error) { printError(error instanceof Error ? error.message : String(error)); } }); for (const action of ['bind', 'unbind']) { const bindingCommand = addGoalBindingOptions(goal .command(`${action} <id>`) .description(`${action === 'bind' ? 'Add' : 'Remove'} one typed enforcement path on an approval requirement`)); if (action === 'unbind') { bindingCommand.option('--confirm', 'Explicitly confirm removing a send, write, or delete safeguard path', false); } bindingCommand.action(async (id, opts) => { try { const result = await new AgentledClient().mutateWorkspaceUseCaseGoal(id, { action, requirementId: opts.requirement, binding: parseGoalBinding(opts), ...(action === 'unbind' && opts.confirm ? { confirm: true } : {}), }); printOutput(result, opts.format); } catch (error) { printError(error instanceof Error ? error.message : String(error)); } }); } goal .command('set-finish-line <id>') .description('Set the declared onboarding-goal finish-line milestone') .requiredOption('--milestone <milestone>', 'find, qualify, prepare, or operate') .option('--format <fmt>', 'Output format', 'json') .action(async (id, opts) => { try { if (!['find', 'qualify', 'prepare', 'operate'].includes(opts.milestone)) { throw new Error('milestone must be find, qualify, prepare, or operate'); } const result = await new AgentledClient().mutateWorkspaceUseCaseGoal(id, { action: 'set-finish-line', milestone: opts.milestone, }); printOutput(result, opts.format); } catch (error) { printError(error instanceof Error ? error.message : String(error)); } }); goal .command('set-goal-brief <id>') .description('Set the Knowledge Text key containing the durable goal brief') .requiredOption('--key <knowledge-text-key>', 'Knowledge Text key for the goal brief') .option('--format <fmt>', 'Output format', 'json') .action(async (id, opts) => { try { const result = await new AgentledClient().mutateWorkspaceUseCaseGoal(id, { action: 'set-goal-brief', goalBriefKey: opts.key, }); printOutput(result, opts.format); } catch (error) { printError(error instanceof Error ? error.message : String(error)); } }); goal .command('bind-skill <id>') .description('Bind one skill reference to a linked use-case agent and role') .requiredOption('--skill-id <id>', 'Built-in or workspace skill ID') .requiredOption('--agent-id <id>', 'Linked AgentEntity ID') .requiredOption('--role <role>', 'Business role the skill serves in this use case') .option('--format <fmt>', 'Output format', 'json') .action(async (id, opts) => { try { const result = await new AgentledClient().mutateWorkspaceUseCaseGoal(id, { action: 'bind-skill', binding: { skillId: opts.skillId, agentId: opts.agentId, role: opts.role, }, }); printOutput(result, opts.format); } catch (error) { printError(error instanceof Error ? error.message : String(error)); } }); goal .command('unbind-skill <id>') .description('Remove one exact skill and agent binding') .requiredOption('--skill-id <id>', 'Built-in or workspace skill ID') .requiredOption('--agent-id <id>', 'Linked AgentEntity ID') .option('--format <fmt>', 'Output format', 'json') .action(async (id, opts) => { try { const result = await new AgentledClient().mutateWorkspaceUseCaseGoal(id, { action: 'unbind-skill', skillId: opts.skillId, agentId: opts.agentId, }); printOutput(result, opts.format); } catch (error) { printError(error instanceof Error ? error.message : String(error)); } }); goal .command('set-primary-crm <id>') .description('Set the primary CRM reference used by this onboarding goal') .requiredOption('--app-id <id>', 'Agentled app ID for the CRM') .requiredOption('--label <label>', 'Business-facing CRM label') .option('--format <fmt>', 'Output format', 'json') .action(async (id, opts) => { try { const result = await new AgentledClient().mutateWorkspaceUseCaseGoal(id, { action: 'set-primary-crm', appId: opts.appId, label: opts.label, }); printOutput(result, opts.format); } catch (error) { printError(error instanceof Error ? error.message : String(error)); } }); const feedback = useCases .command('feedback') .description('Get or update a record Fit assessment without changing its operational status'); feedback .command('get <use-case-id> <row-id>') .description('Get the current Fit assessment and source operational status') .option('--format <fmt>', 'Output format', 'json') .action(async (useCaseId, rowId, opts) => { try { printOutput(await new AgentledClient().getUseCaseRecordFeedback(useCaseId, rowId, 'cli'), opts.format); } catch (error) { printError(error instanceof Error ? error.message : String(error)); } }); feedback .command('set <use-case-id> <row-id>') .description('Set Good fit, Not a fit, or Needs review; does not run workflows or spend credits') .requiredOption('--status <status>', 'good_fit, not_fit, or needs_review') .option('--tag <tags...>', 'Controlled reason tag(s); other requires --comment') .option('--comment <text>', 'Optional untrusted evidence, up to 500 characters') .option('--expected-revision <n>', 'Known current revision; fetched automatically when omitted', parseInt) .option('--idempotency-key <key>', 'Stable retry key; generated automatically when omitted') .option('--format <fmt>', 'Output format', 'json') .action(async (useCaseId, rowId, opts) => { try { const client = new AgentledClient(); const current = opts.expectedRevision === undefined ? await client.getUseCaseRecordFeedback(useCaseId, rowId, 'cli') : null; const expectedRevision = opts.expectedRevision ?? current?.feedback?.revision ?? 0; const result = await client.setUseCaseRecordFeedback(useCaseId, rowId, { status: opts.status, tags: opts.tag, comment: opts.comment, expectedRevision, idempotencyKey: opts.idempotencyKey || randomUUID(), }, 'cli'); printOutput(result, opts.format); } catch (error) { printError(error instanceof Error ? error.message : String(error)); } }); feedback .command('list <use-case-id>') .description('List current Fit assessments; cleared/Unreviewed records are omitted') .option('--status <status>', 'Filter by good_fit, not_fit, or needs_review') .option('--limit <n>', 'Maximum assessments to return', parseInt) .option('--format <fmt>', 'Output format', 'json') .action(async (useCaseId, opts) => { try { const result = await new AgentledClient().listUseCaseRecordFeedback(useCaseId, { status: opts.status, limit: opts.limit, }, 'cli'); printOutput(result, opts.format); } catch (error) { printError(error instanceof Error ? error.message : String(error)); } }); feedback .command('clear <use-case-id> <row-id>') .description('Clear the current Fit assessment back to Unreviewed without changing the source record') .option('--expected-revision <n>', 'Known current revision; fetched automatically when omitted', parseInt) .option('--idempotency-key <key>', 'Stable retry key; generated automatically when omitted') .option('--format <fmt>', 'Output format', 'json') .action(async (useCaseId, rowId, opts) => { try { const client = new AgentledClient(); const current = opts.expectedRevision === undefined ? await client.getUseCaseRecordFeedback(useCaseId, rowId, 'cli') : null; const expectedRevision = opts.expectedRevision ?? current?.feedback?.revision ?? 0; const result = await client.clearUseCaseRecordFeedback(useCaseId, rowId, { expectedRevision, idempotencyKey: opts.idempotencyKey || randomUUID(), }, 'cli'); printOutput(result, opts.format); } catch (error) { printError(error instanceof Error ? error.message : String(error)); } }); useCases .command('update <id>') .description('Update a workspace use case record by stored id, key, or workflowGraphId') .option('--name <name>', 'Use-case display name') .option('--description <text>', 'Use-case description') .option('--setup-hint <text>', 'Setup hint shown in the UI') .option('--status <status>', 'selected, draft, active, paused, or archived') .option('--source <source>', 'onboarding, catalog, custom, or imported') .option('--template-id <id>', 'Catalog template/source ID') .option('--workflow-graph-id <id>', 'Runtime workflowGraphId bridge') .option('--owner-user-id <id>', 'Owner user ID') .option('--collaborator-user-ids <ids>', 'Comma-separated collaborator user IDs') .option('--workflow-ids <ids>', 'Comma-separated linked workflow IDs') .option('--agent-ids <ids>', 'Comma-separated linked agent IDs') .option('--routine-ids <ids>', 'Comma-separated linked routine IDs') .option('--agent-file-ids <ids>', 'Comma-separated linked AgentFile IDs') .option('--knowledge-text-keys <keys>', 'Comma-separated linked KG text keys') .option('--knowledge-list-keys <keys>', 'Comma-separated linked KG list keys') .option('--data-source-ids <ids>', 'Comma-separated linked data source IDs') .option('--config <json>', 'Use-case config JSON; onboarding-goal approval policy must be edited in Use case > Safeguards') .option('--validation <json>', 'Validation metadata JSON object') .option('--metadata <json>', 'Additional metadata JSON object') .option('--input <json>', 'Full update payload JSON (overrides CLI flags)') .option('--file <path>', 'Path to JSON update payload file') .option('--format <fmt>', 'Output format', 'json') .action(async (id, opts) => { try { const payload = opts.input || opts.file ? readJson(opts, 'workspace use-case update payload') : { name: opts.name, description: opts.description, setupHint: opts.setupHint, status: opts.status, source: opts.source, templateId: opts.templateId, workflowGraphId: opts.workflowGraphId, ownerUserId: opts.ownerUserId, collaboratorUserIds: parseCsvList(opts.collaboratorUserIds), workflowIds: parseCsvList(opts.workflowIds), agentIds: parseCsvList(opts.agentIds), routineIds: parseCsvList(opts.routineIds), agentFileIds: parseCsvList(opts.agentFileIds), knowledgeTextKeys: parseCsvList(opts.knowledgeTextKeys), knowledgeListKeys: parseCsvList(opts.knowledgeListKeys), dataSourceIds: parseCsvList(opts.dataSourceIds), config: parseJsonOption(opts.config, 'config'), validation: parseJsonOption(opts.validation, 'validation'), metadata: parseJsonOption(opts.metadata, 'metadata'), }; if (Object.values(payload).every((value) => value === undefined)) { throw new Error('Provide updates via flags, --input, or --file'); } const result = await new AgentledClient().updateWorkspaceUseCase(id, payload); printOutput(result, opts.format); } catch (error) { const message = error instanceof Error ? error.message : String(error); printError(message); } }); useCases .command('archive <id>') .description('Archive a workspace use case without deleting linked records') .option('--format <fmt>', 'Output format', 'json') .action(async (id, opts) => { try { const result = await new AgentledClient().archiveWorkspaceUseCase(id); printOutput(result, opts.format); } catch (error) { const message = error instanceof Error ? error.message : String(error); printError(message); } }); } //# sourceMappingURL=use-cases.js.map