chore(ts): consolidate effect native closeout

This commit is contained in:
elpresidank 2026-06-11 08:34:59 -05:00
parent cd6c9107d7
commit fab718dce8
21 changed files with 199 additions and 3533 deletions

View file

@ -19,8 +19,9 @@ import {
GatewayWorkbenchHttpApi,
TrustGraphRpcs,
} from "@trustgraph/client";
import type { WorkbenchQaApi } from "@/qa/mock-api";
import type { Scope, } from "effect";
import { Cause, Clock, Context, Effect, Layer, Match, Metric, Option, Random, Schema as S, Stream } from "effect";
import { Cause, Clock, Context, Effect, Layer, Match, Metric, Option, Order, Random, Schema as S, Stream } from "effect";
import * as A from "effect/Array";
import * as MutableHashMap from "effect/MutableHashMap";
import * as Predicate from "effect/Predicate";
@ -802,9 +803,9 @@ function ensureNoGatewayResponseError<A>(operation: string, value: A): Effect.Ef
: Effect.fail(WorkbenchPromiseError.make({ cause: value, message: `${operation}: ${message}` }));
}
function qaBaseApi(): import("@trustgraph/client").BaseApi | undefined {
function qaBaseApi(): WorkbenchQaApi | undefined {
if (typeof window === "undefined") return undefined;
return (window as Window & { __TRUSTGRAPH_WORKBENCH_QA_API__?: import("@trustgraph/client").BaseApi }).__TRUSTGRAPH_WORKBENCH_QA_API__;
return (window as Window & { __TRUSTGRAPH_WORKBENCH_QA_API__?: WorkbenchQaApi }).__TRUSTGRAPH_WORKBENCH_QA_API__;
}
function makeWorkbenchGatewayApi(settings: Settings) {
@ -897,9 +898,7 @@ function makeWorkbenchGatewayApi(settings: Settings) {
Effect.map((response) => {
const config = asJsonRecord(response.config);
const promptNs = asJsonRecord(config.prompt);
return Object.keys(promptNs)
.filter((key) => key !== "system")
.sort()
return A.sort(Object.keys(promptNs).filter((key) => key !== "system"), Order.String)
.map((id) => ({ id, name: id }));
}),
),
@ -1826,9 +1825,9 @@ function explainTriplesKey(input: ExplainTriplesInput): string {
const graphs = input.events
.map((event) => event.explainGraph ?? event.explainId ?? "")
.filter((id) => id.length > 0)
.sort()
const sortedGraphs = A.sort(graphs, Order.String)
.join(explainGraphSeparator);
return [input.flowId, input.collection, graphs].join(atomFamilyKeySeparator);
return [input.flowId, input.collection, sortedGraphs].join(atomFamilyKeySeparator);
}
const graphTriplesAtomByKey = Atom.family((key: string) => {

View file

@ -1,5 +1,6 @@
import { lazy, Suspense } from "react";
import { useAtom, useAtomValue } from "@effect/atom-react";
import { Array as A, Order } from "effect";
import { Network, ChevronRight, ChevronDown, Loader2 } from "lucide-react";
import * as Atom from "effect/unstable/reactivity/Atom";
import {
@ -74,7 +75,7 @@ export function ExplainGraph({ explainEvents, collection }: ExplainGraphProps) {
const loading = expanded && resultLoading(result, triples);
const error = resultError(result);
const { data: graphData, typeMap } = triplesToGraph(triples);
const uniqueTypes = Array.from(new Set(Array.from(typeMap.values()).map(localName))).sort();
const uniqueTypes = A.sort(Array.from(new Set(Array.from(typeMap.values()).map(localName))), Order.String);
return (
<div className="mt-2 rounded-md border border-border/50">

View file

@ -1,5 +1,6 @@
import { lazy, Suspense } from "react";
import { useAtom, useAtomRefresh, useAtomValue } from "@effect/atom-react";
import { Array as A, Order } from "effect";
import {
Rotate3d,
Search,
@ -180,7 +181,7 @@ export default function GraphPage() {
const selectedNode = view.selectedNodeId !== null
? data.nodes.find((node) => node.id === view.selectedNodeId)
: undefined;
const uniqueTypes = Array.from(new Set(Array.from(typeMap.values()).map(localName))).sort();
const uniqueTypes = A.sort(Array.from(new Set(Array.from(typeMap.values()).map(localName))), Order.String);
return (
<div className="flex h-full flex-col">

View file

@ -8,7 +8,7 @@ import {
flowIdAtom,
settingsAtom,
} from "@/atoms/workbench";
import type { BaseApi } from "@trustgraph/client";
import type { WorkbenchQaApi } from "@/qa/mock-api";
import { MockWorkbenchFixture, makeMockBaseApi, qaSettingsFromFixture, } from "@/qa/mock-api";
import { Schema as S } from "effect";
@ -21,7 +21,7 @@ export class WorkbenchQaWindowConfig extends S.Class<WorkbenchQaWindowConfig>("W
declare global {
interface Window {
__TRUSTGRAPH_WORKBENCH_QA__?: WorkbenchQaWindowConfig;
__TRUSTGRAPH_WORKBENCH_QA_API__?: BaseApi;
__TRUSTGRAPH_WORKBENCH_QA_API__?: WorkbenchQaApi;
}
}

View file

@ -1,9 +1,26 @@
import type { BaseApi, DocumentMetadata, ProcessingMetadata, StreamingMetadata, Triple } from "@trustgraph/client";
import { makeBaseApiWithRpc, } from "@trustgraph/client";
import { Match, Option, Schema as S } from "effect";
import type { DocumentMetadata, ProcessingMetadata, StreamingMetadata, Triple } from "@trustgraph/client";
import { Array as A, Match, Option, Order, Schema as S } from "effect";
type ConfigValues = Record<string, Record<string, unknown>>;
export interface WorkbenchQaApi {
readonly makeRequest: <RequestType extends object, ResponseType>(
service: string,
request: RequestType,
timeout?: number,
retries?: number,
flow?: string,
) => Promise<ResponseType>;
readonly makeRequestMulti: <RequestType extends object, ResponseType>(
service: string,
request: RequestType,
receiver: (resp: unknown) => boolean,
timeout?: number,
retries?: number,
flow?: string,
) => Promise<ResponseType>;
}
const UnknownRecord = S.Record(S.String, S.Unknown);
const ConfigValuesRecord = S.Record(S.String, UnknownRecord);
@ -358,7 +375,9 @@ function dispatchFlow(state: MockState, request: Record<string, unknown>): unkno
const id = stringValue(request["flow-id"], "default");
return { flow: encodeJson(state.flows.definitions[id] ?? { id, description: "Mock flow" }) };
}
if (operation === "list-blueprints") return { "blueprint-names": Object.keys(state.flows.blueprints).sort() };
if (operation === "list-blueprints") {
return { "blueprint-names": A.sort(Object.keys(state.flows.blueprints), Order.String) };
}
if (operation === "get-blueprint") {
const name = stringValue(request["blueprint-name"], "qa-blueprint");
return { "blueprint-definition": encodeJson(state.flows.blueprints[name] ?? {}) };
@ -563,33 +582,37 @@ function dispatchStream<ResponseType>(
return Promise.resolve({} as ResponseType);
}
export function makeMockBaseApi(fixture: MockWorkbenchFixture = {}): BaseApi {
export function makeMockBaseApi(fixture: MockWorkbenchFixture = {}): WorkbenchQaApi {
const state = createState(fixture);
const token = state.settings.apiKey.length > 0 ? state.settings.apiKey : undefined;
return makeBaseApiWithRpc(state.settings.user, token, state.settings.gatewayUrl, {
dispatch: (input) =>
return {
makeRequest: <RequestType extends object, ResponseType>(
service: string,
request: RequestType,
_timeout?: number,
_retries?: number,
flow?: string,
): Promise<ResponseType> =>
Promise.resolve(
dispatchRequest(
state,
input.service,
input.request,
input.flow,
),
service,
request as Record<string, unknown>,
flow,
) as ResponseType,
),
dispatchStream: (input, receiver) =>
dispatchStream(state, input.service, (message) => {
makeRequestMulti: <RequestType extends object, ResponseType>(
service: string,
_request: RequestType,
receiver: (resp: unknown) => boolean,
): Promise<ResponseType> =>
dispatchStream(state, service, (message) => {
const chunk = message as { response?: unknown; complete?: boolean };
return receiver({
response: chunk.response,
complete: chunk.complete === true,
});
}).then(() => undefined),
subscribe: (listener) => {
listener({ status: token === undefined ? "connected" : "connected" });
return () => {};
},
close: () => Promise.resolve(),
});
}).then(() => ({}) as ResponseType),
};
}
export function qaSettingsFromFixture(fixture: MockWorkbenchFixture = {}) {