feat: Gemini AI integration — conversations, messages, image gen

- Fixed YAML parse error (unquoted colon in description broke @scalar/json-magic)
- Converted orval.config.ts → orval.config.cjs (fixes orval v8 TypeScript config loading)
- Codegen now works: zod schemas + React Query hooks regenerated with Gemini types
- Added Gemini tag, 4 path groups, 8 schemas to openapi.yaml
- lib/integrations-gemini-ai wired: tsconfig refs, api-server package.json dep
- Created routes/gemini.ts: CRUD conversations/messages + SSE chat stream + image gen
- Mounted /gemini router in routes/index.ts
This commit is contained in:
Replit Agent
2026-03-20 02:41:12 +00:00
parent cdb104e34f
commit e86dab0d65
54 changed files with 3620 additions and 28 deletions

View File

@@ -0,0 +1,256 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface HealthStatus {
status: string;
}
export interface ErrorResponse {
error: string;
}
export interface InvoiceInfo {
paymentRequest: string;
amountSats: number;
}
export interface CreateJobRequest {
/** @minLength 1 */
request: string;
}
export interface CreateJobResponse {
jobId: string;
/** ISO 8601 timestamp of job creation */
createdAt: string;
evalInvoice: InvoiceInfo;
}
export type JobState = (typeof JobState)[keyof typeof JobState];
export const JobState = {
awaiting_eval_payment: "awaiting_eval_payment",
evaluating: "evaluating",
rejected: "rejected",
awaiting_work_payment: "awaiting_work_payment",
executing: "executing",
complete: "complete",
failed: "failed",
} as const;
/**
* Cost breakdown shown with the work invoice (estimations at invoice-creation time)
*/
export interface PricingBreakdown {
/** Total estimated cost in USD (token cost + DO infra + margin) */
estimatedCostUsd?: number;
/** Originator margin percentage applied */
marginPct?: number;
/** BTC/USD spot price used to convert the invoice to sats */
btcPriceUsd?: number;
}
/**
* Lifecycle of the refund for this job
*/
export type CostLedgerRefundState =
(typeof CostLedgerRefundState)[keyof typeof CostLedgerRefundState];
export const CostLedgerRefundState = {
not_applicable: "not_applicable",
pending: "pending",
paid: "paid",
} as const;
/**
* Honest post-work accounting stored after the job completes
*/
export interface CostLedger {
actualInputTokens?: number;
actualOutputTokens?: number;
/** Sum of actualInputTokens + actualOutputTokens */
totalTokens?: number;
/** Raw Anthropic token cost (no infra, no margin) */
actualCostUsd?: number;
/** What we honestly charged in USD (actual token cost + DO infra + margin) */
actualChargeUsd?: number;
/** Original estimate used to create the work invoice */
estimatedCostUsd?: number;
/** Honest sats charge (actual cost converted at the locked BTC price) */
actualAmountSats?: number;
/** Amount the user originally paid in sats */
workAmountSats?: number;
/** Sats owed back to the user (workAmountSats - actualAmountSats, >= 0) */
refundAmountSats?: number;
/** Lifecycle of the refund for this job */
refundState?: CostLedgerRefundState;
marginPct?: number;
/** BTC/USD price locked at invoice creation time */
btcPriceUsd?: number;
}
export interface JobStatusResponse {
jobId: string;
state: JobState;
/** ISO 8601 timestamp of job creation (always present) */
createdAt: string;
/** ISO 8601 timestamp of job completion; null when not yet complete */
completedAt?: string | null;
evalInvoice?: InvoiceInfo;
workInvoice?: InvoiceInfo;
pricingBreakdown?: PricingBreakdown;
reason?: string;
result?: string;
costLedger?: CostLedger;
errorMessage?: string;
}
export type SessionState = (typeof SessionState)[keyof typeof SessionState];
export const SessionState = {
awaiting_payment: "awaiting_payment",
active: "active",
paused: "paused",
expired: "expired",
} as const;
export interface SessionInvoiceInfo {
paymentRequest?: string;
amountSats?: number;
/** Only present in stub/dev mode */
paymentHash?: string;
}
export interface CreateSessionRequest {
/**
* Deposit amount (10010,000 sats)
* @minimum 100
* @maximum 10000
*/
amount_sats: number;
}
export interface CreateSessionResponse {
sessionId: string;
state: SessionState;
invoice: SessionInvoiceInfo;
}
export interface SessionStatusResponse {
sessionId: string;
state: SessionState;
balanceSats: number;
minimumBalanceSats?: number;
/** Bearer token for authenticating requests; present when active or paused */
macaroon?: string;
expiresAt?: string;
/** Present when state is awaiting_payment */
invoice?: SessionInvoiceInfo;
/** Present when a topup invoice is outstanding */
pendingTopup?: SessionInvoiceInfo;
}
export interface SessionRequestBody {
/** @minLength 1 */
request: string;
}
export interface SessionCostBreakdown {
evalSats?: number;
workSats?: number;
totalSats?: number;
btcPriceUsd?: number;
}
export type SessionRequestResponseState =
(typeof SessionRequestResponseState)[keyof typeof SessionRequestResponseState];
export const SessionRequestResponseState = {
complete: "complete",
rejected: "rejected",
failed: "failed",
} as const;
export interface SessionRequestResponse {
requestId: string;
state: SessionRequestResponseState;
result?: string;
reason?: string;
errorMessage?: string;
debitedSats: number;
balanceRemaining: number;
cost?: SessionCostBreakdown;
}
export interface TopupSessionResponse {
sessionId: string;
topup: SessionInvoiceInfo;
}
export interface ClaimRefundRequest {
/** BOLT11 invoice for exactly refundAmountSats */
invoice: string;
}
export interface ClaimRefundResponse {
ok: boolean;
refundAmountSats: number;
paymentHash: string;
message: string;
}
export interface DemoResponse {
result: string;
}
export interface GeminiConversation {
id: number;
title: string;
createdAt: string;
}
export interface GeminiMessage {
id: number;
conversationId: number;
role: string;
content: string;
createdAt: string;
}
export interface GeminiConversationWithMessages {
id: number;
title: string;
createdAt: string;
messages: GeminiMessage[];
}
export interface CreateGeminiConversationBody {
title: string;
}
export interface SendGeminiMessageBody {
content: string;
/** Gemini model override (default: gemini-3-flash-preview) */
model?: string;
}
export interface GenerateGeminiImageBody {
prompt: string;
}
export interface GenerateGeminiImageResponse {
b64_json: string;
mimeType: string;
}
export interface GeminiError {
error: string;
}
export type RunDemoParams = {
request: string;
};

File diff suppressed because it is too large Load Diff