Add search and RAG workspace flows
This commit is contained in:
46
scripts/backfill-search-index.ts
Normal file
46
scripts/backfill-search-index.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { indexSearchDocuments } from '@/lib/server/search';
|
||||
|
||||
function getArg(name: string) {
|
||||
const prefix = `--${name}=`;
|
||||
const entry = process.argv.find((value) => value.startsWith(prefix));
|
||||
return entry ? entry.slice(prefix.length).trim() : null;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const source = (getArg('source') ?? 'all').toLowerCase();
|
||||
const ticker = getArg('ticker')?.toUpperCase() ?? null;
|
||||
const accessionNumber = getArg('accession') ?? null;
|
||||
const userId = getArg('user') ?? 'system-backfill';
|
||||
|
||||
const sourceKinds: Array<'filing_document' | 'filing_brief' | 'research_note'> | null = source === 'all'
|
||||
? ['filing_document', 'filing_brief', 'research_note'] as const
|
||||
: source === 'documents'
|
||||
? ['filing_document'] as const
|
||||
: source === 'filings'
|
||||
? ['filing_brief'] as const
|
||||
: source === 'research'
|
||||
? ['research_note'] as const
|
||||
: null;
|
||||
|
||||
if (!sourceKinds) {
|
||||
throw new Error('Unsupported --source value. Use all, documents, filings, or research.');
|
||||
}
|
||||
|
||||
if (sourceKinds.includes('research_note') && !userId) {
|
||||
throw new Error('--user is required when backfilling research notes.');
|
||||
}
|
||||
|
||||
const result = await indexSearchDocuments({
|
||||
userId,
|
||||
ticker,
|
||||
accessionNumber,
|
||||
sourceKinds
|
||||
});
|
||||
|
||||
console.log(JSON.stringify(result, null, 2));
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error instanceof Error ? error.message : error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
@@ -9,7 +9,7 @@ describe('buildLocalDevConfig', () => {
|
||||
expect(config.port).toBe('3000');
|
||||
expect(config.publicOrigin).toBe('http://localhost:3000');
|
||||
expect(config.env.BETTER_AUTH_BASE_URL).toBe('http://localhost:3000');
|
||||
expect(config.env.BETTER_AUTH_TRUSTED_ORIGINS).toBe('http://localhost:3000');
|
||||
expect(config.env.BETTER_AUTH_TRUSTED_ORIGINS).toBe('http://localhost:3000,http://127.0.0.1:3000');
|
||||
expect(config.env.BETTER_AUTH_SECRET).toBe(LOCAL_DEV_SECRET);
|
||||
expect(config.env.DATABASE_URL).toBe('file:data/fiscal.sqlite');
|
||||
expect(config.env.NEXT_PUBLIC_API_URL).toBe('');
|
||||
@@ -27,12 +27,23 @@ describe('buildLocalDevConfig', () => {
|
||||
});
|
||||
|
||||
expect(config.env.BETTER_AUTH_SECRET).toBe('real-secret');
|
||||
expect(config.env.BETTER_AUTH_TRUSTED_ORIGINS).toBe('http://localhost:3000,https://fiscal.b11studio.xyz');
|
||||
expect(config.env.BETTER_AUTH_TRUSTED_ORIGINS)
|
||||
.toBe('http://localhost:3000,http://127.0.0.1:3000,https://fiscal.b11studio.xyz');
|
||||
expect(config.env.DATABASE_URL).toBe('file:data/dev.sqlite');
|
||||
expect(config.overrides.databaseChanged).toBe(false);
|
||||
expect(config.overrides.workflowChanged).toBe(false);
|
||||
});
|
||||
|
||||
it('trusts both localhost and 127.0.0.1 for loopback public origins', () => {
|
||||
const config = buildLocalDevConfig({
|
||||
DEV_PUBLIC_HOST: '127.0.0.1',
|
||||
PORT: '3412'
|
||||
});
|
||||
|
||||
expect(config.publicOrigin).toBe('http://127.0.0.1:3412');
|
||||
expect(config.env.BETTER_AUTH_TRUSTED_ORIGINS).toBe('http://127.0.0.1:3412,http://localhost:3412');
|
||||
});
|
||||
|
||||
it('respects an explicit public origin override', () => {
|
||||
const config = buildLocalDevConfig({
|
||||
DEV_PUBLIC_ORIGIN: 'https://local.fiscal.test:4444/',
|
||||
|
||||
@@ -43,6 +43,34 @@ function toUniqueList(values: string[]) {
|
||||
return Array.from(new Set(values));
|
||||
}
|
||||
|
||||
function isLoopbackHostname(hostname: string) {
|
||||
return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1';
|
||||
}
|
||||
|
||||
function replaceOriginHostname(origin: string, hostname: string) {
|
||||
const url = new URL(origin);
|
||||
url.hostname = hostname;
|
||||
url.hash = '';
|
||||
url.search = '';
|
||||
|
||||
const pathName = url.pathname.replace(/\/$/, '');
|
||||
return `${url.origin}${pathName === '/' ? '' : pathName}`;
|
||||
}
|
||||
|
||||
function buildTrustedOrigins(publicOrigin: string, configuredOrigins: string | undefined) {
|
||||
const trustedOrigins = [publicOrigin];
|
||||
const publicOriginUrl = new URL(publicOrigin);
|
||||
|
||||
if (isLoopbackHostname(publicOriginUrl.hostname)) {
|
||||
trustedOrigins.push(replaceOriginHostname(publicOrigin, 'localhost'));
|
||||
trustedOrigins.push(replaceOriginHostname(publicOrigin, '127.0.0.1'));
|
||||
}
|
||||
|
||||
trustedOrigins.push(...parseCsvList(configuredOrigins));
|
||||
|
||||
return toUniqueList(trustedOrigins).join(',');
|
||||
}
|
||||
|
||||
function coercePort(port: string | undefined) {
|
||||
const parsed = Number.parseInt(port ?? '', 10);
|
||||
if (Number.isInteger(parsed) && parsed > 0 && parsed <= 65535) {
|
||||
@@ -113,10 +141,7 @@ export function buildLocalDevConfig(sourceEnv: EnvMap = process.env): LocalDevCo
|
||||
? DEFAULT_DATABASE_URL
|
||||
: trim(sourceEnv.DATABASE_URL) ?? DEFAULT_DATABASE_URL;
|
||||
const secret = trim(sourceEnv.BETTER_AUTH_SECRET);
|
||||
const trustedOrigins = toUniqueList([
|
||||
publicOrigin,
|
||||
...parseCsvList(sourceEnv.BETTER_AUTH_TRUSTED_ORIGINS)
|
||||
]).join(',');
|
||||
const trustedOrigins = buildTrustedOrigins(publicOrigin, sourceEnv.BETTER_AUTH_TRUSTED_ORIGINS);
|
||||
|
||||
const env: EnvMap = {
|
||||
...sourceEnv,
|
||||
|
||||
Reference in New Issue
Block a user