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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@

### Changed

- Made typed `request()` the sole direct Runtime Host operation API; removed the 17 forwarding
aliases from direct and reconnecting connections while preserving status validation,
subscriptions, capabilities, listeners, lifecycle, and close behavior.
- Collapsed the RuntimeRunner/Flow/Invocation shell into `RuntimeKernel`; backend dispatch,
terminal coalescing, stop/drain, and durable continuation admission now have one production
owner, immutable request snapshots remain enforced at AgentRun acceptance and backend dispatch,
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/main/runtime-host-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1150,7 +1150,7 @@ export class DesktopRuntimeHostClient {
}

queryHostDiagnostics(): Promise<OperationOutput<"host.diagnostics.query">> {
return this.connection.queryHostDiagnostics(2_000);
return this.connection.request('host.diagnostics.query', {}, 2_000);
}

prepareHostRetirement(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1606,7 +1606,6 @@ class FakeConnection {
hostEpoch: 'host-1',
request: <K extends DirectRequestOperationKey>(operation: K, input: OperationInput<K>) =>
this.request(operation, input),
startTurn: (input) => this.request('turn.start', input),
openSessionSubscription: async () => {
const subscription = this.subscriptions[this.openedSubscriptions];
this.openedSubscriptions += 1;
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/runtime-host-service-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1068,7 +1068,7 @@ export async function verifyRuntimeHostManagedServiceReady(
const status = await connected.connection.status(Math.max(1, remaining));
if (status.state === 'ready') {
const [diagnostics, service] = await Promise.all([
connected.connection.queryHostDiagnostics(),
connected.connection.request('host.diagnostics.query', {}),
backend.status(),
]);
if (service.active && service.pid !== null && diagnostics.pid === service.pid) return;
Expand Down Expand Up @@ -1118,7 +1118,7 @@ async function prepareRuntimeHostRetirement(
}
const hostEpoch = connected.connection.hostEpoch;
try {
const diagnostics = await connected.connection.queryHostDiagnostics();
const diagnostics = await connected.connection.request('host.diagnostics.query', {});
if (diagnostics.pid !== expectedPid) {
throw new RuntimeHostServiceManagerError(
'retirement_failed',
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/runtime-host-session-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export interface RuntimeHostMakaSessionDriverInput {

type RuntimeHostSessionDriverConnection = Pick<
RuntimeHostConnection,
'hostEpoch' | 'openSessionSubscription' | 'request' | 'startTurn'
'hostEpoch' | 'openSessionSubscription' | 'request'
>;

export interface RuntimeHostMakaSessionDriver extends MakaSessionDriver {
Expand Down Expand Up @@ -286,7 +286,7 @@ class RuntimeHostMakaSessionDriverImpl implements RuntimeHostMakaSessionDriver {
...(options.turnOrchestration ? { turnOrchestration: options.turnOrchestration } : {}),
...(options.maxSteps !== undefined ? { maxSteps: options.maxSteps } : {}),
};
const result = await this.#connection.startTurn(startInput);
const result = await this.#connection.request('turn.start', startInput);
if (result.kind === 'blocked') {
throw new SkillInvocationBlockedError(result.skillInvocation);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ test('concurrent responses remain framed and correlated in reverse completion or
async ({ connectClient }) => {
const client = await connectClient();
const requests = Array.from({ length: requestCount }, (_, index) =>
client.queryTurn({ sessionId: 'session', turnId: `turn-${index}` }, 5_000),
client.request('turn.query', { sessionId: 'session', turnId: `turn-${index}` }, 5_000),
);
try {
await withTimeout(
Expand Down Expand Up @@ -257,7 +257,7 @@ test('the Client backpressures a healthy request burst at the Host connection li
async ({ connectClient }) => {
const client = await connectClient();
const requests = Array.from({ length: requestCount }, (_, index) =>
client.queryTurn({ sessionId: 'session', turnId: `burst-${index}` }, 5_000),
client.request('turn.query', { sessionId: 'session', turnId: `burst-${index}` }, 5_000),
);
try {
await withTimeout(firstWaveEntered.promise, 1_000, 'first request wave was not admitted');
Expand Down Expand Up @@ -656,7 +656,7 @@ test('an admitted operation settles without connection or residency leakage afte
async ({ connectClient }) => {
const client = await connectClient();
const requestFailure = client
.queryTurn({ sessionId: 'session', turnId: 'disconnect' }, 5_000)
.request('turn.query', { sessionId: 'session', turnId: 'disconnect' }, 5_000)
.then(
() => undefined,
(error: unknown) => error,
Expand Down Expand Up @@ -698,7 +698,7 @@ test('an admitted command reports an unknown outcome when its connection closes'
}),
async ({ connectClient }) => {
const client = await connectClient();
const command = client.startTurn({
const command = client.request('turn.start', {
sessionId: 'session',
turnId: 'interrupted-command',
content: { text: 'start' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,19 @@ test('two Clients share Daily Review config, generation, and restart recovery',
owner = undefined;
[desktop, tui] = await Promise.all([connect(root), connect(root)]);

const initial = await desktop.queryDailyReview({ kind: 'config' });
const initial = await desktop.request('daily-review.query', { kind: 'config' });
assert.deepEqual(initial, {
kind: 'config',
revision: 0,
config: { enabled: false, executeTime: '08:00', modelKey: '' },
});
const mutations = await Promise.all([
desktop.mutateDailyReview({
desktop.request('daily-review.mutate', {
kind: 'update_config',
expectedRevision: 0,
config: { enabled: false, executeTime: '09:00', modelKey: '' },
}),
tui.mutateDailyReview({
tui.request('daily-review.mutate', {
kind: 'update_config',
expectedRevision: 0,
config: { enabled: false, executeTime: '10:00', modelKey: '' },
Expand All @@ -105,8 +105,8 @@ test('two Clients share Daily Review config, generation, and restart recovery',
assert.equal(mutations.filter((result) => result.kind === 'config_committed').length, 1);
assert.equal(mutations.filter((result) => result.kind === 'revision_conflict').length, 1);
assert.deepEqual(
await desktop.queryDailyReview({ kind: 'config' }),
await tui.queryDailyReview({ kind: 'config' }),
await desktop.request('daily-review.query', { kind: 'config' }),
await tui.request('daily-review.query', { kind: 'config' }),
);

const run = {
Expand All @@ -117,15 +117,15 @@ test('two Clients share Daily Review config, generation, and restart recovery',
replaceExisting: false,
};
const [desktopRun, tuiRun] = await Promise.all([
desktop.mutateDailyReview(run),
tui.mutateDailyReview(run),
desktop.request('daily-review.mutate', run),
tui.request('daily-review.mutate', run),
]);
assert.deepEqual(tuiRun, desktopRun);
assert.equal(desktopRun.kind, 'archive');
if (desktopRun.kind !== 'archive') return;
assert.equal(desktopRun.archive.status, 'no_data');

const noModel = await desktop.mutateDailyReview({
const noModel = await desktop.request('daily-review.mutate', {
...run,
offsetDays: 0,
modelKeyOverride: 'missing-provider::missing-model',
Expand All @@ -135,7 +135,7 @@ test('two Clients share Daily Review config, generation, and restart recovery',
assert.equal(noModel.archive.status, 'no_model');
assert.equal(noModel.archive.totals.requestCount, 1);

const enabled = await desktop.mutateDailyReview({
const enabled = await desktop.request('daily-review.mutate', {
kind: 'update_config',
expectedRevision: 1,
config: {
Expand Down Expand Up @@ -164,14 +164,14 @@ test('two Clients share Daily Review config, generation, and restart recovery',
owner = undefined;
tui = await connect(root);
assert.deepEqual(
await tui.queryDailyReview({
await tui.request('daily-review.query', {
kind: 'archive',
archiveId: desktopRun.archive.id,
}),
{ kind: 'archive', archive: desktopRun.archive },
);
assert.deepEqual(
await tui.queryDailyReview({
await tui.request('daily-review.query', {
kind: 'archive',
archiveId: scheduled.id,
}),
Expand Down Expand Up @@ -201,15 +201,15 @@ async function waitForScheduledArchive(
): Promise<DailyReviewArchive> {
const deadline = Date.now() + 5_000;
while (Date.now() < deadline) {
const page = await connection.queryDailyReview({
const page = await connection.request('daily-review.query', {
kind: 'archives',
beforeArchiveId: null,
limit: 10,
});
if (page.kind === 'archives') {
const scheduled = page.archives.find((archive) => archive.trigger === 'cron');
if (scheduled) {
const result = await connection.queryDailyReview({
const result = await connection.request('daily-review.query', {
kind: 'archive',
archiveId: scheduled.id,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ test('two Clients and a restarted production Host share one Deep Research projec
[desktop, tui] = await Promise.all([connect(root), connect(root)]);

const [desktopProjection, tuiProjection] = await Promise.all([
desktop.queryDeepResearch({ sessionId: session.id }),
tui.queryDeepResearch({ sessionId: session.id }),
desktop.request('deep-research.query', { sessionId: session.id }),
tui.request('deep-research.query', { sessionId: session.id }),
]);
assert.deepEqual(tuiProjection, desktopProjection);
assert.equal(desktopProjection.kind, 'snapshot');
Expand Down Expand Up @@ -128,7 +128,10 @@ test('two Clients and a restarted production Host share one Deep Research projec
owner = undefined;
tui = await connect(root);

assert.deepEqual(await tui.queryDeepResearch({ sessionId: session.id }), desktopProjection);
assert.deepEqual(
await tui.request('deep-research.query', { sessionId: session.id }),
desktopProjection,
);
} finally {
await Promise.allSettled([desktop?.close(), tui?.close()]);
await host?.close().catch(() => undefined);
Expand Down
Loading