feat(ts): complete schema-first phase 2

This commit is contained in:
elpresidank 2026-06-11 07:37:59 -05:00
parent 0746d7ffd5
commit be2370ee7b
24 changed files with 465 additions and 433 deletions

View file

@ -430,7 +430,7 @@ const onAgentRequest = Effect.fn("AgentService.onRequest")(function* (
chunk_type: "explain",
content: "",
explain_id: explain.explainId,
explain_triples: explain.triples,
explain_triples: [...explain.triples],
});
}

View file

@ -15,10 +15,8 @@ import type {
TriplesQueryResponse,
ToolRequest,
ToolResponse,
Term,
Triple,
} from "@trustgraph/base";
import {Term as TermSchema} from "@trustgraph/base";
import { Term, Triple } from "@trustgraph/base";
import { Effect, Match } from "effect";
import * as O from "effect/Option";
import * as Predicate from "effect/Predicate";
@ -27,7 +25,7 @@ import type { AgentTool, ToolArg } from "./types.js";
import { agentToolError, } from "./types.js";
const decodeJsonUnknown = S.decodeUnknownOption(S.UnknownFromJsonString);
const decodeTerm = S.decodeUnknownOption(TermSchema);
const decodeTerm = S.decodeUnknownOption(Term);
/**
* Format a Term to a human-readable string.
@ -64,10 +62,10 @@ function parseQuestion(input: string): string {
/**
* Explain data extracted from a graph-rag response.
*/
export interface ExplainData {
explainId: string;
triples: Triple[];
}
export class ExplainData extends S.Class<ExplainData>("ExplainData")({
explainId: S.String,
triples: S.Array(Triple),
}, { description: "Explain payload extracted from a graph-rag response: id plus supporting triples." }) {}
/**
* Query the knowledge graph for information about entities and their relationships.

View file

@ -20,11 +20,11 @@ export const agentToolError = (operation: string, cause: unknown): AgentToolErro
message: errorMessage(cause),
});
export interface ToolArg {
name: string;
type: string;
description: string;
}
export class ToolArg extends S.Class<ToolArg>("ToolArg")({
name: S.String,
type: S.String,
description: S.String,
}, { description: "A named, typed argument accepted by an agent tool." }) {}
export interface AgentTool {
name: string;
@ -43,10 +43,10 @@ export type ReActState =
| "final_answer"
| "complete";
export interface ParsedEvent {
type: "thought" | "action" | "action_input" | "final_answer";
content: string;
}
export class ParsedEvent extends S.Class<ParsedEvent>("ParsedEvent")({
type: S.Literals(["thought", "action", "action_input", "final_answer"]),
content: S.String,
}, { description: "A parsed ReAct stream event with its section content." }) {}
export type OnThought = (text: string, isFinal: boolean) => Effect.Effect<void, AgentToolError>;
export type OnObservation = (text: string, isFinal: boolean) => Effect.Effect<void, AgentToolError>;

View file

@ -8,14 +8,15 @@
import * as MutableHashMap from "effect/MutableHashMap";
import * as O from "effect/Option";
import * as S from "effect/Schema";
export interface CollectionEntry {
user: string;
collection: string;
name: string;
description: string;
tags: string[];
}
export class CollectionEntry extends S.Class<CollectionEntry>("CollectionEntry")({
user: S.String,
collection: S.String,
name: S.String,
description: S.String,
tags: S.Array(S.String),
}, { description: "A librarian collection registration with its metadata tags." }) {}
export interface CollectionManager {
readonly listCollections: (user: string) => CollectionEntry[];

View file

@ -39,10 +39,10 @@ export type TextCompletionRuntimeError =
| TextCompletionProviderError
| TooManyRequestsError;
export interface LanguageModelProviderRequest {
readonly model: string;
readonly temperature: number;
}
export class LanguageModelProviderRequest extends S.Class<LanguageModelProviderRequest>("LanguageModelProviderRequest")({
model: S.String,
temperature: S.Finite,
}, { description: "Resolved model id and temperature for a language-model call." }) {}
export interface LanguageModelProviderOptions<Requirements> {
readonly provider: string;

View file

@ -47,10 +47,10 @@ import * as MutableHashMap from "effect/MutableHashMap";
import * as O from "effect/Option";
import * as S from "effect/Schema";
export interface PromptTemplate {
system: string;
prompt: string;
}
export class PromptTemplate extends S.Class<PromptTemplate>("PromptTemplate")({
system: S.String,
prompt: S.String,
}, { description: "A prompt template: system preamble plus prompt body." }) {}
export interface PromptTemplateConfig extends ProcessorConfig {
configKey?: string;

View file

@ -4,22 +4,22 @@ import { errorMessage } from "@trustgraph/base";
import { Effect } from "effect";
import * as S from "effect/Schema";
export interface QdrantCollectionStatus {
readonly exists: boolean;
}
export class QdrantCollectionStatus extends S.Class<QdrantCollectionStatus>("QdrantCollectionStatus")({
exists: S.Boolean,
}, { description: "Qdrant collection existence probe result." }) {}
export interface QdrantCollectionDescription {
readonly name: string;
}
export class QdrantCollectionDescription extends S.Class<QdrantCollectionDescription>("QdrantCollectionDescription")({
name: S.String,
}, { description: "A named Qdrant collection." }) {}
export interface QdrantCollections {
readonly collections: ReadonlyArray<QdrantCollectionDescription>;
}
export class QdrantCollections extends S.Class<QdrantCollections>("QdrantCollections")({
collections: S.Array(QdrantCollectionDescription),
}, { description: "Qdrant collection listing." }) {}
export interface QdrantScoredPoint {
readonly score: number;
readonly payload?: unknown;
}
export class QdrantScoredPoint extends S.Class<QdrantScoredPoint>("QdrantScoredPoint")({
score: S.Finite,
payload: S.optionalKey(S.Unknown),
}, { description: "A scored Qdrant search hit with optional payload." }) {}
export class QdrantClientError extends S.TaggedErrorClass<QdrantClientError>()("QdrantClientError", {
message: S.String,

View file

@ -20,18 +20,18 @@ export interface QdrantDocQueryConfig {
clientFactory?: QdrantClientFactory;
}
export interface ChunkMatch {
chunkId: string;
score: number;
content?: string;
}
export class ChunkMatch extends S.Class<ChunkMatch>("ChunkMatch")({
chunkId: S.String,
score: S.Finite,
content: S.optionalKey(S.String),
}, { description: "A scored document-chunk match from embeddings query." }) {}
export interface DocEmbeddingsQueryRequest {
vector: number[];
user: string;
collection: string;
limit: number;
}
export class DocEmbeddingsQueryRequest extends S.Class<DocEmbeddingsQueryRequest>("DocEmbeddingsQueryRequest")({
vector: S.Array(S.Finite),
user: S.String,
collection: S.String,
limit: S.Finite,
}, { description: "Document embeddings similarity query request." }) {}
export class QdrantDocEmbeddingsQueryError extends S.TaggedErrorClass<QdrantDocEmbeddingsQueryError>()(
"QdrantDocEmbeddingsQueryError",

View file

@ -10,8 +10,7 @@
* Python reference: trustgraph-flow/trustgraph/query/graph_embeddings/qdrant/service.py
*/
import type { Term } from "@trustgraph/base";
import { errorMessage, } from "@trustgraph/base";
import { Term, errorMessage } from "@trustgraph/base";
import { Config, Context, Effect, Layer } from "effect";
import * as O from "effect/Option";
import * as S from "effect/Schema";
@ -24,17 +23,17 @@ export interface QdrantGraphQueryConfig {
clientFactory?: QdrantClientFactory;
}
export interface EntityMatch {
entity: Term;
score: number;
}
export class EntityMatch extends S.Class<EntityMatch>("EntityMatch")({
entity: Term,
score: S.Finite,
}, { description: "A scored graph-entity match from embeddings query." }) {}
export interface GraphEmbeddingsQueryRequest {
vector: number[];
user: string;
collection: string;
limit: number;
}
export class GraphEmbeddingsQueryRequest extends S.Class<GraphEmbeddingsQueryRequest>("GraphEmbeddingsQueryRequest")({
vector: S.Array(S.Finite),
user: S.String,
collection: S.String,
limit: S.Finite,
}, { description: "Graph embeddings similarity query request." }) {}
export class QdrantGraphEmbeddingsQueryError extends S.TaggedErrorClass<QdrantGraphEmbeddingsQueryError>()(
"QdrantGraphEmbeddingsQueryError",

View file

@ -138,7 +138,7 @@ const onGraphRagRequest = Effect.fn("GraphRagService.onRequest")(function* (
endOfStream: true,
message_type: "explain",
explain_id: `explain-${requestId}`,
explain_triples: result.subgraph,
explain_triples: [...result.subgraph],
};
yield* producer.send(requestId, response);

View file

@ -16,23 +16,22 @@ import type {
Term,
TextCompletionRequest,
TextCompletionResponse,
Triple,
TriplesQueryRequest,
TriplesQueryResponse,
} from "@trustgraph/base";
import { errorMessage } from "@trustgraph/base";
import { Triple, errorMessage } from "@trustgraph/base";
import { Context, Effect, Layer, Match } from "effect";
import * as O from "effect/Option";
import * as S from "effect/Schema";
export interface GraphRagConfig {
entityLimit?: number;
tripleLimit?: number;
maxSubgraphSize?: number;
maxPathLength?: number;
edgeScoreLimit?: number;
edgeLimit?: number;
}
export class GraphRagConfig extends S.Class<GraphRagConfig>("GraphRagConfig")({
entityLimit: S.optionalKey(S.Finite),
tripleLimit: S.optionalKey(S.Finite),
maxSubgraphSize: S.optionalKey(S.Finite),
maxPathLength: S.optionalKey(S.Finite),
edgeScoreLimit: S.optionalKey(S.Finite),
edgeLimit: S.optionalKey(S.Finite),
}, { description: "Graph RAG retrieval tuning limits." }) {}
export interface GraphRagClients {
llm: EffectRequestResponse<TextCompletionRequest, TextCompletionResponse>;
@ -53,10 +52,10 @@ export interface GraphRagQueryOptions {
readonly chunkCallback?: ChunkCallback;
}
export interface GraphRagResult {
answer: string;
subgraph: Triple[];
}
export class GraphRagResult extends S.Class<GraphRagResult>("GraphRagResult")({
answer: S.String,
subgraph: S.Array(Triple),
}, { description: "Graph RAG answer with the supporting subgraph." }) {}
interface NormalizedGraphRagConfig {
entityLimit: number;

View file

@ -22,17 +22,17 @@ export interface QdrantDocEmbeddingsConfig {
clientFactory?: QdrantClientFactory;
}
export interface DocEmbeddingChunk {
chunkId: string;
vector: number[];
content?: string;
}
export class DocEmbeddingChunk extends S.Class<DocEmbeddingChunk>("DocEmbeddingChunk")({
chunkId: S.String,
vector: S.Array(S.Finite),
content: S.optionalKey(S.String),
}, { description: "A document chunk paired with its embedding vector." }) {}
export interface DocEmbeddingsMessage {
user: string;
collection: string;
chunks: DocEmbeddingChunk[];
}
export class DocEmbeddingsMessage extends S.Class<DocEmbeddingsMessage>("DocEmbeddingsMessage")({
user: S.String,
collection: S.String,
chunks: S.Array(DocEmbeddingChunk),
}, { description: "Document embeddings store message: chunks to upsert for a user collection." }) {}
export class QdrantDocEmbeddingsStoreError extends S.TaggedErrorClass<QdrantDocEmbeddingsStoreError>()(
"QdrantDocEmbeddingsStoreError",

View file

@ -8,8 +8,7 @@
* Python reference: trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py
*/
import type { Term } from "@trustgraph/base";
import { errorMessage, } from "@trustgraph/base";
import { Term, errorMessage } from "@trustgraph/base";
import { Config, Context, Effect, Layer, Match, Random } from "effect";
import * as MutableHashSet from "effect/MutableHashSet";
import * as O from "effect/Option";
@ -23,17 +22,17 @@ export interface QdrantGraphEmbeddingsConfig {
clientFactory?: QdrantClientFactory;
}
export interface GraphEmbeddingEntity {
entity: Term;
vector: number[];
chunkId?: string;
}
export class GraphEmbeddingEntity extends S.Class<GraphEmbeddingEntity>("GraphEmbeddingEntity")({
entity: Term,
vector: S.Array(S.Finite),
chunkId: S.optionalKey(S.String),
}, { description: "A graph entity paired with its embedding vector." }) {}
export interface GraphEmbeddingsMessage {
user: string;
collection: string;
entities: GraphEmbeddingEntity[];
}
export class GraphEmbeddingsMessage extends S.Class<GraphEmbeddingsMessage>("GraphEmbeddingsMessage")({
user: S.String,
collection: S.String,
entities: S.Array(GraphEmbeddingEntity),
}, { description: "Graph embeddings store message: entities to upsert for a user collection." }) {}
export class QdrantGraphEmbeddingsStoreError extends S.TaggedErrorClass<QdrantGraphEmbeddingsStoreError>()(
"QdrantGraphEmbeddingsStoreError",