feat(post-application): automatically pull from email (#145)
* feat(post-application): add schema and shared types for provider ingestion (#136) * test(orchestrator): ensure full localStorage shape in vitest setup * feat(post-application): add provider registry and dispatcher framework (#137) (#146) * Implement Gmail provider credential persistence (#147) * Add unified post-application provider action API (#148) * Implement Gmail ingestion sync with 95/60 relevance policy * Implement Gmail ingestion sync with 95/60 relevance policy (#149) * feat(post-application): add job mapping engine with llm rerank fallback * feat(post-application): add inbox review APIs with transactional approve/deny (#151) * feat(post-application): add tracking inbox UI with provider controls (#152) * oauth implementation * UI changes * see past runs in more detail * occurred at comes from email * state mismatch * better UI representation * comments * comments * comments * comments * documentation * explainer * set things manually * scrolling * any found email can be pending * searchable download * Email-to-Job Matching Decision Tree * email viewer list improvement * simplification initial commit * exclude discovered jobs * show only resady * dropdown * mermaid * syntax * targets is the same as logging that is done manually * event label * duplicate avoidance * clean up html * token saving * print * send idx not uuid * remove logging * formatting * better documentation * documentation * comments * process all * comments
This commit is contained in:
@@ -364,6 +364,215 @@ export type ApiResponse<T> =
|
||||
meta: ApiMeta;
|
||||
};
|
||||
|
||||
export const POST_APPLICATION_PROVIDERS = ["gmail", "imap"] as const;
|
||||
export type PostApplicationProvider =
|
||||
(typeof POST_APPLICATION_PROVIDERS)[number];
|
||||
|
||||
export const POST_APPLICATION_PROVIDER_ACTIONS = [
|
||||
"connect",
|
||||
"status",
|
||||
"sync",
|
||||
"disconnect",
|
||||
] as const;
|
||||
export type PostApplicationProviderAction =
|
||||
(typeof POST_APPLICATION_PROVIDER_ACTIONS)[number];
|
||||
|
||||
export const POST_APPLICATION_INTEGRATION_STATUSES = [
|
||||
"disconnected",
|
||||
"connected",
|
||||
"error",
|
||||
] as const;
|
||||
export type PostApplicationIntegrationStatus =
|
||||
(typeof POST_APPLICATION_INTEGRATION_STATUSES)[number];
|
||||
|
||||
export const POST_APPLICATION_SYNC_RUN_STATUSES = [
|
||||
"running",
|
||||
"completed",
|
||||
"failed",
|
||||
"cancelled",
|
||||
] as const;
|
||||
export type PostApplicationSyncRunStatus =
|
||||
(typeof POST_APPLICATION_SYNC_RUN_STATUSES)[number];
|
||||
|
||||
export const POST_APPLICATION_RELEVANCE_DECISIONS = [
|
||||
"relevant",
|
||||
"not_relevant",
|
||||
"needs_llm",
|
||||
] as const;
|
||||
export type PostApplicationRelevanceDecision =
|
||||
(typeof POST_APPLICATION_RELEVANCE_DECISIONS)[number];
|
||||
|
||||
export const POST_APPLICATION_MESSAGE_TYPES = [
|
||||
"interview",
|
||||
"rejection",
|
||||
"offer",
|
||||
"update",
|
||||
"other",
|
||||
] as const;
|
||||
export type PostApplicationMessageType =
|
||||
(typeof POST_APPLICATION_MESSAGE_TYPES)[number];
|
||||
|
||||
export const POST_APPLICATION_ROUTER_STAGE_TARGETS = [
|
||||
"no_change",
|
||||
"applied",
|
||||
"recruiter_screen",
|
||||
"assessment",
|
||||
"hiring_manager_screen",
|
||||
"technical_interview",
|
||||
"onsite",
|
||||
"offer",
|
||||
"rejected",
|
||||
"withdrawn",
|
||||
"closed",
|
||||
] as const;
|
||||
export type PostApplicationRouterStageTarget =
|
||||
(typeof POST_APPLICATION_ROUTER_STAGE_TARGETS)[number];
|
||||
|
||||
export const POST_APPLICATION_PROCESSING_STATUSES = [
|
||||
"auto_linked",
|
||||
"pending_user",
|
||||
"manual_linked",
|
||||
"ignored",
|
||||
] as const;
|
||||
export type PostApplicationProcessingStatus =
|
||||
(typeof POST_APPLICATION_PROCESSING_STATUSES)[number];
|
||||
|
||||
export interface PostApplicationIntegration {
|
||||
id: string;
|
||||
provider: PostApplicationProvider;
|
||||
accountKey: string;
|
||||
displayName: string | null;
|
||||
status: PostApplicationIntegrationStatus;
|
||||
credentials: Record<string, unknown> | null;
|
||||
lastConnectedAt: number | null;
|
||||
lastSyncedAt: number | null;
|
||||
lastError: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface PostApplicationSyncRun {
|
||||
id: string;
|
||||
provider: PostApplicationProvider;
|
||||
accountKey: string;
|
||||
integrationId: string | null;
|
||||
status: PostApplicationSyncRunStatus;
|
||||
startedAt: number;
|
||||
completedAt: number | null;
|
||||
messagesDiscovered: number;
|
||||
messagesRelevant: number;
|
||||
messagesClassified: number;
|
||||
messagesMatched: number;
|
||||
messagesApproved: number;
|
||||
messagesDenied: number;
|
||||
messagesErrored: number;
|
||||
errorCode: string | null;
|
||||
errorMessage: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface PostApplicationMessage {
|
||||
id: string;
|
||||
provider: PostApplicationProvider;
|
||||
accountKey: string;
|
||||
integrationId: string | null;
|
||||
syncRunId: string | null;
|
||||
externalMessageId: string;
|
||||
externalThreadId: string | null;
|
||||
fromAddress: string;
|
||||
fromDomain: string | null;
|
||||
senderName: string | null;
|
||||
subject: string;
|
||||
receivedAt: number;
|
||||
snippet: string;
|
||||
classificationLabel: string | null;
|
||||
classificationConfidence: number | null;
|
||||
classificationPayload: Record<string, unknown> | null;
|
||||
relevanceLlmScore: number | null;
|
||||
relevanceDecision: PostApplicationRelevanceDecision;
|
||||
matchedJobId: string | null;
|
||||
matchConfidence: number | null;
|
||||
stageTarget: PostApplicationRouterStageTarget | null;
|
||||
messageType: PostApplicationMessageType;
|
||||
stageEventPayload: Record<string, unknown> | null;
|
||||
processingStatus: PostApplicationProcessingStatus;
|
||||
decidedAt: number | null;
|
||||
decidedBy: string | null;
|
||||
errorCode: string | null;
|
||||
errorMessage: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface PostApplicationProviderActionConnectRequest {
|
||||
accountKey?: string;
|
||||
payload?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface PostApplicationProviderActionSyncRequest {
|
||||
accountKey?: string;
|
||||
maxMessages?: number;
|
||||
searchDays?: number;
|
||||
}
|
||||
|
||||
export interface PostApplicationProviderStatus {
|
||||
provider: PostApplicationProvider;
|
||||
accountKey: string;
|
||||
connected: boolean;
|
||||
integration: PostApplicationIntegration | null;
|
||||
}
|
||||
|
||||
export interface PostApplicationProviderActionResponse {
|
||||
provider: PostApplicationProvider;
|
||||
action: PostApplicationProviderAction;
|
||||
accountKey: string;
|
||||
status: PostApplicationProviderStatus;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export interface PostApplicationInboxItem {
|
||||
message: PostApplicationMessage;
|
||||
matchedJob?: {
|
||||
id: string;
|
||||
title: string;
|
||||
employer: string;
|
||||
} | null;
|
||||
}
|
||||
|
||||
export type BulkPostApplicationAction = "approve" | "deny";
|
||||
|
||||
export interface BulkPostApplicationActionRequest {
|
||||
action: BulkPostApplicationAction;
|
||||
provider: PostApplicationProvider;
|
||||
accountKey: string;
|
||||
}
|
||||
|
||||
export type BulkPostApplicationActionResult =
|
||||
| {
|
||||
messageId: string;
|
||||
ok: true;
|
||||
message: PostApplicationMessage;
|
||||
stageEventId?: string | null;
|
||||
}
|
||||
| {
|
||||
messageId: string;
|
||||
ok: false;
|
||||
error: {
|
||||
code: string;
|
||||
message: string;
|
||||
};
|
||||
};
|
||||
|
||||
export interface BulkPostApplicationActionResponse {
|
||||
action: BulkPostApplicationAction;
|
||||
requested: number;
|
||||
succeeded: number;
|
||||
failed: number;
|
||||
skipped: number;
|
||||
results: BulkPostApplicationActionResult[];
|
||||
}
|
||||
|
||||
export interface JobsListResponse<TJob = Job> {
|
||||
jobs: TJob[];
|
||||
total: number;
|
||||
|
||||
Reference in New Issue
Block a user