mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-16 02:40:39 +09:00
- Plugin loader: install/reload/remove/reinstall external adapters from npm packages or local directories - Plugin store persisted at ~/.paperclip/adapter-plugins.json - Self-healing UI parser resolution with version caching - UI: Adapter Manager page, dynamic loader, display registry with humanized names for unknown adapter types - Dev watch: exclude adapter-plugins dir from tsx watcher to prevent mid-request server restarts during reinstall - All consumer fallbacks use getAdapterLabel() for consistent display - AdapterTypeDropdown uses controlled open state for proper close behavior - Remove hermes-local from built-in UI (externalized to plugin) - Add docs for external adapters and UI parser contract
57 lines
1.9 KiB
TypeScript
57 lines
1.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
summarizeHeartbeatRunResultJson,
|
|
buildHeartbeatRunIssueComment,
|
|
} from "../services/heartbeat-run-summary.js";
|
|
|
|
describe("summarizeHeartbeatRunResultJson", () => {
|
|
it("truncates text fields and preserves cost aliases", () => {
|
|
const summary = summarizeHeartbeatRunResultJson({
|
|
summary: "a".repeat(600),
|
|
result: "ok",
|
|
message: "done",
|
|
error: "failed",
|
|
total_cost_usd: 1.23,
|
|
cost_usd: 0.45,
|
|
costUsd: 0.67,
|
|
nested: { ignored: true },
|
|
});
|
|
|
|
expect(summary).toEqual({
|
|
summary: "a".repeat(500),
|
|
result: "ok",
|
|
message: "done",
|
|
error: "failed",
|
|
total_cost_usd: 1.23,
|
|
cost_usd: 0.45,
|
|
costUsd: 0.67,
|
|
});
|
|
});
|
|
|
|
it("returns null for non-object and irrelevant payloads", () => {
|
|
expect(summarizeHeartbeatRunResultJson(null)).toBeNull();
|
|
expect(summarizeHeartbeatRunResultJson(["nope"] as unknown as Record<string, unknown>)).toBeNull();
|
|
expect(summarizeHeartbeatRunResultJson({ nested: { only: "ignored" } })).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("buildHeartbeatRunIssueComment", () => {
|
|
it("uses the final summary text for issue comments on successful runs", () => {
|
|
const comment = buildHeartbeatRunIssueComment({
|
|
summary: "## Summary\n\n- fixed deploy config\n- posted issue update",
|
|
});
|
|
|
|
expect(comment).toContain("## Summary");
|
|
expect(comment).toContain("- fixed deploy config");
|
|
expect(comment).not.toContain("Run summary");
|
|
});
|
|
|
|
it("falls back to result or message when summary is missing", () => {
|
|
expect(buildHeartbeatRunIssueComment({ result: "done" })).toBe("done");
|
|
expect(buildHeartbeatRunIssueComment({ message: "completed" })).toBe("completed");
|
|
});
|
|
|
|
it("returns null when there is no usable final text", () => {
|
|
expect(buildHeartbeatRunIssueComment({ costUsd: 1.2 })).toBeNull();
|
|
});
|
|
});
|