feat: remove experimental compatibility shims

This commit is contained in:
Armin Ronacher 2026-09-01 09:51:12 +02:00
parent fa5036836d
commit 7cf456aa1c
8 changed files with 17 additions and 28 deletions

View file

@ -461,7 +461,15 @@ export class SessionWorkerManager {
try {
const options: SessionWorkerOptions = {
sessionDir: this.#sessionDir,
metadata,
metadata: {
id: metadata.id,
createdAt: metadata.createdAt,
storageVersion: metadata.storageVersion,
cwd: metadata.cwd,
path: metadata.path,
modifiedAt: metadata.modifiedAt,
...(metadata.parentSessionId === undefined ? {} : { parentSessionId: metadata.parentSessionId }),
},
pluginManifestPaths: [...pluginManifestPaths],
...(this.#model ?? {}),
};

View file

@ -78,7 +78,6 @@ export const SessionWorkerMetadataSchema = StrictObject({
path: Type.String(),
modifiedAt: Type.Number(),
parentSessionId: Type.Optional(Type.String()),
legacyParentSessionPath: Type.Optional(Type.String()),
});
export const SessionWorkerOptionsSchema = StrictObject({
@ -521,7 +520,7 @@ export type CreateSessionWorkerHarness = (
session: Session<JsonlSessionMetadata>,
options: SessionWorkerOptions,
executionEnv: NodeExecutionEnv,
) => Promise<AgentHarnessInstance | SessionWorkerRuntime>;
) => Promise<SessionWorkerRuntime>;
async function run(options: SessionWorkerOptions, createHarness: CreateSessionWorkerHarness): Promise<void> {
const { sessionDir, metadata } = options;
@ -545,8 +544,7 @@ async function run(options: SessionWorkerOptions, createHarness: CreateSessionWo
let services: SessionWorkerServices | undefined;
try {
session = await repo.open(metadata, TODO_CONTEXT);
const created = await createHarness(session, options, executionEnv);
const runtime: SessionWorkerRuntime = "harness" in created ? created : { harness: created };
const runtime = await createHarness(session, options, executionEnv);
harness = runtime.harness;
lane = runtime.lane ?? (await harness.lane("main", TODO_CONTEXT));
services = await createSessionWorkerServices({

View file

@ -219,8 +219,6 @@ describe("Session worker operations", () => {
});
});
};
if (attachment.invokeService === undefined) throw new Error("Missing service attachment");
await expect(attachment.invokeService(serviceCall, () => {}, BACKGROUND_CONTEXT)).resolves.toEqual({
accepted: true,
});
@ -257,8 +255,6 @@ describe("Session worker operations", () => {
}),
);
};
if (attachment.invokeService === undefined) throw new Error("Missing service attachment");
await expect(attachment.invokeService(serviceCall, () => {}, BACKGROUND_CONTEXT)).rejects.toThrow(
/mismatched operation response/,
);
@ -288,8 +284,6 @@ describe("Session worker operations", () => {
}),
);
};
if (attachment.invokeService === undefined) throw new Error("Missing service attachment");
await expect(attachment.invokeService(serviceCall, () => {}, BACKGROUND_CONTEXT)).rejects.toThrow(
/invalid operation response/,
);
@ -300,7 +294,6 @@ describe("Session worker operations", () => {
test("rejects pending service calls on replacement without stopping the worker", async () => {
const { coordinator, workers, attachment } = await createAttachedWorker();
coordinator.onSend = () => {};
if (attachment.invokeService === undefined) throw new Error("Missing service attachment");
const calling = attachment.invokeService(serviceCall, () => {}, BACKGROUND_CONTEXT);
workers.detach();

View file

@ -2,7 +2,7 @@
Experimental local server for the new durable Session and Agent Harness interfaces.
The current slice supports server- and Session-scoped facet-service routing and multi-presentation attachment. `RoutedServerServiceHost.attachClient()` creates one connection-scoped server service endpoint with narrow attachment-management capabilities. `RoutedSessionHandle.attachClient()` returns a presentation-scoped Session capability. Its optional `invokeService()` forwards an opaque service/member envelope to the selected Session endpoint; the server validates the attachment route but does not load the facet contract.
The current slice supports server- and Session-scoped facet-service routing and multi-presentation attachment. `RoutedServerServiceHost.attachClient()` creates one connection-scoped server service endpoint with narrow attachment-management capabilities. `RoutedSessionHandle.attachClient()` returns a presentation-scoped Session capability. Its `invokeService()` forwards an opaque service/member envelope to the selected Session endpoint; the server validates the attachment route but does not load the facet contract.
- server service calls and subscriptions route opaquely through the connection's `RoutedServerServiceAttachment`;
- the application-owned `SessionDirectory` projects the private catalog into replicated presentation-safe state;

View file

@ -6,7 +6,6 @@ type ServerOperationErrorCode =
| "session_not_found"
| "session_ambiguous"
| "session_not_attached"
| "not_supported"
| "server_draining";
export const INTERNAL_SERVER_ERROR_MESSAGE = "Internal server error";
@ -50,13 +49,6 @@ export class SessionNotAttachedError extends ServerError {
}
}
export class NotSupportedError extends ServerError {
constructor(message: string) {
super("not_supported", message);
this.name = "NotSupportedError";
}
}
export class ServerDrainingError extends ServerError {
constructor() {
super("server_draining", "Server is draining");

View file

@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto";
import type { JsonValue, ServiceCall, ServiceProviderUpdate } from "@earendil-works/chord";
import { BACKGROUND_CONTEXT, type Context, type SessionMetadata } from "@earendil-works/pi-agent-core";
import type { RpcTarget, SessionTarget } from "@earendil-works/pi-protocol";
import { NotSupportedError, ServerDrainingError, SessionNotAttachedError } from "./errors.ts";
import { ServerDrainingError, SessionNotAttachedError } from "./errors.ts";
import type { RoutedSessionAttachment, RoutedSessionHandle, ServerHost } from "./types.ts";
class SessionCleanupError extends AggregateError {}
@ -204,10 +204,7 @@ export class SessionRouter<TMetadata extends SessionMetadata = SessionMetadata>
context: Context,
): Promise<{ result: Promise<JsonValue | undefined> }> {
const attachment = this.requireAttachment(client, target);
const invoke = attachment.lease?.invokeService;
if (invoke === undefined) throw new NotSupportedError("Routed Session does not support plugin services");
const result = invoke.call(
attachment.lease,
const result = attachment.lease!.invokeService(
call,
(subscriptionId, update, updateContext) => publish(subscriptionId, update, updateContext),
context,

View file

@ -17,7 +17,7 @@ export type MaybePromise<T> = T | Promise<T>;
/** One presentation connection's live capability for a hosted Session. */
export interface RoutedSessionAttachment {
/** Route one contract-agnostic service operation to the attached Session endpoint. */
invokeService?(
invokeService(
call: ServiceCall,
publish: (subscriptionId: string, update: ServiceProviderUpdate, context: Context) => MaybePromise<void>,
context: Context,

View file

@ -118,7 +118,7 @@ describe("Session protocol", () => {
openSession: async (candidate) => {
received = candidate;
return {
attachClient: () => ({ release() {} }),
attachClient: () => ({ invokeService: async () => undefined, release() {} }),
close: async () => {},
};
},
@ -413,6 +413,7 @@ describe("routed Session acquisition failures", () => {
acquiring.resolve(undefined);
await continueAcquiring.promise;
return {
invokeService: async () => undefined,
release: () => {
releaseCount += 1;
},