Skip to content
Source
Sign inSign up
Open History to see the last commit

nativeLogging.test.ts

80 lines3.0 KB

1import * as NodeCrypto from "@effect/platform-node/NodeCrypto";
2import * as NodeServices from "@effect/platform-node/NodeServices";
3import * as Layer from "effect/Layer";
4import { ProviderDriverKind, ThreadId } from "@t3tools/contracts";
5import { assert, it } from "@effect/vitest";
6import * as Cause from "effect/Cause";
7import * as Effect from "effect/Effect";
8import * as Exit from "effect/Exit";
9import * as Schema from "effect/Schema";
10import * as AcpErrors from "effect-acp/errors";
11​
12import type * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers";
13import { makeAcpNativeLoggerFactory } from "./nativeLogging.ts";
14​
15const nodeServicesIt = it.layer(Layer.mergeAll(NodeServices.layer, NodeCrypto.layer));
16const encodeUnknownJson = Schema.encodeUnknownSync(Schema.fromJsonString(Schema.Unknown));
17​
18nodeServicesIt("ACP native logging", (it) => {
19 it.effect("records bounded request diagnostics without raw payloads", () =>
20 Effect.gen(function* () {
21 const records: Array<unknown> = [];
22 const nativeEventLogger: ProviderEventLoggers.EventNdjsonLogger = {
23 filePath: "/tmp/provider-native.ndjson",
24 write: (event) => Effect.sync(() => void records.push(event)),
25 close: () => Effect.void,
26 };
27 const makeLogger = yield* makeAcpNativeLoggerFactory();
28 const logger = makeLogger({
29 nativeEventLogger,
30 provider: ProviderDriverKind.make("cursor"),
31 threadId: ThreadId.make("thread-1"),
32 });
33 const secret = "secret-token-value";
34 const requestLogger = logger.requestLogger;
35 assert.exists(requestLogger);
36 if (!requestLogger) return;
37​
38 yield* requestLogger({
39 method: "session/prompt",
40 payload: { prompt: secret, sessionId: secret },
41 status: "failed",
42 cause: Cause.fail(AcpErrors.AcpRequestError.internalError(secret, { token: secret })),
43 });
44 const serialized = encodeUnknownJson(records);
45 assert.notInclude(serialized, secret);
46 assert.include(serialized, '"method":"session/prompt"');
47 assert.include(serialized, '"errorTag":"AcpRequestError"');
48 assert.include(serialized, '"reasonCount":1');
49 }),
50 );
51​
52 it.effect("preserves native writer interruption", () =>
53 Effect.gen(function* () {
54 const makeLogger = yield* makeAcpNativeLoggerFactory();
55 const logger = makeLogger({
56 nativeEventLogger: {
57 filePath: "/tmp/provider-native.ndjson",
58 write: () => Effect.interrupt,
59 close: () => Effect.void,
60 },
61 provider: ProviderDriverKind.make("cursor"),
62 threadId: ThreadId.make("thread-1"),
63 });
64 const requestLogger = logger.requestLogger;
65 assert.exists(requestLogger);
66 if (!requestLogger) return;
67​
68 const exit = yield* requestLogger({
69 method: "session/prompt",
70 payload: {},
71 status: "started",
72 }).pipe(Effect.exit);
73​
74 assert.isTrue(Exit.isFailure(exit));
75 if (Exit.isFailure(exit)) {
76 assert.isTrue(Cause.hasInterruptsOnly(exit.cause));
77 }
78 }),
79 );
80});