You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@texera.apache.org by gi...@apache.org on 2026/07/12 01:29:06 UTC
(texera) branch gh-readonly-queue/main/pr-6354-c7be51cca053faec17eaa786fd18b1d7253047ba created (now 85a56cbea1)
This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a change to branch gh-readonly-queue/main/pr-6354-c7be51cca053faec17eaa786fd18b1d7253047ba
in repository https://gitbox.apache.org/repos/asf/texera.git
at 85a56cbea1 test(agent-service): add unit test coverage for assembleContext (#6354)
This branch includes the following new commits:
new 85a56cbea1 test(agent-service): add unit test coverage for assembleContext (#6354)
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(texera) 01/01: test(agent-service): add unit test coverage for assembleContext (#6354)
Posted by gi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-6354-c7be51cca053faec17eaa786fd18b1d7253047ba
in repository https://gitbox.apache.org/repos/asf/texera.git
commit 85a56cbea19b2ad4a126bb61210e4f9d637bd61e
Author: Meng Wang <me...@uci.edu>
AuthorDate: Sat Jul 11 18:28:43 2026 -0700
test(agent-service): add unit test coverage for assembleContext (#6354)
### What changes were proposed in this PR?
Add unit test coverage for `assembleContext` in
`agent-service/src/agent/util/context-utils.ts` — a pure function
(type-only imports, no network) that groups `ReActStep`s by task,
serializes completed vs ongoing tasks into markdown sections, appends a
dataflow section, and returns `[{ role: "user", content }]`. A `bun
test` `.spec.ts` sits next to the source. No production-code changes.
### Any related issues, documentation, discussions?
Closes #6333.
### How was this PR tested?
```
bun test src/agent/util/context-utils.spec.ts
```
5 pass. `bun run typecheck` and `bun run format:check` are clean. The
spec is pure — it builds `ReActStep` / `WorkflowState` /
`OperatorPredicate` fixtures in-process and covers: empty steps → a
single user message with no task sections; a completed task under `#
Completed Tasks` (`## Task (completed)` with the request + turns); an
unfinished task under `# Ongoing Task`; a `# Current Dataflow` section
when the workflow has operators; and steps sharing a `messageId` grouped
into one task.
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 4.8 [1M context])
---------
Signed-off-by: Meng Wang <me...@uci.edu>
Co-authored-by: Copilot Autofix powered by AI <17...@users.noreply.github.com>
---
agent-service/src/agent/util/context-utils.spec.ts | 103 +++++++++++++++++++++
1 file changed, 103 insertions(+)
diff --git a/agent-service/src/agent/util/context-utils.spec.ts b/agent-service/src/agent/util/context-utils.spec.ts
new file mode 100644
index 0000000000..84af9df3bb
--- /dev/null
+++ b/agent-service/src/agent/util/context-utils.spec.ts
@@ -0,0 +1,103 @@
+/**
+ * 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 { ModelMessage } from "ai";
+import { assembleContext } from "./context-utils";
+import { WorkflowState } from "../workflow-state";
+import type { ReActStep } from "../../types/agent";
+import type { OperatorPredicate } from "../../types/workflow";
+
+function step(messageId: string, role: "user" | "agent", stepId: number, content: string, isEnd: boolean): ReActStep {
+ return {
+ id: `${messageId}-${stepId}`,
+ messageId,
+ stepId,
+ timestamp: 0,
+ role,
+ content,
+ isBegin: true,
+ isEnd,
+ };
+}
+
+function makeOperator(id: string): OperatorPredicate {
+ return {
+ operatorID: id,
+ operatorType: "TestOp",
+ operatorVersion: "1.0",
+ operatorProperties: {},
+ inputPorts: [],
+ outputPorts: [],
+ showAdvanced: false,
+ };
+}
+
+// assembleContext always returns a single user message whose content is a joined string.
+function contentOf(result: ModelMessage[]): string {
+ expect(result).toHaveLength(1);
+ expect(result[0].role).toBe("user");
+ expect(typeof result[0].content).toBe("string");
+ return result[0].content as string;
+}
+
+describe("assembleContext", () => {
+ test("returns a single user message with no task sections for empty steps", () => {
+ const result = assembleContext([], new WorkflowState(), new Map());
+ expect(result).toHaveLength(1);
+ expect(result[0].role).toBe("user");
+ expect(contentOf(result)).toBe("");
+ });
+
+ test("renders a completed task under a Completed Tasks heading", () => {
+ const steps = [step("m1", "user", 0, "do X", true), step("m1", "agent", 1, "thinking", true)];
+ const content = contentOf(assembleContext(steps, new WorkflowState(), new Map()));
+ expect(content).toContain("# Completed Tasks");
+ expect(content).toContain("## Task (completed)");
+ expect(content).toContain("do X"); // the user request
+ expect(content).toContain("### Turn 1"); // the agent step
+ });
+
+ test("renders an unfinished task under an Ongoing Task heading", () => {
+ const steps = [step("m1", "user", 0, "do Y", true), step("m1", "agent", 1, "working", false)];
+ const content = contentOf(assembleContext(steps, new WorkflowState(), new Map()));
+ expect(content).toContain("# Ongoing Task");
+ expect(content).toContain("## Task (ongoing)");
+ });
+
+ test("appends a Current Dataflow section when the workflow has operators", () => {
+ const workflowState = new WorkflowState();
+ workflowState.addOperator(makeOperator("op1"));
+ const content = contentOf(assembleContext([], workflowState, new Map()));
+ expect(content).toContain("# Current Dataflow");
+ expect(content).toContain("## Operators");
+ });
+
+ test("groups steps sharing a messageId into a single task", () => {
+ const steps = [
+ step("m1", "user", 0, "req", true),
+ step("m1", "agent", 1, "turn one", false),
+ step("m1", "agent", 2, "turn two", true),
+ ];
+ const content = contentOf(assembleContext(steps, new WorkflowState(), new Map()));
+ expect((content.match(/## Task/g) ?? []).length).toBe(1);
+ expect(content).toContain("### Turn 1");
+ expect(content).toContain("### Turn 2");
+ });
+});