feat(tools): add minio ingestion into memory namespaces

This commit is contained in:
William Valentin
2026-02-16 14:17:52 -08:00
parent 3203c1f3fe
commit 0be93c20b5
10 changed files with 407 additions and 8 deletions
+128
View File
@@ -0,0 +1,128 @@
import { describe, expect, it, vi } from 'vitest';
import { createMinioIngestTool, minioIngestInternals } from './minio-ingest.js';
import type { BackupConfig } from '../../config/schema.js';
import type { MemoryStore } from '../../memory/store.js';
function makeBackupConfig(overrides?: Partial<BackupConfig>): BackupConfig {
return {
enabled: true,
schedule: undefined,
interval: '24h',
run_on_start: false,
notify: undefined,
failure_threshold: 1,
notify_recovery: true,
local_dir: '~/.local/share/flynn/backups',
include_vectors: true,
minio: {
enabled: true,
endpoint: 'localhost:9000',
access_key: 'minio-admin',
secret_key: 'minio-secret',
bucket: 'flynn-knowledge',
prefix: 'flynn',
secure: false,
},
...overrides,
};
}
describe('minio ingest internals', () => {
it('accepts known text-like extensions', () => {
expect(minioIngestInternals.isLikelyTextObject('notes/today.md')).toBe(true);
expect(minioIngestInternals.isLikelyTextObject('logs/daemon.log')).toBe(true);
});
it('rejects likely binary extensions', () => {
expect(minioIngestInternals.isLikelyTextObject('manual.pdf')).toBe(false);
});
});
describe('createMinioIngestTool', () => {
it('ingests object and writes to memory', async () => {
const write = vi.fn();
const store = { write } as unknown as MemoryStore;
const execRunner = vi.fn(async () => ({
stdout: '# Runbook\n\nRestart service before deploy.\n',
stderr: '',
}));
const tool = createMinioIngestTool(makeBackupConfig(), store, {
execRunner,
now: () => new Date('2026-02-16T15:00:00.000Z'),
});
const result = await tool.execute({
object_key: 'knowledge/runbook.md',
namespace: 'global/runbooks',
mode: 'append',
});
expect(result.success).toBe(true);
expect(result.output).toContain('Ingested MinIO object');
expect(write).toHaveBeenCalledWith(
'global/runbooks',
expect.stringContaining('source: minio://flynn-knowledge/knowledge/runbook.md'),
'append',
);
expect(execRunner).toHaveBeenCalledWith(
'mc',
['cat', 'flynningest/flynn-knowledge/knowledge/runbook.md'],
expect.objectContaining({ env: expect.any(Object) }),
);
});
it('rejects likely binary object unless force=true', async () => {
const write = vi.fn();
const store = { write } as unknown as MemoryStore;
const execRunner = vi.fn();
const tool = createMinioIngestTool(makeBackupConfig(), store, { execRunner });
const result = await tool.execute({ object_key: 'knowledge/diagram.pdf' });
expect(result.success).toBe(false);
expect(result.error).toContain('Unsupported object type');
expect(execRunner).not.toHaveBeenCalled();
});
it('allows non-text extension when force=true', async () => {
const write = vi.fn();
const store = { write } as unknown as MemoryStore;
const execRunner = vi.fn(async () => ({
stdout: 'PDF text extracted upstream',
stderr: '',
}));
const tool = createMinioIngestTool(makeBackupConfig(), store, { execRunner });
const result = await tool.execute({
object_key: 'knowledge/diagram.pdf',
force: true,
mode: 'replace',
});
expect(result.success).toBe(true);
expect(write).toHaveBeenCalledWith(
'global/knowledge',
expect.stringContaining('PDF text extracted upstream'),
'replace',
);
});
it('returns an error when minio is disabled', async () => {
const write = vi.fn();
const store = { write } as unknown as MemoryStore;
const tool = createMinioIngestTool(makeBackupConfig({
minio: {
enabled: false,
endpoint: undefined,
access_key: undefined,
secret_key: undefined,
bucket: undefined,
prefix: 'flynn',
secure: true,
},
}), store);
const result = await tool.execute({ object_key: 'notes/today.md' });
expect(result.success).toBe(false);
expect(result.error).toContain('backup.minio.enabled=true');
});
});