mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-08-22 22:32:17 +10:00
feat(agent): omit resume documents from the copied conversation json
This commit is contained in:
@@ -5,7 +5,7 @@ import { fireEvent, render, screen, within } from "@testing-library/react";
|
||||
import { beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import { i18n } from "@lingui/core";
|
||||
import { I18nProvider } from "@lingui/react";
|
||||
import { AskUserQuestion, AssistantMarkdown } from "./agent-chat";
|
||||
import { AskUserQuestion, AssistantMarkdown, withoutResumeDataForExport } from "./agent-chat";
|
||||
|
||||
describe("AssistantMarkdown", () => {
|
||||
it("renders GitHub-style pipe tables as tables", () => {
|
||||
@@ -27,6 +27,47 @@ describe("AssistantMarkdown", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("withoutResumeDataForExport", () => {
|
||||
it("strips the resume document from tool outputs but keeps everything else", () => {
|
||||
const messages = [
|
||||
{
|
||||
id: "m1",
|
||||
role: "assistant",
|
||||
parts: [
|
||||
{
|
||||
type: "tool-read_resume",
|
||||
toolCallId: "c1",
|
||||
state: "output-available",
|
||||
input: {},
|
||||
output: { id: "r1", updatedAt: "2026-08-20T00:00:00.000Z", data: { basics: { name: "John" } } },
|
||||
},
|
||||
{
|
||||
type: "tool-apply_resume_patch",
|
||||
toolCallId: "c2",
|
||||
state: "output-available",
|
||||
input: { title: "Edit" },
|
||||
output: { actionId: "a1", changedPaths: ["/basics/name"], resume: { basics: { name: "John" } } },
|
||||
},
|
||||
{ type: "text", text: "Done." },
|
||||
],
|
||||
},
|
||||
] as unknown as UIMessage[];
|
||||
|
||||
const exported = withoutResumeDataForExport(messages);
|
||||
|
||||
const exportedParts = (exported[0]?.parts ?? []) as Array<{ output?: Record<string, unknown> }>;
|
||||
expect(exportedParts[0]?.output?.data).toBe("[resume data omitted]");
|
||||
expect(exportedParts[0]?.output?.updatedAt).toBe("2026-08-20T00:00:00.000Z");
|
||||
expect(exportedParts[1]?.output?.resume).toBe("[resume data omitted]");
|
||||
expect(exportedParts[1]?.output?.changedPaths).toEqual(["/basics/name"]);
|
||||
expect(exported[0]?.parts[2]).toEqual({ type: "text", text: "Done." });
|
||||
|
||||
// The live chat state is never mutated — only the copied structure is redacted.
|
||||
const originalParts = (messages[0]?.parts ?? []) as Array<{ output?: Record<string, unknown> }>;
|
||||
expect(originalParts[0]?.output?.data).toEqual({ basics: { name: "John" } });
|
||||
});
|
||||
});
|
||||
|
||||
const questionPart = {
|
||||
type: "tool-ask_user_question",
|
||||
toolCallId: "call-1",
|
||||
|
||||
@@ -200,6 +200,33 @@ type AgentChatComposerProps = {
|
||||
|
||||
const ANSWER_FIELD = "answer";
|
||||
|
||||
const OMITTED_RESUME_DATA = "[resume data omitted]";
|
||||
|
||||
// "Copy JSON" is for sharing/debugging a conversation; the full resume document embedded in every
|
||||
// read_resume result (`output.data`) and fresh-document patch result (`output.resume`) would make
|
||||
// the export enormous and repetitive. Strip those two payloads; everything else copies verbatim.
|
||||
export function withoutResumeDataForExport(messages: UIMessage[]): UIMessage[] {
|
||||
return messages.map((message) => ({
|
||||
...message,
|
||||
parts: message.parts.map((part) => {
|
||||
if (part.type !== "tool-read_resume" && part.type !== "tool-apply_resume_patch") return part;
|
||||
|
||||
const output = "output" in part && typeof part.output === "object" && part.output ? part.output : null;
|
||||
if (!output) return part;
|
||||
const outputRecord = output as Record<string, unknown>;
|
||||
|
||||
if (part.type === "tool-read_resume" && "data" in outputRecord) {
|
||||
return { ...part, output: { ...outputRecord, data: OMITTED_RESUME_DATA } } as UIMessage["parts"][number];
|
||||
}
|
||||
if (part.type === "tool-apply_resume_patch" && "resume" in outputRecord) {
|
||||
return { ...part, output: { ...outputRecord, resume: OMITTED_RESUME_DATA } } as UIMessage["parts"][number];
|
||||
}
|
||||
|
||||
return part;
|
||||
}),
|
||||
}));
|
||||
}
|
||||
|
||||
function toRecord(value: unknown) {
|
||||
return typeof value === "object" && value !== null ? (value as Record<string, unknown>) : null;
|
||||
}
|
||||
@@ -994,7 +1021,7 @@ export function AgentChat({
|
||||
chatStatus: status,
|
||||
isReadOnly,
|
||||
readOnlyReason,
|
||||
messages,
|
||||
messages: withoutResumeDataForExport(messages),
|
||||
actions,
|
||||
},
|
||||
null,
|
||||
|
||||
Reference in New Issue
Block a user