Built-in design generation now runs as an agentic MCP tool-loop (reusing the agent-rs BuiltInProvider), gated behind OPENPENCIL_DESIGN_AGENT_LOOP / the Settings experimental toggle; the orchestrator stays the default. - design-agent system prompt + in-process design toolset (parity-locked with the MCP surface) + flag-gated Intent::Design routing - spawn_agents execution as sequential sub-loops + live creation-mode badges (per-agent glow + 'N/M designing...' header) - new MCP tools: get_guidelines, ToolSearch, get_screenshot, get_editor_state, export_nodes, spawn_agents; style-guide local audit - #27 AI panel restyle: rounded tool cards + green check-rings, gray user bubbles, model-pill bottom toolbar, header, empty-state pills, the PARALLEL AGENTS (agent_team_size) 1x-6x chip dropdown - multi-chat tabs: ChatSessions model (Deref-to-active) + tab row UI (switch / close / + / Cmd+T) with each run bound to its tab Large checkpoint commit spanning the working tree (Rust shell crates).
54 lines
1.8 KiB
TypeScript
54 lines
1.8 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { tmpdir } from 'node:os';
|
|
|
|
import { resolveServableLocalImagePath } from './local-asset';
|
|
|
|
describe('resolveServableLocalImagePath', () => {
|
|
it('resolves an extensionless png file by sniffing its bytes', async () => {
|
|
const dir = mkdtempSync(join(tmpdir(), 'openpencil-local-asset-'));
|
|
try {
|
|
const filePath = join(dir, 'hero');
|
|
writeFileSync(
|
|
filePath,
|
|
Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d]),
|
|
);
|
|
|
|
await expect(resolveServableLocalImagePath(filePath)).resolves.toEqual({
|
|
resolvedPath: filePath,
|
|
mimeType: 'image/png',
|
|
});
|
|
} finally {
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it('resolves a sibling image file when the requested path is missing an extension', async () => {
|
|
const dir = mkdtempSync(join(tmpdir(), 'openpencil-local-asset-'));
|
|
try {
|
|
const filePath = join(dir, 'hero.jpg');
|
|
writeFileSync(filePath, Buffer.from([0xff, 0xd8, 0xff, 0xe0]));
|
|
|
|
await expect(resolveServableLocalImagePath(join(dir, 'hero'))).resolves.toEqual({
|
|
resolvedPath: filePath,
|
|
mimeType: 'image/jpeg',
|
|
});
|
|
} finally {
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it('returns null for explicit unsupported extensions', async () => {
|
|
const dir = mkdtempSync(join(tmpdir(), 'openpencil-local-asset-'));
|
|
try {
|
|
const filePath = join(dir, 'hero.pdf');
|
|
writeFileSync(filePath, Buffer.from('%PDF-1.7'));
|
|
|
|
await expect(resolveServableLocalImagePath(filePath)).resolves.toBeNull();
|
|
} finally {
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
});
|