From 66afe8dbf6cbc0dda96ad43479bf015de1adecb6 Mon Sep 17 00:00:00 2001 From: Xinyuan Lin Date: Fri, 31 Jul 2026 16:50:11 -0700 Subject: [PATCH 1/2] test(agent-service): cover prompt composition --- agent-service/src/agent/prompts.spec.ts | 99 +++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 agent-service/src/agent/prompts.spec.ts diff --git a/agent-service/src/agent/prompts.spec.ts b/agent-service/src/agent/prompts.spec.ts new file mode 100644 index 00000000000..edf4548d4ca --- /dev/null +++ b/agent-service/src/agent/prompts.spec.ts @@ -0,0 +1,99 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { describe, expect, test } from "bun:test"; +import type { OperatorSchema } from "../api/backend-api"; +import { buildSystemPrompt } from "./prompts"; +import { WorkflowSystemMetadata } from "./util/workflow-system-metadata"; + +function makeOperatorSchema(operatorType: string, description: string): OperatorSchema { + return { + operatorType, + operatorVersion: "1.0", + jsonSchema: { + properties: { + condition: { type: "string" }, + }, + required: ["condition"], + }, + additionalMetadata: { + userFriendlyName: operatorType, + operatorGroupName: "Test", + operatorDescription: description, + inputPorts: [], + outputPorts: [], + }, + }; +} + +function makeMetadataStore(): WorkflowSystemMetadata { + const metadataStore = new WorkflowSystemMetadata(); + metadataStore.loadFromMetadata({ + operators: [ + makeOperatorSchema("Filter", "Keeps rows that match a condition."), + makeOperatorSchema("PythonUDFV2", "Runs user-defined Python code."), + makeOperatorSchema("RUDF", "Runs user-defined R code."), + ], + groups: [], + }); + return metadataStore; +} + +describe("buildSystemPrompt", () => { + test("renders only explicitly allowed operators with their descriptions and compact schemas", () => { + const prompt = buildSystemPrompt(makeMetadataStore(), ["Filter"]); + + expect(prompt).toContain("## Filter"); + expect(prompt).toContain("Description: Keeps rows that match a condition."); + expect(prompt).toContain('"condition": {\n "type": "string"'); + expect(prompt).not.toContain("## PythonUDFV2"); + expect(prompt).not.toContain("## RUDF"); + expect(prompt).not.toContain("## Python UDF Guide"); + expect(prompt).not.toContain("## R UDF Guide"); + }); + + test("adds guidance only for the UDF language in a restricted allowlist", () => { + const metadataStore = makeMetadataStore(); + const pythonPrompt = buildSystemPrompt(metadataStore, ["PythonUDFV2"]); + const rPrompt = buildSystemPrompt(metadataStore, ["RUDF"]); + + expect(pythonPrompt).toContain("## Python UDF Guide"); + expect(pythonPrompt).not.toContain("## R UDF Guide"); + expect(rPrompt).toContain("## R UDF Guide"); + expect(rPrompt).not.toContain("## Python UDF Guide"); + }); + + test("uses all metadata operators and both UDF guides when no allowlist is supplied", () => { + const prompt = buildSystemPrompt(makeMetadataStore()); + + expect(prompt).toContain("## Filter"); + expect(prompt).toContain("## PythonUDFV2"); + expect(prompt).toContain("## RUDF"); + expect(prompt).toContain("## Python UDF Guide"); + expect(prompt).toContain("## R UDF Guide"); + }); + + test("reports that no operators are available when a restricted type is absent from metadata", () => { + const prompt = buildSystemPrompt(makeMetadataStore(), ["MissingOperator"]); + + expect(prompt).toContain("No operators available."); + expect(prompt).not.toContain("## Python UDF Guide"); + expect(prompt).not.toContain("## R UDF Guide"); + }); +}); From 409515215f2aab0333ec4581d973fd71f58c2483 Mon Sep 17 00:00:00 2001 From: Xinyuan Lin Date: Fri, 31 Jul 2026 22:33:15 -0700 Subject: [PATCH 2/2] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Xinyuan Lin --- agent-service/src/agent/prompts.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent-service/src/agent/prompts.spec.ts b/agent-service/src/agent/prompts.spec.ts index edf4548d4ca..d4ae6e21516 100644 --- a/agent-service/src/agent/prompts.spec.ts +++ b/agent-service/src/agent/prompts.spec.ts @@ -61,7 +61,7 @@ describe("buildSystemPrompt", () => { expect(prompt).toContain("## Filter"); expect(prompt).toContain("Description: Keeps rows that match a condition."); - expect(prompt).toContain('"condition": {\n "type": "string"'); + expect(prompt).toMatch(/"condition":\s*\{\s*"type":\s*"string"/); expect(prompt).not.toContain("## PythonUDFV2"); expect(prompt).not.toContain("## RUDF"); expect(prompt).not.toContain("## Python UDF Guide");