refactor(coding-agent): migrated artifact management to SessionManager for centralized control

- Moved artifact management from ToolSession to SessionManager for centralized lifecycle control and caching.
- Replaced getArtifactManager() with allocateOutputArtifact() async method in ToolSession interface for simplified artifact allocation.
- Updated bash, fetch, python, and ssh tools to call session.allocateOutputArtifact() directly with optional chaining fallback.
- Fixed Lobsters scraper to handle user fields as strings instead of nested objects in API responses.
This commit is contained in:
can1357
2026-02-22 11:28:58 +01:00
parent 3bbced9b83
commit 469f1546f9
13 changed files with 101 additions and 109 deletions
@@ -2,9 +2,7 @@ import { afterEach, describe, expect, test } from "bun:test";
import * as fs from "node:fs/promises";
import * as os from "node:os";
import * as path from "node:path";
import { ArtifactManager } from "../src/session/artifacts";
import {
allocateOutputArtifact,
DEFAULT_MAX_BYTES,
DEFAULT_MAX_COLUMN,
DEFAULT_MAX_LINES,
@@ -18,7 +16,6 @@ import {
truncateTail,
truncateTailBytes,
} from "../src/session/streaming-output";
import type { ToolSession } from "../src/tools";
const createdTempDirs: string[] = [];
@@ -32,17 +29,6 @@ function byteLength(text: string): number {
return Buffer.byteLength(text, "utf-8");
}
function createSession(overrides: Partial<ToolSession> = {}): ToolSession {
return {
cwd: "/",
hasUI: false,
getSessionFile: () => null,
getSessionSpawns: () => null,
settings: {} as ToolSession["settings"],
...overrides,
};
}
afterEach(async () => {
for (const dir of createdTempDirs.splice(0)) {
await fs.rm(dir, { recursive: true, force: true });
@@ -288,25 +274,6 @@ describe("OutputSink", () => {
});
});
describe("allocateOutputArtifact", () => {
test("returns empty object when session has no artifact manager", async () => {
const session = createSession({ getArtifactManager: undefined });
expect(await allocateOutputArtifact(session, "bash")).toEqual({});
});
test("allocates artifact path via session artifact manager", async () => {
const dir = await createTempDir();
const sessionFile = path.join(dir, "session.jsonl");
await Bun.write(sessionFile, "");
const manager = new ArtifactManager(sessionFile);
const session = createSession({ getArtifactManager: () => manager });
const result = await allocateOutputArtifact(session, "bash");
expect(result.id).toBeDefined();
expect(result.path).toContain(`${path.sep}${result.id}.bash.log`);
});
});
describe("truncation notice formatting", () => {
test("formatTailTruncationNotice returns empty string for non-truncated results", () => {
const truncation = truncateTail("a\nb", { maxLines: 10, maxBytes: 50 });