blob: d1e036565187a45d9a539ab91d458351c82f021f [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { deriveMakaDataRoots, resolveMakaDataRoots } from './workspace-root.js';
import {
configureRuntimeHostPeerClient,
resolveRuntimeHostNativePath,
} from './runtime-host-peer-artifact.js';
import {
parseRuntimeHostCommand,
parseRuntimeHostInstalledUpdateCommand,
type RuntimeHostCliCommand,
} from './runtime-host-cli.js';
import { sessionBundleHelpText } from './runtime-host-help.js';
import { resolveCliUiLocale } from './cli-ui-locale.js';
export type MakaCliCommand =
| {
kind: 'tui';
resumeSessionId?: string;
resumeCwd?: string;
hostProfileId?: string;
projectId?: string;
}
| { kind: 'run'; args: string[] }
| { kind: 'activate'; args: string[] }
| { kind: 'session-export'; args: string[] }
| { kind: 'session-import'; args: string[] }
| { kind: 'eval'; args: string[] }
| { kind: 'acp' }
| RuntimeHostCliCommand
| { kind: 'help'; text: string }
| { kind: 'version'; text: string }
| { kind: 'error'; message: string; exitCode: number; showHelp?: boolean };
export interface MakaCliLaunchOptions {
readonly dataProfileName: string;
readonly cliCommand: string;
readonly capabilityProviderIdentityScope: 'legacy-home' | 'client-data-root';
}
export const RELEASE_MAKA_CLI_LAUNCH_OPTIONS = {
dataProfileName: 'Maka',
cliCommand: 'maka',
capabilityProviderIdentityScope: 'legacy-home',
} satisfies MakaCliLaunchOptions;
export function parseMakaCliArgs(
argv: string[],
version: string,
cliCommand = RELEASE_MAKA_CLI_LAUNCH_OPTIONS.cliCommand,
): MakaCliCommand {
if (argv.length === 0) return { kind: 'tui' };
const [first] = argv;
if (first === '--help' || first === '-h') return { kind: 'help', text: helpText(cliCommand) };
if (first === '--version' || first === '-v') return { kind: 'version', text: version };
if (first === '--acp') {
return argv.length === 1
? { kind: 'acp' }
: {
kind: 'error',
message: 'maka --acp does not accept arguments',
exitCode: 2,
showHelp: false,
};
}
if (first?.startsWith('--')) return parseTuiArgs(argv);
if (first === 'run' || first === '-p') return { kind: 'run', args: argv.slice(1) };
if (first === 'activate') return { kind: 'activate', args: argv.slice(1) };
if (first === 'session-export' || first === 'session-import') {
return argv[1] === '--help' || argv[1] === '-h'
? { kind: 'help', text: sessionBundleHelpText(cliCommand, first) }
: { kind: first, args: argv.slice(1) };
}
if (first === 'eval') return { kind: 'eval', args: argv.slice(1) };
if (first === 'update') return parseRuntimeHostInstalledUpdateCommand(argv.slice(1), cliCommand);
if (first === 'runtime-host') return parseRuntimeHostCommand(argv.slice(1), cliCommand);
return {
kind: 'error',
message: `Unexpected argument: ${first ?? ''}`,
exitCode: 2,
};
}
export function resolveMakaCliExitCode(
commandExitCode: number,
pendingExitCode: number | string | null | undefined,
): number | string {
return pendingExitCode === undefined || pendingExitCode === null || pendingExitCode === 0
? commandExitCode
: pendingExitCode;
}
export function formatMakaCliFatalError(error: unknown): string {
return error instanceof Error ? (error.stack ?? error.message) : String(error);
}
let processExitTimer: NodeJS.Timeout | undefined;
export function beginMakaCliExit(commandExitCode: number): void {
const exitCode = resolveMakaCliExitCode(commandExitCode, process.exitCode);
process.exitCode = exitCode;
if (processExitTimer) return;
processExitTimer = setTimeout(() => process.exit(process.exitCode ?? 0), PROCESS_EXIT_GRACE_MS);
processExitTimer.unref();
}
export function handleMakaCliProcessExit(
exitCode: number,
error?: unknown,
writeFatal: (message: string) => unknown = (message) => process.stderr.write(message),
): void {
beginMakaCliExit(exitCode);
if (error) writeFatal(`${formatMakaCliFatalError(error)}\n`);
}
function helpText(cliCommand: string): string {
return [
`Usage: ${cliCommand}`,
'',
'Launches the Maka terminal UI in the current working directory.',
'',
'Commands:',
...(
[
['', 'Start the TUI'],
['--acp', 'Serve ACP v1 over stdio (initialize, session/new, session/list)'],
['run ...', 'Run one non-interactive model turn'],
['-p ...', `Alias for ${cliCommand} run`],
['activate ...', 'Run one Cloud Session activation and emit JSONL'],
['eval ...', 'Run one declarative multi-arm experiment'],
['session-export ...', 'Write a Session bundle to a file'],
['session-import ...', 'Read a Session bundle back into a workspace'],
['update ...', 'Update this npm-global CLI and its local Runtime Host'],
['runtime-host ...', 'Serve and manage a Runtime Host'],
] as const
).map(([name, summary], _index, entries) => {
// A custom launcher ("npm run cli:dev --") is far wider than `maka`, so the
// column is measured, never assumed.
const width = Math.max(
...entries.map(([other]) => `${cliCommand} ${other}`.trimEnd().length),
);
return ` ${`${cliCommand} ${name}`.trimEnd().padEnd(width + 2)}${summary}`;
}),
'',
'Options:',
' -h, --help Show help',
' -v, --version Show version',
' --resume <session-id> Reopen a previous session in the TUI',
' --resume <id> --cwd <path> Reopen a session after its directory moved',
' --host <profile-id> Connect the TUI to a saved Runtime Host profile',
' --project <project-id> Select an existing Project on a remote Host',
'',
`Run \`${cliCommand} <command> --help\` for a command's own options.`,
].join('\n');
}
export async function runMakaCli(
argv: string[] = process.argv.slice(2),
options: MakaCliLaunchOptions = RELEASE_MAKA_CLI_LAUNCH_OPTIONS,
): Promise<number> {
const version = await readPackageVersion();
const command = parseMakaCliArgs(argv, version, options.cliCommand);
const dataRoots = resolveMakaDataRoots({
profileName: options.dataProfileName,
});
await configureRuntimeHostPeerClient({
cliPath: process.argv[1] ?? '',
clientDataRoot: dataRoots.clientDataRoot,
});
switch (command.kind) {
case 'runtime-host-managed-activate': {
const { runRuntimeHostManagedActivationCli } = await import(
'./runtime-host-activation-command.js'
);
return runRuntimeHostManagedActivationCli({
rootId: command.rootId,
...(command.repairRootAfterRemount ? { repairRootAfterRemount: true } : {}),
});
}
case 'runtime-host-managed-connect': {
const { runRuntimeHostManagedConnectCli } = await import('./runtime-host-connect-command.js');
return runRuntimeHostManagedConnectCli({
rootId: command.rootId,
...(command.repairRootAfterRemount ? { repairRootAfterRemount: true } : {}),
});
}
case 'run': {
const { runRuntimeHostTextCli } = await import('./runtime-host-run-command.js');
return runRuntimeHostTextCli(
command.args,
{ workspaceRoot: () => dataRoots.workspaceRoot },
{},
{
clientDataRoot: dataRoots.clientDataRoot,
cliCommand: options.cliCommand,
},
);
}
case 'activate': {
const { runMakaActivationCli } = await import('./activation-command.js');
return runMakaActivationCli(command.args);
}
case 'session-export': {
const { runMakaSessionExportCli } = await import('./session-export-command.js');
return runMakaSessionExportCli(command.args);
}
case 'session-import': {
const { runMakaSessionImportCli } = await import('./session-import-command.js');
return runMakaSessionImportCli(command.args);
}
case 'eval': {
const { configureInstalledEvalBundle } = await import('./eval-bundle-path.js');
configureInstalledEvalBundle();
const { runMakaEvalCli } = await import('@maka/eval');
return runMakaEvalCli(command.args);
}
case 'acp': {
const { runMakaAcpStdioServer } = await import('./acp/stdio-server.js');
return runMakaAcpStdioServer({
workspaceRoot: dataRoots.workspaceRoot,
clientDataRoot: dataRoots.clientDataRoot,
version,
});
}
case 'runtime-host-serve': {
const { runRuntimeHostServiceCli } = await import('./runtime-host-service-command.js');
if (command.managedDeployment) {
const {
resolveRuntimeHostManagedDeployment,
resolveRuntimeHostNpmDeploymentLayout,
resolveRuntimeHostWebRtcStunUrls,
} = await import('@maka/runtime-host/operator');
const { config } = await resolveRuntimeHostManagedDeployment(
command.managedDeployment.rootId,
);
const peer = config.listeners.directPeer?.enabled ? config.listeners.directPeer : undefined;
const packageLayout = resolveRuntimeHostNpmDeploymentLayout(
config.deploymentRoot,
config.launch.package.integrity,
);
if (process.platform === 'win32') {
const { ownWindowsRuntimeHostProcessTree } = await import(
'./runtime-host-windows-service.js'
);
await ownWindowsRuntimeHostProcessTree(packageLayout.cliPath);
}
return runRuntimeHostServiceCli({
rootPath: config.root.path,
json: command.json,
managedLaunchClaim: {
deploymentId: command.managedDeployment.deploymentId,
configRevision: command.managedDeployment.configRevision,
},
projectDirectoryRoots: config.projectDirectoryRoots,
...(config.listeners.websocket ? { websocket: config.listeners.websocket } : {}),
...(peer
? {
peer: {
nativePath: await resolveRuntimeHostNativePath(packageLayout.cliPath),
keyPath: peer.keyPath,
expectedPeerId: peer.peerId,
listenAddresses: peer.listenAddresses,
coordinationRelays: peer.coordinationRelays,
automaticRelayDiscovery: peer.automaticRelayDiscovery,
webRtcStunUrls: resolveRuntimeHostWebRtcStunUrls(peer.webRtcStunPolicy),
meshDataRoot: join(config.deploymentRoot, 'peer-mesh'),
},
}
: {}),
});
}
if (command.managedServiceConfigPath) {
const { effectiveRuntimeHostProjectDirectoryRoots, readRuntimeHostManagedServiceConfig } =
await import('./runtime-host-service-manager.js');
const config = await readRuntimeHostManagedServiceConfig(command.managedServiceConfigPath);
return runRuntimeHostServiceCli({
rootPath: config.rootPath,
json: command.json,
projectDirectoryRoots: effectiveRuntimeHostProjectDirectoryRoots(config),
websocket: config.websocket,
});
}
return runRuntimeHostServiceCli({
rootPath: command.rootPath ?? dataRoots.workspaceRoot,
json: command.json,
...(command.projectDirectoryRoots
? { projectDirectoryRoots: command.projectDirectoryRoots }
: {}),
...(command.websocket ? { websocket: command.websocket } : {}),
...(command.peer ? { peer: command.peer } : {}),
});
}
case 'runtime-host-installed-update': {
const { runRuntimeHostInstalledUpdateBootstrap } = await import(
'./runtime-host-installed-update-bootstrap.js'
);
return runRuntimeHostInstalledUpdateBootstrap({
rootPath: dataRoots.workspaceRoot,
selector: command.selector,
allowInterruptActiveTasks: command.allowInterruptActiveTasks,
});
}
case 'runtime-host-local-update-apply': {
const { runRuntimeHostInstalledUpdateCoordinator } = await import(
'./runtime-host-installed-update-coordinator.js'
);
return runRuntimeHostInstalledUpdateCoordinator({
rootPath: command.rootPath,
archivePath: command.archivePath,
installedPackageRoot: command.installedPackageRoot,
installedCliPath: command.installedCliPath,
currentVersion: command.currentVersion,
target: {
kind: 'npm_registry',
version: command.targetVersion,
integrity: command.targetIntegrity,
...(command.targetCompatibility === undefined
? {}
: { compatibility: command.targetCompatibility }),
},
allowInterruptActiveTasks: command.allowInterruptActiveTasks,
...(command.expectedSource ? { expectedSource: command.expectedSource } : {}),
});
}
case 'runtime-host-local-update-activate': {
const { runRuntimeHostInstalledUpdateActivator } = await import(
'./runtime-host-installed-update-activator.js'
);
return runRuntimeHostInstalledUpdateActivator({
rootPath: command.rootPath,
expectedRootId: command.expectedRootId,
generation: command.generation,
candidateEntrypoint: command.candidateEntrypoint,
awaitCoordinatorCommit: command.awaitCoordinatorCommit,
...(command.takeoverHostEpoch ? { takeoverHostEpoch: command.takeoverHostEpoch } : {}),
...(command.expectedOwnerInstallationId
? { expectedOwnerInstallationId: command.expectedOwnerInstallationId }
: {}),
...(command.targetVersion ? { targetVersion: command.targetVersion } : {}),
...(command.targetIntegrity ? { targetIntegrity: command.targetIntegrity } : {}),
...(command.awaitCoordinatorCommit ? { inheritableAuthorityLeaseFd: 4 } : {}),
});
}
case 'runtime-host-local-source-retire': {
const { runRuntimeHostLocalSourceRetirement } = await import(
'./runtime-host-local-source-retirement.js'
);
return runRuntimeHostLocalSourceRetirement({
rootPath: command.rootPath,
expectedRootId: command.expectedRootId,
expectedHostEpoch: command.expectedHostEpoch,
activeWorkPolicy: command.allowInterruptActiveTasks
? 'interrupt_active_work'
: 'refuse_active_work',
});
}
case 'runtime-host-setup': {
const { runRuntimeHostSetupCli } = await import('./runtime-host-setup-command.js');
const { RUNTIME_HOST_SETUP_SOURCE_PACKAGE_INTEGRITY_ENV } = await import(
'@maka/runtime-host/operator'
);
return runRuntimeHostSetupCli({
json: command.json,
clientDataRoot: command.clientDataRoot ?? dataRoots.clientDataRoot,
defaultRootPath: dataRoots.workspaceRoot,
sourcePackageRoot: fileURLToPath(new URL('..', import.meta.url)),
version,
sourcePackageIntegrity: process.env[RUNTIME_HOST_SETUP_SOURCE_PACKAGE_INTEGRITY_ENV],
principalId: command.principalId,
preset: command.preset,
lifecycle: command.lifecycle,
deferPairingCommit: command.deferPairingCommit,
bindPairingToClient: command.bindPairingToClient,
...(command.repairRootAfterRemount ? { repairRootAfterRemount: true } : {}),
updateExisting: command.updateExisting,
reuseExistingEnvironment: command.reuseExistingEnvironment,
allowInterruptActiveTasks: command.allowInterruptActiveTasks,
...(command.rootPath ? { rootPath: command.rootPath } : {}),
...(command.projectDirectoryRoots
? { projectDirectoryRoots: command.projectDirectoryRoots }
: {}),
...(command.websocketPort === undefined ? {} : { websocketPort: command.websocketPort }),
...(command.websocketPath ? { websocketPath: command.websocketPath } : {}),
...(command.directPeer ? { directPeer: command.directPeer } : {}),
...(command.expectedTarget ? { expectedTarget: command.expectedTarget } : {}),
});
}
case 'runtime-host-service-manage': {
const { runManagedRuntimeHostServiceCli } = await import(
'./runtime-host-service-management-command.js'
);
const serviceDataRoots = command.clientDataRoot
? deriveMakaDataRoots(command.clientDataRoot)
: dataRoots;
return runManagedRuntimeHostServiceCli({
action: command.action,
json: command.json,
framed: command.framed ?? false,
clientDataRoot: serviceDataRoots.clientDataRoot,
defaultRootPath: serviceDataRoots.workspaceRoot,
nodePath: process.execPath,
cliPath: process.argv[1] ?? '',
...(command.managedRootId ? { managedRootId: command.managedRootId } : {}),
...(command.operatorDeploymentId
? { operatorDeploymentId: command.operatorDeploymentId }
: {}),
...(command.rootPath ? { rootPath: command.rootPath } : {}),
...(command.projectDirectoryRoots
? { projectDirectoryRoots: command.projectDirectoryRoots }
: {}),
...(command.websocketPort === undefined ? {} : { websocketPort: command.websocketPort }),
...(command.websocketPath ? { websocketPath: command.websocketPath } : {}),
...(command.expectedTarget ? { expectedTarget: command.expectedTarget } : {}),
...(command.expectedConfigFingerprint
? { expectedConfigFingerprint: command.expectedConfigFingerprint }
: {}),
...(command.expectedHost ? { expectedHost: command.expectedHost } : {}),
...(command.retainManagedDeployment ? { retainManagedDeployment: true } : {}),
...(command.allowInterruptActiveTasks ? { allowInterruptActiveTasks: true } : {}),
});
}
case 'runtime-host-service-peer': {
const { runRuntimeHostPeerManagementCli } = await import(
'./runtime-host-peer-management-command.js'
);
const serviceDataRoots = command.clientDataRoot
? deriveMakaDataRoots(command.clientDataRoot)
: dataRoots;
return runRuntimeHostPeerManagementCli({
action: command.action,
json: command.json,
framed: command.framed ?? false,
clientDataRoot: serviceDataRoots.clientDataRoot,
defaultRootPath: serviceDataRoots.workspaceRoot,
nodePath: process.execPath,
cliPath: process.argv[1] ?? '',
managedRootId: command.managedRootId,
operatorDeploymentId: command.operatorDeploymentId,
listenAddresses: command.listenAddresses,
...(command.coordinationRelays ? { coordinationRelays: command.coordinationRelays } : {}),
...(command.automaticRelayDiscovery === undefined
? {}
: { automaticRelayDiscovery: command.automaticRelayDiscovery }),
...(command.relayDiscoveryStatus ? { relayDiscoveryStatus: true } : {}),
...(command.webRtcStunPolicy ? { webRtcStunPolicy: command.webRtcStunPolicy } : {}),
...(command.webRtcStunStatus ? { webRtcStunStatus: true } : {}),
...(command.expectedTarget ? { expectedTarget: command.expectedTarget } : {}),
...(command.allowInterruptActiveTasks ? { allowInterruptActiveTasks: true } : {}),
});
}
case 'runtime-host-service-peer-mesh': {
const { runRuntimeHostPeerMeshManagementCli } = await import(
'./runtime-host-peer-mesh-management-command.js'
);
return runRuntimeHostPeerMeshManagementCli({
action: command.action,
json: command.json,
framed: command.framed ?? false,
managedRootId: command.managedRootId,
operatorDeploymentId: command.operatorDeploymentId,
cliPath: process.argv[1] ?? '',
expectedTarget: command.expectedTarget,
...(command.meshId !== undefined ? { meshId: command.meshId } : {}),
...(command.peerId ? { peerId: command.peerId } : {}),
...(command.displayName !== undefined ? { displayName: command.displayName } : {}),
});
}
case 'runtime-host-service-update': {
const { runManagedRuntimeHostSelectedUpdateCli, runManagedRuntimeHostUpdateCli } =
await import('./runtime-host-update-command.js');
const { RUNTIME_HOST_SETUP_SOURCE_PACKAGE_INTEGRITY_ENV } = await import(
'@maka/runtime-host/operator'
);
const sourcePackageIntegrity = process.env[RUNTIME_HOST_SETUP_SOURCE_PACKAGE_INTEGRITY_ENV];
const serviceDataRoots = command.clientDataRoot
? deriveMakaDataRoots(command.clientDataRoot)
: dataRoots;
if (command.selector) {
return runManagedRuntimeHostSelectedUpdateCli({
json: command.json,
framed: command.framed ?? false,
clientDataRoot: serviceDataRoots.clientDataRoot,
defaultRootPath: serviceDataRoots.workspaceRoot,
selector: command.selector,
expectedTarget: command.expectedTarget,
...(command.expectedSourceVersion
? { expectedSourceVersion: command.expectedSourceVersion }
: {}),
...(command.expectedHost ? { expectedHost: command.expectedHost } : {}),
...(command.expectedConfigFingerprint
? { expectedConfigFingerprint: command.expectedConfigFingerprint }
: {}),
...(command.managedRootId ? { managedRootId: command.managedRootId } : {}),
...(command.operatorDeploymentId
? { operatorDeploymentId: command.operatorDeploymentId }
: {}),
...(command.allowManualUpdate ? { allowManualUpdate: true } : {}),
...(command.allowInterruptActiveTasks ? { allowInterruptActiveTasks: true } : {}),
});
}
return runManagedRuntimeHostUpdateCli({
json: command.json,
framed: command.framed ?? false,
clientDataRoot: serviceDataRoots.clientDataRoot,
defaultRootPath: serviceDataRoots.workspaceRoot,
sourcePackageRoot: fileURLToPath(new URL('..', import.meta.url)),
...(sourcePackageIntegrity ? { sourcePackageIntegrity } : {}),
version,
expectedTarget: command.expectedTarget,
...(command.expectedSourceVersion
? { expectedSourceVersion: command.expectedSourceVersion }
: {}),
...(command.expectedHost ? { expectedHost: command.expectedHost } : {}),
...(command.expectedConfigFingerprint
? { expectedConfigFingerprint: command.expectedConfigFingerprint }
: {}),
...(command.managedRootId ? { managedRootId: command.managedRootId } : {}),
...(command.operatorDeploymentId
? { operatorDeploymentId: command.operatorDeploymentId }
: {}),
...(command.allowInterruptActiveTasks ? { allowInterruptActiveTasks: true } : {}),
});
}
case 'runtime-host-service-check-update': {
const { runManagedRuntimeHostUpdateCheckCli } = await import(
'./runtime-host-update-discovery.js'
);
const serviceDataRoots = command.clientDataRoot
? deriveMakaDataRoots(command.clientDataRoot)
: dataRoots;
return runManagedRuntimeHostUpdateCheckCli({
json: command.json,
framed: command.framed ?? false,
clientDataRoot: serviceDataRoots.clientDataRoot,
defaultRootPath: serviceDataRoots.workspaceRoot,
selector: command.selector,
...(command.managedRootId ? { managedRootId: command.managedRootId } : {}),
...(command.operatorDeploymentId
? { operatorDeploymentId: command.operatorDeploymentId }
: {}),
...(command.expectedTarget ? { expectedTarget: command.expectedTarget } : {}),
});
}
case 'runtime-host-service-update-policy':
case 'runtime-host-service-reconcile-update': {
const { runManagedRuntimeHostUpdatePolicyCli, runManagedRuntimeHostUpdateReconcileCli } =
await import('./runtime-host-update-reconciliation.js');
const serviceDataRoots = command.clientDataRoot
? deriveMakaDataRoots(command.clientDataRoot)
: dataRoots;
if (command.kind === 'runtime-host-service-update-policy') {
return runManagedRuntimeHostUpdatePolicyCli({
json: command.json,
framed: command.framed ?? false,
clientDataRoot: serviceDataRoots.clientDataRoot,
defaultRootPath: serviceDataRoots.workspaceRoot,
...(command.policy ? { policy: command.policy } : {}),
...(command.expectedTarget ? { expectedTarget: command.expectedTarget } : {}),
...(command.managedRootId ? { managedRootId: command.managedRootId } : {}),
...(command.operatorDeploymentId
? { operatorDeploymentId: command.operatorDeploymentId }
: {}),
});
}
return runManagedRuntimeHostUpdateReconcileCli({
json: command.json,
framed: command.framed ?? false,
clientDataRoot: serviceDataRoots.clientDataRoot,
defaultRootPath: serviceDataRoots.workspaceRoot,
...(command.expectedTarget ? { expectedTarget: command.expectedTarget } : {}),
...(command.managedRootId ? { managedRootId: command.managedRootId } : {}),
...(command.operatorDeploymentId
? { operatorDeploymentId: command.operatorDeploymentId }
: {}),
});
}
case 'runtime-host-managed-deployment-cleanup': {
const { runManagedRuntimeHostDeploymentCleanupCli } = await import(
'./runtime-host-service-management-command.js'
);
const serviceDataRoots = command.clientDataRoot
? deriveMakaDataRoots(command.clientDataRoot)
: dataRoots;
return runManagedRuntimeHostDeploymentCleanupCli({
clientDataRoot: serviceDataRoots.clientDataRoot,
cliPath: process.argv[1] ?? '',
...(command.managedRootId ? { managedRootId: command.managedRootId } : {}),
...(command.operatorDeploymentId
? { operatorDeploymentId: command.operatorDeploymentId }
: {}),
...(command.finalize ? { finalize: true } : {}),
expectedTarget: command.expectedTarget,
});
}
case 'runtime-host-access-issue': {
const { runRuntimeHostAccessIssueCli } = await import('./runtime-host-access-command.js');
return runRuntimeHostAccessIssueCli({
rootPath: command.rootPath ?? dataRoots.workspaceRoot,
...(command.expectedRootId ? { expectedRootId: command.expectedRootId } : {}),
principalKind: command.principalKind,
principalId: command.principalId,
operationGrants: command.operationGrants,
canPublishClientCapabilities: command.canPublishClientCapabilities,
canUseHostPaths: command.canUseHostPaths,
...(command.capabilityOwnerCredentialId
? { capabilityOwnerCredentialId: command.capabilityOwnerCredentialId }
: {}),
...(command.preset ? { preset: command.preset } : {}),
});
}
case 'runtime-host-access-prepare': {
const { runRuntimeHostAccessPrepareCli } = await import('./runtime-host-access-command.js');
return runRuntimeHostAccessPrepareCli({
rootPath: command.rootPath ?? dataRoots.workspaceRoot,
...(command.expectedRootId ? { expectedRootId: command.expectedRootId } : {}),
currentCredentialFingerprint: command.currentCredentialFingerprint,
});
}
case 'runtime-host-access-connection-code': {
const { runRuntimeHostAccessConnectionCodeCli } = await import(
'./runtime-host-access-command.js'
);
return runRuntimeHostAccessConnectionCodeCli(
{
rootPath: command.rootPath ?? dataRoots.workspaceRoot,
...(command.expectedRootId ? { expectedRootId: command.expectedRootId } : {}),
...(command.name ? { name: command.name } : {}),
},
command.framed,
);
}
case 'runtime-host-access-list': {
const { runRuntimeHostAccessListCli } = await import('./runtime-host-access-command.js');
return runRuntimeHostAccessListCli(
{
rootPath: command.rootPath ?? dataRoots.workspaceRoot,
...(command.expectedRootId ? { expectedRootId: command.expectedRootId } : {}),
},
command.framed,
);
}
case 'runtime-host-access-revoke': {
const { runRuntimeHostAccessRevokeCli } = await import('./runtime-host-access-command.js');
return runRuntimeHostAccessRevokeCli(
{
rootPath: command.rootPath ?? dataRoots.workspaceRoot,
...(command.expectedRootId ? { expectedRootId: command.expectedRootId } : {}),
credentialId: command.credentialId,
...(command.currentCredentialFingerprint
? {
currentCredentialFingerprint: command.currentCredentialFingerprint,
}
: {}),
},
command.framed,
);
}
case 'runtime-host-project-list':
case 'runtime-host-project-add': {
const { runRuntimeHostProjectCli } = await import('./runtime-host-project-command.js');
const rootPath = command.rootPath ?? dataRoots.workspaceRoot;
return command.kind === 'runtime-host-project-list'
? runRuntimeHostProjectCli({ kind: 'list', rootPath })
: runRuntimeHostProjectCli({
kind: 'add',
rootPath,
path: command.path,
prefer: command.prefer,
});
}
case 'runtime-host-plugin': {
const { runRuntimeHostPluginCli } = await import('./runtime-host-plugin-command.js');
return runRuntimeHostPluginCli({
rootPath: command.rootPath ?? dataRoots.workspaceRoot,
action: command.action,
...(command.subject ? { subject: command.subject } : {}),
...(command.targetPath ? { targetPath: command.targetPath } : {}),
...(command.rootId ? { rootId: command.rootId } : {}),
...(command.cursor === undefined ? {} : { cursor: command.cursor }),
...(command.limit === undefined ? {} : { limit: command.limit }),
});
}
case 'runtime-host-capability-provider-serve': {
const { runRuntimeHostCapabilityProviderCli } = await import(
'./runtime-host-capability-provider-command.js'
);
return runRuntimeHostCapabilityProviderCli({
url: command.url,
mcpConfigPath: command.mcpConfigPath,
expectedRootId: command.expectedRootId,
...(options.capabilityProviderIdentityScope === 'client-data-root'
? {
defaultClientIdentityRoot: join(
dataRoots.clientDataRoot,
'runtime-host-capability-providers',
),
}
: {}),
...(command.credentialEnv ? { credentialEnv: command.credentialEnv } : {}),
...(command.clientIdentityPath ? { clientIdentityPath: command.clientIdentityPath } : {}),
});
}
case 'runtime-host-profile-list':
case 'runtime-host-profile-set':
case 'runtime-host-profile-set-environment':
case 'runtime-host-profile-remove': {
const { runRuntimeHostProfileCommand } = await import('./runtime-host-profile-command.js');
const profileOptions = { clientDataRoot: dataRoots.clientDataRoot };
if (command.kind === 'runtime-host-profile-list') {
return runRuntimeHostProfileCommand({ kind: 'list' }, {}, profileOptions);
}
if (command.kind === 'runtime-host-profile-remove') {
return runRuntimeHostProfileCommand({ kind: 'remove', id: command.id }, {}, profileOptions);
}
if (command.kind === 'runtime-host-profile-set-environment') {
return runRuntimeHostProfileCommand(
{
kind: 'set-environment',
id: command.id,
name: command.name,
distribution: command.distribution,
operator: command.operator,
expectedRootId: command.expectedRootId,
},
{},
profileOptions,
);
}
return runRuntimeHostProfileCommand(
{
kind: 'set',
id: command.id,
name: command.name,
transport: command.transport,
expectedRootId: command.expectedRootId,
...(command.credentialEnv ? { credentialEnv: command.credentialEnv } : {}),
},
{},
profileOptions,
);
}
case 'help':
process.stdout.write(`${command.text}\n`);
return 0;
case 'version':
process.stdout.write(`${command.text}\n`);
return 0;
case 'error':
process.stderr.write(
'showHelp' in command && command.showHelp === false
? `${command.message}\n`
: `${command.message}\n\n${helpText(options.cliCommand)}\n`,
);
return command.exitCode;
case 'tui': {
const locale = resolveCliUiLocale(process.env);
if (!locale.ok) {
process.stderr.write(`${locale.message}\n`);
return 2;
}
const { runRuntimeHostTui } = await import('./runtime-host-tui-command.js');
return runRuntimeHostTui({
cliCommand: options.cliCommand,
clientDataRoot: dataRoots.clientDataRoot,
workspaceRoot: dataRoots.workspaceRoot,
locale: locale.locale,
cwd: process.cwd(),
onProcessExit: handleMakaCliProcessExit,
...(command.resumeSessionId ? { resumeSessionId: command.resumeSessionId } : {}),
...(command.resumeCwd ? { resumeCwd: command.resumeCwd } : {}),
...(command.hostProfileId ? { hostProfileId: command.hostProfileId } : {}),
...(command.projectId ? { projectId: command.projectId } : {}),
});
}
}
}
function parseTuiArgs(argv: string[]): MakaCliCommand {
const values = new Map<string, string>();
const supported = new Set(['--resume', '--cwd', '--host', '--project']);
for (let index = 0; index < argv.length; index += 1) {
const option = argv[index];
if (!option || !supported.has(option)) {
return {
kind: 'error',
message: `Unexpected argument: ${option ?? ''}`,
exitCode: 2,
};
}
if (values.has(option)) {
return {
kind: 'error',
message: `Option repeated: ${option}`,
exitCode: 2,
};
}
const value = argv[index + 1];
if (!value || value.startsWith('-')) {
const expected =
option === '--resume' ? 'a session id' : option === '--cwd' ? 'a directory' : 'a value';
return {
kind: 'error',
message: `${option} requires ${expected}`,
exitCode: 2,
};
}
values.set(option, value);
index += 1;
}
if (values.has('--cwd') && !values.has('--resume')) {
return { kind: 'error', message: '--cwd requires --resume', exitCode: 2 };
}
if (values.has('--project') && values.has('--resume')) {
return {
kind: 'error',
message: '--project cannot be used with --resume',
exitCode: 2,
};
}
if (values.has('--cwd') && values.has('--host') && values.get('--host') !== 'local') {
return {
kind: 'error',
message: '--cwd cannot be used with a remote Runtime Host',
exitCode: 2,
};
}
return {
kind: 'tui',
...(values.has('--resume') ? { resumeSessionId: values.get('--resume') } : {}),
...(values.has('--cwd') ? { resumeCwd: values.get('--cwd') } : {}),
...(values.has('--host') ? { hostProfileId: values.get('--host') } : {}),
...(values.has('--project') ? { projectId: values.get('--project') } : {}),
};
}
async function readPackageVersion(): Promise<string> {
const raw = await readFile(new URL('../package.json', import.meta.url), 'utf8');
const parsed = JSON.parse(raw) as { version?: unknown };
return typeof parsed.version === 'string' ? parsed.version : '0.0.0';
}
export function launchMakaCli(options: MakaCliLaunchOptions): void {
runMakaCli(process.argv.slice(2), options).then(
(code) => {
beginMakaCliExit(code);
},
(error) => {
handleMakaCliProcessExit(1, error);
},
);
}
// ShellRun escalates SIGTERM to SIGKILL after two seconds. Keep the CLI alive
// long enough for that cleanup to finish before the final process fallback.
const PROCESS_EXIT_GRACE_MS = 3_000;