Ctrl K
ComunidadGuías…

src/services/assistant.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import type { CliLoginOrganization } from '~/services/cliLogin'
import type { ConsoleClient } from '~/services/consoleClient'
import type { Database } from '~/types/database.types'
import { createCliLoginKeyDependencies, createMcpOAuthKey, resolveCliKeyEligibility } from '~/services/cliLogin'

export type AssistantCard
  = | { type: 'link', title: string, description?: string, path: string }
    | { type: 'question', question: string, options: string[], allowFreeText: boolean }
    | { type: 'confirm', title: string, description: string, tool: string, arguments: Record<string, unknown> }

export interface AssistantAction {
  tool: string
  title: string
  ok: boolean
}

export interface AssistantResponse {
  reply: string
  cards: AssistantCard[]
  actions: AssistantAction[]
}

export interface AssistantTurn {
  role: 'user' | 'assistant'
  content: string
}

export interface AssistantContext {
  path?: string
  orgId?: string
  orgName?: string
  appId?: string
}

export const ASSISTANT_CLIENT_NAME = 'Capgo Assistant'

export class AssistantKeyError extends Error {}

const keyStorageKey = (userId: string) => `capgo-assistant-key:${userId}`

/** The assistant's Capgo API key lives on this device only, like the ChatGPT tokens. */
export function loadAssistantKey(userId: string): string {
  return localStorage.getItem(keyStorageKey(userId)) ?? ''
}

export function saveAssistantKey(userId: string, apikey: string) {
  if (apikey)
    localStorage.setItem(keyStorageKey(userId), apikey)
  else
    localStorage.removeItem(keyStorageKey(userId))
}

/**
 * The assistant calls the hosted MCP tools with a dedicated API key, bound to the organizations the
 * user administers, exactly like an MCP OAuth client. It shows up as "MCP · Capgo Assistant" in the
 * API key list, expires within 90 days and can be revoked there.
 */
export async function createAssistantKey(
  capgo: ConsoleClient<Database>,
  userId: string,
  organizations: CliLoginOrganization[],
): Promise<string> {
  const dependencies = createCliLoginKeyDependencies(capgo, userId)
  const { eligible } = await resolveCliKeyEligibility(organizations, dependencies)
  if (!eligible.length)
    throw new AssistantKeyError('no_eligible_organization')
  return createMcpOAuthKey(eligible, dependencies, ASSISTANT_CLIENT_NAME)
}