UNPKG

@agentled/cli

Version:

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

229 lines 11.1 kB
import { readFileSync } from 'node:fs'; 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 parseJsonObject(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 parseJsonArray(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 viewPayloadFromOptions(opts) { return { name: opts.name, key: opts.key, workspaceSlug: opts.workspaceSlug, navLabel: opts.navLabel, description: opts.description, status: opts.status, source: opts.source, viewType: opts.viewType, iconName: opts.iconName, ownerUserId: opts.ownerUserId, collaboratorUserIds: parseCsvList(opts.collaboratorUserIds), useCaseIds: parseCsvList(opts.useCaseIds), workflowIds: parseCsvList(opts.workflowIds), executionIds: parseCsvList(opts.executionIds), approvalIds: parseCsvList(opts.approvalIds), agentIds: parseCsvList(opts.agentIds), routineIds: parseCsvList(opts.routineIds), knowledgeTextKeys: parseCsvList(opts.knowledgeTextKeys), knowledgeListKeys: parseCsvList(opts.knowledgeListKeys), dataSourceIds: parseCsvList(opts.dataSourceIds), externalSourceIds: parseCsvList(opts.externalSourceIds), dataSources: parseJsonArray(opts.dataSources, 'dataSources'), filters: parseJsonObject(opts.filters, 'filters'), transforms: parseJsonObject(opts.transforms, 'transforms'), layout: parseJsonObject(opts.layout, 'layout'), actions: parseJsonArray(opts.actions, 'actions'), refreshPolicy: parseJsonObject(opts.refreshPolicy, 'refreshPolicy'), config: parseJsonObject(opts.config, 'config'), validation: parseJsonObject(opts.validation, 'validation'), metadata: parseJsonObject(opts.metadata, 'metadata'), placement: parseJsonObject(opts.placement, 'placement'), pinned: opts.pinned === true ? true : opts.unpinned === true ? false : undefined, }; } function removeUndefined(payload) { return Object.fromEntries(Object.entries(payload).filter(([, value]) => value !== undefined)); } function addViewMutationOptions(command, mode) { command .option('--name <name>', mode === 'create' ? 'Workspace view display name (required unless --input/--file provides name)' : 'Workspace view display name') .option('--key <key>', 'Stable workspace-local key, e.g. linkedin-operating-view') .option('--workspace-slug <slug>', 'Optional workspace slug for readable IDs') .option('--nav-label <label>', 'Short sidebar/navigation label; name remains the full page title') .option('--description <text>', 'View description') .option('--status <status>', 'draft, active, paused, or archived') .option('--source <source>', 'agent, user, system, template, or imported') .option('--view-type <type>', 'dashboard, list, funnel, approval_queue, report, or custom') .option('--icon-name <name>', 'Lucide icon name') .option('--owner-user-id <id>', 'Owner user ID') .option('--collaborator-user-ids <ids>', 'Comma-separated collaborator user IDs') .option('--use-case-ids <ids>', 'Comma-separated linked WorkspaceUseCase IDs') .option('--workflow-ids <ids>', 'Comma-separated linked workflow IDs') .option('--execution-ids <ids>', 'Comma-separated linked execution IDs') .option('--approval-ids <ids>', 'Comma-separated linked approval IDs') .option('--agent-ids <ids>', 'Comma-separated linked agent IDs') .option('--routine-ids <ids>', 'Comma-separated linked routine 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('--external-source-ids <ids>', 'Comma-separated linked external source IDs') .option('--data-sources <json>', 'WorkspaceViewDataSource[] JSON; supports KG, workflow, approvals, agents, routines, external API, and custom sources') .option('--filters <json>', 'Filter manifest JSON object') .option('--transforms <json>', 'Transform manifest JSON object') .option('--layout <json>', 'ConfigLayout JSON object used by the Config renderer') .option('--actions <json>', 'WorkspaceViewAction[] JSON; write/send actions still require approval') .option('--refresh-policy <json>', 'Refresh policy JSON object') .option('--config <json>', 'Additional config JSON object') .option('--validation <json>', 'Validation metadata JSON object') .option('--metadata <json>', 'Additional metadata JSON object') .option('--placement <json>', 'Sidebar placement JSON object, e.g. {"type":"workflow","workflowId":"pipeline-1"}') .option('--pinned', 'Pin the view as a workspace-level operating surface') .option('--unpinned', 'Unpin the view'); } export function registerWorkspaceViewCommands(program) { const views = program .command('workspace-views') .alias('views') .description('Manage saved workspace views over KG, workflows, approvals, agents, routines, and external data'); views .command('list') .description('List workspace views and their source/action guidance') .option('--status <status>', 'Filter by status: 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().listWorkspaceViews({ status: opts.status, limit: opts.limit, }); printOutput(result, opts.format); } catch (error) { const message = error instanceof Error ? error.message : String(error); printError(message); } }); const createCommand = views .command('create') .description('Create a saved workspace view manifest without running workflows or mutating source rows') .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'); addViewMutationOptions(createCommand, 'create'); createCommand.action(async (opts) => { try { const payload = opts.input || opts.file ? readJson(opts, 'workspace view payload') : removeUndefined(viewPayloadFromOptions(opts)); if (!payload.name) throw new Error('Provide a view name via --name, --input, or --file'); if (!payload.dataSources) throw new Error('Provide dataSources via --data-sources, --input, or --file'); if (!payload.layout) throw new Error('Provide layout via --layout, --input, or --file'); const result = await new AgentledClient().createWorkspaceView(payload); printOutput(result, opts.format); } catch (error) { const message = error instanceof Error ? error.message : String(error); printError(message); } }); views .command('get <id>') .description('Get a workspace view by stored id or key, including agent read/safety guidance') .option('--format <fmt>', 'Output format', 'json') .action(async (id, opts) => { try { const result = await new AgentledClient().getWorkspaceView(id); printOutput(result, opts.format); } catch (error) { const message = error instanceof Error ? error.message : String(error); printError(message); } }); const updateCommand = views .command('update <id>') .description('Update a workspace view manifest by stored id or key') .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'); addViewMutationOptions(updateCommand, 'update'); updateCommand.action(async (id, opts) => { try { const payload = opts.input || opts.file ? readJson(opts, 'workspace view update payload') : removeUndefined(viewPayloadFromOptions(opts)); if (Object.keys(payload).length === 0) { throw new Error('Provide updates via flags, --input, or --file'); } const result = await new AgentledClient().updateWorkspaceView(id, payload); printOutput(result, opts.format); } catch (error) { const message = error instanceof Error ? error.message : String(error); printError(message); } }); views .command('archive <id>') .description('Archive a workspace view without deleting linked data or source rows') .option('--format <fmt>', 'Output format', 'json') .action(async (id, opts) => { try { const result = await new AgentledClient().archiveWorkspaceView(id); printOutput(result, opts.format); } catch (error) { const message = error instanceof Error ? error.message : String(error); printError(message); } }); } //# sourceMappingURL=workspace-views.js.map