Merge branch 't3code/expand-research-management-plan'

# Conflicts:
#	app/analysis/page.tsx
#	app/watchlist/page.tsx
#	components/shell/app-shell.tsx
#	lib/api.ts
#	lib/query/options.ts
#	lib/server/api/app.ts
#	lib/server/db/index.test.ts
#	lib/server/db/index.ts
#	lib/server/db/schema.ts
#	lib/server/repos/research-journal.ts
#	lib/types.ts
This commit is contained in:
2026-03-07 20:39:49 -05:00
38 changed files with 5533 additions and 427 deletions

View File

@@ -14,6 +14,18 @@ export const queryKeys = {
filings: (ticker: string | null, limit: number) => ['filings', ticker ?? '', limit] as const,
search: (query: string, ticker: string | null, sources: string[], limit: number) => ['search', query, ticker ?? '', sources.join(','), limit] as const,
report: (accessionNumber: string) => ['report', accessionNumber] as const,
researchWorkspace: (ticker: string) => ['research', 'workspace', ticker] as const,
researchLibrary: (
ticker: string,
q: string,
kind: string,
tag: string,
source: string,
linkedToMemo: string,
limit: number
) => ['research', 'library', ticker, q, kind, tag, source, linkedToMemo, limit] as const,
researchMemo: (ticker: string) => ['research', 'memo', ticker] as const,
researchPacket: (ticker: string) => ['research', 'packet', ticker] as const,
watchlist: () => ['watchlist'] as const,
researchJournal: (ticker: string) => ['research', 'journal', ticker] as const,
holdings: () => ['portfolio', 'holdings'] as const,

View File

@@ -6,9 +6,13 @@ import {
getLatestPortfolioInsight,
getPortfolioSummary,
searchKnowledge,
getResearchMemo,
getResearchPacket,
getResearchWorkspace,
getTask,
getTaskTimeline,
listFilings,
listResearchLibrary,
listHoldings,
listRecentTasks,
listResearchJournal,
@@ -18,7 +22,9 @@ import { queryKeys } from '@/lib/query/keys';
import type {
FinancialCadence,
FinancialSurfaceKind,
SearchSource
SearchSource,
ResearchArtifactKind,
ResearchArtifactSource
} from '@/lib/types';
export function companyAnalysisQueryOptions(ticker: string) {
@@ -123,6 +129,68 @@ export function aiReportQueryOptions(accessionNumber: string) {
});
}
export function researchWorkspaceQueryOptions(ticker: string) {
const normalizedTicker = ticker.trim().toUpperCase();
return queryOptions({
queryKey: queryKeys.researchWorkspace(normalizedTicker),
queryFn: () => getResearchWorkspace(normalizedTicker),
staleTime: 15_000
});
}
export function researchLibraryQueryOptions(input: {
ticker: string;
q?: string;
kind?: ResearchArtifactKind;
tag?: string;
source?: ResearchArtifactSource;
linkedToMemo?: boolean;
limit?: number;
}) {
const normalizedTicker = input.ticker.trim().toUpperCase();
const q = input.q?.trim() ?? '';
const kind = input.kind ?? '';
const tag = input.tag?.trim() ?? '';
const source = input.source ?? '';
const linkedToMemo = input.linkedToMemo === undefined ? '' : input.linkedToMemo ? 'true' : 'false';
const limit = input.limit ?? 100;
return queryOptions({
queryKey: queryKeys.researchLibrary(normalizedTicker, q, kind, tag, source, linkedToMemo, limit),
queryFn: () => listResearchLibrary({
ticker: normalizedTicker,
q,
kind: input.kind,
tag,
source: input.source,
linkedToMemo: input.linkedToMemo,
limit
}),
staleTime: 10_000
});
}
export function researchMemoQueryOptions(ticker: string) {
const normalizedTicker = ticker.trim().toUpperCase();
return queryOptions({
queryKey: queryKeys.researchMemo(normalizedTicker),
queryFn: () => getResearchMemo(normalizedTicker),
staleTime: 10_000
});
}
export function researchPacketQueryOptions(ticker: string) {
const normalizedTicker = ticker.trim().toUpperCase();
return queryOptions({
queryKey: queryKeys.researchPacket(normalizedTicker),
queryFn: () => getResearchPacket(normalizedTicker),
staleTime: 10_000
});
}
export function watchlistQueryOptions() {
return queryOptions({
queryKey: queryKeys.watchlist(),