Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
3d72d21
feat(runtime): compare semantic request prefixes
Astro-Han Aug 31, 2026
50ccacb
feat(runtime): seal semantic prefix continuity
Astro-Han Aug 31, 2026
72d3ea1
refactor(runtime): keep root admission capability narrow
Astro-Han Aug 31, 2026
7674a15
feat(runtime-host): carry request prefix continuity
Astro-Han Aug 31, 2026
7f2cfb1
feat(desktop): show request prefix continuity
Astro-Han Aug 31, 2026
50a9c9c
test(runtime): cover prefix continuity boundaries
Astro-Han Aug 31, 2026
0dbea4f
fix(runtime): exclude child runs from prefix continuity
Astro-Han Aug 31, 2026
2d8f7b7
fix(runtime): rebuild continuity from durable lineage
Astro-Han Aug 31, 2026
3a91e96
fix(runtime-host): qualify connection configuration changes
Astro-Han Aug 31, 2026
3dd36d1
fix(desktop): hide stale prefix diagnostics
Astro-Han Aug 31, 2026
c265819
fix(runtime): reject ambiguous prefix baselines
Astro-Han Aug 31, 2026
36cbdd0
fix(runtime-host): align continuity wire contract
Astro-Han Aug 31, 2026
829553c
refactor(test): simplify prefix continuity fixtures
Astro-Han Aug 31, 2026
24d2a1b
feat(desktop): show provider cache usage
Astro-Han Aug 31, 2026
69d6445
fix(runtime): validate canonical prefix anchors
Astro-Han Aug 31, 2026
61a3b1b
chore(desktop): refresh Astryx surface inventory
Astro-Han Sep 1, 2026
55b6335
refactor(runtime): clarify request preservation
Astro-Han Sep 1, 2026
a09f5cc
refactor(desktop): remove request preservation UI
Astro-Han Sep 1, 2026
a6a4aa1
fix(runtime): retry unresolved request preservation
Astro-Han Sep 1, 2026
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
12 changes: 12 additions & 0 deletions packages/runtime-host/src/__tests__/context-protocol.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ test('context operations preserve bounded exact wire values', () => {
turnCount: 2,
estimatedTokens: 12,
},
requestPreservation: {
status: 'diverged',
previousSegmentCount: 8,
preservedSegmentCount: 2,
firstDivergentSegment: { kind: 'message', index: 2, role: '' },
},
},
}),
{
Expand All @@ -96,6 +102,12 @@ test('context operations preserve bounded exact wire values', () => {
turnCount: 2,
estimatedTokens: 12,
},
requestPreservation: {
status: 'diverged',
previousSegmentCount: 8,
preservedSegmentCount: 2,
firstDivergentSegment: { kind: 'message', index: 2, role: '' },
},
},
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import type { BackendCompactHistoryInput } from '@maka/core/backend-types';
import { decodeCanonicalToolResultContent } from '@maka/core/tool-result-record-schema';
import { type ModelCallAttempt, type ModelCallKind } from '@maka/core/model-call-attempt';
import { type RuntimeEvent } from '@maka/core/runtime-event';
import { createDefaultRuntimePolicy } from '@maka/core/runtime-policy';
import { createDefaultRuntimePolicy, type RuntimePolicy } from '@maka/core/runtime-policy';
import type { PlanSessionState, PlanStore } from '@maka/core/plan';
import type { SessionTodoToolStore } from '@maka/runtime/session-todo-tools';
import {
Expand Down Expand Up @@ -184,6 +184,31 @@ test('prepared backend activation builds from its admitted provider snapshot', a
await backend.dispose();
});

test('connection and proxy changes qualify the admitted provider identity', async () => {
const prepare = async (revision: number, networkProxy?: RuntimePolicy['networkProxy']) => {
const input = backendCreationFixture({
abortSignal: new AbortController().signal,
resolveExecutionConnection: async () =>
readyExecutionConnection(undefined, { revision, networkProxy }),
readPricing: async () => ({ revision: 0, overrides: [] }),
});
const { context, ...dependencies } = input;
return prepareHostAiSdkBackend({ context, ...dependencies });
};

const original = (await prepare(1)).providerStateIdentity;
assert.notEqual(original, (await prepare(2)).providerStateIdentity);
assert.notEqual(
original,
(
await prepare(1, {
...createDefaultRuntimePolicy().networkProxy,
enabled: true,
})
).providerStateIdentity,
);
});

test('backend creation aborts a stalled canonical connection read', async () => {
const abort = new AbortController();
const creating = createHostAiSdkBackend(
Expand Down Expand Up @@ -4047,12 +4072,15 @@ function readyExecutionConnection(
customization: {
readonly requestHeaders?: Readonly<Record<string, string>>;
readonly requestBodyOverlay?: Readonly<Record<string, unknown>>;
readonly networkProxy?: RuntimePolicy['networkProxy'];
readonly revision?: number;
readonly vision?: boolean;
} = {},
) {
return {
kind: 'ready',
connection: {
revision: customization.revision ?? 1,
slug: 'backend-creation-connection',
providerType: 'moonshot',
...(baseUrl ? { baseUrl } : {}),
Expand All @@ -4073,7 +4101,7 @@ function readyExecutionConnection(
},
],
},
networkProxy: { enabled: false },
networkProxy: customization.networkProxy ?? { enabled: false },
secretMaterial: {
connection: { secret: API_KEY },
...(customization.requestHeaders
Expand Down
31 changes: 30 additions & 1 deletion packages/runtime-host/src/protocol/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { invalidProtocolFrame } from './errors.js';
import { defineOperation } from './operation-spec.js';
import { decodeContextCompactionOutcome, decodeTurnSnapshot, type TurnSnapshot } from './turn.js';
import type { ContextCompactionOutcome } from '@maka/core/events';
import { isRequestPreservation, type RequestPreservation } from '@maka/runtime/context-diagnostics';

export interface ContextDiagnosticsQueryInput {
readonly sessionId: string;
Expand Down Expand Up @@ -71,6 +72,8 @@ export interface ContextDiagnosticsComposition {
readonly unlabelledToolBytes?: number;
}

export type ContextDiagnosticsRequestPreservation = RequestPreservation;

export type ContextDiagnosticsResult =
| {
readonly status: 'unavailable';
Expand Down Expand Up @@ -98,6 +101,8 @@ export type ContextDiagnosticsResult =
readonly turnCount: number;
readonly estimatedTokens: number;
};
/** Runtime-owned verdict; Host and Desktop must not recompute it. */
readonly requestPreservation?: ContextDiagnosticsRequestPreservation;
};

const QUERY_ERRORS = [
Expand Down Expand Up @@ -174,6 +179,7 @@ function decodeContextDiagnosticsResult(value: unknown): ContextDiagnosticsResul
'contextWindow',
'composition',
'compaction',
'requestPreservation',
],
);
if (record.status === 'unavailable') {
Expand All @@ -196,7 +202,14 @@ function decodeContextDiagnosticsResult(value: unknown): ContextDiagnosticsResul
record,
'Available context diagnostics',
['status', 'providerId', 'modelId', 'completedAt'],
['inputTokens', 'cacheReadInputTokens', 'contextWindow', 'composition', 'compaction'],
[
'inputTokens',
'cacheReadInputTokens',
'contextWindow',
'composition',
'compaction',
'requestPreservation',
],
);
return {
status: 'available',
Expand All @@ -223,9 +236,25 @@ function decodeContextDiagnosticsResult(value: unknown): ContextDiagnosticsResul
...(available.compaction === undefined
? {}
: { compaction: decodeContextDiagnosticsCompaction(available.compaction) }),
...(available.requestPreservation === undefined
? {}
: {
requestPreservation: decodeContextDiagnosticsRequestPreservation(
available.requestPreservation,
),
}),
};
}

function decodeContextDiagnosticsRequestPreservation(
value: unknown,
): ContextDiagnosticsRequestPreservation {
if (!isRequestPreservation(value)) {
throw invalidProtocolFrame('Invalid context diagnostics request preservation');
}
return value;
}

/**
* The tool list is bounded on the wire for the same reason the evidence reads
* are: a Host answer is built in memory, and a registry that grew without limit
Expand Down
4 changes: 3 additions & 1 deletion packages/runtime-host/src/protocol/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ export const RUNTIME_HOST_REGISTRATION_SCHEMA_VERSION = 1 as const;
export const RUNTIME_HOST_PROTOCOL_VERSION = 0 as const;
// Increment when the same protocol version no longer guarantees safe Client-Host
// interoperability. Mismatches are rejected before domain commands are admitted.
export const RUNTIME_HOST_COMPATIBILITY_EPOCH = 87 as const;
export const RUNTIME_HOST_COMPATIBILITY_EPOCH = 88 as const;
// 88: Context diagnostics may carry Runtime-owned request-preservation results.
// Older peers reject this optional field on the closed diagnostics shape.
// 87: The connection catalog projects each model as the Host resolved it —
// a `catalog_entry` item per model, counted by the connection header. Clients
// render those entries instead of merging the stored row against their own
Expand Down
10 changes: 8 additions & 2 deletions packages/runtime-host/src/server/execution-model-authority.ts
Original file line number Diff line number Diff line change
Expand Up @@ -763,15 +763,21 @@ function providerStateIdentityForResolvedExecution(
{ kind: 'ready' }
>,
): `sha256:${string}` {
const credentialBasis = (material: typeof resolved.secretMaterial.connection) =>
material ? { credentialId: material.credentialId, revision: material.revision } : null;
const credentialBasis = (
material: { readonly credentialId?: string; readonly revision?: number } | null | undefined,
) => (material ? { credentialId: material.credentialId, revision: material.revision } : null);
const proxy = resolved.networkProxy.enabled ? resolved.networkProxy : null;
return stableHash({
protocol: 'provider_state_identity_v1',
connectionId: resolved.connection.connectionId,
connectionRevision: resolved.connection.revision,
providerType: resolved.connection.providerType,
endpoint: new URL(effectiveBaseUrl(resolved.connection)).toString(),
credential: credentialBasis(resolved.secretMaterial.connection),
requestHeaders: credentialBasis(resolved.secretMaterial.requestHeaders),
proxy,
proxyCredential:
proxy?.authEnabled === true ? credentialBasis(resolved.secretMaterial.networkProxy) : null,
});
}

Expand Down
Loading