fix: resolve FlowProcessor topic collisions, librarian timeout, tests

Fix critical bug where all FlowProcessor services shared the same spec
names ("request"/"response"), causing them to steal each other's NATS
topics. Now each service uses unique spec names matching the flow config
topic keys (e.g., "text-completion-request", "prompt-request",
"agent-request").

Fix librarian NATS consumer timeout (500ms → 2000ms, below NATS minimum).

Update seed-config and test-pipeline with correct flow topic mappings.
Add prompt template runner script.

Smoke test results: 11/11 passing (config CRUD, WebSocket, LLM,
librarian CRUD). Agent routing verified via manual curl test.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
elpresidank 2026-04-06 01:02:10 -05:00
parent 515fc0c264
commit 25d4227cb5
8 changed files with 147 additions and 98 deletions

View file

@ -47,11 +47,11 @@ export class AgentService extends FlowProcessor {
// Consumer: agent requests
this.registerSpecification(
new ConsumerSpec<AgentRequest>("request", this.onRequest.bind(this)),
new ConsumerSpec<AgentRequest>("agent-request", this.onRequest.bind(this)),
);
// Producer: agent responses (streaming chunks)
this.registerSpecification(new ProducerSpec<AgentResponse>("response"));
this.registerSpecification(new ProducerSpec<AgentResponse>("agent-response"));
// Request-response clients for tool execution
this.registerSpecification(
@ -94,7 +94,7 @@ export class AgentService extends FlowProcessor {
const requestId = properties.id;
if (!requestId) return;
const responseProducer = flowCtx.flow.producer<AgentResponse>("response");
const responseProducer = flowCtx.flow.producer<AgentResponse>("agent-response");
try {
// Build tools from flow requestors

View file

@ -83,14 +83,14 @@ export class LibrarianService extends AsyncProcessor {
while (this.running) {
try {
// Poll librarian requests
const libMsg = await this.libConsumer.receive(500);
const libMsg = await this.libConsumer.receive(2000);
if (libMsg) {
await this.handleLibrarianMessage(libMsg);
await this.libConsumer.acknowledge(libMsg);
}
// Poll collection management requests
const colMsg = await this.colConsumer.receive(500);
const colMsg = await this.colConsumer.receive(2000);
if (colMsg) {
await this.handleCollectionMessage(colMsg);
await this.colConsumer.acknowledge(colMsg);

View file

@ -54,11 +54,11 @@ export class PromptTemplateService extends FlowProcessor {
this.registerSpecification(
new ConsumerSpec<PromptRequest>(
"request",
"prompt-request",
this.onRequest.bind(this),
),
);
this.registerSpecification(new ProducerSpec<PromptResponse>("response"));
this.registerSpecification(new ProducerSpec<PromptResponse>("prompt-response"));
this.registerConfigHandler(this.onPromptConfig.bind(this));
@ -106,7 +106,7 @@ export class PromptTemplateService extends FlowProcessor {
const requestId = properties.id;
if (!requestId) return;
const responseProducer = flowCtx.flow.producer<PromptResponse>("response");
const responseProducer = flowCtx.flow.producer<PromptResponse>("prompt-response");
try {
const template = this.templates.get(msg.name);