111 lines
2.5 KiB
TypeScript
111 lines
2.5 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { test } from "vitest";
|
|
|
|
import {
|
|
collectRecentLogEvents,
|
|
formatMergedLogEvent,
|
|
getProjectSessionKey,
|
|
} from "../cli-logs.js";
|
|
|
|
function jsonl(entries: unknown[]): string {
|
|
return entries.map((entry) => JSON.stringify(entry)).join("\n") + "\n";
|
|
}
|
|
|
|
test("sf logs tail routes merged sources with expected prefixes", () => {
|
|
const root = mkdtempSync(join(tmpdir(), "sf-logs-tail-test-"));
|
|
const project = join(root, "project");
|
|
const sfHome = join(root, ".sf-home");
|
|
|
|
try {
|
|
mkdirSync(join(project, ".sf", "activity"), { recursive: true });
|
|
mkdirSync(
|
|
join(sfHome, "agent", "sessions", getProjectSessionKey(project)),
|
|
{ recursive: true },
|
|
);
|
|
|
|
writeFileSync(
|
|
join(project, ".sf", "notifications.jsonl"),
|
|
jsonl([
|
|
{
|
|
ts: "2026-04-28T10:00:00.000Z",
|
|
severity: "info",
|
|
message: "Notification ready",
|
|
},
|
|
]),
|
|
);
|
|
|
|
writeFileSync(
|
|
join(
|
|
sfHome,
|
|
"agent",
|
|
"sessions",
|
|
getProjectSessionKey(project),
|
|
"2026-04-28T10-00-01_sess.jsonl",
|
|
),
|
|
jsonl([
|
|
{
|
|
type: "message",
|
|
timestamp: "2026-04-28T10:00:01.000Z",
|
|
message: {
|
|
role: "assistant",
|
|
timestamp: 1777370401000,
|
|
content: [
|
|
{ type: "text", text: "Working on it" },
|
|
{ type: "toolCall", name: "Read" },
|
|
],
|
|
stopReason: "toolUse",
|
|
},
|
|
},
|
|
]),
|
|
);
|
|
|
|
writeFileSync(
|
|
join(project, ".sf", "activity", "001-execute-task-M001-S01-T01.jsonl"),
|
|
jsonl([
|
|
{
|
|
type: "message",
|
|
timestamp: "2026-04-28T10:00:02.000Z",
|
|
message: {
|
|
role: "assistant",
|
|
timestamp: 1777370402000,
|
|
content: [{ type: "toolCall", name: "Bash" }],
|
|
stopReason: "toolUse",
|
|
},
|
|
},
|
|
]),
|
|
);
|
|
|
|
writeFileSync(
|
|
join(project, ".sf", "audit-log.jsonl"),
|
|
jsonl([
|
|
{
|
|
ts: "2026-04-28T10:00:03.000Z",
|
|
severity: "error",
|
|
component: "engine",
|
|
message: "Audit failure",
|
|
},
|
|
]),
|
|
);
|
|
|
|
const output = collectRecentLogEvents({
|
|
basePath: project,
|
|
sfHome,
|
|
limit: 10,
|
|
})
|
|
.map(formatMergedLogEvent)
|
|
.join("");
|
|
|
|
assert.match(output, /\[notif\] Notification ready/);
|
|
assert.match(
|
|
output,
|
|
/\[session\] assistant: Working on it \| tools: Read \| stop: toolUse/,
|
|
);
|
|
assert.match(output, /\[activity\] tools: Bash \| stop: toolUse/);
|
|
assert.match(output, /\[audit\] \[engine\] Audit failure/);
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|