Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions packages/cli/src/__tests__/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ describe('Maka CLI args', () => {
{ kind: 'eval', args: ['task-run', 'inspect', 'run-1'] },
],
[['inspect', 'run-1', '--json'], { kind: 'inspect', args: ['run-1', '--json'] }],
[['runtime-host', 'serve'], { kind: 'runtime-host-serve' }],
[
['runtime-host', 'serve', '--root', '/srv/maka'],
{ kind: 'runtime-host-serve', rootPath: '/srv/maka' },
],
[
['runtime-host'],
{ kind: 'error', message: 'runtime-host requires the serve command', exitCode: 2 },
],
[
['runtime-host', 'serve', '--root'],
{ kind: 'error', message: '--root requires a directory', exitCode: 2 },
],
[['run', 'hello', '--max-steps', '3'], { kind: 'run', args: ['hello', '--max-steps', '3'] }],
[['-p', 'hello', '--max-steps', '3'], { kind: 'run', args: ['hello', '--max-steps', '3'] }],
[['--version'], { kind: 'version', text: '0.1.0' }],
Expand Down
31 changes: 31 additions & 0 deletions packages/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type MakaCliCommand =
| { kind: 'activate'; args: string[] }
| { kind: 'eval'; args: string[] }
| { kind: 'inspect'; args: string[] }
| { kind: 'runtime-host-serve'; rootPath?: string }
| { kind: 'help'; text: string }
| { kind: 'version'; text: string }
| { kind: 'error'; message: string; exitCode: number };
Expand Down Expand Up @@ -43,6 +44,7 @@ export function parseMakaCliArgs(argv: string[], version: string): MakaCliComman
if (first === 'activate') return { kind: 'activate', args: argv.slice(1) };
if (first === 'eval') return { kind: 'eval', args: argv.slice(1) };
if (first === 'inspect') return { kind: 'inspect', args: argv.slice(1) };
if (first === 'runtime-host') return parseRuntimeHostCommand(argv.slice(1));
return {
kind: 'error',
message: `Unexpected argument: ${first ?? ''}`,
Expand Down Expand Up @@ -96,6 +98,7 @@ function helpText(): string {
' maka -p ... Alias for maka run',
' maka eval ... Run evaluation and autonomous task commands',
' maka inspect ... Inspect Session, AgentRun, or TaskRun evidence',
' maka runtime-host serve [--root <path>] Run a local Runtime Host service',
'',
'Options:',
' -h, --help Show help',
Expand Down Expand Up @@ -130,6 +133,10 @@ export async function runMakaCli(argv: string[] = process.argv.slice(2)): Promis
const { runMakaInspectCli } = await import('./inspect-command.js');
return runMakaInspectCli(command.args);
}
case 'runtime-host-serve': {
const { runRuntimeHostServiceCli } = await import('./runtime-host-service-command.js');
return runRuntimeHostServiceCli(command.rootPath ?? resolveMakaWorkspaceRoot());
}
case 'help':
process.stdout.write(`${command.text}\n`);
return 0;
Expand All @@ -153,6 +160,30 @@ export async function runMakaCli(argv: string[] = process.argv.slice(2)): Promis
}
}

function parseRuntimeHostCommand(argv: string[]): MakaCliCommand {
if (argv[0] !== 'serve') {
return {
kind: 'error',
message: argv[0]
? `Unexpected runtime-host command: ${argv[0]}`
: 'runtime-host requires the serve command',
exitCode: 2,
};
}
if (argv[1] === undefined) return { kind: 'runtime-host-serve' };
if (argv[1] !== '--root') {
return { kind: 'error', message: `Unexpected argument: ${argv[1]}`, exitCode: 2 };
}
const rootPath = argv[2];
if (!rootPath || rootPath.startsWith('-')) {
return { kind: 'error', message: '--root requires a directory', exitCode: 2 };
}
if (argv[3] !== undefined) {
return { kind: 'error', message: `Unexpected argument: ${argv[3]}`, exitCode: 2 };
}
return { kind: 'runtime-host-serve', rootPath };
}

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 };
Expand Down
14 changes: 14 additions & 0 deletions packages/cli/src/runtime-host-service-command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {
installRuntimeHostLogCapture,
runRuntimeHostProcessLifecycle,
startExecutionRuntimeHostService,
} from '@maka/runtime-host/server';

export async function runRuntimeHostServiceCli(rootPath: string): Promise<number> {
installRuntimeHostLogCapture();
const host = await startExecutionRuntimeHostService({ rootPath });
await runRuntimeHostProcessLifecycle(host, {
onReady: () => process.stdout.write(`Runtime Host service is ready at ${host.endpoint}\n`),
});
return 0;
}
16 changes: 8 additions & 8 deletions packages/runtime-host/src/__tests__/artifact-protocol.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import {
decodeClientFrame,
decodeHostFrame,
encodeArtifactQueryResult,
encodeProtocolFrame,
encodeProtocolMessage,
HOST_OPERATION_SPECS,
RUNTIME_HOST_MAX_FRAME_BYTES,
RUNTIME_HOST_MAX_MESSAGE_BYTES,
RuntimeHostProtocolError,
} from '../protocol/index.js';
import { encodeArtifactProjection } from '../protocol/artifact.js';
Expand Down Expand Up @@ -66,7 +66,7 @@ describe('Artifact protocol', () => {
);
});

test('bounds sequential Artifact read chunks below the frame limit', () => {
test('bounds sequential Artifact read chunks below the message limit', () => {
const bytes = Buffer.alloc(ARTIFACT_READ_CHUNK_MAX_BYTES, 9);
assert.doesNotThrow(() =>
response('artifact.query', {
Expand Down Expand Up @@ -107,7 +107,7 @@ describe('Artifact protocol', () => {
);
});

test('bounds chunked attachment publication below the frame limit', () => {
test('bounds chunked attachment publication below the message limit', () => {
const bytes = Buffer.alloc(ARTIFACT_INGEST_CHUNK_MAX_BYTES, 7);
const digest = `sha256:${'a'.repeat(64)}`;
assert.doesNotThrow(() =>
Expand Down Expand Up @@ -169,7 +169,7 @@ describe('Artifact protocol', () => {
uploadId: 'upload-1',
}),
);
const frame = encodeProtocolFrame({
const frame = encodeProtocolMessage({
requestId: 'artifact-ingest-chunk',
operation: 'artifact.ingest',
input: {
Expand All @@ -180,7 +180,7 @@ describe('Artifact protocol', () => {
chunkBase64: bytes.toString('base64'),
},
});
assert.ok(frame.byteLength <= RUNTIME_HOST_MAX_FRAME_BYTES);
assert.ok(frame.byteLength <= RUNTIME_HOST_MAX_MESSAGE_BYTES);

for (const chunkBase64 of [
Buffer.alloc(ARTIFACT_INGEST_CHUNK_MAX_BYTES + 1).toString('base64'),
Expand Down Expand Up @@ -368,12 +368,12 @@ describe('Artifact protocol', () => {
Buffer.byteLength(JSON.stringify(maximumBinary), 'utf8') <= ARTIFACT_RESULT_MAX_BYTES,
);
assert.ok(
encodeProtocolFrame({
encodeProtocolMessage({
requestId: 'artifact-binary',
operation: 'artifact.query',
ok: true,
result: maximumBinary,
}).byteLength <= RUNTIME_HOST_MAX_FRAME_BYTES,
}).byteLength <= RUNTIME_HOST_MAX_MESSAGE_BYTES,
);
});

Expand Down
Loading
Loading