feat(coding-agent/tools): added binary routing for notebook, sqlite, and archive payloads

- Added archive format sniffing to identify ZIP, TAR, and TAR.GZ from file bytes.
- Added MIME/extension and header-based routing for notebook, sqlite, and archive payloads.
- Added archive entry rendering with slash-terminated dirs and size suffixes.
- Added tests for archive, sqlite, notebook, and fallback binary dispatch scenarios.
This commit is contained in:
can1357
2026-06-07 06:55:52 +02:00
parent 9bd9e3127e
commit cbd7c20105
5 changed files with 590 additions and 29 deletions
@@ -5,6 +5,14 @@ import { ToolError } from "./tool-errors";
const SQLITE_MAGIC = new Uint8Array([
0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x33, 0x00,
]);
export function looksLikeSqlite(bytes: Uint8Array): boolean {
if (bytes.byteLength < SQLITE_MAGIC.byteLength) return false;
for (const [index, byte] of SQLITE_MAGIC.entries()) {
if (bytes[index] !== byte) return false;
}
return true;
}
const SQLITE_PATH_PATTERN = /\.(?:sqlite3?|db3?)(?=(?::|\?|$))/gi;
const DEFAULT_QUERY_LIMIT = 20;
const DEFAULT_SCHEMA_SAMPLE_LIMIT = 5;
@@ -443,18 +451,7 @@ export function parseSqlitePathCandidates(filePath: string): SqlitePathCandidate
export async function isSqliteFile(absolutePath: string): Promise<boolean> {
try {
const bytes = await Bun.file(absolutePath).slice(0, SQLITE_MAGIC.byteLength).bytes();
if (bytes.length !== SQLITE_MAGIC.byteLength) {
return false;
}
for (const [index, byte] of SQLITE_MAGIC.entries()) {
if (bytes[index] !== byte) {
return false;
}
}
return true;
return looksLikeSqlite(await Bun.file(absolutePath).slice(0, SQLITE_MAGIC.byteLength).bytes());
} catch {
return false;
}