Diffs: route plugin context through artifacts

This commit is contained in:
Gustavo Madeira Santana
2026-03-19 00:22:43 -04:00
parent a98ffa41d0
commit 83d284610c
11 changed files with 204 additions and 24 deletions

View File

@@ -2,7 +2,7 @@ import crypto from "node:crypto";
import fs from "node:fs/promises";
import path from "node:path";
import type { PluginLogger } from "../api.js";
import type { DiffArtifactMeta, DiffOutputFormat } from "./types.js";
import type { DiffArtifactContext, DiffArtifactMeta, DiffOutputFormat } from "./types.js";
const DEFAULT_TTL_MS = 30 * 60 * 1000;
const MAX_TTL_MS = 6 * 60 * 60 * 1000;
@@ -16,11 +16,13 @@ type CreateArtifactParams = {
inputKind: DiffArtifactMeta["inputKind"];
fileCount: number;
ttlMs?: number;
context?: DiffArtifactContext;
};
type CreateStandaloneFileArtifactParams = {
format?: DiffOutputFormat;
ttlMs?: number;
context?: DiffArtifactContext;
};
type StandaloneFileMeta = {
@@ -29,6 +31,7 @@ type StandaloneFileMeta = {
createdAt: string;
expiresAt: string;
filePath: string;
context?: DiffArtifactContext;
};
type ArtifactMetaFileName = "meta.json" | "file-meta.json";
@@ -69,6 +72,7 @@ export class DiffArtifactStore {
expiresAt: expiresAt.toISOString(),
viewerPath: `${VIEWER_PREFIX}/${id}/${token}`,
htmlPath,
...(params.context ? { context: params.context } : {}),
};
await fs.mkdir(artifactDir, { recursive: true });
@@ -127,7 +131,7 @@ export class DiffArtifactStore {
async createStandaloneFileArtifact(
params: CreateStandaloneFileArtifactParams = {},
): Promise<{ id: string; filePath: string; expiresAt: string }> {
): Promise<{ id: string; filePath: string; expiresAt: string; context?: DiffArtifactContext }> {
await this.ensureRoot();
const id = crypto.randomBytes(10).toString("hex");
@@ -143,6 +147,7 @@ export class DiffArtifactStore {
createdAt: createdAt.toISOString(),
expiresAt,
filePath: this.normalizeStoredPath(filePath, "filePath"),
...(params.context ? { context: params.context } : {}),
};
await fs.mkdir(artifactDir, { recursive: true });
@@ -152,6 +157,7 @@ export class DiffArtifactStore {
id,
filePath: meta.filePath,
expiresAt: meta.expiresAt,
...(meta.context ? { context: meta.context } : {}),
};
}
@@ -268,6 +274,7 @@ export class DiffArtifactStore {
createdAt: value.createdAt,
expiresAt: value.expiresAt,
filePath: this.normalizeStoredPath(value.filePath, "filePath"),
...(value.context ? { context: normalizeArtifactContext(value.context) } : {}),
};
} catch (error) {
this.logger?.warn(`Failed to normalize standalone diff metadata for ${id}: ${String(error)}`);
@@ -356,3 +363,23 @@ function isExpired(meta: { expiresAt: string }): boolean {
function isFileNotFound(error: unknown): boolean {
return error instanceof Error && "code" in error && error.code === "ENOENT";
}
function normalizeArtifactContext(value: unknown): DiffArtifactContext | undefined {
if (!value || typeof value !== "object" || Array.isArray(value)) {
return undefined;
}
const raw = value as Record<string, unknown>;
const context = {
agentId: normalizeOptionalString(raw.agentId),
sessionId: normalizeOptionalString(raw.sessionId),
messageChannel: normalizeOptionalString(raw.messageChannel),
agentAccountId: normalizeOptionalString(raw.agentAccountId),
};
return Object.values(context).some((entry) => entry !== undefined) ? context : undefined;
}
function normalizeOptionalString(value: unknown): string | undefined {
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
}