blob: 096479011b72d212477bdac029b457c11e0bae3c [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 { withTimeout } from '@maka/core/test-only/async-primitives';
import assert from 'node:assert/strict';
import { fork, type ChildProcess } from 'node:child_process';
import { randomUUID } from 'node:crypto';
import {
appendFile,
chmod,
mkdir,
mkdtemp,
readFile,
readdir,
rm,
writeFile,
} from 'node:fs/promises';
import { createServer, type Server } from 'node:http';
import { connect, type Socket } from 'node:net';
import { tmpdir } from 'node:os';
import { dirname, join } from 'node:path';
import { DatabaseSync } from 'node:sqlite';
import { test } from 'node:test';
import { TOOL_BOUNDARY_PROTOCOL_V1 } from '@maka/core/runtime-event';
import { canonicalToolArgsHash } from '@maka/core/tool-args-identity';
import type { MessageContent } from '@maka/core/events';
import type { ConnectionCatalogEntry } from '@maka/core/runtime-policy';
import {
decodeStoredMessage as decodePersistedStoredMessage,
type StoredMessage,
} from '@maka/core/session';
import { markPersisted } from '@maka/core/persisted-value';
import type { SessionTodoItem } from '@maka/core/session-todo';
import type { ScheduledTask } from '@maka/core/scheduled-task';
import { isTerminalRuntimeEvent } from '@maka/core/runtime-event';
import type { RuntimeEvent } from '@maka/core/runtime-event';
import { buildSessionTodoTools } from '@maka/runtime/session-todo-tools';
import {
buildRecoveredTerminalRuntimeEvent,
classifyTerminalRuntimeLedger,
commitTerminalRunWithRuntimeFact,
} from '@maka/runtime/terminal-run-commit';
import {
FAKE_ASK_SANDBOX_BOUNDARY_PROMPT,
FAKE_ASK_USER_QUESTION_PROMPT,
FAKE_WAIT_FOR_STEERING_PROMPT,
} from '@maka/runtime/test-only/fake-backend';
import { type MakaTool, type MakaToolContext } from '@maka/runtime/tool-runtime';
import {
openInteractiveExecutionStoresForRead,
openInteractiveExecutionStoresForWrite,
} from '@maka/storage/execution-stores';
import { OPERATIONAL_STATE_DATABASE_NAME } from '@maka/storage/operational-state-store';
import { openInteractiveRuntimePolicyStoresForWrite } from '@maka/storage/runtime-policy-stores';
import {
resolveRootControlNamespace,
resolveStorageRoot,
tryAcquireInteractiveRootOwner,
tryAcquireInteractiveRootReader,
type StorageRootCapability,
} from '@maka/storage/root-authority';
import { openInteractiveSessionTodoStoreForWrite } from '@maka/storage/session-todo-authority';
import {
connectRuntimeHost,
RuntimeHostOperationError,
RuntimeHostSubscriptionError,
type RuntimeHostConnection,
type RuntimeHostSessionSubscription,
} from '../client/index.js';
import {
decodeHostFrame,
RUNTIME_HOST_PROTOCOL_VERSION,
type ConnectionCatalogQueryResult,
type InteractionPendingSnapshot,
type SubscriptionFrame,
type TurnMessageSubmitInput,
type TurnSnapshot,
} from '../protocol/index.js';
import { SessionAdmissionGate } from '../server/session-admission-gate.js';
import { HostSessionTodoCoordinator } from '../server/session-todo-coordinator.js';
import { FramedTransport } from '../transport/framed-transport.js';
import {
CONNECTION_EFFECT_MODEL_IDS,
type ExecutionFixture,
PROCESS_TIMEOUT_MS,
SubscriptionProbe,
assertJsonLines,
attachment,
connectClient,
requireStartedTurn,
operationError,
quotedContent,
sendStartWithoutReadingResponse,
startConnectionEffectProvider,
userRuntimeContent,
waitForDurableMessageConflict,
waitForPendingInteraction,
waitForRunningTurn,
waitForTerminalTurn,
waitForTurn,
withExecutionRoot,
} from './fixtures/execution-host-suite.js';
const decodeStoredMessage = (value: unknown): StoredMessage =>
decodePersistedStoredMessage(markPersisted<StoredMessage>(value));
test('production Host resumes a Session through the ScheduledTask authority', {
timeout: 30_000,
}, async () => {
await withExecutionRoot(async (fixture) => {
const host = await fixture.startHost();
const desktop = await connectClient(fixture.root);
const tui = await connectClient(fixture.root);
try {
const heartbeat = await desktop.request('scheduled-task.mutate', {
kind: 'create',
input: {
title: 'session resume execution proof',
intentBody: 'Complete the scheduled execution proof.',
schedule: { kind: 'once', runAt: Date.now() + 5_000 },
effect: { kind: 'session_resume', sessionId: fixture.sessionId },
},
});
assert.equal(heartbeat.kind, 'task');
if (heartbeat.kind !== 'task') {
return;
}
const observedHeartbeat = await waitForScheduledTaskCompletion(tui, heartbeat.task.id);
assert.ok(observedHeartbeat.runs[0]?.runId);
assert.equal(observedHeartbeat.lastError, null);
const deletedHeartbeat = await tui.request('scheduled-task.mutate', {
kind: 'delete',
taskId: heartbeat.task.id,
});
assert.equal(deletedHeartbeat.kind, 'deleted');
} finally {
await Promise.allSettled([desktop.close(), tui.close()]);
await fixture.stopHost(host);
}
});
});
test('production Host fails slug-only ScheduledTask Agent runs before binding execution identity', {
timeout: 30_000,
}, async () => {
await withExecutionRoot(async (fixture) => {
const seededConnection = await fixture.seedConnectionEffect(
'http://127.0.0.1:1',
'test-secret',
);
const host = await fixture.startHost();
const desktop = await connectClient(fixture.root);
try {
const created = await desktop.request('scheduled-task.mutate', {
kind: 'create',
input: {
title: 'legacy agent-run identity proof',
intentBody: 'Do not execute with a replacement account.',
schedule: { kind: 'once', runAt: Date.now() + 60_000 },
effect: {
kind: 'agent_run',
execution: {
cwd: fixture.root,
llmConnectionId: seededConnection.connectionId,
llmConnectionSlug: seededConnection.slug,
model: seededConnection.enabledModelIds[0]!,
permissionMode: 'ask',
collaborationMode: 'agent',
orchestrationMode: 'default',
},
},
},
});
assert.equal(created.kind, 'task');
if (created.kind !== 'task') return;
// Simulate a record written by a pre-#3927 build. Legacy rows remain
// readable, but must fail closed before a Session or AgentRun is bound.
const database = new DatabaseSync(join(fixture.root, OPERATIONAL_STATE_DATABASE_NAME));
try {
database
.prepare(
`UPDATE workflow_scheduled_tasks
SET record_json = json_remove(record_json, '$.effect.execution.llmConnectionId')
WHERE task_id = ?`,
)
.run(created.task.id);
} finally {
database.close();
}
const fired = await desktop.request('scheduled-task.mutate', {
kind: 'trigger_now',
taskId: created.task.id,
});
assert.equal(fired.kind, 'task');
if (fired.kind !== 'task') return;
assert.equal(
fired.task.lastError,
'ScheduledTask Agent runs require an immutable model connection identity',
);
assert.equal(fired.task.runs.length, 1);
assert.equal(fired.task.runs[0]?.outcome, 'failed');
assert.equal(fired.task.runs[0]?.sessionId, undefined);
assert.equal(fired.task.runs[0]?.runId, undefined);
} finally {
await desktop.close();
await fixture.stopHost(host);
}
});
});
test('two UDS Clients never rebind an Agent ScheduledTask after Connection slug reuse', {
timeout: 30_000,
}, async () => {
await withExecutionRoot(async (fixture) => {
const original = await fixture.seedConnectionEffect('http://127.0.0.1:1', 'test-secret');
const model = original.enabledModelIds[0]!;
const host = await fixture.startHost();
const creator = await connectClient(fixture.root);
const trigger = await connectClient(fixture.root);
try {
const created = await creator.request('scheduled-task.mutate', {
kind: 'create',
input: {
title: 'Connection slug reuse proof',
intentBody: 'The deleted account must never be replaced silently.',
schedule: { kind: 'once', runAt: Date.now() + 60_000 },
effect: {
kind: 'agent_run',
execution: {
cwd: fixture.root,
llmConnectionId: original.connectionId,
llmConnectionSlug: original.slug,
model,
permissionMode: 'ask',
collaborationMode: 'agent',
orchestrationMode: 'default',
},
},
},
});
assert.equal(created.kind, 'task');
if (created.kind !== 'task') return;
const catalog = await trigger.request('connection.catalog.query', { kind: 'start' });
assert.equal(catalog.kind, 'page');
if (catalog.kind !== 'page') return;
const header = catalog.items.find(
(item) => item.kind === 'connection' && item.connectionId === original.connectionId,
);
assert.equal(header?.kind, 'connection');
if (header?.kind !== 'connection') return;
const removed = await trigger.request('connection.catalog.remove', {
expected: { connectionId: original.connectionId, revision: header.revision },
});
assert.equal(removed.kind, 'committed');
if (removed.kind !== 'committed') return;
const replacement = await trigger.request('connection.catalog.create', {
expectedCatalogRevision: removed.catalogRevision,
connection: {
slug: original.slug,
name: 'Replacement account',
providerType: original.providerType,
...(original.baseUrl === undefined ? {} : { baseUrl: original.baseUrl }),
enabled: true,
enabledModelIds: [model],
},
});
assert.equal(replacement.kind, 'committed');
if (replacement.kind !== 'committed') return;
assert.notEqual(replacement.connection.connectionId, original.connectionId);
const fired = await trigger.request('scheduled-task.mutate', {
kind: 'trigger_now',
taskId: created.task.id,
});
assert.equal(fired.kind, 'task');
if (fired.kind !== 'task') return;
assert.equal(fired.task.runs[0]?.outcome, 'failed');
assert.equal(fired.task.lastError, 'ScheduledTask model connection identity changed');
const failedRun = fired.task.runs[0];
assert.ok(failedRun?.sessionId);
assert.ok(failedRun?.runId);
const databaseAfterFire = new DatabaseSync(
join(fixture.root, OPERATIONAL_STATE_DATABASE_NAME),
);
try {
assert.equal(
databaseAfterFire
.prepare('SELECT 1 AS present FROM session_metadata WHERE session_id = ?')
.get(failedRun.sessionId),
undefined,
);
assert.equal(
databaseAfterFire
.prepare('SELECT 1 AS present FROM core_agent_runs WHERE run_id = ?')
.get(failedRun.runId),
undefined,
);
} finally {
databaseAfterFire.close();
}
} finally {
await Promise.allSettled([creator.close(), trigger.close()]);
await fixture.stopHost(host);
}
});
});
test('production Host settles dispatched Client Capabilities before publishing Ready', async () => {
await withExecutionRoot(async (fixture) => {
const prepared = await seedDispatchedClientCapability(fixture);
const host = await fixture.startHost({
sessionId: fixture.sessionId,
runId: prepared.runId,
});
try {
const outcome = host.recoveryOutcome;
assert.equal(outcome?.content?.kind, 'function_response');
if (outcome?.content?.kind !== 'function_response') return;
assert.equal(outcome.content.name, prepared.toolName);
assert.equal(outcome.content.isError, true);
assert.ok(outcome.content.result && typeof outcome.content.result === 'object');
const recovered = outcome.content.result as {
kind?: unknown;
uncertainOutcome?: unknown;
};
assert.equal(recovered.kind, 'text');
assert.deepEqual(recovered.uncertainOutcome, {
code: 'outcome_unknown',
retrySafe: false,
});
} finally {
await fixture.stopHost(host);
}
});
});
test('dual UDS Clients query the same persisted SessionTodo snapshot across Host restart', async () => {
await withExecutionRoot(async (fixture) => {
const initial: SessionTodoItem[] = Array.from({ length: 129 }, (_, index) => ({
content: `Authority acceptance todo ${index + 1}`,
status: index === 0 ? 'in_progress' : 'pending',
}));
await withOwnedSessionTodoToolPort(fixture, async (_coordinator, tools) => {
const write = requireSessionTodoWriteTool(tools);
await write.impl(write.parameters.parse({ todos: initial }), sessionTodoToolContext(fixture));
});
const host = await fixture.startHost();
const desktop = await connectClient(fixture.root);
const tui = await connectClient(fixture.root);
try {
const [desktopProjection, tuiProjection] = await Promise.all([
desktop.request('session.todo.query', { sessionId: fixture.sessionId }),
tui.request('session.todo.query', { sessionId: fixture.sessionId }),
]);
assert.deepEqual(desktopProjection, { sessionId: fixture.sessionId, items: initial });
assert.deepEqual(tuiProjection, desktopProjection);
} finally {
await Promise.allSettled([desktop.close(), tui.close()]);
await fixture.stopHost(host);
}
const changed = [
{ content: 'Changed after authority reacquisition', status: 'completed' },
] as const;
await withOwnedSessionTodoToolPort(fixture, async (_coordinator, tools) => {
const write = requireSessionTodoWriteTool(tools);
await write.impl(write.parameters.parse({ todos: changed }), sessionTodoToolContext(fixture));
});
const successorHost = await fixture.startHost();
const successor = await connectClient(fixture.root);
try {
assert.deepEqual(
await successor.request('session.todo.query', { sessionId: fixture.sessionId }),
{
sessionId: fixture.sessionId,
items: changed,
},
);
} finally {
await successor.close();
await fixture.stopHost(successorHost);
}
});
});
async function seedDispatchedClientCapability(
fixture: ExecutionFixture,
): Promise<{ runId: string; toolName: string }> {
const owner = await tryAcquireInteractiveRootOwner(fixture.capability);
assert.ok(owner);
if (!owner) throw new Error('Unable to acquire execution root for Client Capability setup');
let stores: Awaited<ReturnType<typeof openInteractiveExecutionStoresForWrite>> | undefined;
try {
stores = await openInteractiveExecutionStoresForWrite(owner.lease);
const operationId = 'client-capability-before-ready';
const invocationId = `${operationId}-invocation`;
const runId = `${operationId}-run`;
const turnId = `${operationId}-turn`;
const providerToolCallId = `${operationId}-call`;
const toolName = 'mcp__client_fixture__navigate';
const args = { url: 'https://example.test/recovery' };
const canonicalArgsHash = canonicalToolArgsHash(toolName, args);
const call: RuntimeEvent = {
id: `${operationId}_call`,
invocationId,
runId,
sessionId: fixture.sessionId,
turnId,
ts: 10,
partial: false,
role: 'model',
author: 'agent',
content: {
kind: 'function_call',
id: providerToolCallId,
name: toolName,
args,
},
refs: { operationId, toolCallId: providerToolCallId },
};
const dispatch: RuntimeEvent = {
id: `${operationId}_dispatch`,
invocationId,
runId,
sessionId: fixture.sessionId,
turnId,
ts: 10,
partial: false,
role: 'system',
author: 'system',
actions: {
toolDispatch: {
protocol: TOOL_BOUNDARY_PROTOCOL_V1,
operationId,
providerToolCallId,
toolName,
canonicalArgsHash,
recoveryMode: 'outcome_unknown',
},
},
refs: { operationId, toolCallId: providerToolCallId },
};
await stores.runtimeEventStore.commitToolPrepared({
operationId,
journalEventId: `${operationId}_prepared`,
runtimeEvent: call,
dispatchRuntimeEvent: dispatch,
providerToolCallId,
toolName,
canonicalArgsHash,
recoveryMode: 'outcome_unknown',
committedAt: 10,
});
return { runId, toolName };
} finally {
await stores?.sessionStore.close?.();
await owner.close();
}
}
test('two UDS Clients share one Runtime Policy authority and CAS winner', async () => {
await withExecutionRoot(async (fixture) => {
const host = await fixture.startHost();
const first = await connectClient(fixture.root);
const second = await connectClient(fixture.root);
try {
const initial = await first.request('runtime.policy.query', {});
assert.deepEqual(await second.request('runtime.policy.query', {}), initial);
const outcomes = await Promise.all([
first.request('runtime.policy.mutate', {
expectedRevision: initial.revision,
operation: {
kind: 'set_personalization',
value: { displayName: 'Desktop', assistantTone: 'precise' },
},
}),
second.request('runtime.policy.mutate', {
expectedRevision: initial.revision,
operation: {
kind: 'set_memory',
value: { enabled: false, agentReadEnabled: false },
},
}),
]);
assert.deepEqual(outcomes.map((outcome) => outcome.kind).sort(), [
'committed',
'revision_conflict',
]);
assert.deepEqual(
await first.request('runtime.policy.query', {}),
await second.request('runtime.policy.query', {}),
);
} finally {
await Promise.allSettled([first.close(), second.close()]);
await fixture.stopHost(host);
}
});
});
test('two UDS Clients serialize same-provider account creation through one Host lane', async () => {
const provider = await startConnectionEffectProvider({ responseDelayMs: 50 });
try {
await withExecutionRoot(async (fixture) => {
const host = await fixture.startHost();
const desktop = await connectClient(fixture.root);
const tui = await connectClient(fixture.root);
const secrets = ['desktop-account-secret', 'tui-account-secret'] as const;
let identities: Array<{ connectionId: string; slug: string }> = [];
try {
const results = await Promise.all(
[desktop, tui].map((client, index) =>
client.request('connection.onboarding.save', {
target: { kind: 'create', providerType: 'openai-compatible' },
apiKey: secrets[index]!,
baseUrl: provider.baseUrl,
enabledModelIds: [CONNECTION_EFFECT_MODEL_IDS[0]!],
}),
),
);
assert.ok(results.every((result) => result.kind === 'saved'));
identities = results.map((result) => {
if (result.kind !== 'saved') throw new Error('Onboarding did not save');
return {
connectionId: result.connection.connectionId,
slug: result.connection.slug,
};
});
assert.notEqual(identities[0]?.connectionId, identities[1]?.connectionId);
assert.deepEqual(identities.map(({ slug }) => slug).sort(), [
'openai-compatible',
'openai-compatible-2',
]);
} finally {
await Promise.allSettled([desktop.close(), tui.close()]);
await fixture.stopHost(host);
}
const owner = await tryAcquireInteractiveRootOwner(fixture.capability);
assert.ok(owner);
if (!owner) return;
try {
const stores = await openInteractiveRuntimePolicyStoresForWrite(owner.lease);
const catalog = await stores.connectionCatalog.getSnapshot();
assert.deepEqual(
catalog.connections
.filter(({ providerType }) => providerType === 'openai-compatible')
.map(({ connectionId, slug }) => ({ connectionId, slug }))
.sort((left, right) => left.slug.localeCompare(right.slug)),
[...identities].sort((left, right) => left.slug.localeCompare(right.slug)),
);
for (const [index, identity] of identities.entries()) {
assert.equal(
(
await stores.operations.exportCredentialMaterial({
scope: 'connection',
connectionId: identity.connectionId,
kind: 'api_key',
})
)?.secret,
secrets[index],
);
}
} finally {
await owner.close();
}
assert.deepEqual(
provider.requests.map(({ authorization }) => authorization).sort(),
secrets.map((secret) => `Bearer ${secret}`).sort(),
);
});
} finally {
await provider.close();
}
});
test('two UDS Clients await slow connection effects against one canonical catalog', async () => {
const provider = await startConnectionEffectProvider({ responseDelayMs: 2_100 });
try {
await withExecutionRoot(async (fixture) => {
const secret = 'connection-effect-secret';
const connection = await fixture.seedConnectionEffect(provider.baseUrl, secret);
const host = await fixture.startHost();
const desktop = await connectClient(fixture.root);
const tui = await connectClient(fixture.root);
try {
assert.equal(desktop.hostEpoch, tui.hostEpoch);
assert.notEqual(desktop.connectionId, tui.connectionId);
const fetchInput = { connectionId: connection.connectionId };
const fetched = await desktop.request('connection.models.fetch', {
...fetchInput,
});
assert.equal(fetched.kind, 'committed');
if (fetched.kind !== 'committed') return;
assert.equal(fetched.modelCount, CONNECTION_EFFECT_MODEL_IDS.length);
assert.equal(fetched.source, 'fetched');
const firstPage = await tui.request('connection.catalog.query', { kind: 'start' });
assert.equal(firstPage.kind, 'page');
if (firstPage.kind !== 'page') return;
type CatalogPage = Extract<ConnectionCatalogQueryResult, { readonly kind: 'page' }>;
const pages: CatalogPage[] = [firstPage];
let observed: CatalogPage = firstPage;
while (observed.nextCursor) {
const nextResult: ConnectionCatalogQueryResult = await tui.request(
'connection.catalog.query',
{
kind: 'continue',
revision: observed.revision,
cursor: observed.nextCursor,
},
);
assert.equal(nextResult.kind, 'page');
if (nextResult.kind !== 'page') return;
pages.push(nextResult);
observed = nextResult;
}
assert.ok(pages.length > 1);
assert.ok(pages.every((page) => page.revision === fetched.catalogRevision));
assert.deepEqual(
pages.flatMap((page) =>
page.items.flatMap((item) => (item.kind === 'model' ? [item.model.id] : [])),
),
CONNECTION_EFFECT_MODEL_IDS,
);
const testInput = {
connectionId: connection.connectionId,
modelId: CONNECTION_EFFECT_MODEL_IDS[0]!,
};
const tested = await tui.request('connection.test.run', {
...testInput,
});
assert.equal(tested.kind, 'committed');
if (tested.kind !== 'committed') return;
assert.equal(tested.test.kind, 'verified');
const canonical = await desktop.request('connection.catalog.query', { kind: 'start' });
assert.equal(canonical.kind, 'page');
if (canonical.kind !== 'page') return;
const header = canonical.items.find(
(item) => item.kind === 'connection' && item.connectionId === connection.connectionId,
);
assert.equal(header?.kind, 'connection');
if (header?.kind === 'connection') {
assert.deepEqual(header.lastTest, {
status: 'verified',
checkedAt: tested.test.checkedAt,
});
}
assert.equal(
JSON.stringify([fetchInput, fetched, pages, testInput, tested, canonical]).includes(
secret,
),
false,
);
assert.equal(provider.requests.length, 2);
assert.ok(
provider.requests.every(({ authorization }) => authorization === `Bearer ${secret}`),
);
assert.deepEqual(
provider.requests.map(({ method, url }) => ({
method,
url,
})),
[
{
method: 'GET',
url: '/v1/models',
},
{
method: 'POST',
url: '/v1/chat/completions',
},
],
);
} finally {
await Promise.allSettled([desktop.close(), tui.close()]);
await fixture.stopHost(host);
}
});
} finally {
await provider.close();
}
});
test('two Clients share one execution after the starting Client disconnects', async () => {
await withExecutionRoot(async (fixture) => {
const host = await fixture.startHost();
const first = await connectClient(fixture.root);
const second = await connectClient(fixture.root);
const turnId = randomUUID();
const started = requireStartedTurn(
await first.request(
'turn.start',
{
sessionId: fixture.sessionId,
turnId,
content: { text: FAKE_ASK_USER_QUESTION_PROMPT },
},
PROCESS_TIMEOUT_MS,
),
);
assert.equal(started.turnId, turnId);
const secondSubscription = await second.openSessionSubscription({
sessionId: fixture.sessionId,
transcript: { kind: 'tail', maxBytes: 16 * 1024 },
});
const transcript = await secondSubscription.loadTranscript(decodeStoredMessage);
assert.ok(
transcript.some(
(message) =>
message.type === 'user' &&
message.turnId === turnId &&
message.text === FAKE_ASK_USER_QUESTION_PROMPT,
),
);
const secondProbe = new SubscriptionProbe(secondSubscription);
await assert.rejects(
() =>
second.request(
'turn.start',
{
sessionId: fixture.sessionId,
turnId: randomUUID(),
content: { text: 'must stay busy' },
},
PROCESS_TIMEOUT_MS,
),
operationError('session_busy'),
);
await first.close();
const pending = await waitForPendingInteraction(secondSubscription, secondProbe, started.runId);
assert.equal(pending.sessionId, fixture.sessionId);
assert.equal(pending.turnId, turnId);
assert.equal(pending.runId, started.runId);
const questionRequest = pending.request;
assert.ok(questionRequest.kind === 'question');
assert.deepEqual(
await second.request('interaction.query', {
sessionId: fixture.sessionId,
interactionId: pending.interactionId,
}),
pending,
);
const observed = await second.request('turn.query', {
sessionId: fixture.sessionId,
turnId,
});
assert.equal(observed.runId, started.runId);
assert.ok(observed.status === 'running' || observed.status === 'waiting_for_user');
const stopped = await second.request(
'turn.stop',
{
sessionId: fixture.sessionId,
turnId,
runId: started.runId,
},
PROCESS_TIMEOUT_MS,
);
assert.equal(stopped.status, 'cancelled');
const closed = await second.request('interaction.query', {
sessionId: fixture.sessionId,
interactionId: pending.interactionId,
});
assert.equal(closed.sessionId, fixture.sessionId);
assert.equal(closed.turnId, turnId);
assert.equal(closed.runId, started.runId);
assert.equal(closed.status, 'closed');
assert.equal(closed.outcome.kind, 'closure');
if (closed.outcome.kind === 'closure') assert.equal(closed.outcome.reason, 'turn_stopped');
await assert.rejects(
() =>
second.request('interaction.answer', {
sessionId: fixture.sessionId,
interactionId: pending.interactionId,
answer: {
kind: 'question',
answers: questionRequest.questions.map(() => null),
},
}),
operationError('already_resolved'),
);
const nextTurnId = randomUUID();
const next = requireStartedTurn(
await second.request(
'turn.start',
{
sessionId: fixture.sessionId,
turnId: nextTurnId,
content: { text: FAKE_ASK_USER_QUESTION_PROMPT },
},
PROCESS_TIMEOUT_MS,
),
);
assert.deepEqual(
requireStartedTurn(
await second.request(
'turn.start',
{
sessionId: fixture.sessionId,
turnId,
content: { text: FAKE_ASK_USER_QUESTION_PROMPT },
},
PROCESS_TIMEOUT_MS,
),
),
stopped,
);
assert.deepEqual(
await second.request('turn.stop', {
sessionId: fixture.sessionId,
turnId,
runId: started.runId,
}),
stopped,
);
const nextObserved = await second.request('turn.query', {
sessionId: fixture.sessionId,
turnId: nextTurnId,
});
assert.equal(nextObserved.runId, next.runId);
assert.ok(nextObserved.status === 'running' || nextObserved.status === 'waiting_for_user');
await second.request(
'turn.stop',
{
sessionId: fixture.sessionId,
turnId: nextTurnId,
runId: next.runId,
},
PROCESS_TIMEOUT_MS,
);
await secondSubscription.close();
await secondProbe.done;
await second.close();
await fixture.stopHost(host);
const ledger = await fixture.readTurn(turnId);
assert.equal(ledger.runs.length, 1);
assert.equal(ledger.userMessages.length, 1);
assert.equal(ledger.terminalEvents.length, 1);
assert.equal(ledger.classification.kind, 'fact');
if (ledger.classification.kind === 'fact') {
assert.equal(ledger.classification.fact.runStatus, 'cancelled');
assert.notEqual(ledger.classification.fact.failureClass, 'app_restarted');
}
});
});
test('regenerate replays the durable source content with one recoverable root identity', async () => {
await withExecutionRoot(async (fixture) => {
const host = await fixture.startHost();
const client = await connectClient(fixture.root);
const sourceTurnId = randomUUID();
const regeneratedTurnId = randomUUID();
try {
await client.request(
'turn.start',
{
sessionId: fixture.sessionId,
turnId: sourceTurnId,
content: quotedContent('repeat this request'),
},
PROCESS_TIMEOUT_MS,
);
await waitForTerminalTurn(client, fixture.sessionId, sourceTurnId);
const started = await client.request(
'turn.regenerate',
{
sessionId: fixture.sessionId,
sourceTurnId,
turnId: regeneratedTurnId,
},
PROCESS_TIMEOUT_MS,
);
const terminal = await waitForTerminalTurn(client, fixture.sessionId, regeneratedTurnId);
assert.equal(terminal.runId, started.runId);
assert.deepEqual(
await client.request('turn.regenerate', {
sessionId: fixture.sessionId,
sourceTurnId,
turnId: regeneratedTurnId,
}),
terminal,
);
} finally {
await client.close();
await fixture.stopHost(host);
}
const ledger = await fixture.readTurn(regeneratedTurnId);
assert.equal(ledger.runs.length, 1);
assert.equal(ledger.userMessages.length, 1);
assert.equal(ledger.runs[0]?.opening.lineage?.parentTurnId, sourceTurnId);
assert.equal(ledger.runs[0]?.opening.lineage?.regeneratedFromTurnId, sourceTurnId);
assert.deepEqual(
{
text: ledger.userMessages[0]?.text,
quotes: ledger.userMessages[0]?.quotes,
},
quotedContent('repeat this request'),
);
});
});
test('regenerate rejects self-source and legacy target collisions without draining Host', async () => {
await withExecutionRoot(async (fixture) => {
const firstHost = await fixture.startHost();
const first = await connectClient(fixture.root);
const sourceTurnId = randomUUID();
await first.request('turn.start', {
sessionId: fixture.sessionId,
turnId: sourceTurnId,
content: { text: 'source request' },
});
await waitForTerminalTurn(first, fixture.sessionId, sourceTurnId);
await assert.rejects(
first.request('turn.regenerate', {
sessionId: fixture.sessionId,
sourceTurnId,
turnId: sourceTurnId,
}),
operationError('operation_conflict'),
);
await first.close();
await fixture.stopHost(firstHost);
const legacy = await fixture.seedSafeBoundaryContinuationSource();
const secondHost = await fixture.startHost();
const second = await connectClient(fixture.root);
try {
await assert.rejects(
second.request('turn.regenerate', {
sessionId: fixture.sessionId,
sourceTurnId,
turnId: legacy.sourceTurnId,
}),
operationError('operation_conflict'),
);
const followingTurnId = randomUUID();
await second.request('turn.start', {
sessionId: fixture.sessionId,
turnId: followingTurnId,
content: { text: 'Host remains available' },
});
assert.equal(
(await waitForTerminalTurn(second, fixture.sessionId, followingTurnId)).status,
'completed',
);
} finally {
await second.close();
await fixture.stopHost(secondHost);
}
assert.deepEqual(await fixture.readTurnFootprint(legacy.sourceTurnId), {
admitted: false,
runCount: 1,
userMessageCount: 0,
});
});
});
test('context actions share root admission and expose backend capability honestly', async () => {
await withExecutionRoot(async (fixture) => {
const host = await fixture.startHost();
const first = await connectClient(fixture.root);
const second = await connectClient(fixture.root);
const turnId = randomUUID();
const unavailableTurnId = randomUUID();
try {
assert.deepEqual(
await first.request('context.diagnostics.query', {
sessionId: fixture.sessionId,
}),
{
status: 'unavailable',
reason: 'no_completed_request',
},
);
const started = requireStartedTurn(
await first.request('turn.start', {
sessionId: fixture.sessionId,
turnId,
content: { text: FAKE_ASK_USER_QUESTION_PROMPT },
}),
);
await waitForRunningTurn(second, fixture.sessionId, turnId);
await assert.rejects(
second.request('context.compact', {
sessionId: fixture.sessionId,
turnId: randomUUID(),
}),
operationError('session_busy'),
);
await second.request('turn.stop', {
sessionId: fixture.sessionId,
turnId,
runId: started.runId,
});
await assert.rejects(
second.request('context.compact', {
sessionId: fixture.sessionId,
turnId: unavailableTurnId,
}),
operationError('operation_unavailable'),
);
await assert.rejects(
second.request('context.diagnostics.query', { sessionId: 'missing-session' }),
operationError('not_found'),
);
} finally {
await Promise.allSettled([first.close(), second.close()]);
await fixture.stopHost(host);
}
assert.deepEqual(await fixture.readTurnFootprint(unavailableTurnId), {
admitted: false,
runCount: 0,
userMessageCount: 0,
});
});
});
test('a disconnected Client leaves a durable Interaction that another Client can answer', async () => {
await withExecutionRoot(async (fixture) => {
const firstHost = await fixture.startHost();
const first = await connectClient(fixture.root);
const turnId = randomUUID();
const started = requireStartedTurn(
await first.request('turn.start', {
sessionId: fixture.sessionId,
turnId,
content: { text: FAKE_ASK_USER_QUESTION_PROMPT },
}),
);
await first.close();
const second = await connectClient(fixture.root);
const subscription = await second.openSessionSubscription({
sessionId: fixture.sessionId,
transcript: { kind: 'none' },
});
const probe = new SubscriptionProbe(subscription);
const pending = await waitForPendingInteraction(subscription, probe, started.runId);
assert.equal(pending.sessionId, fixture.sessionId);
assert.equal(pending.turnId, turnId);
assert.equal(pending.runId, started.runId);
assert.equal(pending.status, 'pending');
const questionRequest = pending.request;
assert.ok(questionRequest.kind === 'question');
assert.deepEqual(
await second.request('interaction.query', {
sessionId: fixture.sessionId,
interactionId: pending.interactionId,
}),
pending,
);
const answer = {
kind: 'question' as const,
answers: questionRequest.questions.map((question) => question.options[0]?.label ?? null),
};
const winner = await second.request('interaction.answer', {
sessionId: fixture.sessionId,
interactionId: pending.interactionId,
answer,
});
assert.equal(winner.sessionId, fixture.sessionId);
assert.equal(winner.turnId, turnId);
assert.equal(winner.runId, started.runId);
assert.equal(winner.status, 'answered');
assert.equal(winner.outcome.kind, 'question_answer');
assert.deepEqual(winner.outcome.answers, answer.answers);
assert.deepEqual(
await second.request('interaction.query', {
sessionId: fixture.sessionId,
interactionId: pending.interactionId,
}),
winner,
);
assert.deepEqual(
await second.request('interaction.answer', {
sessionId: fixture.sessionId,
interactionId: pending.interactionId,
answer,
}),
winner,
);
const resumed = await probe.waitFor(
(frame) =>
frame.kind === 'subscription.session_projection' &&
frame.snapshot.session.status === 'running' &&
frame.snapshot.rootTurn?.runId === started.runId &&
frame.snapshot.rootTurn.status === 'running' &&
frame.snapshot.interactions.pending.length === 0,
'continuity did not publish the resumed Turn after the question answer',
);
assert.equal(resumed.kind, 'subscription.session_projection');
const completed = await waitForTerminalTurn(second, fixture.sessionId, turnId);
assert.equal(completed.runId, started.runId);
assert.equal(completed.status, 'completed');
await subscription.close();
await probe.done;
await second.close();
await fixture.stopHost(firstHost);
const secondHost = await fixture.startHost();
const observer = await connectClient(fixture.root);
assert.deepEqual(
await observer.request('interaction.query', {
sessionId: fixture.sessionId,
interactionId: pending.interactionId,
}),
winner,
);
assert.deepEqual(
await observer.request('interaction.answer', {
sessionId: fixture.sessionId,
interactionId: pending.interactionId,
answer,
}),
winner,
);
assert.deepEqual(
await observer.request('turn.query', { sessionId: fixture.sessionId, turnId }),
completed,
);
await observer.close();
await fixture.stopHost(secondHost);
});
});
test('two UDS Clients settle one hosted sandbox boundary and resume its exact Run', async () => {
await withExecutionRoot(async (fixture) => {
const firstHost = await fixture.startHost();
const starter = await connectClient(fixture.root);
const first = await connectClient(fixture.root);
const second = await connectClient(fixture.root);
const subscription = await first.openSessionSubscription({
sessionId: fixture.sessionId,
transcript: { kind: 'none' },
});
const probe = new SubscriptionProbe(subscription);
const turnId = randomUUID();
const started = requireStartedTurn(
await starter.request('turn.start', {
sessionId: fixture.sessionId,
turnId,
content: { text: FAKE_ASK_SANDBOX_BOUNDARY_PROMPT },
}),
);
await starter.close();
const pending = await waitForPendingInteraction(subscription, probe, started.runId);
assert.equal(pending.sessionId, fixture.sessionId);
assert.equal(pending.turnId, turnId);
assert.equal(pending.runId, started.runId);
assert.equal(pending.status, 'pending');
assert.equal(pending.request.kind, 'sandbox_boundary');
if (pending.request.kind !== 'sandbox_boundary') return;
assert.deepEqual(pending.request.expansion, { network: { enabled: true } });
const answer = {
sessionId: fixture.sessionId,
interactionId: pending.interactionId,
answer: { kind: 'sandbox_boundary', decision: 'allow' },
} as const;
const [firstWinner, secondWinner] = await Promise.all([
first.request('interaction.answer', answer),
second.request('interaction.answer', answer),
]);
assert.deepEqual(firstWinner, secondWinner);
assert.equal(firstWinner.status, 'answered');
assert.equal(firstWinner.outcome.kind, 'sandbox_boundary_decision');
if (firstWinner.outcome.kind !== 'sandbox_boundary_decision') return;
assert.equal(firstWinner.outcome.decision, 'allow');
assert.equal(firstWinner.outcome.status, 'approved');
assert.equal(Number.isSafeInteger(firstWinner.outcome.committedAt), true);
assert.deepEqual(
await first.request('interaction.query', {
sessionId: fixture.sessionId,
interactionId: pending.interactionId,
}),
firstWinner,
);
await probe.waitFor(
(frame) =>
frame.kind === 'subscription.session_projection' &&
frame.snapshot.rootTurn?.runId === started.runId &&
frame.snapshot.interactions.pending.length === 0,
'continuity did not publish the resumed Turn after the sandbox boundary answer',
);
const completed = await waitForTerminalTurn(first, fixture.sessionId, turnId);
assert.equal(completed.runId, started.runId);
assert.equal(completed.status, 'completed');
await subscription.close();
await probe.done;
await Promise.allSettled([first.close(), second.close()]);
await fixture.stopHost(firstHost);
const secondHost = await fixture.startHost();
const observer = await connectClient(fixture.root);
assert.deepEqual(
await observer.request('interaction.query', {
sessionId: fixture.sessionId,
interactionId: pending.interactionId,
}),
firstWinner,
);
assert.deepEqual(
await observer.request('turn.query', { sessionId: fixture.sessionId, turnId }),
completed,
);
await observer.close();
await fixture.stopHost(secondHost);
});
});
type SessionTodoWriteTool = MakaTool<{ todos: SessionTodoItem[] }, string> & {
parameters: { parse(value: unknown): { todos: SessionTodoItem[] } };
};
async function withOwnedSessionTodoToolPort<T>(
fixture: ExecutionFixture,
run: (coordinator: HostSessionTodoCoordinator, tools: MakaTool[]) => Promise<T>,
): Promise<T> {
const owner = await tryAcquireInteractiveRootOwner(fixture.capability);
assert.ok(owner);
if (!owner) throw new Error('Unable to acquire the interactive SessionTodo tool port');
let writer: Awaited<ReturnType<typeof openInteractiveSessionTodoStoreForWrite>> | undefined;
try {
writer = await openInteractiveSessionTodoStoreForWrite(owner.lease);
const coordinator = new HostSessionTodoCoordinator(
writer,
new SessionAdmissionGate(),
{ probeSessionRemoval: async () => ({ kind: 'present' }) },
() => {},
() => {},
);
return await run(coordinator, buildSessionTodoTools(coordinator));
} finally {
writer?.close();
await owner.close();
}
}
function requireSessionTodoWriteTool(tools: readonly MakaTool[]): SessionTodoWriteTool {
const tool = tools.find((candidate) => candidate.name === 'todo_write');
assert.ok(tool, 'Expected todo_write Runtime tool');
return tool as SessionTodoWriteTool;
}
function sessionTodoToolContext(fixture: ExecutionFixture): MakaToolContext {
return {
sessionId: fixture.sessionId,
cwd: fixture.root,
runId: randomUUID(),
turnId: randomUUID(),
toolCallId: randomUUID(),
abortSignal: new AbortController().signal,
emitOutput: () => {},
};
}
async function waitForScheduledTaskCompletion(
client: RuntimeHostConnection,
taskId: string,
): Promise<ScheduledTask> {
const deadline = Date.now() + 20_000;
let last: ScheduledTask | null = null;
while (Date.now() < deadline) {
const result = await client.request('scheduled-task.query', {
kind: 'get',
taskId,
});
if (result.kind === 'task' && result.task?.status === 'completed') return result.task;
if (result.kind === 'task') last = result.task;
if (result.kind === 'task' && result.task?.lastError) {
throw new Error(`ScheduledTask execution failed: ${result.task.lastError}`);
}
await new Promise((resolve) => setTimeout(resolve, 50));
}
throw new Error(
`ScheduledTask ${taskId} did not settle before the deadline: ${JSON.stringify(last)}`,
);
}