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
54 changes: 54 additions & 0 deletions apps/server/src/peer/PeerLinks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import { NodeHttpServer } from "@effect/platform-node";
import { type ExecutionEnvironmentDescriptor, OrchestratorMcpFailure } from "@t3tools/contracts";
import { expect, it } from "@effect/vitest";
import * as Context from "effect/Context";
import * as Deferred from "effect/Deferred";
import * as Duration from "effect/Duration";
import * as Effect from "effect/Effect";
import * as Fiber from "effect/Fiber";
import * as Layer from "effect/Layer";
import * as Option from "effect/Option";
import * as Ref from "effect/Ref";
import * as Schema from "effect/Schema";
import * as HttpRouter from "effect/http/HttpRouter";
import * as SqlClient from "effect/sql/SqlClient";
import * as TestClock from "effect/testing/TestClock";
import { Tool, Toolkit } from "effect/ai";
Expand Down Expand Up @@ -339,6 +342,57 @@ it.effect("never sends a link's token to an address that stops answering as that
).pipe(Effect.provide(NodeHttpServer.layerTest)),
);

it.effect("cancelling a descriptor probe aborts its request and leaves later resolves fresh", () =>
Effect.scoped(
Effect.gen(function* () {
const hold = yield* Ref.make(false);
const requests = yield* Ref.make(0);
const entered = yield* Deferred.make<void>();
const interrupted = yield* Deferred.make<void>();
const holdDescriptor = HttpRouter.middleware(
(httpEffect) =>
Effect.gen(function* () {
const request = yield* HttpServerRequest.HttpServerRequest;
if (request.url.startsWith("/.well-known/t3/environment")) {
yield* Ref.update(requests, (count) => count + 1);
if (yield* Ref.get(hold)) {
return yield* Deferred.succeed(entered, undefined).pipe(
Effect.andThen(Effect.never),
Effect.onInterrupt(() =>
Deferred.succeed(interrupted, undefined).pipe(Effect.asVoid),
),
Effect.interruptible,
);
}
}
return yield* httpEffect;
}),
{ global: true },
);
const b = yield* servePeer(
box,
Layer.merge(McpHttpServer.toolkitRegistration(ProbeToolkit, probeHandlers), holdDescriptor),
);
const a = yield* makeA(laptop);
const pairing = yield* b.auth.issuePairingCredential();
yield* a.links.link({ url: b.url, pairingCode: pairing.credential, access: "auto" });
yield* Ref.set(b.bearers, []);
yield* Ref.set(requests, 0);
yield* Ref.set(hold, true);

const resolving = yield* a.links.resolve(box.environmentId).pipe(Effect.forkScoped);
yield* Deferred.await(entered);
yield* Fiber.interrupt(resolving);
yield* Deferred.await(interrupted);

yield* Ref.set(hold, false);
expect((yield* a.links.resolve(box.environmentId)).url).toBe(b.url);
expect(yield* Ref.get(requests)).toBe(2);
expect(yield* Ref.get(b.bearers)).toEqual([]);
}),
).pipe(Effect.provide(NodeHttpServer.layerTest)),
);

it.effect("reads one stored link without asking the peer", () =>
Effect.scoped(
Effect.gen(function* () {
Expand Down
8 changes: 7 additions & 1 deletion apps/server/src/peer/PeerLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,19 @@ import * as Schema from "effect/Schema";
import * as SqlClient from "effect/sql/SqlClient";
import * as FetchHttpClient from "effect/http/FetchHttpClient";
import * as HttpClient from "effect/http/HttpClient";
import * as HttpApi from "effect/http-api/HttpApi";
import * as HttpApiClient from "effect/http-api/HttpApiClient";
import { isLocalLoopbackHost, isTailnetHost } from "@t3tools/shared/hostClassification";

import * as ServerSecretStore from "../auth/ServerSecretStore.ts";
import * as ServerEnvironment from "../environment/ServerEnvironment.ts";
import * as ServerSettings from "../serverSettings.ts";

const PeerHttpApi = HttpApi.make(EnvironmentHttpApi.identifier)
.add(EnvironmentHttpApi.groups.metadata)
.add(EnvironmentHttpApi.groups.mcpOAuth)
.annotateMerge(EnvironmentHttpApi.annotations);

/** The redirect registered for a link. Nothing ever listens there: the code comes back in the response. */
const LINK_REDIRECT_URI = "http://127.0.0.1/t3code-peer-link";
/**
Expand Down Expand Up @@ -185,7 +191,7 @@ const make = Effect.gen(function* () {
);

const clientFor = (origin: string) =>
HttpApiClient.make(EnvironmentHttpApi, { baseUrl: origin }).pipe(
HttpApiClient.make(PeerHttpApi, { baseUrl: origin }).pipe(
Effect.provideService(HttpClient.HttpClient, peerHttpClient),
);

Expand Down
Loading