From 5776171d278d5f7fd5fb92fe41b3f49ca79b18a3 Mon Sep 17 00:00:00 2001 From: elpresidank Date: Sat, 30 May 2026 09:56:23 -0500 Subject: [PATCH] saving --- ts/package.json | 1 + ts/packages/flow/src/flow-manager/service.ts | 3 + ts/packages/workbench/Containerfile | 9 +- ts/scripts/seed-flows.ts | 157 +++++++++++++++++++ 4 files changed, 165 insertions(+), 5 deletions(-) create mode 100644 ts/scripts/seed-flows.ts diff --git a/ts/package.json b/ts/package.json index 68859da8..16d60f16 100644 --- a/ts/package.json +++ b/ts/package.json @@ -15,6 +15,7 @@ "llm:openai": "bun scripts/run-llm-openai.ts", "test:pipeline": "bun scripts/test-pipeline.ts", "seed": "bun scripts/seed-config.ts", + "seed:flows": "bun scripts/seed-flows.ts", "prompt": "bun scripts/run-prompt.ts", "agent": "bun scripts/run-agent.ts", "librarian": "bun scripts/run-librarian.ts", diff --git a/ts/packages/flow/src/flow-manager/service.ts b/ts/packages/flow/src/flow-manager/service.ts index 6b7c83d7..2388c978 100644 --- a/ts/packages/flow/src/flow-manager/service.ts +++ b/ts/packages/flow/src/flow-manager/service.ts @@ -92,6 +92,9 @@ const DEFAULT_BLUEPRINT: Blueprint = { // Librarian RPC (for PDF decoder) "librarian-request": "tg.flow.librarian-request", "librarian-response": "tg.flow.librarian-response", + // MCP tool invocation + "mcp-tool-request": "tg.flow.mcp-tool-request", + "mcp-tool-response": "tg.flow.mcp-tool-response", }, }; diff --git a/ts/packages/workbench/Containerfile b/ts/packages/workbench/Containerfile index d31ed69a..4619ee78 100644 --- a/ts/packages/workbench/Containerfile +++ b/ts/packages/workbench/Containerfile @@ -3,11 +3,10 @@ # --------------------------------------------------------------------------- # Stage 1: Build # --------------------------------------------------------------------------- -FROM node:22-slim AS builder -RUN corepack enable && corepack prepare pnpm@9.15.0 --activate +FROM oven/bun:1.3.13-slim AS builder WORKDIR /app -COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json tsconfig.base.json tsconfig.json ./ +COPY package.json bun.lock pnpm-workspace.yaml turbo.json tsconfig.base.json tsconfig.json ./ COPY packages/base/package.json packages/base/tsconfig.json packages/base/ COPY packages/client/package.json packages/client/tsconfig.json packages/client/ COPY packages/flow/package.json packages/flow/tsconfig.json packages/flow/ @@ -15,10 +14,10 @@ COPY packages/cli/package.json packages/cli/tsconfig.json packages/cli/ COPY packages/mcp/package.json packages/mcp/tsconfig.json packages/mcp/ COPY packages/workbench/package.json packages/workbench/tsconfig.json packages/workbench/vite.config.ts packages/workbench/ -RUN pnpm install --frozen-lockfile +RUN bun install --frozen-lockfile COPY packages/ packages/ -RUN pnpm build --filter=@trustgraph/workbench +RUN bunx --bun turbo build --filter=@trustgraph/workbench # --------------------------------------------------------------------------- # Stage 2: Serve diff --git a/ts/scripts/seed-flows.ts b/ts/scripts/seed-flows.ts new file mode 100644 index 00000000..743d4680 --- /dev/null +++ b/ts/scripts/seed-flows.ts @@ -0,0 +1,157 @@ +/** + * Seed flow-manager flow instances for demos. + * + * Usage: bun run seed:flows + * Requires: gateway + flow-manager + config service running + */ + +const GATEWAY_URL = process.env.GATEWAY_URL ?? "http://localhost:8088"; + +const FLOW_TOPICS = { + // Document processing pipeline + "decode-input": "tg.flow.document", + "decode-output": "tg.flow.text-document", + "decode-triples": "tg.flow.triples", + "chunk-input": "tg.flow.text-document", + "chunk-output": "tg.flow.chunk", + "chunk-triples": "tg.flow.triples", + "extract-input": "tg.flow.chunk", + "extract-triples": "tg.flow.triples", + "extract-entity-contexts": "tg.flow.entity-contexts", + // Storage consumers + "store-triples-input": "tg.flow.triples", + "store-graph-embeddings-input": "tg.flow.entity-contexts", + // LLM text completion + "text-completion-request": "tg.flow.text-completion-request", + "text-completion-response": "tg.flow.text-completion-response", + // Prompt service + "prompt-request": "tg.flow.prompt-request", + "prompt-response": "tg.flow.prompt-response", + // Graph RAG + "graph-rag-request": "tg.flow.graph-rag-request", + "graph-rag-response": "tg.flow.graph-rag-response", + // Document RAG + "document-rag-request": "tg.flow.document-rag-request", + "document-rag-response": "tg.flow.document-rag-response", + // Triples query + "triples-request": "tg.flow.triples-request", + "triples-response": "tg.flow.triples-response", + // Agent + "agent-request": "tg.flow.agent-request", + "agent-response": "tg.flow.agent-response", + // Embeddings + "embeddings-request": "tg.flow.embeddings-request", + "embeddings-response": "tg.flow.embeddings-response", + // Graph embeddings query + "graph-embeddings-request": "tg.flow.graph-embeddings-request", + "graph-embeddings-response": "tg.flow.graph-embeddings-response", + // Document embeddings query + "document-embeddings-request": "tg.flow.document-embeddings-request", + "document-embeddings-response": "tg.flow.document-embeddings-response", + // Librarian RPC (for PDF decoder) + "librarian-request": "tg.flow.librarian-request", + "librarian-response": "tg.flow.librarian-response", + // MCP tool invocation + "mcp-tool-request": "tg.flow.mcp-tool-request", + "mcp-tool-response": "tg.flow.mcp-tool-response", +} as const; + +const SEEDED_FLOWS = [ + { + id: "default", + description: "Full-stack default pipeline for ingestion, RAG, and agent demos.", + }, + { + id: "beep-hole", + description: "Workbench sandbox flow for ad hoc experiments.", + }, + { + id: "ai-graph-demo", + description: "Graph RAG over the seeded AI industry knowledge graph.", + }, + { + id: "doc-rag-demo", + description: "Document RAG over the seeded demo document chunks.", + }, + { + id: "agent-demo", + description: "Agent flow wired to seeded knowledge and document tools.", + }, +] as const; + +async function postJson(path: string, body: Record): Promise { + const res = await fetch(`${GATEWAY_URL}${path}`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(body), + }); + const data = await res.json() as T & { error?: { message?: string } }; + if (!res.ok) { + throw new Error(`HTTP ${res.status}: ${JSON.stringify(data)}`); + } + if (data.error !== undefined) { + throw new Error(data.error.message ?? JSON.stringify(data.error)); + } + return data; +} + +async function listFlows(): Promise> { + const response = await postJson<{ "flow-ids"?: string[] }>("/api/v1/flow", { + operation: "list-flows", + }); + return new Set(response["flow-ids"] ?? []); +} + +async function startMissingFlows(existing: Set): Promise { + for (const flow of SEEDED_FLOWS) { + if (existing.has(flow.id)) { + console.log(` Flow ${flow.id}: already running`); + continue; + } + + await postJson("/api/v1/flow", { + operation: "start-flow", + "flow-id": flow.id, + "blueprint-name": "default", + description: flow.description, + parameters: { + user: "default", + collection: "default", + }, + }); + existing.add(flow.id); + console.log(` Flow ${flow.id}: started`); + } +} + +async function ensureFlowConfig(): Promise { + const values = Object.fromEntries( + SEEDED_FLOWS.map((flow) => [flow.id, { topics: FLOW_TOPICS }]), + ); + + const response = await postJson<{ version?: number }>("/api/v1/config", { + operation: "put", + keys: ["flows"], + values, + }); + console.log(` Flow config topics pushed -> version ${response.version ?? "unknown"}`); +} + +async function main(): Promise { + console.log("Seeding TrustGraph flows...\n"); + + const existing = await listFlows(); + await startMissingFlows(existing); + + console.log("\nAligning flow config topics..."); + await ensureFlowConfig(); + + const finalFlows = [...(await listFlows())].sort(); + console.log(`\nActive flows: ${finalFlows.join(", ")}`); + console.log("\nFlow seeding complete."); +} + +main().catch((err) => { + console.error("Seed flows failed:", err); + process.exit(1); +});