authorgravatar for maxtheyoung@gmail.comMaxwell Young <maxtheyoung@gmail.com> 2026-07-18 07:51:16+12:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-07-17 21:51:16+02:00
logbcd640bf4d81df20ac5686ff0ca86d861f909be2
tree2cbd09cd447d00850caeff753a9cc0c35ced17a0
parentb49a2e677c6fba6d705ad16dbd913f56df4035d6
signature Signed by PGP key B5690EEEBB952194

[codex] prevent ACP assistant ID collisions after restarts (#3932)

Co-authored-by: Julius Marminge <julius0216@outlook.com>

14 files changed, 90 insertions(+), 14 deletions(-)

apps/server/src/provider/Drivers/CursorDriver.ts+2
...@@ -101,6 +101,7 @@ export const CursorDriver: ProviderDriver<CursorSettings, CursorDriverEnv> = {...@@ -101,6 +101,7 @@ export const CursorDriver: ProviderDriver<CursorSettings, CursorDriverEnv> = {
101 defaultConfig: (): CursorSettings => decodeCursorSettings({}),101 defaultConfig: (): CursorSettings => decodeCursorSettings({}),
102 create: ({ instanceId, displayName, accentColor, environment, enabled, config }) =>102 create: ({ instanceId, displayName, accentColor, environment, enabled, config }) =>
103 Effect.gen(function* () {103 Effect.gen(function* () {
104 const crypto = yield* Crypto.Crypto;
104 const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;105 const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
105 const fileSystem = yield* FileSystem.FileSystem;106 const fileSystem = yield* FileSystem.FileSystem;
106 const path = yield* Path.Path;107 const path = yield* Path.Path;
...@@ -133,6 +134,7 @@ export const CursorDriver: ProviderDriver<CursorSettings, CursorDriverEnv> = {...@@ -133,6 +134,7 @@ export const CursorDriver: ProviderDriver<CursorSettings, CursorDriverEnv> = {
133134
134 const checkProvider = checkCursorProviderStatus(effectiveConfig, processEnv).pipe(135 const checkProvider = checkCursorProviderStatus(effectiveConfig, processEnv).pipe(
135 Effect.map(stampIdentity),136 Effect.map(stampIdentity),
137 Effect.provideService(Crypto.Crypto, crypto),
136 Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner),138 Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner),
137 Effect.provideService(FileSystem.FileSystem, fileSystem),139 Effect.provideService(FileSystem.FileSystem, fileSystem),
138 Effect.provideService(Path.Path, path),140 Effect.provideService(Path.Path, path),
apps/server/src/provider/Drivers/GrokDriver.ts+2
...@@ -84,6 +84,7 @@ export const GrokDriver: ProviderDriver<GrokSettings, GrokDriverEnv> = {...@@ -84,6 +84,7 @@ export const GrokDriver: ProviderDriver<GrokSettings, GrokDriverEnv> = {
84 defaultConfig: (): GrokSettings => decodeGrokSettings({}),84 defaultConfig: (): GrokSettings => decodeGrokSettings({}),
85 create: ({ instanceId, displayName, accentColor, environment, enabled, config }) =>85 create: ({ instanceId, displayName, accentColor, environment, enabled, config }) =>
86 Effect.gen(function* () {86 Effect.gen(function* () {
87 const crypto = yield* Crypto.Crypto;
87 const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;88 const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
88 const httpClient = yield* HttpClient.HttpClient;89 const httpClient = yield* HttpClient.HttpClient;
89 const serverSettings = yield* ServerSettingsService;90 const serverSettings = yield* ServerSettingsService;
...@@ -114,6 +115,7 @@ export const GrokDriver: ProviderDriver<GrokSettings, GrokDriverEnv> = {...@@ -114,6 +115,7 @@ export const GrokDriver: ProviderDriver<GrokSettings, GrokDriverEnv> = {
114115
115 const checkProvider = checkGrokProviderStatus(effectiveConfig, processEnv).pipe(116 const checkProvider = checkGrokProviderStatus(effectiveConfig, processEnv).pipe(
116 Effect.map(stampIdentity),117 Effect.map(stampIdentity),
118 Effect.provideService(Crypto.Crypto, crypto),
117 Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner),119 Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner),
118 );120 );
119121
apps/server/src/provider/Layers/CursorAdapter.test.ts+5-2
...@@ -228,7 +228,7 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => {...@@ -228,7 +228,7 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => {
228 assert.isDefined(delta);228 assert.isDefined(delta);
229 if (delta?.type === "content.delta") {229 if (delta?.type === "content.delta") {
230 assert.equal(delta.payload.delta, "hello from mock");230 assert.equal(delta.payload.delta, "hello from mock");
231 assert.match(String(delta.itemId), /^assistant:mock-session-1:segment:0$/);231 assert.match(String(delta.itemId), /^assistant:mock-session-1:runtime:[^:]+:segment:0$/);
232 }232 }
233233
234 const assistantCompleted = runtimeEvents.find(234 const assistantCompleted = runtimeEvents.find(
...@@ -687,7 +687,10 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => {...@@ -687,7 +687,10 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => {
687 if (contentDelta?.type === "content.delta") {687 if (contentDelta?.type === "content.delta") {
688 assert.equal(String(contentDelta.turnId), String(turn.turnId));688 assert.equal(String(contentDelta.turnId), String(turn.turnId));
689 assert.equal(contentDelta.payload.delta, "hello from mock");689 assert.equal(contentDelta.payload.delta, "hello from mock");
690 assert.equal(String(contentDelta.itemId), "assistant:mock-session-1:segment:0");690 assert.match(
691 String(contentDelta.itemId),
692 /^assistant:mock-session-1:runtime:[^:]+:segment:0$/,
693 );
691 }694 }
692 });695 });
693696
apps/server/src/provider/Layers/CursorAdapter.ts+1
...@@ -558,6 +558,7 @@ export function makeCursorAdapter(...@@ -558,6 +558,7 @@ export function makeCursorAdapter(
558 : {}),558 : {}),
559 ...acpNativeLoggers,559 ...acpNativeLoggers,
560 }).pipe(560 }).pipe(
561 Effect.provideService(Crypto.Crypto, crypto),
561 Effect.provideService(Scope.Scope, sessionScope),562 Effect.provideService(Scope.Scope, sessionScope),
562 Effect.mapError(563 Effect.mapError(
563 (cause) =>564 (cause) =>
apps/server/src/provider/Layers/CursorProvider.test.ts+2-1
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1import * as NodeOS from "node:os";1import * as NodeOS from "node:os";
22
3import * as NodeServices from "@effect/platform-node/NodeServices";3import * as NodeServices from "@effect/platform-node/NodeServices";
4import type * as Crypto from "effect/Crypto";
4import * as Effect from "effect/Effect";5import * as Effect from "effect/Effect";
5import * as FileSystem from "effect/FileSystem";6import * as FileSystem from "effect/FileSystem";
6import * as Path from "effect/Path";7import * as Path from "effect/Path";
...@@ -28,7 +29,7 @@ const runNode = <A, E>(...@@ -28,7 +29,7 @@ const runNode = <A, E>(
28 effect: Effect.Effect<29 effect: Effect.Effect<
29 A,30 A,
30 E,31 E,
31 ChildProcessSpawner.ChildProcessSpawner | FileSystem.FileSystem | Path.Path32 ChildProcessSpawner.ChildProcessSpawner | Crypto.Crypto | FileSystem.FileSystem | Path.Path
32 >,33 >,
33): Promise<A> => Effect.runPromise(effect.pipe(Effect.provide(NodeServices.layer)));34): Promise<A> => Effect.runPromise(effect.pipe(Effect.provide(NodeServices.layer)));
3435
apps/server/src/provider/Layers/CursorProvider.ts+2-1
...@@ -11,6 +11,7 @@ import type {...@@ -11,6 +11,7 @@ import type {
11import { ProviderDriverKind } from "@t3tools/contracts";11import { ProviderDriverKind } from "@t3tools/contracts";
12import type * as EffectAcpSchema from "effect-acp/schema";12import type * as EffectAcpSchema from "effect-acp/schema";
13import { causeErrorTag } from "@t3tools/shared/observability";13import { causeErrorTag } from "@t3tools/shared/observability";
14import * as Crypto from "effect/Crypto";
14import * as DateTime from "effect/DateTime";15import * as DateTime from "effect/DateTime";
15import * as Effect from "effect/Effect";16import * as Effect from "effect/Effect";
16import * as Exit from "effect/Exit";17import * as Exit from "effect/Exit";
...@@ -992,7 +993,7 @@ export const checkCursorProviderStatus = Effect.fn("checkCursorProviderStatus")(...@@ -992,7 +993,7 @@ export const checkCursorProviderStatus = Effect.fn("checkCursorProviderStatus")(
992): Effect.fn.Return<993): Effect.fn.Return<
993 ServerProviderDraft,994 ServerProviderDraft,
994 never,995 never,
995 ChildProcessSpawner.ChildProcessSpawner | FileSystem.FileSystem | Path.Path996 ChildProcessSpawner.ChildProcessSpawner | Crypto.Crypto | FileSystem.FileSystem | Path.Path
996> {997> {
997 const checkedAt = DateTime.formatIso(yield* DateTime.now);998 const checkedAt = DateTime.formatIso(yield* DateTime.now);
998 const fallbackModels = getCursorFallbackModels(cursorSettings);999 const fallbackModels = getCursorFallbackModels(cursorSettings);
apps/server/src/provider/Layers/GrokAdapter.ts+1
...@@ -596,6 +596,7 @@ export function makeGrokAdapter(grokSettings: GrokSettings, options?: GrokAdapte...@@ -596,6 +596,7 @@ export function makeGrokAdapter(grokSettings: GrokSettings, options?: GrokAdapte
596 : {}),596 : {}),
597 ...acpNativeLoggers,597 ...acpNativeLoggers,
598 }).pipe(598 }).pipe(
599 Effect.provideService(Crypto.Crypto, crypto),
599 Effect.provideService(Scope.Scope, sessionScope),600 Effect.provideService(Scope.Scope, sessionScope),
600 Effect.mapError(601 Effect.mapError(
601 (cause) =>602 (cause) =>
apps/server/src/provider/Layers/GrokProvider.ts+6-1
...@@ -7,6 +7,7 @@ import {...@@ -7,6 +7,7 @@ import {
7} from "@t3tools/contracts";7} from "@t3tools/contracts";
8import type * as EffectAcpSchema from "effect-acp/schema";8import type * as EffectAcpSchema from "effect-acp/schema";
9import { causeErrorTag } from "@t3tools/shared/observability";9import { causeErrorTag } from "@t3tools/shared/observability";
10import * as Crypto from "effect/Crypto";
10import * as DateTime from "effect/DateTime";11import * as DateTime from "effect/DateTime";
11import * as Effect from "effect/Effect";12import * as Effect from "effect/Effect";
12import * as Exit from "effect/Exit";13import * as Exit from "effect/Exit";
...@@ -167,7 +168,11 @@ const runGrokVersionCommand = (...@@ -167,7 +168,11 @@ const runGrokVersionCommand = (
167export const checkGrokProviderStatus = Effect.fn("checkGrokProviderStatus")(function* (168export const checkGrokProviderStatus = Effect.fn("checkGrokProviderStatus")(function* (
168 grokSettings: GrokSettings,169 grokSettings: GrokSettings,
169 environment: NodeJS.ProcessEnv = process.env,170 environment: NodeJS.ProcessEnv = process.env,
170): Effect.fn.Return<ServerProviderDraft, never, ChildProcessSpawner.ChildProcessSpawner> {171): Effect.fn.Return<
172 ServerProviderDraft,
173 never,
174 ChildProcessSpawner.ChildProcessSpawner | Crypto.Crypto
175> {
171 const checkedAt = DateTime.formatIso(yield* DateTime.now);176 const checkedAt = DateTime.formatIso(yield* DateTime.now);
172 const fallbackModels = grokModelsFromSettings(grokSettings.customModels);177 const fallbackModels = grokModelsFromSettings(grokSettings.customModels);
173178
apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts+37
...@@ -116,6 +116,43 @@ describe("AcpSessionRuntime", () => {...@@ -116,6 +116,43 @@ describe("AcpSessionRuntime", () => {
116 ),116 ),
117 );117 );
118118
119 it.effect("keeps assistant item IDs unique when a provider session restarts", () => {
120 const collectFirstAssistantItemId = Effect.gen(function* () {
121 const runtime = yield* AcpSessionRuntime.AcpSessionRuntime;
122 const started = yield* runtime.start();
123 expect(started.sessionId).toBe("mock-session-1");
124
125 yield* runtime.prompt({
126 prompt: [{ type: "text", text: "hi" }],
127 });
128
129 const events = Array.from(yield* Stream.runCollect(Stream.take(runtime.getEvents(), 4)));
130 const assistantStart = events.find((event) => event._tag === "AssistantItemStarted");
131 expect(assistantStart?._tag).toBe("AssistantItemStarted");
132 return assistantStart?._tag === "AssistantItemStarted" ? assistantStart.itemId : "";
133 }).pipe(
134 Effect.provide(
135 AcpSessionRuntime.layer({
136 spawn: {
137 command: mockAgentCommand,
138 args: mockAgentArgs,
139 },
140 cwd: process.cwd(),
141 clientInfo: { name: "t3-test", version: "0.0.0" },
142 authMethodId: "test",
143 }),
144 ),
145 Effect.scoped,
146 );
147
148 return Effect.gen(function* () {
149 const beforeRestart = yield* collectFirstAssistantItemId;
150 const afterRestart = yield* collectFirstAssistantItemId;
151
152 expect(afterRestart).not.toBe(beforeRestart);
153 }).pipe(Effect.provide(NodeServices.layer));
154 });
155
119 it.effect("drops session updates emitted for a child ACP session", () =>156 it.effect("drops session updates emitted for a child ACP session", () =>
120 Effect.gen(function* () {157 Effect.gen(function* () {
121 const runtime = yield* AcpSessionRuntime.AcpSessionRuntime;158 const runtime = yield* AcpSessionRuntime.AcpSessionRuntime;
apps/server/src/provider/acp/AcpSessionRuntime.ts+22-5
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1import * as Cause from "effect/Cause";1import * as Cause from "effect/Cause";
2import * as Clock from "effect/Clock";2import * as Clock from "effect/Clock";
3import * as Context from "effect/Context";3import * as Context from "effect/Context";
4import * as Crypto from "effect/Crypto";
4import * as Deferred from "effect/Deferred";5import * as Deferred from "effect/Deferred";
5import * as Duration from "effect/Duration";6import * as Duration from "effect/Duration";
6import * as Effect from "effect/Effect";7import * as Effect from "effect/Effect";
...@@ -270,14 +271,24 @@ export const make = (...@@ -270,14 +271,24 @@ export const make = (
270): Effect.Effect<271): Effect.Effect<
271 AcpSessionRuntime["Service"],272 AcpSessionRuntime["Service"],
272 EffectAcpErrors.AcpError,273 EffectAcpErrors.AcpError,
273 ChildProcessSpawner.ChildProcessSpawner | Scope.Scope274 ChildProcessSpawner.ChildProcessSpawner | Crypto.Crypto | Scope.Scope
274> =>275> =>
275 Effect.gen(function* () {276 Effect.gen(function* () {
277 const crypto = yield* Crypto.Crypto;
276 const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;278 const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
277 const runtimeScope = yield* Scope.Scope;279 const runtimeScope = yield* Scope.Scope;
278 const eventQueue = yield* Queue.unbounded<AcpSessionRuntimeEvent>();280 const eventQueue = yield* Queue.unbounded<AcpSessionRuntimeEvent>();
279 const modeStateRef = yield* Ref.make<AcpSessionModeState | undefined>(undefined);281 const modeStateRef = yield* Ref.make<AcpSessionModeState | undefined>(undefined);
280 const toolCallsRef = yield* Ref.make(new Map<string, AcpToolCallState>());282 const toolCallsRef = yield* Ref.make(new Map<string, AcpToolCallState>());
283 const assistantItemRuntimeId = yield* crypto.randomUUIDv4.pipe(
284 Effect.mapError(
285 (cause) =>
286 new EffectAcpErrors.AcpTransportError({
287 detail: "Failed to generate an ACP assistant item runtime identifier.",
288 cause,
289 }),
290 ),
291 );
281 const assistantSegmentRef = yield* Ref.make<AcpAssistantSegmentState>({ nextSegmentIndex: 0 });292 const assistantSegmentRef = yield* Ref.make<AcpAssistantSegmentState>({ nextSegmentIndex: 0 });
282 const configOptionsRef = yield* Ref.make(sessionConfigOptionsFromSetup(undefined));293 const configOptionsRef = yield* Ref.make(sessionConfigOptionsFromSetup(undefined));
283 const startStateRef = yield* Ref.make<AcpStartState>({ _tag: "NotStarted" });294 const startStateRef = yield* Ref.make<AcpStartState>({ _tag: "NotStarted" });
...@@ -387,6 +398,7 @@ export const make = (...@@ -387,6 +398,7 @@ export const make = (
387 modeStateRef,398 modeStateRef,
388 toolCallsRef,399 toolCallsRef,
389 assistantSegmentRef,400 assistantSegmentRef,
401 assistantItemRuntimeId,
390 params: notification,402 params: notification,
391 });403 });
392 }),404 }),
...@@ -802,7 +814,7 @@ export const layer = (...@@ -802,7 +814,7 @@ export const layer = (
802): Layer.Layer<814): Layer.Layer<
803 AcpSessionRuntime,815 AcpSessionRuntime,
804 EffectAcpErrors.AcpError,816 EffectAcpErrors.AcpError,
805 ChildProcessSpawner.ChildProcessSpawner817 ChildProcessSpawner.ChildProcessSpawner | Crypto.Crypto
806> => Layer.effect(AcpSessionRuntime, make(options));818> => Layer.effect(AcpSessionRuntime, make(options));
807819
808function sessionConfigOptionsFromSetup(820function sessionConfigOptionsFromSetup(
...@@ -834,12 +846,14 @@ const handleSessionUpdate = ({...@@ -834,12 +846,14 @@ const handleSessionUpdate = ({
834 modeStateRef,846 modeStateRef,
835 toolCallsRef,847 toolCallsRef,
836 assistantSegmentRef,848 assistantSegmentRef,
849 assistantItemRuntimeId,
837 params,850 params,
838}: {851}: {
839 readonly queue: Queue.Queue<AcpSessionRuntimeEvent>;852 readonly queue: Queue.Queue<AcpSessionRuntimeEvent>;
840 readonly modeStateRef: Ref.Ref<AcpSessionModeState | undefined>;853 readonly modeStateRef: Ref.Ref<AcpSessionModeState | undefined>;
841 readonly toolCallsRef: Ref.Ref<Map<string, AcpToolCallState>>;854 readonly toolCallsRef: Ref.Ref<Map<string, AcpToolCallState>>;
842 readonly assistantSegmentRef: Ref.Ref<AcpAssistantSegmentState>;855 readonly assistantSegmentRef: Ref.Ref<AcpAssistantSegmentState>;
856 readonly assistantItemRuntimeId: string;
843 readonly params: EffectAcpSchema.SessionNotification;857 readonly params: EffectAcpSchema.SessionNotification;
844}): Effect.Effect<void> =>858}): Effect.Effect<void> =>
845 Effect.gen(function* () {859 Effect.gen(function* () {
...@@ -887,6 +901,7 @@ const handleSessionUpdate = ({...@@ -887,6 +901,7 @@ const handleSessionUpdate = ({
887 queue,901 queue,
888 assistantSegmentRef,902 assistantSegmentRef,
889 sessionId: params.sessionId,903 sessionId: params.sessionId,
904 assistantItemRuntimeId,
890 });905 });
891 yield* Queue.offer(queue, {906 yield* Queue.offer(queue, {
892 ...event,907 ...event,
...@@ -924,17 +939,19 @@ function shouldEmitToolCallUpdate(...@@ -924,17 +939,19 @@ function shouldEmitToolCallUpdate(
924 return previous === undefined || previous.title !== next.title || previous.detail !== next.detail;939 return previous === undefined || previous.title !== next.title || previous.detail !== next.detail;
925}940}
926941
927const assistantItemId = (sessionId: string, segmentIndex: number) =>942const assistantItemId = (sessionId: string, runtimeId: string, segmentIndex: number) =>
928 `assistant:${sessionId}:segment:${segmentIndex}`;943 `assistant:${sessionId}:runtime:${runtimeId}:segment:${segmentIndex}`;
929944
930const ensureActiveAssistantSegment = ({945const ensureActiveAssistantSegment = ({
931 queue,946 queue,
932 assistantSegmentRef,947 assistantSegmentRef,
933 sessionId,948 sessionId,
949 assistantItemRuntimeId,
934}: {950}: {
935 readonly queue: Queue.Queue<AcpSessionRuntimeEvent>;951 readonly queue: Queue.Queue<AcpSessionRuntimeEvent>;
936 readonly assistantSegmentRef: Ref.Ref<AcpAssistantSegmentState>;952 readonly assistantSegmentRef: Ref.Ref<AcpAssistantSegmentState>;
937 readonly sessionId: string;953 readonly sessionId: string;
954 readonly assistantItemRuntimeId: string;
938}) =>955}) =>
939 Ref.modify<AcpAssistantSegmentState, EnsureActiveAssistantSegmentResult>(956 Ref.modify<AcpAssistantSegmentState, EnsureActiveAssistantSegmentResult>(
940 assistantSegmentRef,957 assistantSegmentRef,
...@@ -942,7 +959,7 @@ const ensureActiveAssistantSegment = ({...@@ -942,7 +959,7 @@ const ensureActiveAssistantSegment = ({
942 if (current.activeItemId) {959 if (current.activeItemId) {
943 return [{ itemId: current.activeItemId }, current] as const;960 return [{ itemId: current.activeItemId }, current] as const;
944 }961 }
945 const itemId = assistantItemId(sessionId, current.nextSegmentIndex);962 const itemId = assistantItemId(sessionId, assistantItemRuntimeId, current.nextSegmentIndex);
946 return [963 return [
947 {964 {
948 itemId,965 itemId,
apps/server/src/provider/acp/CursorAcpSupport.ts+2-1
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1import { type CursorSettings, type ProviderOptionSelection } from "@t3tools/contracts";1import { type CursorSettings, type ProviderOptionSelection } from "@t3tools/contracts";
2import * as Crypto from "effect/Crypto";
2import * as Effect from "effect/Effect";3import * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";4import * as Layer from "effect/Layer";
4import * as Scope from "effect/Scope";5import * as Scope from "effect/Scope";
...@@ -50,7 +51,7 @@ export const makeCursorAcpRuntime = (...@@ -50,7 +51,7 @@ export const makeCursorAcpRuntime = (
50): Effect.Effect<51): Effect.Effect<
51 AcpSessionRuntime.AcpSessionRuntime["Service"],52 AcpSessionRuntime.AcpSessionRuntime["Service"],
52 EffectAcpErrors.AcpError,53 EffectAcpErrors.AcpError,
53 Scope.Scope54 Crypto.Crypto | Scope.Scope
54> =>55> =>
55 Effect.gen(function* () {56 Effect.gen(function* () {
56 const acpContext = yield* Layer.build(57 const acpContext = yield* Layer.build(
apps/server/src/provider/acp/GrokAcpSupport.ts+2-1
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1import { type GrokSettings, ProviderDriverKind } from "@t3tools/contracts";1import { type GrokSettings, ProviderDriverKind } from "@t3tools/contracts";
2import * as Crypto from "effect/Crypto";
2import * as Effect from "effect/Effect";3import * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";4import * as Layer from "effect/Layer";
4import * as Scope from "effect/Scope";5import * as Scope from "effect/Scope";
...@@ -55,7 +56,7 @@ export const makeGrokAcpRuntime = (...@@ -55,7 +56,7 @@ export const makeGrokAcpRuntime = (
55): Effect.Effect<56): Effect.Effect<
56 AcpSessionRuntime.AcpSessionRuntime["Service"],57 AcpSessionRuntime.AcpSessionRuntime["Service"],
57 EffectAcpErrors.AcpError,58 EffectAcpErrors.AcpError,
58 Scope.Scope59 Crypto.Crypto | Scope.Scope
59> =>60> =>
60 Effect.gen(function* () {61 Effect.gen(function* () {
61 const acpContext = yield* Layer.build(62 const acpContext = yield* Layer.build(
apps/server/src/textGeneration/CursorTextGeneration.ts+3-1
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1import * as Crypto from "effect/Crypto";
1import * as Effect from "effect/Effect";2import * as Effect from "effect/Effect";
2import * as Option from "effect/Option";3import * as Option from "effect/Option";
3import * as Ref from "effect/Ref";4import * as Ref from "effect/Ref";
...@@ -38,6 +39,7 @@ export const makeCursorTextGeneration = Effect.fn("makeCursorTextGeneration")(fu...@@ -38,6 +39,7 @@ export const makeCursorTextGeneration = Effect.fn("makeCursorTextGeneration")(fu
38 cursorSettings: CursorSettings,39 cursorSettings: CursorSettings,
39 environment?: NodeJS.ProcessEnv,40 environment?: NodeJS.ProcessEnv,
40) {41) {
42 const crypto = yield* Crypto.Crypto;
41 const commandSpawner = yield* ChildProcessSpawner.ChildProcessSpawner;43 const commandSpawner = yield* ChildProcessSpawner.ChildProcessSpawner;
42 const resolvedEnvironment = environment ?? process.env;44 const resolvedEnvironment = environment ?? process.env;
4345
...@@ -66,7 +68,7 @@ export const makeCursorTextGeneration = Effect.fn("makeCursorTextGeneration")(fu...@@ -66,7 +68,7 @@ export const makeCursorTextGeneration = Effect.fn("makeCursorTextGeneration")(fu
66 childProcessSpawner: commandSpawner,68 childProcessSpawner: commandSpawner,
67 cwd,69 cwd,
68 clientInfo: { name: "t3-code-git-text", version: "0.0.0" },70 clientInfo: { name: "t3-code-git-text", version: "0.0.0" },
69 });71 }).pipe(Effect.provideService(Crypto.Crypto, crypto));
7072
71 yield* runtime.handleSessionUpdate((notification) => {73 yield* runtime.handleSessionUpdate((notification) => {
72 const update = notification.update;74 const update = notification.update;
apps/server/src/textGeneration/GrokTextGeneration.ts+3-1
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1import * as Crypto from "effect/Crypto";
1import * as Effect from "effect/Effect";2import * as Effect from "effect/Effect";
2import * as Option from "effect/Option";3import * as Option from "effect/Option";
3import * as Ref from "effect/Ref";4import * as Ref from "effect/Ref";
...@@ -37,6 +38,7 @@ export const makeGrokTextGeneration = Effect.fn("makeGrokTextGeneration")(functi...@@ -37,6 +38,7 @@ export const makeGrokTextGeneration = Effect.fn("makeGrokTextGeneration")(functi
37 grokSettings: GrokSettings,38 grokSettings: GrokSettings,
38 environment: NodeJS.ProcessEnv = process.env,39 environment: NodeJS.ProcessEnv = process.env,
39) {40) {
41 const crypto = yield* Crypto.Crypto;
40 const commandSpawner = yield* ChildProcessSpawner.ChildProcessSpawner;42 const commandSpawner = yield* ChildProcessSpawner.ChildProcessSpawner;
4143
42 const runGrokJson = <S extends Schema.Top>({44 const runGrokJson = <S extends Schema.Top>({
...@@ -65,7 +67,7 @@ export const makeGrokTextGeneration = Effect.fn("makeGrokTextGeneration")(functi...@@ -65,7 +67,7 @@ export const makeGrokTextGeneration = Effect.fn("makeGrokTextGeneration")(functi
65 childProcessSpawner: commandSpawner,67 childProcessSpawner: commandSpawner,
66 cwd,68 cwd,
67 clientInfo: { name: "t3-code-git-text", version: "0.0.0" },69 clientInfo: { name: "t3-code-git-text", version: "0.0.0" },
68 });70 }).pipe(Effect.provideService(Crypto.Crypto, crypto));
6971
70 yield* runtime.handleSessionUpdate((notification) => {72 yield* runtime.handleSessionUpdate((notification) => {
71 const update = notification.update;73 const update = notification.update;