summaryrefslogtreecommitdiffhomepage
path: root/packages/cli/src/render.test.ts
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-05 21:20:34 +0900
committerAdam Malczewski <[email protected]>2026-06-05 21:20:34 +0900
commit552c22d74e5df915088d9e9ff4a286c96c2a54d6 (patch)
tree7d9db1052bab91ef994446d80efc3bfc38026cad /packages/cli/src/render.test.ts
parent7fb3269c698ae583ea7997ce206c4ae252fd3218 (diff)
downloaddispatch-552c22d74e5df915088d9e9ff4a286c96c2a54d6.tar.gz
dispatch-552c22d74e5df915088d9e9ff4a286c96c2a54d6.zip
feat(cli): one-shot terminal client (models, chat, --text/--file/--cwd/--conversation)
HTTP client of transport-contract; pure-core arg/render/ndjson + injected fetch/fs shell. Docs: GLOSSARY (credential/key/model name/model catalog), tasks.md milestone, ORCHESTRATOR geography.
Diffstat (limited to 'packages/cli/src/render.test.ts')
-rw-r--r--packages/cli/src/render.test.ts147
1 files changed, 147 insertions, 0 deletions
diff --git a/packages/cli/src/render.test.ts b/packages/cli/src/render.test.ts
new file mode 100644
index 0000000..bfdb791
--- /dev/null
+++ b/packages/cli/src/render.test.ts
@@ -0,0 +1,147 @@
+import type { AgentEvent } from "@dispatch/transport-contract";
+import { describe, expect, it } from "vitest";
+import { renderEvent } from "./render.js";
+
+describe("renderEvent", () => {
+ const opts = { showReasoning: false };
+ const optsReasoning = { showReasoning: true };
+
+ it("renders text-delta as stdout", () => {
+ const e: AgentEvent = {
+ type: "text-delta",
+ conversationId: "c",
+ turnId: "t",
+ delta: "hello",
+ };
+ expect(renderEvent(e, opts)).toEqual({ stdout: "hello" });
+ });
+
+ it("hides reasoning-delta by default", () => {
+ const e: AgentEvent = {
+ type: "reasoning-delta",
+ conversationId: "c",
+ turnId: "t",
+ delta: "thinking...",
+ };
+ expect(renderEvent(e, opts)).toBeUndefined();
+ });
+
+ it("shows reasoning-delta when showReasoning is true", () => {
+ const e: AgentEvent = {
+ type: "reasoning-delta",
+ conversationId: "c",
+ turnId: "t",
+ delta: "thinking...",
+ };
+ expect(renderEvent(e, optsReasoning)).toEqual({ stdout: "thinking..." });
+ });
+
+ it("renders tool-call with name and JSON input", () => {
+ const e: AgentEvent = {
+ type: "tool-call",
+ conversationId: "c",
+ turnId: "t",
+ toolCallId: "tc1",
+ toolName: "read_file",
+ input: { path: "/foo" },
+ };
+ const result = renderEvent(e, opts);
+ expect(result?.stdout).toContain("[tool] read_file");
+ expect(result?.stdout).toContain('"/foo"');
+ });
+
+ it("renders tool-output data as stdout", () => {
+ const e: AgentEvent = {
+ type: "tool-output",
+ conversationId: "c",
+ turnId: "t",
+ toolCallId: "tc1",
+ data: "some output",
+ stream: "stdout",
+ };
+ expect(renderEvent(e, opts)).toEqual({ stdout: "some output" });
+ });
+
+ it("renders tool-result without error", () => {
+ const e: AgentEvent = {
+ type: "tool-result",
+ conversationId: "c",
+ turnId: "t",
+ toolCallId: "tc1",
+ toolName: "read_file",
+ content: "file contents",
+ isError: false,
+ };
+ expect(renderEvent(e, opts)).toEqual({
+ stdout: "[tool:read_file] file contents\n",
+ });
+ });
+
+ it("renders tool-result with error flag", () => {
+ const e: AgentEvent = {
+ type: "tool-result",
+ conversationId: "c",
+ turnId: "t",
+ toolCallId: "tc1",
+ toolName: "read_file",
+ content: "not found",
+ isError: true,
+ };
+ expect(renderEvent(e, opts)).toEqual({
+ stdout: "[tool:read_file] ERROR not found\n",
+ });
+ });
+
+ it("renders usage event", () => {
+ const e: AgentEvent = {
+ type: "usage",
+ conversationId: "c",
+ turnId: "t",
+ usage: { inputTokens: 100, outputTokens: 50 },
+ };
+ expect(renderEvent(e, opts)).toEqual({
+ stdout: "\n[usage] in=100 out=50\n",
+ });
+ });
+
+ it("renders error event to stderr", () => {
+ const e: AgentEvent = {
+ type: "error",
+ conversationId: "c",
+ turnId: "t",
+ message: "something went wrong",
+ };
+ expect(renderEvent(e, opts)).toEqual({
+ stderr: "[error] something went wrong\n",
+ });
+ });
+
+ it("returns undefined for status", () => {
+ const e: AgentEvent = {
+ type: "status",
+ conversationId: "c",
+ status: "running",
+ };
+ expect(renderEvent(e, opts)).toBeUndefined();
+ });
+
+ it("returns undefined for turn-start", () => {
+ const e: AgentEvent = { type: "turn-start", conversationId: "c", turnId: "t" };
+ expect(renderEvent(e, opts)).toBeUndefined();
+ });
+
+ it("returns undefined for turn-sealed", () => {
+ const e: AgentEvent = { type: "turn-sealed", conversationId: "c", turnId: "t" };
+ expect(renderEvent(e, opts)).toBeUndefined();
+ });
+
+ it("returns undefined for done", () => {
+ const e: AgentEvent = {
+ type: "done",
+ conversationId: "c",
+ turnId: "t",
+ reason: "completed",
+ };
+ expect(renderEvent(e, opts)).toBeUndefined();
+ });
+});