This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git

commit 050c226a6e9c605c1a9c6ae8adae9920af053def
Author: Xinyuan Lin <[email protected]>
AuthorDate: Fri Jul 31 22:34:44 2026 -0700

    test(agent-service): cover prompt composition (#7190)
    
    ### What changes were proposed in this PR?
    
    Adds isolated unit coverage for agent system-prompt composition from
    workflow metadata. The tests exercise allowlist filtering,
    language-specific UDF guidance, the default all-operator path, and the
    missing-operator fallback.
    
    ### Any related issues, documentation, discussions?
    
    Closes #7187
    
    ### How was this PR tested?
    
    - `bun test src/agent/prompts.spec.ts` — 4 passed.
    - `bun run typecheck`
    - `bunx prettier --check "src/**/*.{ts,js,json}"`
    
    Mutation proof (each production change was reverted):
    
    | Production mutation | Focused test result |
    | --- | --- |
    | Inverted non-empty allowlist selection | 3 failed |
    | Omitted operator descriptions | 1 failed |
    | Changed the no-operators fallback message | 1 failed |
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Generated-by: Codex (GPT-5)
    
    ---------
    
    Signed-off-by: Xinyuan Lin <[email protected]>
    Co-authored-by: Copilot Autofix powered by AI 
<[email protected]>
---
 agent-service/src/agent/prompts.spec.ts | 99 +++++++++++++++++++++++++++++++++
 1 file changed, 99 insertions(+)

diff --git a/agent-service/src/agent/prompts.spec.ts 
b/agent-service/src/agent/prompts.spec.ts
new file mode 100644
index 0000000000..d4ae6e2151
--- /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).toMatch(/"condition":\s*\{\s*"type":\s*"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");
+  });
+});

Reply via email to