@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
JavaScript
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