feat(ts): add real quality gates — Biome lint + effect-law ratchet + class inventory

- biome.json (2.4.16, linter-only) wired as "lint" in all six packages
- scripts/check-effect-laws.ts: Effect-native law enforcement encoding the
  adapted beep-effect effect-first/schema-first laws (no native JSON/switch/
  sort/fetch/timers, no process.env, no throw new, no Effect.run* outside
  boundaries, no Schema-suffixed constants, no node:fs/path, AST-based
  pure-data interface detection per law 38/39)
- ratcheting baseline allowlist (95 entries / 290 findings) that must shrink
  to documented exemptions only; stale counts fail the gate
- root lint chains turbo lint + law check + native-class inventory
- fix all 163 initial Biome findings: import-type style, templates, two `any`s,
  ten non-null assertions (librarian getService gate, A.matchRight in atoms,
  ensureNode returning nodes, main.tsx mount guard)

Gates: lint, check:tsgo, build, test (force, 11 tasks) all green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
elpresidank 2026-06-11 06:40:01 -05:00
parent cf12defcd8
commit 0746d7ffd5
109 changed files with 951 additions and 611 deletions

95
ts/biome.json Normal file
View file

@ -0,0 +1,95 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.16/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"root": true,
"files": {
"includes": [
"packages/*/src/**",
"scripts/**",
"!**/node_modules",
"!**/dist",
"!**/.turbo",
"!**/__snapshots__"
]
},
"css": {
"parser": {
"tailwindDirectives": true
}
},
"formatter": {
"enabled": false
},
"assist": {
"enabled": false
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"security": {
"noGlobalEval": "error"
},
"a11y": {
"useFocusableInteractive": "off",
"useAriaPropsForRole": "off",
"useSemanticElements": "off",
"useKeyWithClickEvents": "off",
"noStaticElementInteractions": "off",
"noSvgWithoutTitle": "off",
"useButtonType": "off",
"noLabelWithoutControl": "off"
},
"complexity": {
"noBannedTypes": "off",
"noForEach": "off",
"noUselessFragments": "off"
},
"correctness": {
"noUnusedImports": "error",
"noUnusedVariables": "off",
"noUnusedFunctionParameters": "off",
"useExhaustiveDependencies": "off",
"useHookAtTopLevel": "off",
"useYield": "off",
"noChildrenProp": "off"
},
"performance": {
"noDelete": "off",
"noAccumulatingSpread": "off"
},
"suspicious": {
"noDebugger": "error",
"noExplicitAny": "error",
"noConfusingVoidType": "off",
"noAssignInExpressions": "off",
"noArrayIndexKey": "off",
"noDoubleEquals": "off",
"noThenProperty": "off",
"noRedeclare": "off"
},
"style": {
"noNonNullAssertion": "error",
"useImportType": {
"level": "error",
"options": {
"style": "separatedType"
}
},
"useAsConstAssertion": "error",
"useDefaultParameterLast": "error",
"useSelfClosingElements": "error",
"useSingleVarDeclarator": "error",
"useNumberNamespace": "error",
"noInferrableTypes": "error",
"noUselessElse": "error",
"noParameterAssign": "off",
"noUnusedTemplateLiteral": "off"
}
}
}
}

View file

