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
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ test('drives the Desktop Pricing adapter through a real Runtime Host connection'
});
const connected = await connectRuntimeHost({
rootPath: base,
surface: 'desktop',
protocol: {
min: RUNTIME_HOST_PROTOCOL_VERSION,
max: RUNTIME_HOST_PROTOCOL_VERSION,
Expand All @@ -114,7 +113,6 @@ test('drives the Desktop Pricing adapter through a real Runtime Host connection'
await client.close();
const reconnected = await connectRuntimeHost({
rootPath: base,
surface: 'desktop',
protocol: {
min: RUNTIME_HOST_PROTOCOL_VERSION,
max: RUNTIME_HOST_PROTOCOL_VERSION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ test('drives Desktop Session operations through a real Runtime Host connection',
});
const connected = await connectRuntimeHost({
rootPath: base,
surface: 'desktop',
protocol: {
min: RUNTIME_HOST_PROTOCOL_VERSION,
max: RUNTIME_HOST_PROTOCOL_VERSION,
Expand Down Expand Up @@ -351,7 +350,6 @@ test('drives the renderer Session execution facade through real UDS framing', as
});
const connected = await connectRuntimeHost({
rootPath: base,
surface: 'desktop',
protocol: {
min: RUNTIME_HOST_PROTOCOL_VERSION,
max: RUNTIME_HOST_PROTOCOL_VERSION,
Expand Down Expand Up @@ -476,7 +474,6 @@ test('drives bounded Session domain projections through real UDS framing', async
});
const connected = await connectRuntimeHost({
rootPath: base,
surface: 'desktop',
protocol: {
min: RUNTIME_HOST_PROTOCOL_VERSION,
max: RUNTIME_HOST_PROTOCOL_VERSION,
Expand Down
2 changes: 0 additions & 2 deletions apps/desktop/src/main/runtime-host-desktop-candidate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,6 @@ async function startRemoteDesktopRuntimeHostCandidate(
const connection = await connectRemoteRuntimeHostProfile({
profile: remote.profile,
credential: remote.credential,
surface: "desktop",
clientInstanceId: input.clientInstanceId ?? randomUUID(),
...(input.signal === undefined ? {} : { signal: input.signal }),
...(input.connectTimeoutMs === undefined
Expand Down Expand Up @@ -671,7 +670,6 @@ function connectInput(
): ConnectOrSpawnRuntimeHostInput {
return {
rootPath: input.rootPath,
surface: "desktop",
protocol: {
min: RUNTIME_HOST_PROTOCOL_VERSION,
max: RUNTIME_HOST_PROTOCOL_VERSION,
Expand Down
88 changes: 73 additions & 15 deletions packages/cli/src/__tests__/runtime-host-cli-context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
RUNTIME_HOST_COMPATIBILITY_EPOCH,
RUNTIME_HOST_PROTOCOL_VERSION,
RUNTIME_HOST_REGISTRATION_SCHEMA_VERSION,
type ClientSurface,
type HostIncompatible,
} from '@maka/runtime-host/protocol';
import {
Expand Down Expand Up @@ -50,7 +49,6 @@ test('CLI Runtime Host bootstrap launches the execution composition', async () =
const context = await connectRuntimeHostCli(
{
rootPath: '/runtime-host-root',
surface: 'activation',
},
{
connectOrSpawn: async (input) => {
Expand Down Expand Up @@ -80,7 +78,7 @@ test('CLI Runtime Host bootstrap launches the execution composition', async () =
test('non-interactive CLI reports how to retire an incompatible Runtime Host', async () => {
await assert.rejects(
connectRuntimeHostCli(
{ rootPath: '/runtime-host-root', surface: 'run' },
{ rootPath: '/runtime-host-root' },
{
connectOrSpawn: async () => ({
kind: 'incompatible',
Expand Down Expand Up @@ -123,7 +121,7 @@ test('non-interactive CLI reports how to retire an incompatible Runtime Host', a
test('CLI explains a service Host without inventing resident work', async () => {
await assert.rejects(
connectRuntimeHostCli(
{ rootPath: '/runtime-host-root', surface: 'run' },
{ rootPath: '/runtime-host-root' },
{
connectOrSpawn: async () => ({
kind: 'incompatible',
Expand Down Expand Up @@ -166,7 +164,7 @@ test('Runtime Host conflict waits only after an explicit wait answer', () => {
test('CLI reports an actionable stored-data startup failure', async () => {
await assert.rejects(
connectRuntimeHostCli(
{ rootPath: '/runtime-host-root', surface: 'run' },
{ rootPath: '/runtime-host-root' },
{
connectOrSpawn: async () => ({
kind: 'failed',
Expand Down Expand Up @@ -200,7 +198,7 @@ test('remote CLI profiles pin root identity and resolve credential outside the p
close: async () => {},
} as unknown as RuntimeHostConnection;
const context = await connectRuntimeHostCli(
{ rootPath: '/unused-local-root', surface: 'run', profileId: 'office' },
{ rootPath: '/unused-local-root', profileId: 'office' },
{
connectOrSpawn: async () => {
throw new Error('remote profile must not use local discovery');
Expand Down Expand Up @@ -292,7 +290,6 @@ test('remote CLI profile state and Client identity use the explicit Client Data
{
rootPath: '/unused-local-root',
clientDataRoot,
surface: 'run',
profileId: 'office',
},
{
Expand All @@ -316,36 +313,97 @@ test('remote CLI profile state and Client identity use the explicit Client Data
await context.close();
});

test('CLI and TUI remote profiles preserve shared compatibility errors', async () => {
test('remote CLI enables SSH prompts only for an explicitly interactive TTY', async (t) => {
const stdinIsTTY = Object.getOwnPropertyDescriptor(process.stdin, 'isTTY');
const stdoutIsTTY = Object.getOwnPropertyDescriptor(process.stdout, 'isTTY');
t.after(() => {
if (stdinIsTTY) Object.defineProperty(process.stdin, 'isTTY', stdinIsTTY);
else Reflect.deleteProperty(process.stdin, 'isTTY');
if (stdoutIsTTY) Object.defineProperty(process.stdout, 'isTTY', stdoutIsTTY);
else Reflect.deleteProperty(process.stdout, 'isTTY');
});
Object.defineProperty(process.stdin, 'isTTY', { configurable: true, value: true });
Object.defineProperty(process.stdout, 'isTTY', { configurable: true, value: true });

const rootId = 'd'.repeat(64);
const profile: RemoteRuntimeHostProfile = {
id: 'office',
name: 'Office',
kind: 'remote',
transport: {
kind: 'ssh',
destination: 'operator@runtime.example.com',
remotePort: 7443,
websocketPath: '/runtime-host',
},
rootId,
};
const sshInteractions: string[] = [];
const connect = async (interactiveSsh?: boolean) =>
connectRuntimeHostCli(
{
rootPath: '/unused-local-root',
profileId: profile.id,
...(interactiveSsh === undefined ? {} : { interactiveSsh }),
},
{
connectRemoteProfile: async (input) => {
assert.ok(input.sshInteraction);
sshInteractions.push(input.sshInteraction);
return {
rootId,
hostEpoch: 'host-remote',
connectionId: `connection-${sshInteractions.length}`,
selectedProtocol: 0,
closed: new Promise<void>(() => {}),
status: async () => ({ state: 'ready' }),
subscribeConfigurationChanges: () => () => {},
subscribeProjectCatalogChanges: () => () => {},
subscribeSessionCatalogChanges: () => () => {},
subscribeScheduledTaskChanges: () => () => {},
close: async () => {},
} as unknown as RuntimeHostConnection;
},
profileCatalog: singleRemoteProfileCatalog(profile),
loadClientInstanceId: async () => '44444444-4444-4444-8444-444444444444',
readConnectionCatalog: async () => ({ revision: 1, defaultTarget: null, connections: [] }),
},
);

const interactive = await connect(true);
await interactive.close();
const nonInteractive = await connect();
await nonInteractive.close();

assert.deepEqual(sshInteractions, ['inherit', 'batch']);
});

test('remote profiles preserve shared compatibility errors', async () => {
const cases: readonly {
readonly surface: Extract<ClientSurface, 'run' | 'tui'>;
readonly handshake: HostIncompatible;
}[] = [
{
surface: 'run',
handshake: incompatibleRemoteHandshake({
compatibilityEpoch: RUNTIME_HOST_COMPATIBILITY_EPOCH - 1,
}),
},
{
surface: 'tui',
handshake: incompatibleRemoteHandshake({
protocolMin: RUNTIME_HOST_PROTOCOL_VERSION + 1,
protocolMax: RUNTIME_HOST_PROTOCOL_VERSION + 2,
}),
},
{
surface: 'run',
handshake: incompatibleRemoteHandshake({
compositionId: 'maka.other-composition',
compositionRevision: 'other-revision',
}),
},
];

for (const { surface, handshake } of cases) {
for (const [index, { handshake }] of cases.entries()) {
const profile: RemoteRuntimeHostProfile = {
id: `office-${surface}-${handshake.compositionRevision}`,
id: `office-${index}-${handshake.compositionRevision}`,
name: 'Office',
kind: 'remote',
transport: { kind: 'tls', url: 'wss://runtime.example.com/runtime-host' },
Expand All @@ -354,7 +412,7 @@ test('CLI and TUI remote profiles preserve shared compatibility errors', async (
await assert.rejects(
() =>
connectRuntimeHostCli(
{ rootPath: '/unused-local-root', surface, profileId: profile.id },
{ rootPath: '/unused-local-root', profileId: profile.id },
{
connectRemoteProfile: (input) =>
connectRemoteRuntimeHostProfile(input, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,6 @@ function runFixture(input: {
connection,
connectionCatalog(),
{
surface: 'run',
workspaceRoot: '/data',
cwd: '/workspace',
...(input.graph ? { enableAgentGraph: true } : {}),
Expand Down
5 changes: 0 additions & 5 deletions packages/cli/src/activation-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ export interface MakaActivationDeps {
}

export interface MakaActivationContextInput {
readonly surface: 'activation';
readonly workspaceRoot: string;
readonly stateRoot: string;
readonly configRoot: string;
Expand Down Expand Up @@ -428,7 +427,6 @@ export async function runMakaActivationCli(
};
try {
context = await deps.createContext({
surface: 'activation',
workspaceRoot: roots.workspaceRoot,
stateRoot: roots.stateRoot,
configRoot: roots.configRoot,
Expand Down Expand Up @@ -811,15 +809,13 @@ async function createRuntimeHostActivationContext(
): Promise<MakaActivationContext> {
const connected = await connectRuntimeHostCli({
rootPath: input.stateRoot,
surface: 'activation',
});
try {
const target = resolveRuntimeHostCliTarget(connected.catalog, {
...(input.requestedConnectionSlug ? { connectionSlug: input.requestedConnectionSlug } : {}),
...(input.requestedModel ? { model: input.requestedModel } : {}),
});
const runContext = createRuntimeHostRunContext(connected.connection, connected.catalog, {
surface: 'activation',
workspaceRoot: input.stateRoot,
cwd: input.cwd,
requestedConnectionSlug: target.connection.slug,
Expand Down Expand Up @@ -855,7 +851,6 @@ async function createRuntimeHostActivationContext(
async function listRuntimeHostActivationSessions(stateRoot: string): Promise<SessionSummary[]> {
const connected = await connectRuntimeHostCli({
rootPath: stateRoot,
surface: 'activation',
});
try {
return (await readRuntimeHostSessions(connected.connection)).flatMap((session) =>
Expand Down
2 changes: 0 additions & 2 deletions packages/cli/src/run-command-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ export interface MakaRunOutcome {
}

export interface MakaRunContextInput {
surface: 'run' | 'activation';
workspaceRoot: string;
cwd: string;
requestedConnectionSlug?: string;
Expand Down Expand Up @@ -266,7 +265,6 @@ export async function runMakaTextCliCore(
let context: MakaRunContext;
try {
context = await deps.createContext({
surface: 'run',
workspaceRoot,
cwd: selection.cwd,
...(selection.kind === 'existing' || parsed.options.connection
Expand Down
1 change: 0 additions & 1 deletion packages/cli/src/runtime-host-access-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ export async function runRuntimeHostAccessRevokeCli(
async function connectLocalOwner(rootPath: string) {
const result = await connectExistingRuntimeHost({
rootPath,
surface: 'run',
protocol: PROTOCOL,
});
if (result.kind !== 'connected') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ async function connectRemoteCapabilityProvider(input: {
const connected = await connectRemoteRuntimeHost({
url: input.url,
credential: input.credential,
surface: 'capability-provider',
protocol: { min: RUNTIME_HOST_PROTOCOL_VERSION, max: RUNTIME_HOST_PROTOCOL_VERSION },
compositionId: INTERACTIVE_RUNTIME_HOST_COMPOSITION_ID,
clientInstanceId: input.clientInstanceId,
Expand Down
7 changes: 2 additions & 5 deletions packages/cli/src/runtime-host-cli-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {
RUNTIME_HOST_COMPATIBILITY_EPOCH,
RUNTIME_HOST_PROTOCOL_VERSION,
type HostRegistration,
type ClientSurface,
type HostIncompatible,
} from '@maka/runtime-host/protocol';
import { resolveMakaClientDataRoot } from '@maka/storage';
Expand Down Expand Up @@ -63,9 +62,9 @@ interface RuntimeHostCliContextDeps {
export async function connectRuntimeHostCli(
input: {
readonly rootPath: string;
readonly surface: ClientSurface;
readonly profileId?: string;
readonly clientDataRoot?: string;
readonly interactiveSsh?: boolean;
Comment thread
Sun-GLiang marked this conversation as resolved.
},
overrides: Partial<RuntimeHostCliContextDeps> = {},
): Promise<RuntimeHostCliConnectionContext> {
Expand All @@ -89,7 +88,6 @@ export async function connectRuntimeHostCli(
);
const connectInput = {
rootPath: input.rootPath,
surface: input.surface,
protocol: { min: RUNTIME_HOST_PROTOCOL_VERSION, max: RUNTIME_HOST_PROTOCOL_VERSION },
clientInstanceId,
compositionId: INTERACTIVE_RUNTIME_HOST_COMPOSITION_ID,
Expand All @@ -103,7 +101,6 @@ export async function connectRuntimeHostCli(
return deps.connectRemoteProfile({
profile,
credential: resolvedProfile.credential!,
surface: input.surface,
clientInstanceId,
sshInteraction,
...(signal ? { signal } : {}),
Expand All @@ -128,7 +125,7 @@ export async function connectRuntimeHostCli(
};
const initialConnection = await connect(
undefined,
input.surface === 'tui' && process.stdin.isTTY && process.stdout.isTTY ? 'inherit' : 'batch',
input.interactiveSsh && process.stdin.isTTY && process.stdout.isTTY ? 'inherit' : 'batch',
);
const connection = await createRuntimeHostReconnectingConnection({
initialConnection,
Expand Down
1 change: 0 additions & 1 deletion packages/cli/src/runtime-host-project-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ function defaultDeps(): RuntimeHostProjectCommandDeps {
async function connectLocalOwner(rootPath: string): Promise<RuntimeHostConnection> {
const result = await connectExistingRuntimeHost({
rootPath,
surface: 'run',
protocol: PROTOCOL,
});
if (result.kind !== 'connected') {
Expand Down
1 change: 0 additions & 1 deletion packages/cli/src/runtime-host-run-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ function defaultRuntimeHostRunCommandDeps(): RuntimeHostRunCommandDeps {
connect: (rootPath, hostProfileId, clientDataRoot) =>
connectRuntimeHostCli({
rootPath,
surface: 'run',
...(hostProfileId ? { profileId: hostProfileId } : {}),
clientDataRoot,
}),
Expand Down
1 change: 0 additions & 1 deletion packages/cli/src/runtime-host-service-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,6 @@ async function waitForManagedRuntimeHostReady(
const remaining = deadline - Date.now();
const connected = await connectExistingRuntimeHost({
rootPath: config.rootPath,
surface: 'run',
protocol: { min: RUNTIME_HOST_PROTOCOL_VERSION, max: RUNTIME_HOST_PROTOCOL_VERSION },
connectTimeoutMs: Math.max(1, Math.min(500, remaining)),
handshakeTimeoutMs: Math.max(1, Math.min(500, remaining)),
Expand Down
1 change: 0 additions & 1 deletion packages/cli/src/runtime-host-setup-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,6 @@ async function verifyRuntimeHostSetupCredential(input: {
credential: input.credential,
expectedRootId: input.rootId,
compositionId: INTERACTIVE_RUNTIME_HOST_COMPOSITION_ID,
surface: 'run',
protocol: { min: RUNTIME_HOST_PROTOCOL_VERSION, max: RUNTIME_HOST_PROTOCOL_VERSION },
});
if (result.kind !== 'connected') {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/runtime-host-tui-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ async function runFirstRunOnboarding(
const connected = await connectRuntimeHostCli({
clientDataRoot,
rootPath,
surface: 'tui',
interactiveSsh: true,
...(hostProfileId ? { profileId: hostProfileId } : {}),
});
try {
Expand Down
Loading