@ -8,6 +8,7 @@
"effect": "4.0.0-beta.78", "effect": "4.0.0-beta.78",
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "^2",
"@effect/platform-bun": "4.0.0-beta.78", "@effect/platform-bun": "4.0.0-beta.78",
"@effect/tsgo": "0.14.0", "@effect/tsgo": "0.14.0",
"@effect/vitest": "4.0.0-beta.78", "@effect/vitest": "4.0.0-beta.78",
@ -190,6 +191,24 @@
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "7.27.1", "@babel/helper-validator-identifier": "7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="], "@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "7.27.1", "@babel/helper-validator-identifier": "7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
"@biomejs/biome": ["@biomejs/biome@2.4.16", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.16", "@biomejs/cli-darwin-x64": "2.4.16", "@biomejs/cli-linux-arm64": "2.4.16", "@biomejs/cli-linux-arm64-musl": "2.4.16", "@biomejs/cli-linux-x64": "2.4.16", "@biomejs/cli-linux-x64-musl": "2.4.16", "@biomejs/cli-win32-arm64": "2.4.16", "@biomejs/cli-win32-x64": "2.4.16" }, "bin": { "biome": "bin/biome" } }, "sha512-x9ajFh1zChVybCiM3TN6OD4phAqLgtPZjFrZF+aTMYCPjwBO+k529TX7PPsAqtGNLeV4UgzwQnowEgS7bGmzcA=="],
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.16", "", { "os": "darwin", "cpu": "arm64" }, "sha512-wxPvu4XOA85YJk9ixSWUmq/QBHbid85BISbOAqqBM/5xQpPk9ayjk5375tOlSC0BeCwNSbPFafQBm+vBumXq0A=="],
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.16", "", { "os": "darwin", "cpu": "x64" }, "sha512-xFCqGPwYusQJp4N4NJLi1XJiZqjwFdjhT+KqtNy+Ug3qgfczqnTa6MSDvxJF6TkuDLoYJItMapz6tAf7kCekFw=="],
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.16", "", { "os": "linux", "cpu": "arm64" }, "sha512-2kFb4//jxfZaP6D+Rj5VkHkxgyD9EoRAVBEQb8PKRv+s4NO2zYNJKXFaJmK1CmhufJOWEfpHKaRbOja7qjmdhQ=="],
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.16", "", { "os": "linux", "cpu": "arm64" }, "sha512-oYxnW0ARfJkr72ezzF2OR8N/rtkgLUQeYtF8cFhVswbknHxtTcmzSsanVJP8yQKnGpGpc2ck6c5zLvHahL6Cbg=="],
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.16", "", { "os": "linux", "cpu": "x64" }, "sha512-NbcBbi/nJqn5baae6wqRXdS7Gadf2uRpehSh6vMSYpG8OhkXl/Xg8aorWrJ+9VWqAT5ml90alLvorkpMW0nBwQ=="],
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.16", "", { "os": "linux", "cpu": "x64" }, "sha512-iHDS+MCM65DPqWGu+ECC3uoALyj2H7F4nVUPxIPjz/PIl94EUu+EDfGZDzFP+NY1EOPVt9NQvwFqq7HdMmowdg=="],
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.16", "", { "os": "win32", "cpu": "arm64" }, "sha512-0rgImMsNb5v/chhkIFe3wu7PEFClS6RBAYUijGL9UsYN3PanSaoK24HSSuSJb1pYbYYVjzAyZTl3gtjJ84BM8A=="],
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.16", "", { "os": "win32", "cpu": "x64" }, "sha512-Kp85jgoBHa05gix6UIRjfCDiUV3w/8VIdZ247VyyO2gEjaw12WEVhdIjlxp/AMzXxqxQwbxNTDVZ3Mwd2RG5rw=="],
"@effect/ai-anthropic": ["@effect/ai-anthropic@4.0.0-beta.78", "", { "peerDependencies": { "effect": "^4.0.0-beta.78" } }, "sha512-FZzwvKx2k+UIDJyv+FWMtC2CKRxJMWTII+z8EmMcT6tw1uzkkn+ouIyJ32AU+lfveKScNV1SXL4ml3VdcYGy/g=="], "@effect/ai-anthropic": ["@effect/ai-anthropic@4.0.0-beta.78", "", { "peerDependencies": { "effect": "^4.0.0-beta.78" } }, "sha512-FZzwvKx2k+UIDJyv+FWMtC2CKRxJMWTII+z8EmMcT6tw1uzkkn+ouIyJ32AU+lfveKScNV1SXL4ml3VdcYGy/g=="],
"@effect/atom-react": ["@effect/atom-react@4.0.0-beta.78", "", { "peerDependencies": { "effect": "^4.0.0-beta.78", "react": "^19.2.4", "scheduler": "*" } }, "sha512-cgxDXJaD0wlbQXbp6tiEmmY+yajwurB0ynkFG20RVucvH4LsQMB3ogiHe0mt42wGggfbVYMEDxgBpQdqDRY8yA=="], "@effect/atom-react": ["@effect/atom-react@4.0.0-beta.78", "", { "peerDependencies": { "effect": "^4.0.0-beta.78", "react": "^19.2.4", "scheduler": "*" } }, "sha512-cgxDXJaD0wlbQXbp6tiEmmY+yajwurB0ynkFG20RVucvH4LsQMB3ogiHe0mt42wGggfbVYMEDxgBpQdqDRY8yA=="],

View file

@ -4,7 +4,9 @@
"scripts": { "scripts": {
"build": "bunx --bun turbo build", "build": "bunx --bun turbo build",
"dev": "bunx --bun turbo dev", "dev": "bunx --bun turbo dev",
"lint": "bunx --bun turbo lint", "lint": "bunx --bun turbo lint && bun run lint:laws",
"lint:laws": "bun scripts/check-effect-laws.ts && bun scripts/inventory-native-classes.ts",
"lint:laws:baseline": "bun scripts/check-effect-laws.ts --write-baseline",
"test": "bunx --bun turbo test", "test": "bunx --bun turbo test",
"check": "bun run check:tsgo", "check": "bun run check:tsgo",
"check:tsgo": "effect-tsgo patch && tsgo -b tsconfig.json", "check:tsgo": "effect-tsgo patch && tsgo -b tsconfig.json",
@ -44,6 +46,7 @@
"llm:mistral": "bun scripts/run-llm-mistral.ts" "llm:mistral": "bun scripts/run-llm-mistral.ts"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "^2",
"@effect/platform-bun": "4.0.0-beta.78", "@effect/platform-bun": "4.0.0-beta.78",
"@effect/tsgo": "0.14.0", "@effect/tsgo": "0.14.0",
"@effect/vitest": "4.0.0-beta.78", "@effect/vitest": "4.0.0-beta.78",
@ -55,7 +58,6 @@
"pdf-lib": "^1.17.1", "pdf-lib": "^1.17.1",
"tsx": "^4.21.0", "tsx": "^4.21.0",
"turbo": "^2.5.0", "turbo": "^2.5.0",
"typescript": "^5.8.0", "typescript": "^5.8.0",
"vitest": "^4.1.6" "vitest": "^4.1.6"
}, },

View file

@ -17,7 +17,8 @@
"build": "bunx --bun tsc", "build": "bunx --bun tsc",
"dev": "tsc --watch", "dev": "tsc --watch",
"clean": "rm -rf dist", "clean": "rm -rf dist",
"test": "bunx --bun vitest run" "test": "bunx --bun vitest run",
"lint": "bunx --bun biome check src"
}, },
"dependencies": { "dependencies": {
"effect": "4.0.0-beta.78", "effect": "4.0.0-beta.78",

View file

@ -1,13 +1,12 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { Effect } from "effect"; import { Effect } from "effect";
import { makeConsumer, type ConsumerOptions, type FlowContext } from "../messaging/consumer.js"; import type { FlowContext } from "../messaging/consumer.js";
import { makeConsumer, } from "../messaging/consumer.js";
import type { import type {
PubSubBackend, PubSubBackend,
BackendConsumer, BackendConsumer,
Message, Message,
BackendProducer, BackendProducer,
CreateProducerOptions,
CreateConsumerOptions,
} from "../backend/types.js"; } from "../backend/types.js";
import { tooManyRequestsError } from "../errors.js"; import { tooManyRequestsError } from "../errors.js";
import type { Flow } from "../processor/flow.js"; import type { Flow } from "../processor/flow.js";

View file

@ -1,6 +1,16 @@
import { describe, expect, it } from "@effect/vitest"; import { describe, expect, it } from "@effect/vitest";
import { ConfigProvider, Effect, Fiber } from "effect"; import { ConfigProvider, Effect, Fiber } from "effect";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import type {
BackendConsumer,
BackendProducer,
CreateConsumerOptions,
CreateProducerOptions,
EmbeddingsRequest,
EmbeddingsResponse,
Message,
PubSubBackend,
} from "../index.js";
import { import {
Embeddings, Embeddings,
EmbeddingsService, EmbeddingsService,
@ -9,14 +19,6 @@ import {
embeddingsError, embeddingsError,
runProcessorScoped, runProcessorScoped,
topics, topics,
type BackendConsumer,
type BackendProducer,
type CreateConsumerOptions,
type CreateProducerOptions,
type EmbeddingsRequest,
type EmbeddingsResponse,
type Message,
type PubSubBackend,
} from "../index.js"; } from "../index.js";
class WaitForTimeout extends S.TaggedErrorClass<WaitForTimeout>()( class WaitForTimeout extends S.TaggedErrorClass<WaitForTimeout>()(

View file

@ -1,6 +1,15 @@
import { describe, expect, it } from "@effect/vitest"; import { describe, expect, it } from "@effect/vitest";
import { ConfigProvider, Effect, Fiber } from "effect"; import { ConfigProvider, Effect, Fiber } from "effect";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import type {
BackendConsumer,
BackendProducer,
CreateConsumerOptions,
CreateProducerOptions,
Message,
ProcessorConfig,
PubSubBackend,
} from "../index.js";
import { import {
FlowProcessor, FlowProcessor,
MessagingRuntimeLive, MessagingRuntimeLive,
@ -9,13 +18,6 @@ import {
runFlowProcessorDefinitionScoped, runFlowProcessorDefinitionScoped,
runProcessorScoped, runProcessorScoped,
topics, topics,
type BackendConsumer,
type BackendProducer,
type CreateConsumerOptions,
type CreateProducerOptions,
type Message,
type ProcessorConfig,
type PubSubBackend,
} from "../index.js"; } from "../index.js";
class WaitForTimeout extends S.TaggedErrorClass<WaitForTimeout>()( class WaitForTimeout extends S.TaggedErrorClass<WaitForTimeout>()(

View file

@ -2,6 +2,15 @@ import { describe, expect, it } from "@effect/vitest";
import { ConfigProvider, Duration, Effect, Fiber } from "effect"; import { ConfigProvider, Duration, Effect, Fiber } from "effect";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import * as TestClock from "effect/testing/TestClock"; import * as TestClock from "effect/testing/TestClock";
import type {
BackendConsumer,
BackendProducer,
CreateConsumerOptions,
CreateProducerOptions,
FlowContext,
Message,
PubSubBackend,
} from "../index.js";
import { import {
makeConsumerSpec, makeConsumerSpec,
Flow, Flow,
@ -10,13 +19,6 @@ import {
makeProducerSpec, makeProducerSpec,
PubSub, PubSub,
makeRequestResponseSpec, makeRequestResponseSpec,
type BackendConsumer,
type BackendProducer,
type CreateConsumerOptions,
type CreateProducerOptions,
type FlowContext,
type Message,
type PubSubBackend,
} from "../index.js"; } from "../index.js";
function createMessage<T>(value: T, properties: Record<string, string> = {}): Message<T> { function createMessage<T>(value: T, properties: Record<string, string> = {}): Message<T> {

View file

@ -1,6 +1,15 @@
import { describe, expect, it } from "@effect/vitest"; import { describe, expect, it } from "@effect/vitest";
import { Duration, Effect, Fiber } from "effect"; import { Duration, Effect, Fiber } from "effect";
import * as TestClock from "effect/testing/TestClock"; import * as TestClock from "effect/testing/TestClock";
import type {
BackendConsumer,
BackendProducer,
CreateConsumerOptions,
CreateProducerOptions,
FlowContext,
Message,
PubSubBackend,
} from "../index.js";
import { import {
PubSub, PubSub,
defaultMessagingRuntimeConfig, defaultMessagingRuntimeConfig,
@ -11,13 +20,6 @@ import {
runEffectProducerScoped, runEffectProducerScoped,
runFlowScoped, runFlowScoped,
tooManyRequestsError, tooManyRequestsError,
type BackendConsumer,
type BackendProducer,
type CreateConsumerOptions,
type CreateProducerOptions,
type FlowContext,
type Message,
type PubSubBackend,
} from "../index.js"; } from "../index.js";
import type { Flow } from "../processor/flow.js"; import type { Flow } from "../processor/flow.js";
import { Flow as RuntimeFlow } from "../processor/flow.js"; import { Flow as RuntimeFlow } from "../processor/flow.js";

View file

@ -1,13 +1,15 @@
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
import { Effect } from "effect"; import { Effect } from "effect";
import type {
BackendConsumer,
BackendProducer,
CreateConsumerOptions,
CreateProducerOptions,
PubSubBackend,
} from "../index.js";
import { import {
makeProducer, makeProducer,
pubSubError, pubSubError,
type BackendConsumer,
type BackendProducer,
type CreateConsumerOptions,
type CreateProducerOptions,
type PubSubBackend,
} from "../index.js"; } from "../index.js";
class ProducerBackend implements PubSubBackend { class ProducerBackend implements PubSubBackend {

View file

@ -1,13 +1,15 @@
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
import { Effect } from "effect"; import { Effect } from "effect";
import type {
BackendConsumer,
BackendProducer,
CreateConsumerOptions,
CreateProducerOptions,
Message,
PubSubBackend,
} from "../index.js";
import { import {
makeRequestResponse, makeRequestResponse,
type BackendConsumer,
type BackendProducer,
type CreateConsumerOptions,
type CreateProducerOptions,
type Message,
type PubSubBackend,
} from "../index.js"; } from "../index.js";
function createMessage<T>(value: T, properties: Record<string, string> = {}): Message<T> { function createMessage<T>(value: T, properties: Record<string, string> = {}): Message<T> {

View file

@ -1,18 +1,20 @@
import { describe, expect, it } from "@effect/vitest"; import { describe, expect, it } from "@effect/vitest";
import { Effect } from "effect"; import { Effect } from "effect";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import type {
BackendConsumer,
BackendProducer,
CreateConsumerOptions,
CreateProducerOptions,
Message,
ProcessorConfig,
PubSubBackend,
} from "../index.js";
import { import {
PubSub, PubSub,
makeAsyncProcessor, makeAsyncProcessor,
pubSubError, pubSubError,
runProcessorScoped, runProcessorScoped,
type BackendConsumer,
type BackendProducer,
type CreateConsumerOptions,
type CreateProducerOptions,
type Message,
type ProcessorConfig,
type PubSubBackend,
} from "../index.js"; } from "../index.js";
class RuntimeServicesTestError extends S.TaggedErrorClass<RuntimeServicesTestError>()( class RuntimeServicesTestError extends S.TaggedErrorClass<RuntimeServicesTestError>()(

View file

@ -8,16 +8,18 @@
* Python reference: trustgraph-base/trustgraph/base/pulsar_backend.py * Python reference: trustgraph-base/trustgraph/base/pulsar_backend.py
*/ */
import type {
NatsConnection,
JetStreamClient,
JetStreamManager,
Consumer as NatsJsConsumer,
JsMsg,
JetStreamPublishOptions,
} from "nats";
import { import {
connect, connect,
ErrorCode, ErrorCode,
type NatsConnection,
type JetStreamClient,
type JetStreamManager,
type Consumer as NatsJsConsumer,
headers, headers,
type JsMsg,
type JetStreamPublishOptions,
NatsError, NatsError,
StringCodec, StringCodec,
AckPolicy, AckPolicy,
@ -36,7 +38,8 @@ import type {
CreateConsumerOptions, CreateConsumerOptions,
Message, Message,
} from "./types.js"; } from "./types.js";
import { pubSubError, type PubSubError } from "../errors.js"; import type { PubSubError } from "../errors.js";
import { pubSubError, } from "../errors.js";
const sc = StringCodec(); const sc = StringCodec();

View file

@ -7,20 +7,25 @@
import type { PubSubBackend } from "../backend/types.js"; import type { PubSubBackend } from "../backend/types.js";
import { PubSub } from "../backend/pubsub.js"; import { PubSub } from "../backend/pubsub.js";
import type { Flow } from "../processor/flow.js"; import type { Flow } from "../processor/flow.js";
import { import type {
MessagingHandlerError, MessagingHandlerError,
MessagingLifecycleError,
} from "../errors.js";
import {
TooManyRequestsError, TooManyRequestsError,
messagingHandlerError, messagingHandlerError,
messagingLifecycleError, messagingLifecycleError,
type MessagingLifecycleError,
} from "../errors.js"; } from "../errors.js";
import { Config as EffectConfig, Effect, Exit, Scope } from "effect"; import type { Config as EffectConfig, } from "effect";
import { Effect, Exit, Scope } from "effect";
import * as P from "effect/Predicate"; import * as P from "effect/Predicate";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import { loadMessagingRuntimeConfig } from "../runtime/index.ts"; import { loadMessagingRuntimeConfig } from "../runtime/index.ts";
import type {
EffectConsumer,
} from "./runtime.js";
import { import {
makeEffectConsumerFromPubSub, makeEffectConsumerFromPubSub,
type EffectConsumer,
} from "./runtime.js"; } from "./runtime.js";
export type MessageHandler<T> = ( export type MessageHandler<T> = (

View file

@ -8,11 +8,14 @@ import type { PubSubBackend } from "../backend/types.js";
import type { ProducerMetrics } from "../metrics/index.ts"; import type { ProducerMetrics } from "../metrics/index.ts";
import { Effect, Exit, Scope } from "effect"; import { Effect, Exit, Scope } from "effect";
import { PubSub } from "../backend/pubsub.js"; import { PubSub } from "../backend/pubsub.js";
import { makeEffectProducerFromPubSub, type EffectProducer } from "./runtime.js"; import type { EffectProducer } from "./runtime.js";
import { makeEffectProducerFromPubSub, } from "./runtime.js";
import type {
MessagingDeliveryError,
MessagingLifecycleError,
} from "../errors.js";
import { import {
messagingLifecycleError, messagingLifecycleError,
type MessagingDeliveryError,
type MessagingLifecycleError,
} from "../errors.js"; } from "../errors.js";
export interface Producer<T> { export interface Producer<T> {

View file

@ -7,21 +7,26 @@
* Python reference: trustgraph-base/trustgraph/base/request_response_spec.py * Python reference: trustgraph-base/trustgraph/base/request_response_spec.py
*/ */
import { Config as EffectConfig, Effect, Exit, Scope } from "effect"; import type { Config as EffectConfig, } from "effect";
import { Effect, Exit, Scope } from "effect";
import type { PubSubBackend } from "../backend/types.js"; import type { PubSubBackend } from "../backend/types.js";
import { PubSub } from "../backend/pubsub.js"; import { PubSub } from "../backend/pubsub.js";
import type {
MessagingDeliveryError,
MessagingLifecycleError,
MessagingTimeoutError,
PubSubError,
} from "../errors.js";
import { import {
messagingLifecycleError, messagingLifecycleError,
type MessagingDeliveryError,
type MessagingLifecycleError,
type MessagingTimeoutError,
type PubSubError,
} from "../errors.js"; } from "../errors.js";
import { loadMessagingRuntimeConfig } from "../runtime/index.ts"; import { loadMessagingRuntimeConfig } from "../runtime/index.ts";
import type {
EffectRequestOptions,
EffectRequestResponse,
} from "./runtime.js";
import { import {
makeEffectRequestResponseFromPubSub, makeEffectRequestResponseFromPubSub,
type EffectRequestOptions,
type EffectRequestResponse,
} from "./runtime.js"; } from "./runtime.js";
export interface RequestResponseOptions { export interface RequestResponseOptions {

View file

@ -3,6 +3,9 @@
*/ */
import { randomUUID } from "node:crypto"; import { randomUUID } from "node:crypto";
import type {
Scope,
} from "effect";
import { import {
Context, Context,
Deferred, Deferred,
@ -14,7 +17,6 @@ import {
Ref, Ref,
Result, Result,
Schedule, Schedule,
Scope,
Stream, Stream,
} from "effect"; } from "effect";
import * as O from "effect/Option"; import * as O from "effect/Option";
@ -26,7 +28,16 @@ import type {
CreateProducerOptions, CreateProducerOptions,
Message, Message,
} from "../backend/types.js"; } from "../backend/types.js";
import { PubSub, type PubSubService } from "../backend/pubsub.js"; import type { PubSubService } from "../backend/pubsub.js";
import { PubSub, } from "../backend/pubsub.js";
import type {
FlowRuntimeError,
MessagingDeliveryError,
MessagingHandlerError,
MessagingLifecycleError,
MessagingTimeoutError,
PubSubError,
} from "../errors.js";
import { import {
flowRuntimeError, flowRuntimeError,
messagingDeliveryError, messagingDeliveryError,
@ -34,20 +45,16 @@ import {
messagingLifecycleError, messagingLifecycleError,
messagingTimeoutError, messagingTimeoutError,
TooManyRequestsError, TooManyRequestsError,
type FlowRuntimeError,
type MessagingDeliveryError,
type MessagingHandlerError,
type MessagingLifecycleError,
type MessagingTimeoutError,
type PubSubError,
} from "../errors.js"; } from "../errors.js";
import type { ProducerMetrics } from "../metrics/index.js"; import type { ProducerMetrics } from "../metrics/index.js";
import type { FlowContext } from "./consumer.js"; import type { FlowContext } from "./consumer.js";
import type { Flow } from "../processor/flow.js"; import type { Flow } from "../processor/flow.js";
import type { SpecRuntimeRequirements } from "../spec/types.js"; import type { SpecRuntimeRequirements } from "../spec/types.js";
import type {
MessagingRuntimeConfig,
} from "../runtime/messaging-config.js";
import { import {
loadMessagingRuntimeConfig, loadMessagingRuntimeConfig,
type MessagingRuntimeConfig,
} from "../runtime/messaging-config.js"; } from "../runtime/messaging-config.js";
const isTooManyRequestsError = S.is(TooManyRequestsError); const isTooManyRequestsError = S.is(TooManyRequestsError);

View file

@ -4,7 +4,8 @@
* Python reference: trustgraph-base/trustgraph/base/metrics.py * Python reference: trustgraph-base/trustgraph/base/metrics.py
*/ */
import { Effect, Metric } from "effect"; import type { Effect, } from "effect";
import { Metric } from "effect";
import { PrometheusMetrics } from "effect/unstable/observability"; import { PrometheusMetrics } from "effect/unstable/observability";
export const prometheusContentType = "text/plain; version=0.0.4; charset=utf-8"; export const prometheusContentType = "text/plain; version=0.0.4; charset=utf-8";

View file

@ -8,8 +8,10 @@
import type { PubSubBackend } from "../backend/types.js"; import type { PubSubBackend } from "../backend/types.js";
import { makeNatsBackend, makeNatsBackendScoped } from "../backend/nats.js"; import { makeNatsBackend, makeNatsBackendScoped } from "../backend/nats.js";
import { Cause, Config as EffectConfig, Context, Effect } from "effect"; import type { Cause, Config as EffectConfig, } from "effect";
import { processorLifecycleError, type ProcessorLifecycleError } from "../errors.js"; import { Context, Effect } from "effect";
import type { ProcessorLifecycleError } from "../errors.js";
import { processorLifecycleError, } from "../errors.js";
import { loadProcessorRuntimeConfig } from "../runtime/config.js"; import { loadProcessorRuntimeConfig } from "../runtime/config.js";
export interface ProcessorConfig { export interface ProcessorConfig {

View file

@ -7,23 +7,28 @@
* Python reference: trustgraph-base/trustgraph/base/flow_processor.py * Python reference: trustgraph-base/trustgraph/base/flow_processor.py
*/ */
import type {
AsyncProcessorRuntime,
EffectConfigHandler,
ProcessorRuntime,
ProcessorConfig,
} from "./async-processor.js";
import { import {
makeAsyncProcessor, makeAsyncProcessor,
type AsyncProcessorRuntime,
type EffectConfigHandler,
type ProcessorRuntime,
type ProcessorConfig,
} from "./async-processor.js"; } from "./async-processor.js";
import type { Spec } from "../spec/types.js"; import type { Spec } from "../spec/types.js";
import type { BackendConsumer, PubSubBackend } from "../backend/types.js"; import type { BackendConsumer, PubSubBackend } from "../backend/types.js";
import { Flow, type FlowDefinition } from "./flow.js"; import type { FlowDefinition } from "./flow.js";
import { Flow, } from "./flow.js";
import { topics } from "../schema/topics.js"; import { topics } from "../schema/topics.js";
import type {
FlowRuntimeError,
ProcessorLifecycleError,
PubSubError,
} from "../errors.js";
import { import {
errorMessage, errorMessage,
pubSubError, pubSubError,
type FlowRuntimeError,
type ProcessorLifecycleError,
type PubSubError,
} from "../errors.js"; } from "../errors.js";
import { import {
ConsumerFactory, ConsumerFactory,
@ -37,7 +42,8 @@ import {
} from "../messaging/runtime.js"; } from "../messaging/runtime.js";
import { makePubSubService, PubSub } from "../backend/pubsub.js"; import { makePubSubService, PubSub } from "../backend/pubsub.js";
import { loadMessagingRuntimeConfig } from "../runtime/index.ts"; import { loadMessagingRuntimeConfig } from "../runtime/index.ts";
import { Config as EffectConfig, Context, Duration, Effect, Exit, Scope } from "effect"; import type { Config as EffectConfig, Context, } from "effect";
import { Duration, Effect, Exit, Scope } from "effect";
import * as MutableHashMap from "effect/MutableHashMap"; import * as MutableHashMap from "effect/MutableHashMap";
import * as O from "effect/Option"; import * as O from "effect/Option";
import * as S from "effect/Schema"; import * as S from "effect/Schema";

View file

@ -4,30 +4,35 @@
* Python reference: trustgraph-base/trustgraph/base/flow.py * Python reference: trustgraph-base/trustgraph/base/flow.py
*/ */
import { Config as EffectConfig, Context, Effect, Exit, Scope } from "effect"; import type { Config as EffectConfig, Context, } from "effect";
import { Effect, Exit, Scope } from "effect";
import * as MutableHashMap from "effect/MutableHashMap"; import * as MutableHashMap from "effect/MutableHashMap";
import * as O from "effect/Option"; import * as O from "effect/Option";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import type { PubSubBackend } from "../backend/types.js"; import type { PubSubBackend } from "../backend/types.js";
import { makePubSubService } from "../backend/pubsub.js"; import { makePubSubService } from "../backend/pubsub.js";
import type {
FlowParameterDecodeError,
FlowResourceNotFoundError,
MessagingDeliveryError,
MessagingLifecycleError,
MessagingTimeoutError,
PubSubError,
} from "../errors.js";
import { import {
flowParameterDecodeError, flowParameterDecodeError,
flowResourceNotFoundError, flowResourceNotFoundError,
type FlowParameterDecodeError,
type FlowResourceNotFoundError,
type MessagingDeliveryError,
type MessagingLifecycleError,
type MessagingTimeoutError,
type PubSubError,
} from "../errors.js"; } from "../errors.js";
import type {
EffectConsumer,
EffectProducer,
EffectRequestOptions,
EffectRequestResponse,
} from "../messaging/runtime.js";
import { import {
ConsumerFactory, ConsumerFactory,
ProducerFactory, ProducerFactory,
RequestResponseFactory, RequestResponseFactory,
type EffectConsumer,
type EffectProducer,
type EffectRequestOptions,
type EffectRequestResponse,
makeConsumerFactoryService, makeConsumerFactoryService,
makeProducerFactoryService, makeProducerFactoryService,
makeRequestResponseFactoryService, makeRequestResponseFactoryService,

View file

@ -5,11 +5,12 @@
* executable path while the processor internals remain Promise-based. * executable path while the processor internals remain Promise-based.
*/ */
import { Config as EffectConfig, Effect, Layer } from "effect"; import type { Config as EffectConfig, } from "effect";
import { import { Effect, Layer } from "effect";
type FlowRuntimeError, import type {
type ProcessorLifecycleError, FlowRuntimeError,
type PubSubError, ProcessorLifecycleError,
PubSubError,
} from "../errors.js"; } from "../errors.js";
import { makeNatsBackendScoped } from "../backend/nats.js"; import { makeNatsBackendScoped } from "../backend/nats.js";
import { makePubSubService, PubSub } from "../backend/pubsub.js"; import { makePubSubService, PubSub } from "../backend/pubsub.js";
@ -23,9 +24,11 @@ import {
makeRequestResponseFactoryService, makeRequestResponseFactoryService,
runFlowRuntimeScoped, runFlowRuntimeScoped,
} from "../messaging/runtime.js"; } from "../messaging/runtime.js";
import type {
ProcessorRuntimeConfigOptions,
} from "../runtime/config.js";
import { import {
loadProcessorRuntimeConfig, loadProcessorRuntimeConfig,
type ProcessorRuntimeConfigOptions,
} from "../runtime/config.js"; } from "../runtime/config.js";
import { loadMessagingRuntimeConfig } from "../runtime/messaging-config.js"; import { loadMessagingRuntimeConfig } from "../runtime/messaging-config.js";
import type { import type {

View file

@ -5,11 +5,13 @@
*/ */
import { Context, Effect } from "effect"; import { Context, Effect } from "effect";
import type {
EmbeddingsError,
FlowResourceNotFoundError,
MessagingDeliveryError,
} from "../errors.js";
import { import {
errorMessage, errorMessage,
type EmbeddingsError,
type FlowResourceNotFoundError,
type MessagingDeliveryError,
} from "../errors.js"; } from "../errors.js";
import type { FlowContext } from "../messaging/consumer.js"; import type { FlowContext } from "../messaging/consumer.js";
import { makeFlowProcessor } from "../processor/index.ts"; import { makeFlowProcessor } from "../processor/index.ts";

View file

@ -6,10 +6,12 @@
import { Context, Effect, Stream } from "effect"; import { Context, Effect, Stream } from "effect";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import type {
FlowResourceNotFoundError,
MessagingDeliveryError,
} from "../errors.js";
import { import {
errorMessage, errorMessage,
type FlowResourceNotFoundError,
type MessagingDeliveryError,
} from "../errors.js"; } from "../errors.js";
import type { FlowContext } from "../messaging/consumer.js"; import type { FlowContext } from "../messaging/consumer.js";
import { makeFlowProcessor } from "../processor/index.ts"; import { makeFlowProcessor } from "../processor/index.ts";

View file

@ -8,12 +8,14 @@ import { Effect } from "effect";
import type { Spec } from "./types.js"; import type { Spec } from "./types.js";
import type { SpecRuntimeRequirements } from "./types.js"; import type { SpecRuntimeRequirements } from "./types.js";
import type { Flow, FlowDefinition } from "../processor/flow.js"; import type { Flow, FlowDefinition } from "../processor/flow.js";
import { import type {
ConsumerFactory, EffectMessageHandler,
type EffectMessageHandler,
} from "../messaging/runtime.js"; } from "../messaging/runtime.js";
import { import {
type PubSubError, ConsumerFactory,
} from "../messaging/runtime.js";
import type {
PubSubError,
} from "../errors.js"; } from "../errors.js";
declare const ConsumerSpecType: unique symbol; declare const ConsumerSpecType: unique symbol;

View file

@ -7,13 +7,17 @@
import { Effect } from "effect"; import { Effect } from "effect";
import type { SpecRuntimeRequirements } from "./types.js"; import type { SpecRuntimeRequirements } from "./types.js";
import type { Flow, FlowDefinition } from "../processor/flow.js"; import type { Flow, FlowDefinition } from "../processor/flow.js";
import { import type {
flowResourceNotFoundError, FlowResourceNotFoundError,
type FlowResourceNotFoundError, PubSubError,
type PubSubError,
} from "../errors.js"; } from "../errors.js";
import { import {
type EffectProducer, flowResourceNotFoundError,
} from "../errors.js";
import type {
EffectProducer,
} from "../messaging/runtime.js";
import {
ProducerFactory, ProducerFactory,
} from "../messaging/runtime.js"; } from "../messaging/runtime.js";

View file

@ -10,13 +10,17 @@
import { Effect } from "effect"; import { Effect } from "effect";
import type { SpecRuntimeRequirements } from "./types.js"; import type { SpecRuntimeRequirements } from "./types.js";
import type { Flow, FlowDefinition } from "../processor/flow.js"; import type { Flow, FlowDefinition } from "../processor/flow.js";
import { import type {
flowResourceNotFoundError, FlowResourceNotFoundError,
type FlowResourceNotFoundError, PubSubError,
type PubSubError,
} from "../errors.js"; } from "../errors.js";
import { import {
type EffectRequestResponse, flowResourceNotFoundError,
} from "../errors.js";
import type {
EffectRequestResponse,
} from "../messaging/runtime.js";
import {
RequestResponseFactory, RequestResponseFactory,
} from "../messaging/runtime.js"; } from "../messaging/runtime.js";

View file

@ -9,7 +9,8 @@
"build": "bunx --bun tsc", "build": "bunx --bun tsc",
"dev": "tsc --watch", "dev": "tsc --watch",
"clean": "rm -rf dist", "clean": "rm -rf dist",
"test": "bunx --bun vitest run --passWithNoTests --exclude=dist/**" "test": "bunx --bun vitest run --passWithNoTests --exclude=dist/**",
"lint": "bunx --bun biome check src"
}, },
"dependencies": { "dependencies": {
"@effect/platform-bun": "4.0.0-beta.78", "@effect/platform-bun": "4.0.0-beta.78",

View file

@ -7,7 +7,8 @@
import { Effect } from "effect"; import { Effect } from "effect";
import * as Argument from "effect/unstable/cli/Argument"; import * as Argument from "effect/unstable/cli/Argument";
import * as Command from "effect/unstable/cli/Command"; import * as Command from "effect/unstable/cli/Command";
import { cliCommandError, withGatewayClient, type CliCommandError } from "./util.js"; import type { CliCommandError } from "./util.js";
import { cliCommandError, withGatewayClient, } from "./util.js";
function asRecord(value: unknown): Record<string, unknown> { function asRecord(value: unknown): Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value) return typeof value === "object" && value !== null && !Array.isArray(value)

View file

@ -2,11 +2,13 @@
* Shared CLI utilities. * Shared CLI utilities.
*/ */
import type {
BaseApi,
TrustGraphGatewayClient,
} from "@trustgraph/client";
import { import {
createTrustGraphSocket, createTrustGraphSocket,
makeTrustGraphGatewayClientScoped, makeTrustGraphGatewayClientScoped,
type BaseApi,
type TrustGraphGatewayClient,
} from "@trustgraph/client"; } from "@trustgraph/client";
import { Duration, Effect } from "effect"; import { Duration, Effect } from "effect";
import * as O from "effect/Option"; import * as O from "effect/Option";

View file

@ -19,7 +19,8 @@
"build": "bunx --bun tsc", "build": "bunx --bun tsc",
"dev": "tsc --watch", "dev": "tsc --watch",
"clean": "rm -rf dist", "clean": "rm -rf dist",
"test": "bunx --bun vitest run" "test": "bunx --bun vitest run",
"lint": "bunx --bun biome check src"
}, },
"dependencies": { "dependencies": {
"effect": "4.0.0-beta.78" "effect": "4.0.0-beta.78"
@ -36,7 +37,6 @@
"@effect/vitest": "4.0.0-beta.78", "@effect/vitest": "4.0.0-beta.78",
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"@types/ws": "^8.5.0", "@types/ws": "^8.5.0",
"typescript": "^5.8.0", "typescript": "^5.8.0",
"vitest": "^4.1.6", "vitest": "^4.1.6",
"happy-dom": "^20.0.0" "happy-dom": "^20.0.0"

View file

@ -1,6 +1,7 @@
import { describe, it, expect, vi, beforeEach } from "vitest"; import { describe, it, expect, vi, beforeEach } from "vitest";
import type { BaseApi } from "../socket/trustgraph-socket";
import { FlowsApi, TrustGraphSocketError } from "../socket/trustgraph-socket"; import { FlowsApi, TrustGraphSocketError } from "../socket/trustgraph-socket";
import { FlowResponse } from "../models/messages"; import type { FlowResponse } from "../models/messages";
describe("FlowsApi", () => { describe("FlowsApi", () => {
let mockApi: { let mockApi: {
@ -12,8 +13,7 @@ describe("FlowsApi", () => {
mockApi = { mockApi = {
makeRequest: vi.fn(), makeRequest: vi.fn(),
}; };
// eslint-disable-next-line @typescript-eslint/no-explicit-any flowsApi = FlowsApi(mockApi as unknown as BaseApi);
flowsApi = FlowsApi(mockApi as any);
}); });
describe("startFlow", () => { describe("startFlow", () => {

View file

@ -342,7 +342,7 @@ describe("Message Types", () => {
type: "library-error", type: "library-error",
}); });
expect(response["document-metadatas"]).toHaveLength(1); expect(response["document-metadatas"]).toHaveLength(1);
expect(response["document-metadatas"]![0].id).toBe("doc-1"); expect(response["document-metadatas"]?.[0].id).toBe("doc-1");
}); });
}); });

View file

@ -1,8 +1,10 @@
import { Effect } from "effect"; import { Effect } from "effect";
import { describe, expect, it, vi } from "vitest"; import { describe, expect, it, vi } from "vitest";
import { DispatchError, DispatchStreamChunk } from "../rpc/contract"; import { DispatchError, DispatchStreamChunk } from "../rpc/contract";
import { type DispatchInput, type RpcConnectionState, withDispatchRequestPolicy } from "../socket/effect-rpc-client"; import type { DispatchInput, RpcConnectionState, } from "../socket/effect-rpc-client";
import { type ConnectionState, makeBaseApiWithRpc } from "../socket/trustgraph-socket"; import { withDispatchRequestPolicy } from "../socket/effect-rpc-client";
import type { ConnectionState, } from "../socket/trustgraph-socket";
import { makeBaseApiWithRpc } from "../socket/trustgraph-socket";
const input: DispatchInput = { const input: DispatchInput = {
scope: "global", scope: "global",

View file

@ -1,6 +1,8 @@
import { describe, expect, it, vi } from "vitest"; import { describe, expect, it, vi } from "vitest";
import { import type {
BaseApi, BaseApi,
} from "../socket/trustgraph-socket";
import {
ConfigApi, ConfigApi,
KnowledgeApi, KnowledgeApi,
LibrarianApi, LibrarianApi,

View file

@ -5,38 +5,38 @@
// TrustGraph namespace // TrustGraph namespace
export const TG = "https://trustgraph.ai/ns/"; export const TG = "https://trustgraph.ai/ns/";
export const TG_QUERY = TG + "query"; export const TG_QUERY = `${TG}query`;
export const TG_EDGE_COUNT = TG + "edgeCount"; export const TG_EDGE_COUNT = `${TG}edgeCount`;
export const TG_SELECTED_EDGE = TG + "selectedEdge"; export const TG_SELECTED_EDGE = `${TG}selectedEdge`;
export const TG_EDGE = TG + "edge"; export const TG_EDGE = `${TG}edge`;
export const TG_REASONING = TG + "reasoning"; export const TG_REASONING = `${TG}reasoning`;
export const TG_CONTENT = TG + "content"; export const TG_CONTENT = `${TG}content`;
export const TG_REIFIES = TG + "reifies"; export const TG_REIFIES = `${TG}reifies`;
export const TG_DOCUMENT = TG + "document"; export const TG_DOCUMENT = `${TG}document`;
// W3C PROV-O namespace // W3C PROV-O namespace
export const PROV = "http://www.w3.org/ns/prov#"; export const PROV = "http://www.w3.org/ns/prov#";
export const PROV_STARTED_AT_TIME = PROV + "startedAtTime"; export const PROV_STARTED_AT_TIME = `${PROV}startedAtTime`;
export const PROV_WAS_DERIVED_FROM = PROV + "wasDerivedFrom"; export const PROV_WAS_DERIVED_FROM = `${PROV}wasDerivedFrom`;
export const PROV_WAS_GENERATED_BY = PROV + "wasGeneratedBy"; export const PROV_WAS_GENERATED_BY = `${PROV}wasGeneratedBy`;
export const PROV_ACTIVITY = PROV + "Activity"; export const PROV_ACTIVITY = `${PROV}Activity`;
export const PROV_ENTITY = PROV + "Entity"; export const PROV_ENTITY = `${PROV}Entity`;
// RDFS namespace // RDFS namespace
export const RDFS = "http://www.w3.org/2000/01/rdf-schema#"; export const RDFS = "http://www.w3.org/2000/01/rdf-schema#";
export const RDFS_LABEL = RDFS + "label"; export const RDFS_LABEL = `${RDFS}label`;
// RDF namespace // RDF namespace
export const RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; export const RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
export const RDF_TYPE = RDF + "type"; export const RDF_TYPE = `${RDF}type`;
// Schema.org namespace (used in document metadata) // Schema.org namespace (used in document metadata)
export const SCHEMA = "https://schema.org/"; export const SCHEMA = "https://schema.org/";
export const SCHEMA_NAME = SCHEMA + "name"; export const SCHEMA_NAME = `${SCHEMA}name`;
export const SCHEMA_DESCRIPTION = SCHEMA + "description"; export const SCHEMA_DESCRIPTION = `${SCHEMA}description`;
export const SCHEMA_AUTHOR = SCHEMA + "author"; export const SCHEMA_AUTHOR = `${SCHEMA}author`;
export const SCHEMA_KEYWORDS = SCHEMA + "keywords"; export const SCHEMA_KEYWORDS = `${SCHEMA}keywords`;
// SKOS namespace // SKOS namespace
export const SKOS = "http://www.w3.org/2004/02/skos/core#"; export const SKOS = "http://www.w3.org/2004/02/skos/core#";
export const SKOS_DEFINITION = SKOS + "definition"; export const SKOS_DEFINITION = `${SKOS}definition`;

View file

@ -4,7 +4,8 @@ import * as RpcClient from "effect/unstable/rpc/RpcClient";
import type { RpcClientError } from "effect/unstable/rpc/RpcClientError"; import type { RpcClientError } from "effect/unstable/rpc/RpcClientError";
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization"; import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
import * as Socket from "effect/unstable/socket/Socket"; import * as Socket from "effect/unstable/socket/Socket";
import { DispatchPayload, DispatchError, TrustGraphRpcs, type DispatchStreamChunk } from "../rpc/contract.js"; import type { DispatchStreamChunk } from "../rpc/contract.js";
import { DispatchPayload, DispatchError, TrustGraphRpcs, } from "../rpc/contract.js";
type TrustGraphRpcClient = RpcClient.RpcClient< type TrustGraphRpcClient = RpcClient.RpcClient<
RpcGroup.Rpcs<typeof TrustGraphRpcs>, RpcGroup.Rpcs<typeof TrustGraphRpcs>,

View file

@ -1,10 +1,12 @@
// Import core types and classes for the TrustGraph API // Import core types and classes for the TrustGraph API
import type { Term, Triple } from "../models/Triple.js"; import type { Term, Triple } from "../models/Triple.js";
import type {
EffectRpcClient,
DispatchInput,
DispatchOptions,
RpcConnectionState,
} from "./effect-rpc-client.js";
import { import {
type EffectRpcClient,
type DispatchInput,
type DispatchOptions,
type RpcConnectionState,
makeEffectRpcClient, makeEffectRpcClient,
} from "./effect-rpc-client.js"; } from "./effect-rpc-client.js";
import { getDefaultSocketUrl, getRandomValues } from "./websocket-adapter.js"; import { getDefaultSocketUrl, getRandomValues } from "./websocket-adapter.js";
@ -479,7 +481,7 @@ export function makeBaseApi(
hasApiKey: isNonEmptyString(token), hasApiKey: isNonEmptyString(token),
}), }),
); );
let lastError: string | undefined = undefined; let lastError: string | undefined ;
let rpcState: RpcConnectionState = { status: "connecting" }; let rpcState: RpcConnectionState = { status: "connecting" };
const api = { const api = {
@ -536,7 +538,7 @@ export function makeBaseApi(
* Format: {clientTag}-{incrementingNumber} * Format: {clientTag}-{incrementingNumber}
*/ */
getNextId() { getNextId() {
const mid = api.tag + "-" + api.id.toString(); const mid = `${api.tag}-${api.id.toString()}`;
api.id++; api.id++;
return mid; return mid;
}, },
@ -2530,11 +2532,10 @@ export function makeKnowledgeApi(api: BaseApi) {
// End of stream - notify receiver and signal completion // End of stream - notify receiver and signal completion
receiver(msg, true); receiver(msg, true);
return true; return true;
} else { }
// Regular message - continue streaming // Regular message - continue streaming
receiver(msg, false); receiver(msg, false);
return false; return false;
}
}; };
return this.api.makeRequestMulti<LibraryRequest, LibraryResponse>( return this.api.makeRequestMulti<LibraryRequest, LibraryResponse>(

View file

@ -56,8 +56,7 @@ export interface IsomorphicWebSocket {
addEventListener(type: "close", listener: (event: WsCloseEvent) => void): void; addEventListener(type: "close", listener: (event: WsCloseEvent) => void): void;
addEventListener(type: "open", listener: (event: WsEvent) => void): void; addEventListener(type: "open", listener: (event: WsEvent) => void): void;
addEventListener(type: "error", listener: (event: WsEvent) => void): void; addEventListener(type: "error", listener: (event: WsEvent) => void): void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any removeEventListener(type: string, listener: (...args: ReadonlyArray<never>) => void): void;
removeEventListener(type: string, listener: (...args: any[]) => void): void;
} }
/** Constructor signature for an isomorphic WebSocket implementation. */ /** Constructor signature for an isomorphic WebSocket implementation. */

View file

@ -8,7 +8,8 @@
"build": "bunx --bun tsc", "build": "bunx --bun tsc",
"dev": "tsc --watch", "dev": "tsc --watch",
"clean": "rm -rf dist", "clean": "rm -rf dist",
"test": "bunx --bun vitest run" "test": "bunx --bun vitest run",
"lint": "bunx --bun biome check src"
}, },
"dependencies": { "dependencies": {
"@effect/ai-anthropic": "4.0.0-beta.78", "@effect/ai-anthropic": "4.0.0-beta.78",

View file

@ -2,19 +2,21 @@ import { describe, expect, it } from "@effect/vitest";
import { ConfigProvider, Effect, Fiber } from "effect"; import { ConfigProvider, Effect, Fiber } from "effect";
import * as EffectChunk from "effect/Chunk"; import * as EffectChunk from "effect/Chunk";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import type {
BackendConsumer,
BackendProducer,
Chunk,
CreateConsumerOptions,
CreateProducerOptions,
Message,
PubSubBackend,
TextDocument,
} from "@trustgraph/base";
import { import {
MessagingRuntimeLive, MessagingRuntimeLive,
PubSub, PubSub,
runProcessorScoped, runProcessorScoped,
topics, topics,
type BackendConsumer,
type BackendProducer,
type Chunk,
type CreateConsumerOptions,
type CreateProducerOptions,
type Message,
type PubSubBackend,
type TextDocument,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { ChunkingService } from "../chunking/service.js"; import { ChunkingService } from "../chunking/service.js";
import { recursiveSplit } from "../chunking/recursive-splitter.js"; import { recursiveSplit } from "../chunking/recursive-splitter.js";

View file

@ -1,16 +1,20 @@
import { Effect } from "effect"; import { Effect } from "effect";
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
import type {
FalkorDBClosableClient as FalkorDBQueryClient,
FalkorDBQueryGraph,
} from "../query/triples/falkordb.js";
import { import {
FalkorDBTriplesQueryLive, FalkorDBTriplesQueryLive,
FalkorDBTriplesQueryService, FalkorDBTriplesQueryService,
type FalkorDBClosableClient as FalkorDBQueryClient,
type FalkorDBQueryGraph,
} from "../query/triples/falkordb.js"; } from "../query/triples/falkordb.js";
import type {
FalkorDBClosableClient as FalkorDBStoreClient,
FalkorDBStoreGraph,
} from "../storage/triples/falkordb.js";
import { import {
FalkorDBTriplesStoreLive, FalkorDBTriplesStoreLive,
FalkorDBTriplesStoreService, FalkorDBTriplesStoreService,
type FalkorDBClosableClient as FalkorDBStoreClient,
type FalkorDBStoreGraph,
} from "../storage/triples/falkordb.js"; } from "../storage/triples/falkordb.js";
class FakeFalkorDBClient implements FalkorDBStoreClient, FalkorDBQueryClient { class FakeFalkorDBClient implements FalkorDBStoreClient, FalkorDBQueryClient {

View file

@ -1,18 +1,20 @@
import {Effect, HashMap, Option, SynchronizedRef} from "effect"; import {Effect, HashMap, Option, SynchronizedRef} from "effect";
import {describe, expect, it} from "vitest"; import {describe, expect, it} from "vitest";
import type {
BackendConsumer,
BackendProducer,
ConfigRequest,
ConfigResponse,
CreateConsumerOptions,
CreateProducerOptions,
FlowRequest,
FlowResponse,
Message,
PubSubBackend,
RequestResponse,
} from "@trustgraph/base";
import { import {
topics, topics,
type BackendConsumer,
type BackendProducer,
type ConfigRequest,
type ConfigResponse,
type CreateConsumerOptions,
type CreateProducerOptions,
type FlowRequest,
type FlowResponse,
type Message,
type PubSubBackend,
type RequestResponse,
} from "@trustgraph/base"; } from "@trustgraph/base";
import {FlowManagerError, makeFlowManagerService} from "../flow-manager/service.js"; import {FlowManagerError, makeFlowManagerService} from "../flow-manager/service.js";

View file

@ -3,7 +3,8 @@ import { Effect, Exit, Scope } from "effect";
import { HttpRouter, HttpServerResponse } from "effect/unstable/http"; import { HttpRouter, HttpServerResponse } from "effect/unstable/http";
import type { DispatcherManager } from "../gateway/dispatch/manager.js"; import type { DispatcherManager } from "../gateway/dispatch/manager.js";
import type { GatewayRpcServer } from "../gateway/rpc-server.js"; import type { GatewayRpcServer } from "../gateway/rpc-server.js";
import { makeGatewayRoutes, type GatewayConfig } from "../gateway/server.js"; import type { GatewayConfig } from "../gateway/server.js";
import { makeGatewayRoutes, } from "../gateway/server.js";
interface DispatchCall { interface DispatchCall {
readonly scope: "global" | "flow"; readonly scope: "global" | "flow";

View file

@ -3,17 +3,19 @@ import {tmpdir} from "node:os";
import {join} from "node:path"; import {join} from "node:path";
import {Effect, HashMap, Option, SynchronizedRef} from "effect"; import {Effect, HashMap, Option, SynchronizedRef} from "effect";
import {describe, expect, it} from "vitest"; import {describe, expect, it} from "vitest";
import type {
BackendConsumer,
BackendProducer,
CreateConsumerOptions,
CreateProducerOptions,
KnowledgeRequest,
KnowledgeResponse,
Message,
PubSubBackend,
Triple,
} from "@trustgraph/base";
import { import {
topics, topics,
type BackendConsumer,
type BackendProducer,
type CreateConsumerOptions,
type CreateProducerOptions,
type KnowledgeRequest,
type KnowledgeResponse,
type Message,
type PubSubBackend,
type Triple,
} from "@trustgraph/base"; } from "@trustgraph/base";
import {makeKnowledgeCoreService} from "../cores/service.js"; import {makeKnowledgeCoreService} from "../cores/service.js";

View file

@ -3,15 +3,15 @@ import {tmpdir} from "node:os";
import {join} from "node:path"; import {join} from "node:path";
import {Effect} from "effect"; import {Effect} from "effect";
import {describe, expect, it} from "vitest"; import {describe, expect, it} from "vitest";
import { import type {
type BackendConsumer, BackendConsumer,
type BackendProducer, BackendProducer,
type CreateConsumerOptions, CreateConsumerOptions,
type CreateProducerOptions, CreateProducerOptions,
type DocumentMetadata, DocumentMetadata,
type Message, Message,
type PubSubBackend, PubSubBackend,
type Triple, Triple,
} from "@trustgraph/base"; } from "@trustgraph/base";
import {makeLibrarianService} from "../librarian/service.js"; import {makeLibrarianService} from "../librarian/service.js";

View file

@ -1,19 +1,21 @@
import { describe, expect, it } from "@effect/vitest"; import { describe, expect, it } from "@effect/vitest";
import { ConfigProvider, Effect, Fiber } from "effect"; import { ConfigProvider, Effect, Fiber } from "effect";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import type {
BackendConsumer,
BackendProducer,
CreateConsumerOptions,
CreateProducerOptions,
Message,
PromptRequest,
PromptResponse,
PubSubBackend,
} from "@trustgraph/base";
import { import {
MessagingRuntimeLive, MessagingRuntimeLive,
PubSub, PubSub,
runProcessorScoped, runProcessorScoped,
topics, topics,
type BackendConsumer,
type BackendProducer,
type CreateConsumerOptions,
type CreateProducerOptions,
type Message,
type PromptRequest,
type PromptResponse,
type PubSubBackend,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { PromptTemplateService } from "../prompt/template.js"; import { PromptTemplateService } from "../prompt/template.js";

View file

@ -15,8 +15,10 @@ import type {
TriplesQueryRequest, TriplesQueryRequest,
TriplesQueryResponse, TriplesQueryResponse,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { makeDocumentRagEngine, type DocumentRagClients } from "../retrieval/document-rag.js"; import type { DocumentRagClients } from "../retrieval/document-rag.js";
import { makeGraphRagEngine, type GraphRagClients } from "../retrieval/graph-rag.js"; import { makeDocumentRagEngine, } from "../retrieval/document-rag.js";
import type { GraphRagClients } from "../retrieval/graph-rag.js";
import { makeGraphRagEngine, } from "../retrieval/graph-rag.js";
const requestor = <TReq, TRes>( const requestor = <TReq, TRes>(
handler: (request: TReq) => TRes, handler: (request: TReq) => TRes,

View file

@ -14,22 +14,23 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js"; import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import type {
ProcessorConfig,
FlowContext,
FlowProcessorRuntime,
ToolRequest,
ToolResponse,
EffectConfigHandler,
FlowResourceNotFoundError,
MessagingDeliveryError,
Spec,
} from "@trustgraph/base";
import { import {
makeFlowProcessor, makeFlowProcessor,
makeConsumerSpec, makeConsumerSpec,
makeProducerSpec, makeProducerSpec,
makeFlowProcessorProgram, makeFlowProcessorProgram,
errorMessage, errorMessage,
type ProcessorConfig,
type FlowContext,
type FlowProcessorRuntime,
type ToolRequest,
type ToolResponse,
type EffectConfigHandler,
type FlowResourceNotFoundError,
type MessagingDeliveryError,
type Spec,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { Context, Effect, Layer, Ref } from "effect"; import { Context, Effect, Layer, Ref } from "effect";
import * as O from "effect/Option"; import * as O from "effect/Option";

View file

@ -19,6 +19,27 @@
import { import {
NodeRuntime, NodeRuntime,
} from "@effect/platform-node"; } from "@effect/platform-node";
import type {
ProcessorConfig,
FlowContext,
FlowProcessorRuntime,
AgentRequest,
AgentResponse,
TextCompletionRequest,
TextCompletionResponse,
GraphRagRequest,
GraphRagResponse,
DocumentRagRequest,
DocumentRagResponse,
TriplesQueryRequest,
TriplesQueryResponse,
ToolRequest,
ToolResponse,
EffectConfigHandler,
FlowResourceNotFoundError,
MessagingDeliveryError,
Spec,
} from "@trustgraph/base";
import { import {
makeFlowProcessor, makeFlowProcessor,
makeConsumerSpec, makeConsumerSpec,
@ -26,37 +47,19 @@ import {
makeRequestResponseSpec, makeRequestResponseSpec,
makeFlowProcessorProgram, makeFlowProcessorProgram,
errorMessage, errorMessage,
type ProcessorConfig,
type FlowContext,
type FlowProcessorRuntime,
type AgentRequest,
type AgentResponse,
type TextCompletionRequest,
type TextCompletionResponse,
type GraphRagRequest,
type GraphRagResponse,
type DocumentRagRequest,
type DocumentRagResponse,
type TriplesQueryRequest,
type TriplesQueryResponse,
type ToolRequest,
type ToolResponse,
type EffectConfigHandler,
type FlowResourceNotFoundError,
type MessagingDeliveryError,
type Spec,
} from "@trustgraph/base"; } from "@trustgraph/base";
import {Context, Effect, Layer, Match, Ref} from "effect"; import {Context, Effect, Layer, Match, Ref} from "effect";
import * as O from "effect/Option"; import * as O from "effect/Option";
import * as Predicate from "effect/Predicate"; import * as Predicate from "effect/Predicate";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import type {
ExplainData,
} from "./tools.js";
import { import {
createKnowledgeQueryTool, createKnowledgeQueryTool,
createDocumentQueryTool, createDocumentQueryTool,
createTriplesQueryTool, createTriplesQueryTool,
createMcpTool, createMcpTool,
type ExplainData,
} from "./tools.js"; } from "./tools.js";
import { buildReActPrompt } from "./prompt.js"; import { buildReActPrompt } from "./prompt.js";
import { filterToolsByGroupAndState } from "../tool-filter.js"; import { filterToolsByGroupAndState } from "../tool-filter.js";
@ -550,9 +553,9 @@ export function parseReActResponse(text: string): {
const firstLine = trimmed.slice("Final Answer:".length).trim(); const firstLine = trimmed.slice("Final Answer:".length).trim();
const remainingLines = lines.slice(i + 1).join("\n").trim(); const remainingLines = lines.slice(i + 1).join("\n").trim();
finalAnswer = finalAnswer =
firstLine + (remainingLines.length > 0 ? "\n" + remainingLines : ""); firstLine + (remainingLines.length > 0 ? `\n${remainingLines}` : "");
break; break;
} else if (trimmed.startsWith("Thought:")) { }if (trimmed.startsWith("Thought:")) {
currentSection = "thought"; currentSection = "thought";
const content = trimmed.slice("Thought:".length).trim(); const content = trimmed.slice("Thought:".length).trim();
if (content.length > 0) { if (content.length > 0) {
@ -577,14 +580,14 @@ export function parseReActResponse(text: string): {
// Continuation line for current section // Continuation line for current section
Match.value(currentSection).pipe( Match.value(currentSection).pipe(
Match.when("thought", () => { Match.when("thought", () => {
thought += "\n" + trimmed; thought += `\n${trimmed}`;
}), }),
Match.when("action", () => { Match.when("action", () => {
// Action should be a single line (tool name), but handle multi-line // Action should be a single line (tool name), but handle multi-line
action += " " + trimmed; action += ` ${trimmed}`;
}), }),
Match.when("action_input", () => { Match.when("action_input", () => {
actionInput += "\n" + trimmed; actionInput += `\n${trimmed}`;
}), }),
Match.exhaustive, Match.exhaustive,
); );

View file

@ -23,8 +23,8 @@ import { Effect, Match } from "effect";
import * as O from "effect/Option"; import * as O from "effect/Option";
import * as Predicate from "effect/Predicate"; import * as Predicate from "effect/Predicate";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import type { AgentTool, ToolArg } from "./types.js";
import { agentToolError, type AgentTool, type ToolArg } from "./types.js"; import { agentToolError, } from "./types.js";
const decodeJsonUnknown = S.decodeUnknownOption(S.UnknownFromJsonString); const decodeJsonUnknown = S.decodeUnknownOption(S.UnknownFromJsonString);
const decodeTerm = S.decodeUnknownOption(TermSchema); const decodeTerm = S.decodeUnknownOption(TermSchema);

View file

@ -30,7 +30,7 @@ function isToolAvailable(
const config = tool.config ?? {}; const config = tool.config ?? {};
// Get tool groups (default to ["default"]) // Get tool groups (default to ["default"])
let toolGroups = config["group"] as string[] | string | undefined; let toolGroups = config.group as string[] | string | undefined;
if (toolGroups === undefined) toolGroups = ["default"]; if (toolGroups === undefined) toolGroups = ["default"];
if (!Array.isArray(toolGroups)) toolGroups = [toolGroups]; if (!Array.isArray(toolGroups)) toolGroups = [toolGroups];
@ -56,6 +56,6 @@ function isToolAvailable(
* Get the next state after successful tool execution. * Get the next state after successful tool execution.
*/ */
export function getNextState(tool: AgentTool, currentState: string): string { export function getNextState(tool: AgentTool, currentState: string): string {
const nextState = tool.config?.["state"] as string | undefined; const nextState = tool.config?.state as string | undefined;
return nextState ?? currentState; return nextState ?? currentState;
} }

View file

@ -9,20 +9,22 @@
* Python reference: trustgraph-flow/trustgraph/chunking/recursive_splitter/service.py * Python reference: trustgraph-flow/trustgraph/chunking/recursive_splitter/service.py
*/ */
import type {
ProcessorConfig,
FlowProcessorRuntime,
FlowContext,
FlowResourceNotFoundError,
MessagingDeliveryError,
TextDocument,
Chunk,
Triples,
Spec,
} from "@trustgraph/base";
import { import {
makeFlowProcessor, makeFlowProcessor,
makeConsumerSpec, makeConsumerSpec,
makeProducerSpec, makeProducerSpec,
makeParameterSpec, makeParameterSpec,
type ProcessorConfig,
type FlowProcessorRuntime,
type FlowContext,
type FlowResourceNotFoundError,
type MessagingDeliveryError,
type TextDocument,
type Chunk,
type Triples,
type Spec,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import { makeFlowProcessorProgram } from "@trustgraph/base"; import { makeFlowProcessorProgram } from "@trustgraph/base";

View file

@ -8,6 +8,16 @@ import {NodeRuntime} from "@effect/platform-node";
import {Duration, Effect, HashMap, Match, Option, SynchronizedRef} from "effect"; import {Duration, Effect, HashMap, Match, Option, SynchronizedRef} from "effect";
import * as Predicate from "effect/Predicate"; import * as Predicate from "effect/Predicate";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import type {
AsyncProcessorRuntime,
BackendConsumer,
BackendProducer,
ConfigOperation,
ConfigRequest,
ConfigResponse,
Message,
ProcessorConfig,
} from "@trustgraph/base";
import { import {
ConfigRequest as ConfigRequestSchema, ConfigRequest as ConfigRequestSchema,
ConfigResponse as ConfigResponseSchema, ConfigResponse as ConfigResponseSchema,
@ -18,14 +28,6 @@ import {
optionalStringConfig, optionalStringConfig,
processorLifecycleError, processorLifecycleError,
topics, topics,
type AsyncProcessorRuntime,
type BackendConsumer,
type BackendProducer,
type ConfigOperation,
type ConfigRequest,
type ConfigResponse,
type Message,
type ProcessorConfig,
} from "@trustgraph/base"; } from "@trustgraph/base";
import {readTextFileEffect, writeTextFileEffect} from "../runtime/effect-files.js"; import {readTextFileEffect, writeTextFileEffect} from "../runtime/effect-files.js";

View file

@ -5,6 +5,17 @@
*/ */
import {NodeRuntime} from "@effect/platform-node"; import {NodeRuntime} from "@effect/platform-node";
import type {
AsyncProcessorRuntime,
BackendConsumer,
BackendProducer,
KnowledgeOperation,
KnowledgeRequest,
KnowledgeResponse,
Message,
ProcessorConfig,
PubSubError,
} from "@trustgraph/base";
import { import {
KnowledgeRequest as KnowledgeRequestSchema, KnowledgeRequest as KnowledgeRequestSchema,
KnowledgeResponse as KnowledgeResponseSchema, KnowledgeResponse as KnowledgeResponseSchema,
@ -17,15 +28,6 @@ import {
optionalStringConfig, optionalStringConfig,
processorLifecycleError, processorLifecycleError,
topics, topics,
type AsyncProcessorRuntime,
type BackendConsumer,
type BackendProducer,
type KnowledgeOperation,
type KnowledgeRequest,
type KnowledgeResponse,
type Message,
type ProcessorConfig,
type PubSubError,
} from "@trustgraph/base"; } from "@trustgraph/base";
import {Duration, Effect, HashMap, Match, SynchronizedRef} from "effect"; import {Duration, Effect, HashMap, Match, SynchronizedRef} from "effect";
import * as O from "effect/Option"; import * as O from "effect/Option";

View file

@ -15,26 +15,28 @@
import { getDocument } from "pdfjs-dist/legacy/build/pdf.mjs"; import { getDocument } from "pdfjs-dist/legacy/build/pdf.mjs";
import type { TextItem } from "pdfjs-dist/types/src/display/api.js"; import type { TextItem } from "pdfjs-dist/types/src/display/api.js";
import type {
ProcessorConfig,
FlowProcessorRuntime,
FlowContext,
FlowResourceNotFoundError,
Document,
TextDocument,
Triples,
Triple,
Term,
LibrarianRequest,
LibrarianResponse,
MessagingDeliveryError,
MessagingLifecycleError,
MessagingTimeoutError,
Spec,
} from "@trustgraph/base";
import { import {
makeFlowProcessor, makeFlowProcessor,
makeConsumerSpec, makeConsumerSpec,
makeProducerSpec, makeProducerSpec,
makeRequestResponseSpec, makeRequestResponseSpec,
type ProcessorConfig,
type FlowProcessorRuntime,
type FlowContext,
type FlowResourceNotFoundError,
type Document,
type TextDocument,
type Triples,
type Triple,
type Term,
type LibrarianRequest,
type LibrarianResponse,
type MessagingDeliveryError,
type MessagingLifecycleError,
type MessagingTimeoutError,
type Spec,
errorMessage, errorMessage,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";

View file

@ -8,14 +8,16 @@ import { NodeRuntime } from "@effect/platform-node";
import { Config, Effect, Layer } from "effect"; import { Config, Effect, Layer } from "effect";
import * as O from "effect/Option"; import * as O from "effect/Option";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import type {
EmbeddingsServiceShape,
ProcessorConfig,
} from "@trustgraph/base";
import { import {
Embeddings, Embeddings,
EmbeddingsError, EmbeddingsError,
errorMessage, errorMessage,
makeEmbeddingsService, makeEmbeddingsService,
makeEmbeddingsSpecs, makeEmbeddingsSpecs,
type EmbeddingsServiceShape,
type ProcessorConfig,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { makeFlowProcessorProgram } from "@trustgraph/base"; import { makeFlowProcessorProgram } from "@trustgraph/base";

View file

@ -10,29 +10,31 @@
* Python reference: trustgraph-flow/trustgraph/extract/knowledge/service.py * Python reference: trustgraph-flow/trustgraph/extract/knowledge/service.py
*/ */
import type {
ProcessorConfig,
FlowProcessorRuntime,
FlowContext,
Chunk,
Triples,
EntityContexts,
EntityContext,
PromptRequest,
PromptResponse,
TextCompletionRequest,
TextCompletionResponse,
Triple,
Term,
FlowResourceNotFoundError,
MessagingDeliveryError,
EffectRequestResponse,
Spec,
} from "@trustgraph/base";
import { import {
makeFlowProcessor, makeFlowProcessor,
makeConsumerSpec, makeConsumerSpec,
makeProducerSpec, makeProducerSpec,
makeRequestResponseSpec, makeRequestResponseSpec,
makeFlowProcessorProgram, makeFlowProcessorProgram,
type ProcessorConfig,
type FlowProcessorRuntime,
type FlowContext,
type Chunk,
type Triples,
type EntityContexts,
type EntityContext,
type PromptRequest,
type PromptResponse,
type TextCompletionRequest,
type TextCompletionResponse,
type Triple,
type Term,
type FlowResourceNotFoundError,
type MessagingDeliveryError,
type EffectRequestResponse,
type Spec,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import { Effect } from "effect"; import { Effect } from "effect";
@ -375,7 +377,7 @@ function jsonCandidates(raw: string): ReadonlyArray<string> {
const partial = arrayMatch[0]; const partial = arrayMatch[0];
const lastBrace = partial.lastIndexOf("}"); const lastBrace = partial.lastIndexOf("}");
if (lastBrace > 0) { if (lastBrace > 0) {
candidates.push(partial.slice(0, lastBrace + 1) + "]"); candidates.push(`${partial.slice(0, lastBrace + 1)}]`);
} }
} }

View file

@ -14,21 +14,23 @@
* Python reference: trustgraph-flow/trustgraph/flow/service.py * Python reference: trustgraph-flow/trustgraph/flow/service.py
*/ */
import type {
ProcessorConfig,
AsyncProcessorRuntime,
BackendConsumer,
BackendProducer,
RequestResponse,
ConfigRequest,
ConfigResponse,
FlowRequest,
FlowResponse,
} from "@trustgraph/base";
import { import {
makeAsyncProcessor, makeAsyncProcessor,
type ProcessorConfig,
type AsyncProcessorRuntime,
type BackendConsumer,
type BackendProducer,
topics, topics,
makeRequestResponse, makeRequestResponse,
type RequestResponse,
type ConfigRequest,
type ConfigResponse,
FlowRequest as FlowRequestSchema, FlowRequest as FlowRequestSchema,
FlowResponse as FlowResponseSchema, FlowResponse as FlowResponseSchema,
type FlowRequest,
type FlowResponse,
errorMessage, errorMessage,
processorLifecycleError, processorLifecycleError,
} from "@trustgraph/base"; } from "@trustgraph/base";

View file

@ -9,6 +9,15 @@
*/ */
import { Clock, Effect, Exit, HashMap, HashSet, Option, Random, Scope, SynchronizedRef, Tuple } from "effect"; import { Clock, Effect, Exit, HashMap, HashSet, Option, Random, Scope, SynchronizedRef, Tuple } from "effect";
import type {
EffectRequestResponse,
MessagingDeliveryError,
MessagingLifecycleError,
MessagingTimeoutError,
PubSubBackend,
PubSubError,
RequestResponseFactoryService,
} from "@trustgraph/base";
import { import {
loadMessagingRuntimeConfig, loadMessagingRuntimeConfig,
makeNatsBackend, makeNatsBackend,
@ -17,19 +26,14 @@ import {
makeRequestResponseFactoryService, makeRequestResponseFactoryService,
messagingDeliveryError, messagingDeliveryError,
messagingLifecycleError, messagingLifecycleError,
type EffectRequestResponse,
type MessagingDeliveryError,
type MessagingLifecycleError,
type MessagingTimeoutError,
type PubSubBackend,
type PubSubError,
type RequestResponseFactoryService,
} from "@trustgraph/base"; } from "@trustgraph/base";
import type { GatewayConfig } from "../server.js"; import type { GatewayConfig } from "../server.js";
import type {
DispatchSerializationError,
} from "./serialize.js";
import { import {
translateRequestEffect, translateRequestEffect,
translateResponseEffect, translateResponseEffect,
type DispatchSerializationError,
} from "./serialize.js"; } from "./serialize.js";
export type EffectResponder<E = never, R = never> = ( export type EffectResponder<E = never, R = never> = (

View file

@ -18,6 +18,10 @@
* Python reference: trustgraph-base/trustgraph/messaging/translators/primitives.py * Python reference: trustgraph-base/trustgraph/messaging/translators/primitives.py
*/ */
import type {
Term,
Triple,
} from "@trustgraph/base";
import { import {
BlankTerm, BlankTerm,
errorMessage, errorMessage,
@ -26,8 +30,6 @@ import {
Term as TermSchema, Term as TermSchema,
Triple as TripleSchema, Triple as TripleSchema,
TripleTerm, TripleTerm,
type Term,
type Triple,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { Effect, HashSet, Match } from "effect"; import { Effect, HashSet, Match } from "effect";
import * as O from "effect/Option"; import * as O from "effect/Option";

View file

@ -1,10 +1,12 @@
import { Cause, Effect, Layer, Queue, Scope } from "effect"; import type { Cause, Scope } from "effect";
import { HttpServerRequest, HttpServerResponse } from "effect/unstable/http"; import { Effect, Layer, Queue, } from "effect";
import type { HttpServerRequest, HttpServerResponse } from "effect/unstable/http";
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization"; import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
import * as RpcServer from "effect/unstable/rpc/RpcServer"; import * as RpcServer from "effect/unstable/rpc/RpcServer";
import { errorMessage } from "@trustgraph/base"; import { errorMessage } from "@trustgraph/base";
import type { DispatcherManager, DispatcherStreamError } from "./dispatch/manager.js"; import type { DispatcherManager, DispatcherStreamError } from "./dispatch/manager.js";
import { DispatchError, DispatchPayload, DispatchStreamChunk, TrustGraphRpcs } from "./rpc-contract.js"; import type { DispatchPayload, } from "./rpc-contract.js";
import { DispatchError, DispatchStreamChunk, TrustGraphRpcs } from "./rpc-contract.js";
export interface GatewayRpcServer { export interface GatewayRpcServer {
readonly httpEffect: Effect.Effect< readonly httpEffect: Effect.Effect<

View file

@ -12,17 +12,21 @@ import * as O from "effect/Option";
import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/unstable/http"; import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/unstable/http";
import { HttpApiBuilder } from "effect/unstable/httpapi"; import { HttpApiBuilder } from "effect/unstable/httpapi";
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization"; import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
import type {
PubSubBackend,
} from "@trustgraph/base";
import { import {
formatPrometheusMetrics, formatPrometheusMetrics,
messagingLifecycleError, messagingLifecycleError,
optionalStringConfig, optionalStringConfig,
prometheusContentType, prometheusContentType,
toTgError, toTgError,
type PubSubBackend,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { GatewayWorkbenchHttpApi } from "@trustgraph/client/rpc/contract"; import { GatewayWorkbenchHttpApi } from "@trustgraph/client/rpc/contract";
import { makeDispatcherManagerScoped, type DispatcherManager } from "./dispatch/manager.js"; import type { DispatcherManager } from "./dispatch/manager.js";
import { makeGatewayRpcServer, type GatewayRpcServer } from "./rpc-server.js"; import { makeDispatcherManagerScoped, } from "./dispatch/manager.js";
import type { GatewayRpcServer } from "./rpc-server.js";
import { makeGatewayRpcServer, } from "./rpc-server.js";
export interface GatewayConfig { export interface GatewayConfig {
port: number; port: number;

View file

@ -10,32 +10,36 @@
* Python reference: trustgraph-flow/trustgraph/librarian/service/service.py * Python reference: trustgraph-flow/trustgraph/librarian/service/service.py
*/ */
import type {
ProcessorConfig,
AsyncProcessorRuntime,
BackendConsumer,
BackendProducer,
LibrarianRequest,
LibrarianResponse,
CollectionManagementRequest,
CollectionManagementResponse,
DocumentMetadata,
ProcessingMetadata,
} from "@trustgraph/base";
import { import {
errorMessage, errorMessage,
makeAsyncProcessor, makeAsyncProcessor,
makeProcessorProgram, makeProcessorProgram,
type ProcessorConfig,
type AsyncProcessorRuntime,
type BackendConsumer,
type BackendProducer,
topics, topics,
type LibrarianRequest,
type LibrarianResponse,
type CollectionManagementRequest,
type CollectionManagementResponse,
DocumentMetadata as DocumentMetadataSchema, DocumentMetadata as DocumentMetadataSchema,
type DocumentMetadata,
ProcessingMetadata as ProcessingMetadataSchema, ProcessingMetadata as ProcessingMetadataSchema,
type ProcessingMetadata,
Triple as TripleSchema, Triple as TripleSchema,
processorLifecycleError, processorLifecycleError,
} from "@trustgraph/base"; } from "@trustgraph/base";
import type { Message } from "@trustgraph/base"; import type { Message } from "@trustgraph/base";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import { Clock, Config, DateTime, Duration, Effect, Match, Option, Random, SynchronizedRef } from "effect"; import { Clock, Config, DateTime, Duration, Effect, Match, Option, Random, SynchronizedRef } from "effect";
import * as A from "effect/Array";
import * as MutableHashMap from "effect/MutableHashMap"; import * as MutableHashMap from "effect/MutableHashMap";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import { makeCollectionManager, type CollectionManager } from "./collection-manager.js"; import type { CollectionManager } from "./collection-manager.js";
import { makeCollectionManager, } from "./collection-manager.js";
import { import {
ensureDirectoryEffect, ensureDirectoryEffect,
joinPath, joinPath,
@ -127,13 +131,10 @@ const decodePersistedLibrarianState = (
); );
const randomUuid: Effect.Effect<string> = Effect.gen(function* () { const randomUuid: Effect.Effect<string> = Effect.gen(function* () {
const bytes: number[] = []; const raw = yield* Effect.forEach(A.range(0, 15), () => Random.nextIntBetween(0, 255));
for (let index = 0; index < 16; index += 1) { const bytes = A.map(raw, (byte, index) =>
bytes.push(yield* Random.nextIntBetween(0, 255)); index === 6 ? (byte & 0x0f) | 0x40 : index === 8 ? (byte & 0x3f) | 0x80 : byte,
} );
bytes[6] = (bytes[6]! & 0x0f) | 0x40;
bytes[8] = (bytes[8]! & 0x3f) | 0x80;
const hex = bytes.map((byte) => byte.toString(16).padStart(2, "0")); const hex = bytes.map((byte) => byte.toString(16).padStart(2, "0"));
return [ return [
@ -760,25 +761,24 @@ export function makeLibrarianService(config: LibrarianServiceConfig): LibrarianS
handleLibrarianOperation: function(this: LibrarianService, request: LibrarianRequest): Effect.Effect<LibrarianResponse, LibrarianServiceError> { handleLibrarianOperation: function(this: LibrarianService, request: LibrarianRequest): Effect.Effect<LibrarianResponse, LibrarianServiceError> {
const service = this;
return Match.value(request.operation).pipe( return Match.value(request.operation).pipe(
Match.when("add-document", () => service.addDocument(request)), Match.when("add-document", () => this.addDocument(request)),
Match.when("remove-document", () => service.removeDocument(request)), Match.when("remove-document", () => this.removeDocument(request)),
Match.when("update-document", () => service.updateDocument(request)), Match.when("update-document", () => this.updateDocument(request)),
Match.when("list-documents", () => service.listDocuments(request)), Match.when("list-documents", () => this.listDocuments(request)),
Match.when("get-document-metadata", () => getDocumentMetadataEffect(request)), Match.when("get-document-metadata", () => getDocumentMetadataEffect(request)),
Match.when("get-document-content", () => service.getDocumentContent(request)), Match.when("get-document-content", () => this.getDocumentContent(request)),
Match.when("add-child-document", () => service.addChildDocument(request)), Match.when("add-child-document", () => this.addChildDocument(request)),
Match.when("list-children", () => listChildrenEffect(request)), Match.when("list-children", () => listChildrenEffect(request)),
Match.when("add-processing", () => service.addProcessing(request)), Match.when("add-processing", () => this.addProcessing(request)),
Match.when("remove-processing", () => service.removeProcessing(request)), Match.when("remove-processing", () => this.removeProcessing(request)),
Match.when("list-processing", () => service.listProcessing(request)), Match.when("list-processing", () => this.listProcessing(request)),
Match.when("begin-upload", () => service.beginUpload(request)), Match.when("begin-upload", () => this.beginUpload(request)),
Match.when("upload-chunk", () => uploadChunkEffect(request)), Match.when("upload-chunk", () => uploadChunkEffect(request)),
Match.when("complete-upload", () => service.completeUpload(request)), Match.when("complete-upload", () => this.completeUpload(request)),
Match.when("get-upload-status", () => getUploadStatusEffect(request)), Match.when("get-upload-status", () => getUploadStatusEffect(request)),
Match.when("abort-upload", () => abortUploadEffect(request)), Match.when("abort-upload", () => abortUploadEffect(request)),
Match.when("list-uploads", () => service.listUploads(request)), Match.when("list-uploads", () => this.listUploads(request)),
Match.when("stream-document", () => Match.when("stream-document", () =>
Effect.fail( Effect.fail(
librarianServiceError("stream-document", "stream-document must be handled as a streaming operation"), librarianServiceError("stream-document", "stream-document must be handled as a streaming operation"),
@ -1427,7 +1427,7 @@ export function makeLibrarianService(config: LibrarianServiceConfig): LibrarianS
// ---------- Persistence ---------- // ---------- Persistence ----------
persist: Effect.gen(function* () { persist: Effect.gen(function* () {
const current = service!; const current = yield* getService;
const serviceState = yield* SynchronizedRef.get(current.state); const serviceState = yield* SynchronizedRef.get(current.state);
const data = { const data = {
documents: Object.fromEntries(serviceState.documents), documents: Object.fromEntries(serviceState.documents),
@ -1448,7 +1448,7 @@ export function makeLibrarianService(config: LibrarianServiceConfig): LibrarianS
loadFromDisk: Effect.gen(function* () { loadFromDisk: Effect.gen(function* () {
const current = service!; const current = yield* getService;
const parsed = yield* Effect.gen(function* () { const parsed = yield* Effect.gen(function* () {
const raw = yield* readTextFileEffect(current.persistPath).pipe( const raw = yield* readTextFileEffect(current.persistPath).pipe(
Effect.mapError((cause) => librarianServiceError("persist-read", cause)), Effect.mapError((cause) => librarianServiceError("persist-read", cause)),

View file

@ -10,16 +10,22 @@
import { AzureOpenAI } from "openai"; import { AzureOpenAI } from "openai";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import type {
Llm,
LlmProvider,
ProcessorConfig,
LlmResult,
} from "@trustgraph/base";
import { import {
makeLlmService, makeLlmService,
makeFlowProcessorProgram, makeFlowProcessorProgram,
makeLlmSpecs, makeLlmSpecs,
type Llm,
type LlmProvider,
type ProcessorConfig,
type LlmResult,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { Effect, Stream } from "effect"; import { Effect, Stream } from "effect";
import type {
TextCompletionConfigError,
TextCompletionRuntimeError,
} from "./common.ts";
import { import {
llmStreamPart, llmStreamPart,
makeTextCompletionLayer, makeTextCompletionLayer,
@ -27,8 +33,6 @@ import {
providerStatusError, providerStatusError,
requiredString, requiredString,
streamTextCompletionChunks, streamTextCompletionChunks,
type TextCompletionConfigError,
type TextCompletionRuntimeError,
} from "./common.ts"; } from "./common.ts";
export type AzureOpenAIProcessorConfig = ProcessorConfig & { export type AzureOpenAIProcessorConfig = ProcessorConfig & {

View file

@ -6,23 +6,27 @@
import { AnthropicClient, AnthropicLanguageModel } from "@effect/ai-anthropic"; import { AnthropicClient, AnthropicLanguageModel } from "@effect/ai-anthropic";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import type {
Llm,
LlmProvider,
ProcessorConfig,
} from "@trustgraph/base";
import { import {
makeLlmService, makeLlmService,
makeFlowProcessorProgram, makeFlowProcessorProgram,
makeLlmSpecs, makeLlmSpecs,
type Llm,
type LlmProvider,
type ProcessorConfig,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { Effect, Layer, Redacted } from "effect"; import { Effect, Layer, Redacted } from "effect";
import { FetchHttpClient } from "effect/unstable/http"; import { FetchHttpClient } from "effect/unstable/http";
import type {
TextCompletionConfigError,
TextCompletionRuntimeError,
} from "./common.ts";
import { import {
makeLanguageModelProvider, makeLanguageModelProvider,
makeTextCompletionLayer, makeTextCompletionLayer,
optionalStringConfig, optionalStringConfig,
requiredString, requiredString,
type TextCompletionConfigError,
type TextCompletionRuntimeError,
} from "./common.ts"; } from "./common.ts";
export type ClaudeProcessorConfig = ProcessorConfig & { export type ClaudeProcessorConfig = ProcessorConfig & {

View file

@ -1,18 +1,22 @@
import type {
LlmChunk,
LlmResult,
LlmProvider,
} from "@trustgraph/base";
import { import {
Llm, Llm,
TooManyRequestsError, TooManyRequestsError,
errorMessage, errorMessage,
makeLlmServiceShape, makeLlmServiceShape,
type LlmChunk,
type LlmResult,
type LlmProvider,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { Config, Context, Effect, Layer, Match, Ref, Result, Stream } from "effect"; import type { Context, } from "effect";
import { Config, Effect, Layer, Match, Ref, Result, Stream } from "effect";
import * as O from "effect/Option"; import * as O from "effect/Option";
import * as Predicate from "effect/Predicate"; import * as Predicate from "effect/Predicate";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import type * as Scope from "effect/Scope"; import type * as Scope from "effect/Scope";
import { AiError, LanguageModel, Prompt, Response } from "effect/unstable/ai"; import type { LanguageModel, Prompt, Response } from "effect/unstable/ai";
import { AiError, } from "effect/unstable/ai";
export class TextCompletionConfigError extends S.TaggedErrorClass<TextCompletionConfigError>()( export class TextCompletionConfigError extends S.TaggedErrorClass<TextCompletionConfigError>()(
"TextCompletionConfigError", "TextCompletionConfigError",

View file

@ -8,16 +8,22 @@
import { Mistral } from "@mistralai/mistralai"; import { Mistral } from "@mistralai/mistralai";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import type {
Llm,
LlmProvider,
ProcessorConfig,
LlmResult,
} from "@trustgraph/base";
import { import {
makeLlmService, makeLlmService,
makeFlowProcessorProgram, makeFlowProcessorProgram,
makeLlmSpecs, makeLlmSpecs,
type Llm,
type LlmProvider,
type ProcessorConfig,
type LlmResult,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { Effect, Stream } from "effect"; import { Effect, Stream } from "effect";
import type {
TextCompletionConfigError,
TextCompletionRuntimeError,
} from "./common.ts";
import { import {
llmStreamPart, llmStreamPart,
makeTextCompletionLayer, makeTextCompletionLayer,
@ -26,8 +32,6 @@ import {
requiredString, requiredString,
streamTextCompletionChunks, streamTextCompletionChunks,
textFromContent, textFromContent,
type TextCompletionConfigError,
type TextCompletionRuntimeError,
} from "./common.ts"; } from "./common.ts";
export type MistralProcessorConfig = ProcessorConfig & { export type MistralProcessorConfig = ProcessorConfig & {

View file

@ -8,24 +8,28 @@
import { Ollama } from "ollama"; import { Ollama } from "ollama";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import type {
Llm,
LlmProvider,
ProcessorConfig,
LlmResult,
} from "@trustgraph/base";
import { import {
makeLlmService, makeLlmService,
makeFlowProcessorProgram, makeFlowProcessorProgram,
makeLlmSpecs, makeLlmSpecs,
type Llm,
type LlmProvider,
type ProcessorConfig,
type LlmResult,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { Effect, Stream } from "effect"; import { Effect, Stream } from "effect";
import type {
TextCompletionConfigError,
TextCompletionRuntimeError,
} from "./common.ts";
import { import {
llmStreamPart, llmStreamPart,
makeTextCompletionLayer, makeTextCompletionLayer,
optionalStringConfig, optionalStringConfig,
providerRuntimeError, providerRuntimeError,
streamTextCompletionChunks, streamTextCompletionChunks,
type TextCompletionConfigError,
type TextCompletionRuntimeError,
} from "./common.ts"; } from "./common.ts";
export type OllamaProcessorConfig = ProcessorConfig & { export type OllamaProcessorConfig = ProcessorConfig & {
@ -68,7 +72,7 @@ const makeOllamaProviderFromClient = (
_temperature?: number, _temperature?: number,
) => { ) => {
const modelName = model ?? defaultModel; const modelName = model ?? defaultModel;
const fullPrompt = system + "\n\n" + prompt; const fullPrompt = `${system}\n\n${prompt}`;
return Effect.tryPromise({ return Effect.tryPromise({
try: () => try: () =>
@ -95,7 +99,7 @@ const makeOllamaProviderFromClient = (
_temperature?: number, _temperature?: number,
) => { ) => {
const modelName = model ?? defaultModel; const modelName = model ?? defaultModel;
const fullPrompt = system + "\n\n" + prompt; const fullPrompt = `${system}\n\n${prompt}`;
return Stream.fromEffect( return Stream.fromEffect(
Effect.tryPromise({ Effect.tryPromise({

View file

@ -11,16 +11,22 @@
import OpenAI from "openai"; import OpenAI from "openai";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import type {
Llm,
LlmProvider,
ProcessorConfig,
LlmResult,
} from "@trustgraph/base";
import { import {
makeLlmService, makeLlmService,
makeFlowProcessorProgram, makeFlowProcessorProgram,
makeLlmSpecs, makeLlmSpecs,
type Llm,
type LlmProvider,
type ProcessorConfig,
type LlmResult,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { Effect, Stream } from "effect"; import { Effect, Stream } from "effect";
import type {
TextCompletionConfigError,
TextCompletionRuntimeError,
} from "./common.ts";
import { import {
llmStreamPart, llmStreamPart,
makeTextCompletionLayer, makeTextCompletionLayer,
@ -28,8 +34,6 @@ import {
providerStatusError, providerStatusError,
requiredString, requiredString,
streamTextCompletionChunks, streamTextCompletionChunks,
type TextCompletionConfigError,
type TextCompletionRuntimeError,
} from "./common.ts"; } from "./common.ts";
export type OpenAICompatibleProcessorConfig = ProcessorConfig & { export type OpenAICompatibleProcessorConfig = ProcessorConfig & {

View file

@ -6,16 +6,22 @@
import OpenAI from "openai"; import OpenAI from "openai";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import type {
Llm,
LlmProvider,
ProcessorConfig,
LlmResult,
} from "@trustgraph/base";
import { import {
makeLlmService, makeLlmService,
makeFlowProcessorProgram, makeFlowProcessorProgram,
makeLlmSpecs, makeLlmSpecs,
type Llm,
type LlmProvider,
type ProcessorConfig,
type LlmResult,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { Effect, Stream } from "effect"; import { Effect, Stream } from "effect";
import type {
TextCompletionConfigError,
TextCompletionRuntimeError,
} from "./common.ts";
import { import {
llmStreamPart, llmStreamPart,
makeTextCompletionLayer, makeTextCompletionLayer,
@ -23,8 +29,6 @@ import {
providerStatusError, providerStatusError,
requiredString, requiredString,
streamTextCompletionChunks, streamTextCompletionChunks,
type TextCompletionConfigError,
type TextCompletionRuntimeError,
} from "./common.ts"; } from "./common.ts";
export type OpenAIProcessorConfig = ProcessorConfig & { export type OpenAIProcessorConfig = ProcessorConfig & {

View file

@ -24,19 +24,21 @@
* Python reference: trustgraph-flow/trustgraph/prompt/template/service.py * Python reference: trustgraph-flow/trustgraph/prompt/template/service.py
*/ */
import type {
ProcessorConfig,
EffectConfigHandler,
FlowContext,
FlowProcessorRuntime,
FlowResourceNotFoundError,
MessagingDeliveryError,
PromptRequest,
PromptResponse,
Spec,
} from "@trustgraph/base";
import { import {
makeFlowProcessor, makeFlowProcessor,
makeConsumerSpec, makeConsumerSpec,
makeProducerSpec, makeProducerSpec,
type ProcessorConfig,
type EffectConfigHandler,
type FlowContext,
type FlowProcessorRuntime,
type FlowResourceNotFoundError,
type MessagingDeliveryError,
type PromptRequest,
type PromptResponse,
type Spec,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import { makeFlowProcessorProgram } from "@trustgraph/base"; import { makeFlowProcessorProgram } from "@trustgraph/base";

View file

@ -1,4 +1,5 @@
import { QdrantClient, type QdrantClientParams } from "@qdrant/js-client-rest"; import type { QdrantClientParams } from "@qdrant/js-client-rest";
import { QdrantClient, } from "@qdrant/js-client-rest";
import { errorMessage } from "@trustgraph/base"; import { errorMessage } from "@trustgraph/base";
import { Effect } from "effect"; import { Effect } from "effect";
import * as S from "effect/Schema"; import * as S from "effect/Schema";

View file

@ -7,30 +7,34 @@
* Python reference: trustgraph-flow/trustgraph/query/doc_embeddings/qdrant/service.py * Python reference: trustgraph-flow/trustgraph/query/doc_embeddings/qdrant/service.py
*/ */
import type {
ProcessorConfig,
FlowProcessorRuntime,
FlowProcessorStartEffect,
FlowContext,
FlowResourceNotFoundError,
MessagingDeliveryError,
DocumentEmbeddingsRequest,
DocumentEmbeddingsResponse,
Spec,
} from "@trustgraph/base";
import { import {
makeFlowProcessor, makeFlowProcessor,
makeConsumerSpec, makeConsumerSpec,
makeProducerSpec, makeProducerSpec,
processorLifecycleError, processorLifecycleError,
type ProcessorConfig,
type FlowProcessorRuntime,
type FlowProcessorStartEffect,
type FlowContext,
type FlowResourceNotFoundError,
type MessagingDeliveryError,
type DocumentEmbeddingsRequest,
type DocumentEmbeddingsResponse,
type Spec,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import { makeFlowProcessorProgram } from "@trustgraph/base"; import { makeFlowProcessorProgram } from "@trustgraph/base";
import { Effect } from "effect"; import { Effect } from "effect";
import type {
QdrantDocQueryConfig,
QdrantDocEmbeddingsQueryError,
} from "./qdrant-doc.js";
import { import {
QdrantDocEmbeddingsQueryLive, QdrantDocEmbeddingsQueryLive,
QdrantDocEmbeddingsQueryService, QdrantDocEmbeddingsQueryService,
makeQdrantDocEmbeddingsQueryServiceEffect, makeQdrantDocEmbeddingsQueryServiceEffect,
type QdrantDocQueryConfig,
type QdrantDocEmbeddingsQueryError,
} from "./qdrant-doc.js"; } from "./qdrant-doc.js";
const DocumentEmbeddingsResponseProducer = makeProducerSpec<DocumentEmbeddingsResponse>("document-embeddings-response"); const DocumentEmbeddingsResponseProducer = makeProducerSpec<DocumentEmbeddingsResponse>("document-embeddings-response");

View file

@ -11,7 +11,8 @@ import { errorMessage } from "@trustgraph/base";
import { Config, Context, Effect, Layer } from "effect"; import { Config, Context, Effect, Layer } from "effect";
import * as O from "effect/Option"; import * as O from "effect/Option";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import { makeQdrantClient, type QdrantClientFactory, type QdrantClientLike } from "../../qdrant/client.js"; import type { QdrantClientFactory, QdrantClientLike } from "../../qdrant/client.js";
import { makeQdrantClient, } from "../../qdrant/client.js";
export interface QdrantDocQueryConfig { export interface QdrantDocQueryConfig {
url?: string; url?: string;

View file

@ -7,30 +7,34 @@
* Python reference: trustgraph-flow/trustgraph/query/graph_embeddings/qdrant/service.py * Python reference: trustgraph-flow/trustgraph/query/graph_embeddings/qdrant/service.py
*/ */
import type {
ProcessorConfig,
FlowProcessorRuntime,
FlowProcessorStartEffect,
FlowContext,
FlowResourceNotFoundError,
MessagingDeliveryError,
GraphEmbeddingsRequest,
GraphEmbeddingsResponse,
Spec,
} from "@trustgraph/base";
import { import {
makeFlowProcessor, makeFlowProcessor,
makeConsumerSpec, makeConsumerSpec,
makeProducerSpec, makeProducerSpec,
processorLifecycleError, processorLifecycleError,
type ProcessorConfig,
type FlowProcessorRuntime,
type FlowProcessorStartEffect,
type FlowContext,
type FlowResourceNotFoundError,
type MessagingDeliveryError,
type GraphEmbeddingsRequest,
type GraphEmbeddingsResponse,
type Spec,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import { makeFlowProcessorProgram } from "@trustgraph/base"; import { makeFlowProcessorProgram } from "@trustgraph/base";
import { Effect } from "effect"; import { Effect } from "effect";
import type {
QdrantGraphQueryConfig,
QdrantGraphEmbeddingsQueryError,
} from "./qdrant-graph.js";
import { import {
QdrantGraphEmbeddingsQueryLive, QdrantGraphEmbeddingsQueryLive,
QdrantGraphEmbeddingsQueryService, QdrantGraphEmbeddingsQueryService,
makeQdrantGraphEmbeddingsQueryServiceEffect, makeQdrantGraphEmbeddingsQueryServiceEffect,
type QdrantGraphQueryConfig,
type QdrantGraphEmbeddingsQueryError,
} from "./qdrant-graph.js"; } from "./qdrant-graph.js";
const GraphEmbeddingsResponseProducer = makeProducerSpec<GraphEmbeddingsResponse>("graph-embeddings-response"); const GraphEmbeddingsResponseProducer = makeProducerSpec<GraphEmbeddingsResponse>("graph-embeddings-response");

View file

@ -10,11 +10,13 @@
* Python reference: trustgraph-flow/trustgraph/query/graph_embeddings/qdrant/service.py * Python reference: trustgraph-flow/trustgraph/query/graph_embeddings/qdrant/service.py
*/ */
import { errorMessage, type Term } from "@trustgraph/base"; import type { Term } from "@trustgraph/base";
import { errorMessage, } from "@trustgraph/base";
import { Config, Context, Effect, Layer } from "effect"; import { Config, Context, Effect, Layer } from "effect";
import * as O from "effect/Option"; import * as O from "effect/Option";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import { makeQdrantClient, type QdrantClientFactory, type QdrantClientLike } from "../../qdrant/client.js"; import type { QdrantClientFactory, QdrantClientLike } from "../../qdrant/client.js";
import { makeQdrantClient, } from "../../qdrant/client.js";
export interface QdrantGraphQueryConfig { export interface QdrantGraphQueryConfig {
url?: string; url?: string;

View file

@ -7,30 +7,34 @@
* Python reference: trustgraph-flow/trustgraph/query/triples/falkordb/service.py * Python reference: trustgraph-flow/trustgraph/query/triples/falkordb/service.py
*/ */
import type {
ProcessorConfig,
FlowProcessorRuntime,
FlowProcessorStartEffect,
FlowContext,
FlowResourceNotFoundError,
MessagingDeliveryError,
TriplesQueryRequest,
TriplesQueryResponse,
Spec,
} from "@trustgraph/base";
import { import {
makeFlowProcessor, makeFlowProcessor,
makeConsumerSpec, makeConsumerSpec,
makeProducerSpec, makeProducerSpec,
processorLifecycleError, processorLifecycleError,
type ProcessorConfig,
type FlowProcessorRuntime,
type FlowProcessorStartEffect,
type FlowContext,
type FlowResourceNotFoundError,
type MessagingDeliveryError,
type TriplesQueryRequest,
type TriplesQueryResponse,
type Spec,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import { makeFlowProcessorProgram } from "@trustgraph/base"; import { makeFlowProcessorProgram } from "@trustgraph/base";
import { Effect } from "effect"; import { Effect } from "effect";
import type {
FalkorDBQueryConfig,
FalkorDBTriplesQueryError,
} from "./falkordb.js";
import { import {
FalkorDBTriplesQueryLive, FalkorDBTriplesQueryLive,
FalkorDBTriplesQueryService, FalkorDBTriplesQueryService,
makeFalkorDBTriplesQueryServiceScoped, makeFalkorDBTriplesQueryServiceScoped,
type FalkorDBQueryConfig,
type FalkorDBTriplesQueryError,
} from "./falkordb.js"; } from "./falkordb.js";
const TriplesResponseProducer = makeProducerSpec<TriplesQueryResponse>("triples-response"); const TriplesResponseProducer = makeProducerSpec<TriplesQueryResponse>("triples-response");

View file

@ -7,7 +7,8 @@
*/ */
import { createClient, Graph } from "falkordb"; import { createClient, Graph } from "falkordb";
import { errorMessage, type Term, type Triple } from "@trustgraph/base"; import type { Term, Triple } from "@trustgraph/base";
import { errorMessage, } from "@trustgraph/base";
import { Config, Context, Effect, Layer, Match } from "effect"; import { Config, Context, Effect, Layer, Match } from "effect";
import * as Predicate from "effect/Predicate"; import * as Predicate from "effect/Predicate";
import * as S from "effect/Schema"; import * as S from "effect/Schema";

View file

@ -8,36 +8,40 @@
*/ */
import {NodeRuntime} from "@effect/platform-node"; import {NodeRuntime} from "@effect/platform-node";
import type {
DocumentEmbeddingsRequest,
DocumentEmbeddingsResponse,
DocumentRagRequest,
DocumentRagResponse,
EmbeddingsRequest,
EmbeddingsResponse,
FlowContext,
FlowProcessorRuntime,
FlowResourceNotFoundError,
MessagingDeliveryError,
ProcessorConfig,
PromptRequest,
PromptResponse,
Spec,
TextCompletionRequest,
TextCompletionResponse,
} from "@trustgraph/base";
import { import {
makeConsumerSpec, makeConsumerSpec,
makeFlowProcessor, makeFlowProcessor,
makeProducerSpec, makeProducerSpec,
makeRequestResponseSpec, makeRequestResponseSpec,
makeFlowProcessorProgram, makeFlowProcessorProgram,
type DocumentEmbeddingsRequest,
type DocumentEmbeddingsResponse,
type DocumentRagRequest,
type DocumentRagResponse,
type EmbeddingsRequest,
type EmbeddingsResponse,
type FlowContext,
type FlowProcessorRuntime,
type FlowResourceNotFoundError,
type MessagingDeliveryError,
type ProcessorConfig,
type PromptRequest,
type PromptResponse,
type Spec,
type TextCompletionRequest,
type TextCompletionResponse,
} from "@trustgraph/base"; } from "@trustgraph/base";
import {Effect} from "effect"; import {Effect} from "effect";
import type {
DocumentRagEngineError,
DocumentRagClients,
} from "./document-rag.js";
import { import {
DocumentRagEngine, DocumentRagEngine,
DocumentRagEngineError,
DocumentRagLive, DocumentRagLive,
makeDocumentRagEngine, makeDocumentRagEngine,
type DocumentRagClients,
} from "./document-rag.js"; } from "./document-rag.js";
const DocumentRagResponseProducer = makeProducerSpec<DocumentRagResponse>("document-rag-response"); const DocumentRagResponseProducer = makeProducerSpec<DocumentRagResponse>("document-rag-response");

View file

@ -8,39 +8,43 @@
*/ */
import {NodeRuntime} from "@effect/platform-node"; import {NodeRuntime} from "@effect/platform-node";
import type {
FlowContext,
FlowProcessorRuntime,
FlowResourceNotFoundError,
GraphEmbeddingsRequest,
GraphEmbeddingsResponse,
GraphRagRequest,
GraphRagResponse,
EmbeddingsRequest,
EmbeddingsResponse,
MessagingDeliveryError,
ProcessorConfig,
PromptRequest,
PromptResponse,
Spec,
TextCompletionRequest,
TextCompletionResponse,
TriplesQueryRequest,
TriplesQueryResponse,
} from "@trustgraph/base";
import { import {
makeConsumerSpec, makeConsumerSpec,
makeFlowProcessor, makeFlowProcessor,
makeProducerSpec, makeProducerSpec,
makeRequestResponseSpec, makeRequestResponseSpec,
makeFlowProcessorProgram, makeFlowProcessorProgram,
type FlowContext,
type FlowProcessorRuntime,
type FlowResourceNotFoundError,
type GraphEmbeddingsRequest,
type GraphEmbeddingsResponse,
type GraphRagRequest,
type GraphRagResponse,
type EmbeddingsRequest,
type EmbeddingsResponse,
type MessagingDeliveryError,
type ProcessorConfig,
type PromptRequest,
type PromptResponse,
type Spec,
type TextCompletionRequest,
type TextCompletionResponse,
type TriplesQueryRequest,
type TriplesQueryResponse,
} from "@trustgraph/base"; } from "@trustgraph/base";
import {Effect} from "effect"; import {Effect} from "effect";
import type {
GraphRagEngineError,
GraphRagClients,
GraphRagConfig,
} from "./graph-rag.js";
import { import {
GraphRagEngine, GraphRagEngine,
GraphRagEngineError,
GraphRagLive, GraphRagLive,
makeGraphRagEngine, makeGraphRagEngine,
type GraphRagClients,
type GraphRagConfig,
} from "./graph-rag.js"; } from "./graph-rag.js";
const GraphRagResponseProducer = makeProducerSpec<GraphRagResponse>("graph-rag-response"); const GraphRagResponseProducer = makeProducerSpec<GraphRagResponse>("graph-rag-response");

View file

@ -9,33 +9,37 @@
* Python reference: trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/service.py * Python reference: trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/service.py
*/ */
import type {
ProcessorConfig,
FlowProcessorRuntime,
FlowProcessorStartEffect,
FlowContext,
FlowResourceNotFoundError,
MessagingDeliveryError,
MessagingLifecycleError,
MessagingTimeoutError,
EntityContexts,
EmbeddingsRequest,
EmbeddingsResponse,
Spec,
} from "@trustgraph/base";
import { import {
makeFlowProcessor, makeFlowProcessor,
makeConsumerSpec, makeConsumerSpec,
makeRequestResponseSpec, makeRequestResponseSpec,
processorLifecycleError, processorLifecycleError,
type ProcessorConfig,
type FlowProcessorRuntime,
type FlowProcessorStartEffect,
type FlowContext,
type FlowResourceNotFoundError,
type MessagingDeliveryError,
type MessagingLifecycleError,
type MessagingTimeoutError,
type EntityContexts,
type EmbeddingsRequest,
type EmbeddingsResponse,
type Spec,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import { makeFlowProcessorProgram } from "@trustgraph/base"; import { makeFlowProcessorProgram } from "@trustgraph/base";
import { Effect } from "effect"; import { Effect } from "effect";
import type {
QdrantGraphEmbeddingsConfig,
QdrantGraphEmbeddingsStoreError,
} from "./qdrant-graph.js";
import { import {
QdrantGraphEmbeddingsStoreLive, QdrantGraphEmbeddingsStoreLive,
QdrantGraphEmbeddingsStoreService, QdrantGraphEmbeddingsStoreService,
makeQdrantGraphEmbeddingsStoreServiceEffect, makeQdrantGraphEmbeddingsStoreServiceEffect,
type QdrantGraphEmbeddingsConfig,
type QdrantGraphEmbeddingsStoreError,
} from "./qdrant-graph.js"; } from "./qdrant-graph.js";
type GraphEmbeddingsStoreRequirements = QdrantGraphEmbeddingsStoreService; type GraphEmbeddingsStoreRequirements = QdrantGraphEmbeddingsStoreService;

View file

@ -13,7 +13,8 @@ import { Config, Effect, Random } from "effect";
import * as MutableHashSet from "effect/MutableHashSet"; import * as MutableHashSet from "effect/MutableHashSet";
import * as O from "effect/Option"; import * as O from "effect/Option";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import { makeQdrantClient, type QdrantClientFactory, type QdrantClientLike } from "../../qdrant/client.js"; import type { QdrantClientFactory, QdrantClientLike } from "../../qdrant/client.js";
import { makeQdrantClient, } from "../../qdrant/client.js";
export interface QdrantDocEmbeddingsConfig { export interface QdrantDocEmbeddingsConfig {
url?: string; url?: string;

View file

@ -8,12 +8,14 @@
* Python reference: trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py * Python reference: trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py
*/ */
import { errorMessage, type Term } from "@trustgraph/base"; import type { Term } from "@trustgraph/base";
import { errorMessage, } from "@trustgraph/base";
import { Config, Context, Effect, Layer, Match, Random } from "effect"; import { Config, Context, Effect, Layer, Match, Random } from "effect";
import * as MutableHashSet from "effect/MutableHashSet"; import * as MutableHashSet from "effect/MutableHashSet";
import * as O from "effect/Option"; import * as O from "effect/Option";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import { makeQdrantClient, type QdrantClientFactory, type QdrantClientLike } from "../../qdrant/client.js"; import type { QdrantClientFactory, QdrantClientLike } from "../../qdrant/client.js";
import { makeQdrantClient, } from "../../qdrant/client.js";
export interface QdrantGraphEmbeddingsConfig { export interface QdrantGraphEmbeddingsConfig {
url?: string; url?: string;

View file

@ -8,26 +8,30 @@
* Python reference: trustgraph-flow/trustgraph/storage/triples/falkordb/service.py * Python reference: trustgraph-flow/trustgraph/storage/triples/falkordb/service.py
*/ */
import type {
ProcessorConfig,
FlowProcessorRuntime,
FlowProcessorStartEffect,
FlowContext,
Triples,
Spec,
} from "@trustgraph/base";
import { import {
makeFlowProcessor, makeFlowProcessor,
makeConsumerSpec, makeConsumerSpec,
processorLifecycleError, processorLifecycleError,
type ProcessorConfig,
type FlowProcessorRuntime,
type FlowProcessorStartEffect,
type FlowContext,
type Triples,
type Spec,
} from "@trustgraph/base"; } from "@trustgraph/base";
import { NodeRuntime } from "@effect/platform-node"; import { NodeRuntime } from "@effect/platform-node";
import { makeFlowProcessorProgram } from "@trustgraph/base"; import { makeFlowProcessorProgram } from "@trustgraph/base";
import { Effect } from "effect"; import { Effect } from "effect";
import type {
FalkorDBConfig,
FalkorDBTriplesStoreError,
} from "./falkordb.js";
import { import {
FalkorDBTriplesStoreLive, FalkorDBTriplesStoreLive,
FalkorDBTriplesStoreService, FalkorDBTriplesStoreService,
makeFalkorDBTriplesStoreServiceScoped, makeFalkorDBTriplesStoreServiceScoped,
type FalkorDBConfig,
type FalkorDBTriplesStoreError,
} from "./falkordb.js"; } from "./falkordb.js";
const onStoreTriplesMessage = Effect.fn("TriplesStoreService.onMessage")(function* ( const onStoreTriplesMessage = Effect.fn("TriplesStoreService.onMessage")(function* (

View file

@ -8,7 +8,8 @@
*/ */
import { createClient, Graph } from "falkordb"; import { createClient, Graph } from "falkordb";
import { errorMessage, type Term, type Triple } from "@trustgraph/base"; import type { Term, Triple } from "@trustgraph/base";
import { errorMessage, } from "@trustgraph/base";
import { Config, Context, Effect, Layer, Match } from "effect"; import { Config, Context, Effect, Layer, Match } from "effect";
import * as S from "effect/Schema"; import * as S from "effect/Schema";

View file

@ -8,7 +8,8 @@
"build": "bunx --bun tsc", "build": "bunx --bun tsc",
"dev": "tsc --watch", "dev": "tsc --watch",
"clean": "rm -rf dist", "clean": "rm -rf dist",
"test": "bunx --bun vitest run --passWithNoTests --exclude=dist/**" "test": "bunx --bun vitest run --passWithNoTests --exclude=dist/**",
"lint": "bunx --bun biome check src"
}, },
"dependencies": { "dependencies": {
"@trustgraph/base": "workspace:*", "@trustgraph/base": "workspace:*",

View file

@ -1,5 +1,6 @@
import { describe, expect, it } from "@effect/vitest"; import { describe, expect, it } from "@effect/vitest";
import { DispatchStreamChunk, type BaseApi, type TrustGraphGatewayClient } from "@trustgraph/client"; import type { BaseApi, TrustGraphGatewayClient } from "@trustgraph/client";
import { DispatchStreamChunk, } from "@trustgraph/client";
import { Effect, Layer, Stream } from "effect"; import { Effect, Layer, Stream } from "effect";
import * as S from "effect/Schema"; import * as S from "effect/Schema";
import { McpServer } from "effect/unstable/ai"; import { McpServer } from "effect/unstable/ai";
@ -226,7 +227,7 @@ const makeNativeTestClientEffect = Effect.fn("makeNativeTestClient")(function*(
const textContent = (result: McpSchema.CallToolResult): string => { const textContent = (result: McpSchema.CallToolResult): string => {
const [content] = result.content; const [content] = result.content;
expect(content?.type).toBe("text"); expect(content?.type).toBe("text");
return "text" in content! ? content.text : ""; return content !== undefined && "text" in content ? content.text : "";
}; };
describe("Effect MCP server", () => { describe("Effect MCP server", () => {

View file

@ -1,11 +1,13 @@
import {BunHttpServer, BunRuntime} from "@effect/platform-bun"; import {BunHttpServer, BunRuntime} from "@effect/platform-bun";
import {NodeRuntime, NodeStdio} from "@effect/platform-node"; import {NodeRuntime, NodeStdio} from "@effect/platform-node";
import type {
BaseApi,
Term as ClientTerm,
TrustGraphGatewayClient,
} from "@trustgraph/client";
import { import {
createTrustGraphSocket, createTrustGraphSocket,
makeTrustGraphGatewayClientScoped, makeTrustGraphGatewayClientScoped,
type BaseApi,
type Term as ClientTerm,
type TrustGraphGatewayClient,
} from "@trustgraph/client"; } from "@trustgraph/client";
import {Config, Context, Effect, Layer} from "effect"; import {Config, Context, Effect, Layer} from "effect";
import * as O from "effect/Option"; import * as O from "effect/Option";

View file

@ -7,7 +7,8 @@
"dev": "vite", "dev": "vite",
"build": "tsc && vite build", "build": "tsc && vite build",
"preview": "vite preview", "preview": "vite preview",
"qa:browser": "playwright test" "qa:browser": "playwright test",
"lint": "bunx --bun biome check src"
}, },
"dependencies": { "dependencies": {
"@effect/atom-react": "4.0.0-beta.78", "@effect/atom-react": "4.0.0-beta.78",

View file

@ -1,25 +1,29 @@
import { Clipboard as BrowserClipboard } from "@effect/platform-browser"; import { Clipboard as BrowserClipboard } from "@effect/platform-browser";
import * as BrowserHttpClient from "@effect/platform-browser/BrowserHttpClient"; import * as BrowserHttpClient from "@effect/platform-browser/BrowserHttpClient";
import * as BrowserKeyValueStore from "@effect/platform-browser/BrowserKeyValueStore"; import * as BrowserKeyValueStore from "@effect/platform-browser/BrowserKeyValueStore";
import type {
GraphRagOptions,
BaseApi,
BeginUploadResponse,
ChunkedUploadDocumentMetadata,
CompleteUploadResponse,
ConnectionState,
DocumentMetadata,
ExplainEvent,
StreamingMetadata,
Term,
Triple,
UploadChunkResponse,
} from "@trustgraph/client";
import { import {
DispatchPayload, DispatchPayload,
GatewayWorkbenchHttpApi, GatewayWorkbenchHttpApi,
type GraphRagOptions,
makeBaseApi, makeBaseApi,
TrustGraphRpcs, TrustGraphRpcs,
type BaseApi,
type BeginUploadResponse,
type ChunkedUploadDocumentMetadata,
type CompleteUploadResponse,
type ConnectionState,
type DocumentMetadata,
type ExplainEvent,
type StreamingMetadata,
type Term,
type Triple,
type UploadChunkResponse,
} from "@trustgraph/client"; } from "@trustgraph/client";
import { Cause, Clock, Context, Effect, Layer, Match, Metric, Option, Random, Schema as S, Scope, Stream } from "effect"; import type { Scope, } from "effect";
import { Cause, Clock, Context, Effect, Layer, Match, Metric, Option, Random, Schema as S, Stream } from "effect";
import * as A from "effect/Array";
import * as MutableHashMap from "effect/MutableHashMap"; import * as MutableHashMap from "effect/MutableHashMap";
import * as Predicate from "effect/Predicate"; import * as Predicate from "effect/Predicate";
import { HttpClient, HttpClientRequest } from "effect/unstable/http"; import { HttpClient, HttpClientRequest } from "effect/unstable/http";
@ -28,7 +32,7 @@ import * as RpcClient from "effect/unstable/rpc/RpcClient";
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization"; import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"; import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
import * as Atom from "effect/unstable/reactivity/Atom"; import * as Atom from "effect/unstable/reactivity/Atom";
import * as AtomRegistry from "effect/unstable/reactivity/AtomRegistry"; import type * as AtomRegistry from "effect/unstable/reactivity/AtomRegistry";
import * as AtomHttpApi from "effect/unstable/reactivity/AtomHttpApi"; import * as AtomHttpApi from "effect/unstable/reactivity/AtomHttpApi";
import * as AtomRpc from "effect/unstable/reactivity/AtomRpc"; import * as AtomRpc from "effect/unstable/reactivity/AtomRpc";
import * as Reactivity from "effect/unstable/reactivity/Reactivity"; import * as Reactivity from "effect/unstable/reactivity/Reactivity";
@ -1490,14 +1494,15 @@ function updateConversation(get: Atom.FnContext, f: (current: ConversationState)
} }
function updateLastMessage(get: Atom.FnContext, updater: (prev: ChatMessage) => ChatMessage): void { function updateLastMessage(get: Atom.FnContext, updater: (prev: ChatMessage) => ChatMessage): void {
updateConversation(get, (current) => { updateConversation(get, (current) =>
if (current.messages.length === 0) return current; A.matchRight(current.messages, {
const last = current.messages[current.messages.length - 1]!; onEmpty: () => current,
return { onNonEmpty: (init, last) => ({
...current, ...current,
messages: [...current.messages.slice(0, -1), updater(last)], messages: [...init, updater(last)],
}; }),
}); }),
);
} }
function refreshConfigAtoms(get: Atom.FnContext): void { function refreshConfigAtoms(get: Atom.FnContext): void {

View file

@ -9,11 +9,13 @@ import {
resultError, resultError,
resultLoading, resultLoading,
} from "@/atoms/workbench"; } from "@/atoms/workbench";
import type {
GraphNode,
GraphLink,
} from "@/lib/graph-utils";
import { import {
triplesToGraph, triplesToGraph,
localName, localName,
type GraphNode,
type GraphLink,
directedGraphLinkProps, directedGraphLinkProps,
DEFAULT_GRAPH_NODE_COLOR, DEFAULT_GRAPH_NODE_COLOR,
} from "@/lib/graph-utils"; } from "@/lib/graph-utils";

View file

@ -1,7 +1,9 @@
import type { ReactNode } from "react"; import type { ReactNode } from "react";
import type {
FallbackProps,
} from "react-error-boundary";
import { import {
ErrorBoundary as ReactErrorBoundary, ErrorBoundary as ReactErrorBoundary,
type FallbackProps,
} from "react-error-boundary"; } from "react-error-boundary";
import { AlertTriangle, RefreshCw } from "lucide-react"; import { AlertTriangle, RefreshCw } from "lucide-react";
import { Effect } from "effect"; import { Effect } from "effect";

View file

@ -1,7 +1,8 @@
import { useAtomSet, useAtomValue } from "@effect/atom-react"; import { useAtomSet, useAtomValue } from "@effect/atom-react";
import { X } from "lucide-react"; import { X } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { notificationsAtom, removeNotificationAtom, type Notification } from "@/atoms/workbench"; import type { Notification } from "@/atoms/workbench";
import { notificationsAtom, removeNotificationAtom, } from "@/atoms/workbench";
const typeStyles: Record<Notification["type"], string> = { const typeStyles: Record<Notification["type"], string> = {
success: "border-success/40 bg-success/10 text-success", success: "border-success/40 bg-success/10 text-success",

View file

@ -134,8 +134,8 @@
.animate-\[glow-drift-2_15s_ease-in-out_infinite\], .animate-\[glow-drift-2_15s_ease-in-out_infinite\],
.animate-\[glow-drift-3_25s_ease-in-out_infinite\], .animate-\[glow-drift-3_25s_ease-in-out_infinite\],
.animate-\[glow-fade-in_1\.2s_ease-out_forwards\] { .animate-\[glow-fade-in_1\.2s_ease-out_forwards\] {
animation: none !important; animation: none;
opacity: 0.7 !important; opacity: 0.7;
} }
} }

View file

@ -123,16 +123,18 @@ export function triplesToGraph(triples: Triple[]): {
const nodeMap = new Map<string, GraphNode>(); const nodeMap = new Map<string, GraphNode>();
const links: GraphLink[] = []; const links: GraphLink[] = [];
const ensureNode = (uri: string): void => { const ensureNode = (uri: string): GraphNode => {
if (!nodeMap.has(uri)) { const existing = nodeMap.get(uri);
const type = typeMap.get(uri); if (existing !== undefined) return existing;
nodeMap.set(uri, { const type = typeMap.get(uri);
id: uri, const node: GraphNode = {
label: labelMap.get(uri) ?? localName(uri), id: uri,
color: hashColor(type !== undefined ? localName(type) : uri), label: labelMap.get(uri) ?? localName(uri),
degree: 0, color: hashColor(type !== undefined ? localName(type) : uri),
}); degree: 0,
} };
nodeMap.set(uri, node);
return node;
}; };
for (const t of triples) { for (const t of triples) {
@ -151,10 +153,8 @@ export function triplesToGraph(triples: Triple[]): {
const oIsEntity = isIri(t.o) || t.o.t === "l"; const oIsEntity = isIri(t.o) || t.o.t === "l";
if (!sIsEntity || !oIsEntity) continue; if (!sIsEntity || !oIsEntity) continue;
ensureNode(sVal); ensureNode(sVal).degree++;
ensureNode(oVal); ensureNode(oVal).degree++;
nodeMap.get(sVal)!.degree++;
nodeMap.get(oVal)!.degree++;
links.push({ links.push({
source: sVal, source: sVal,

View file

@ -1,4 +1,5 @@
import { type ClassValue, clsx } from "clsx"; import type { ClassValue, } from "clsx";
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge"; import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) { export function cn(...inputs: ClassValue[]) {

View file

@ -13,7 +13,13 @@ function AppRoot() {
return <App />; return <App />;
} }
ReactDOM.createRoot(document.getElementById("root")!).render( const rootElement = document.getElementById("root");
if (rootElement === null) {
// Host boundary: the workbench cannot render without its mount point.
throw new Error("Workbench root element #root not found");
}
ReactDOM.createRoot(rootElement).render(
<React.StrictMode> <React.StrictMode>
<RegistryProvider defaultIdleTTL={1_000} initialValues={getWorkbenchQaInitialValues()}> <RegistryProvider defaultIdleTTL={1_000} initialValues={getWorkbenchQaInitialValues()}>
<AppRoot /> <AppRoot />

View file

@ -15,6 +15,9 @@ import {
} from "lucide-react"; } from "lucide-react";
import Markdown from "react-markdown"; import Markdown from "react-markdown";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import type {
ChatMessage,
} from "@/atoms/workbench";
import { import {
agentPhaseExpandedAtom, agentPhaseExpandedAtom,
cancelChatAtom, cancelChatAtom,
@ -27,7 +30,6 @@ import {
setConversationInputAtom, setConversationInputAtom,
settingsAtom, settingsAtom,
submitMessageAtom, submitMessageAtom,
type ChatMessage,
} from "@/atoms/workbench"; } from "@/atoms/workbench";
import { AutoTextarea } from "@/components/ui/textarea"; import { AutoTextarea } from "@/components/ui/textarea";
import { MessageActions } from "@/components/chat/message-actions"; import { MessageActions } from "@/components/chat/message-actions";

View file

@ -19,14 +19,16 @@ import {
settingsAtom, settingsAtom,
} from "@/atoms/workbench"; } from "@/atoms/workbench";
import type { Triple } from "@trustgraph/client"; import type { Triple } from "@trustgraph/client";
import type {
GraphNode,
GraphLink,
} from "@/lib/graph-utils";
import { import {
localName, localName,
triplesToGraph, triplesToGraph,
RDFS_LABEL, RDFS_LABEL,
RDF_TYPE, RDF_TYPE,
termValue, termValue,
type GraphNode,
type GraphLink,
directedGraphLinkProps, directedGraphLinkProps,
DEFAULT_GRAPH_NODE_COLOR, DEFAULT_GRAPH_NODE_COLOR,
} from "@/lib/graph-utils"; } from "@/lib/graph-utils";

Some files were not shown because too many files have changed in this diff Show more