### Install Xcode Command Line Tools Source: https://github.com/simonschubert/kai/blob/main/fastlane/README.md Installs the latest version of the Xcode command line tools required for Fastlane. This is a prerequisite for using Fastlane effectively. ```sh xcode-select --install ``` -------------------------------- ### Upload Screenshots to Play Store (Android) Source: https://github.com/simonschubert/kai/blob/main/fastlane/README.md Command to upload localized screenshots to the Google Play Store for an Android application using Fastlane. Assumes Fastlane is installed and configured. ```sh [bundle exec] fastlane android upload_screenshots ``` -------------------------------- ### Memory Store Operations in Kotlin Source: https://context7.com/simonschubert/kai/llms.txt Demonstrates how to use MemoryStore to manage persistent memories across conversations. It covers storing general memories, categorized learnings, reinforcing existing memories to increment their hit count, retrieving memories by category, fetching promotion candidates, getting all memories, and forgetting (deleting) memories. ```kotlin val appSettings = AppSettings(settings) val memoryStore = MemoryStore(appSettings) // Store a general memory val entry = memoryStore.store( key = "user_name", content = "John", category = MemoryCategory.GENERAL ) // Returns: MemoryEntry(key="user_name", content="John", hitCount=1, ...) // Store a categorized learning val learning = memoryStore.store( key = "prefers_dark_mode", content = "User prefers dark mode for all UI elements", category = MemoryCategory.PREFERENCE, source = "user_correction" ) // Reinforce a memory when it's useful (increments hitCount) val reinforced = memoryStore.reinforceMemory("user_name") // Returns: MemoryEntry with hitCount incremented // Get memories by category val preferences = memoryStore.getMemoriesByCategory(MemoryCategory.PREFERENCE) val learnings = memoryStore.getMemoriesByCategory(MemoryCategory.LEARNING) val errors = memoryStore.getMemoriesByCategory(MemoryCategory.ERROR) // Get promotion candidates (hitCount >= 5) val candidates = memoryStore.getPromotionCandidates(minHits = 5) // Get all memories val allMemories = memoryStore.getAllMemories() // Delete a memory val deleted = memoryStore.forget("user_name") // Returns: true if removed, false if not found ``` -------------------------------- ### Deploy AAB to Play Store Production (Android) Source: https://github.com/simonschubert/kai/blob/main/fastlane/README.md Command to deploy an Android App Bundle (AAB) to the production track of the Google Play Store using Fastlane. Requires prior setup and configuration of Fastlane. ```sh [bundle exec] fastlane android deploy ``` -------------------------------- ### Manage Application Settings and Service Configuration Source: https://context7.com/simonschubert/kai/llms.txt Demonstrates how to initialize AppSettings, manage API keys, configure service instances, set system prompts, and handle JSON import/export for configuration persistence. ```kotlin val settings = Settings() val appSettings = AppSettings(settings) appSettings.selectService(Service.OpenAI) appSettings.setApiKey(Service.OpenAI, "sk-...") appSettings.setSelectedModelId(Service.OpenAI, "gpt-4-turbo") val newInstanceId = appSettings.generateInstanceId("openai") appSettings.setInstanceApiKey("openai_2", "sk-different-key") appSettings.setSoulText("You are Kai, a friendly AI assistant...") appSettings.setMemoryEnabled(true) appSettings.setToolEnabled("web_search", true) val exportedJson = appSettings.exportToJson(listOf("web_search", "get_local_time", "memory_store")) appSettings.importFromJson(json = exportedJson, toolIds = listOf("web_search"), sections = setOf(ImportSection.SERVICES), replace = true) appSettings.runMigrations(legacySettings = null) ``` -------------------------------- ### Manage MCP Servers and Tools in Kotlin Source: https://context7.com/simonschubert/kai/llms.txt Demonstrates how to initialize the McpServerManager, register external MCP servers, discover tools, and manage connection states. It also shows direct client usage for tool execution. ```kotlin val mcpManager = McpServerManager(appSettings) val server = mcpManager.addServer( name = "Context7", url = "https://mcp.context7.com/mcp", headers = mapOf("Authorization" to "Bearer token123") ) val toolsResult = mcpManager.connectAndDiscoverTools(server.id) toolsResult.onSuccess { tools -> tools.forEach { tool -> println("Tool: ${tool.name} - ${tool.description}") } }.onFailure { error -> println("Connection failed: ${error.message}") } val servers = mcpManager.getServers() mcpManager.setServerEnabled(server.id, enabled = true) val serverTools = mcpManager.getToolsForServer(server.id) val enabledMcpTools = mcpManager.getEnabledMcpTools() mcpManager.connectEnabledServers() val isConnected = mcpManager.isConnected(server.id) mcpManager.removeServer(server.id) mcpManager.disconnectAll() val client = McpClient( url = "https://mcp.example.com/mcp", headers = emptyMap() ) client.initialize() val toolDefs = client.listTools() val result = client.callTool("tool_name", JsonObject(mapOf("arg" to JsonPrimitive("value")))) client.close() ``` -------------------------------- ### Tool System Overview Source: https://context7.com/simonschubert/kai/llms.txt Demonstrates the definition and usage of various tools within the Kai system, including built-in tools like WebSearchTool and custom tool definitions. ```APIDOC ## Tool System Tools extend AI capabilities with web search, memory operations, scheduling, and more. Each tool defines a schema with parameters and an execute function. ### Built-in Web Search Tool ```kotlin object WebSearchTool : Tool { override val schema = ToolSchema( name = "web_search", description = "Search the web for current information", parameters = mapOf( "query" to ParameterSchema("string", "The search query", required = true) ) ) override suspend fun execute(args: Map): Any { val query = args["query"]?.toString() ?: return mapOf("error" to "Missing query") // Returns: { "success": true, "results": [...] } } } ``` ### Memory Tools ```kotlin val memoryTools = CommonTools.getMemoryTools(memoryStore) // Includes: memory_store, memory_forget, memory_learn, memory_reinforce ``` ### Scheduling Tools ```kotlin val schedulingTools = SchedulingTools.getSchedulingTools(taskStore) // Includes: schedule_task, cancel_task, list_tasks ``` ### Common Tools ```kotlin val enabledTools = CommonTools.getCommonTools(appSettings) // Returns tools that are enabled in settings: web_search, get_local_time, etc. ``` ### Custom Tool Definition: Get Weather ```kotlin val customTool = object : Tool { override val schema = ToolSchema( name = "get_weather", description = "Get current weather for a location", parameters = mapOf( "location" to ParameterSchema("string", "City name", required = true), "units" to ParameterSchema("string", "celsius or fahrenheit", required = false) ) ) override suspend fun execute(args: Map): Any { val location = args["location"]?.toString() ?: return mapOf("error" to "Missing location") val units = args["units"]?.toString() ?: "celsius" // Fetch weather data... return mapOf( "success" to true, "temperature" to 22, "units" to units, "condition" to "sunny" ) } } ``` ``` -------------------------------- ### Define Custom AI Tools in Kotlin Source: https://context7.com/simonschubert/kai/llms.txt Demonstrates how to implement the Tool interface to create custom AI-accessible functions. It requires defining a ToolSchema with parameters and implementing the execute function to handle tool logic. ```kotlin val customTool = object : Tool { override val schema = ToolSchema( name = "get_weather", description = "Get current weather for a location", parameters = mapOf( "location" to ParameterSchema("string", "City name", required = true), "units" to ParameterSchema("string", "celsius or fahrenheit", required = false) ) ) override suspend fun execute(args: Map): Any { val location = args["location"]?.toString() ?: return mapOf("error" to "Missing location") val units = args["units"]?.toString() ?: "celsius" return mapOf( "success" to true, "temperature" to 22, "units" to units, "condition" to "sunny" ) } } ``` -------------------------------- ### Generate and Upload Store Screenshots Source: https://github.com/simonschubert/kai/blob/main/README.md Generates localized screenshots for the Play Store across all supported locales using Gradle, followed by an upload process via Fastlane. ```bash ./gradlew :screenshotTests:generateStoreScreenshots bundle exec fastlane android upload_screenshots ``` -------------------------------- ### Manage Scheduled Tasks with TaskStore Source: https://context7.com/simonschubert/kai/llms.txt Shows how to use TaskStore to create, retrieve, and update tasks. It supports both one-time execution via epoch timestamps and recurring tasks using cron expressions. ```kotlin val taskStore = TaskStore(appSettings) // Schedule a one-time task val task = taskStore.addTask( description = "Remind about meeting", prompt = "Remind me: You have a team meeting in 15 minutes.", scheduledAtEpochMs = System.currentTimeMillis() + 900_000, cron = null ) // Schedule a recurring task with cron val recurringTask = taskStore.addTask( description = "Daily standup reminder", prompt = "It's time for the daily standup meeting!", scheduledAtEpochMs = 0, cron = "0 9 * * 1-5" ) ``` -------------------------------- ### Configure LLM Services in Kotlin Source: https://context7.com/simonschubert/kai/llms.txt Defines and configures various LLM services like Anthropic and OpenAI-compatible APIs. It includes details on service IDs, API key requirements, model selection, and base URLs. Services can be retrieved by ID or accessed as a list of all available services. ```kotlin data object Anthropic : Service( id = "anthropic", displayName = "Anthropic", requiresApiKey = true, defaultModel = null, settingsKeyPrefix = "anthropic", chatUrl = "https://api.anthropic.com/v1/messages", modelsUrl = "https://api.anthropic.com/v1/models", apiKeyUrl = "https://console.anthropic.com/settings/keys" ) data object OpenAICompatible : Service( id = "openai-compatible", displayName = "OpenAI-Compatible API", requiresApiKey = false, supportsOptionalApiKey = true, defaultModel = null, chatUrl = "/chat/completions", modelsUrl = "/models" ) // Get service by ID val service = Service.fromId("anthropic") // All available services val allServices = Service.all // Returns list of all 20+ services // Default base URL for local APIs val localUrl = Service.DEFAULT_OPENAI_COMPATIBLE_BASE_URL // "http://localhost:11434/v1" ``` -------------------------------- ### Task Scheduling API Source: https://context7.com/simonschubert/kai/llms.txt Details on how to use the TaskStore to schedule, manage, and retrieve tasks, including one-time and recurring tasks with cron support. ```APIDOC ## Task Scheduling TaskStore manages scheduled and recurring tasks with cron expression support. Tasks can fire prompts to the AI at specified times. ### Initialize TaskStore ```kotlin val taskStore = TaskStore(appSettings) ``` ### Schedule a One-Time Task ```kotlin val task = taskStore.addTask( description = "Remind about meeting", prompt = "Remind me: You have a team meeting in 15 minutes.", scheduledAtEpochMs = System.currentTimeMillis() + 900_000, // 15 minutes cron = null ) // Returns: ScheduledTask(id="uuid", description="...", status=PENDING, ...) ``` ### Schedule a Recurring Task with Cron ```kotlin val recurringTask = taskStore.addTask( description = "Daily standup reminder", prompt = "It's time for the daily standup meeting!", scheduledAtEpochMs = 0, // Computed from cron cron = "0 9 * * 1-5" // 9 AM Monday-Friday ) ``` ### Retrieve Tasks ```kotlin // Get all tasks val allTasks = taskStore.getAllTasks() // Get pending tasks only val pendingTasks = taskStore.getPendingTasks() // Get tasks due for execution val dueTasks = taskStore.getDueTasks() ``` ### Update a Task ```kotlin val updatedTask = taskStore.updateTask( task.copy( status = TaskStatus.COMPLETED, lastResult = "User acknowledged the reminder" ) ) ``` ### Remove a Task ```kotlin val removed = taskStore.removeTask(task.id) ``` ### Using Scheduling Tools via AI ```kotlin val scheduleTaskTool = SchedulingTools.scheduleTaskTool(taskStore) val result = scheduleTaskTool.execute(mapOf( "description" to "Check email", "prompt" to "Check for important emails and summarize them", "execute_at" to "2025-03-15T09:00:00", "cron" to null )) ``` ``` -------------------------------- ### Update README Screenshots Source: https://github.com/simonschubert/kai/blob/main/README.md Executes the Gradle task to update screenshots used in the project README. This process is triggered automatically by CI on every push. ```bash ./gradlew :screenshotTests:updateScreenshots ``` -------------------------------- ### Configure and Execute Heartbeat Self-Checks in Kotlin Source: https://context7.com/simonschubert/kai/llms.txt Explains the HeartbeatManager functionality, including configuration management, checking if a heartbeat is due, building context-aware prompts, and logging execution results. ```kotlin val heartbeatManager = HeartbeatManager(appSettings, memoryStore, taskStore, emailStore) val config = heartbeatManager.getConfig() heartbeatManager.saveConfig(config.copy(intervalMinutes = 60)) val isDue = heartbeatManager.isHeartbeatDue() val recentResponses = listOf("All systems normal", "Reminded user about meeting") val prompt = heartbeatManager.buildHeartbeatPrompt(recentResponses) heartbeatManager.recordHeartbeat(success = true) heartbeatManager.recordHeartbeat(success = false, error = "Network timeout") val log = heartbeatManager.getHeartbeatLog() log.forEach { entry -> println("${entry.timestampEpochMs}: ${if (entry.success) "OK" else entry.error}") } heartbeatManager.markHeartbeatExecuted() val defaultPrompt = HeartbeatManager.DEFAULT_HEARTBEAT_PROMPT ``` -------------------------------- ### android deploy Source: https://github.com/simonschubert/kai/blob/main/fastlane/README.md Deploys an Android App Bundle (AAB) to the Google Play Store production track. ```APIDOC ## CLI COMMAND: android deploy ### Description Deploys the generated Android App Bundle (AAB) to the production track of the Google Play Store. ### Method CLI Execution ### Endpoint fastlane android deploy ### Parameters None ### Request Example ```bash bundle exec fastlane android deploy ``` ### Response #### Success Response (0) - **status** (string) - Indicates successful deployment of the AAB to production. ``` -------------------------------- ### Make Chat Requests with Different LLM APIs in Kotlin Source: https://context7.com/simonschubert/kai/llms.txt Handles HTTP communication for chat requests to LLM providers including OpenAI-compatible, Anthropic, and Gemini. It supports automatic tool conversion and provides error handling for common exceptions like rate limits and invalid API keys. ```kotlin val requests = Requests() // OpenAI-compatible chat (works with OpenAI, Groq, DeepSeek, Mistral, etc.) val credentials = ServiceCredentials( apiKey = "sk-...", modelId = "gpt-4", baseUrl = "" // Optional, for self-hosted ) val messages = listOf( OpenAICompatibleChatRequestDto.Message( role = "system", content = "You are a helpful assistant." ), OpenAICompatibleChatRequestDto.Message( role = "user", content = "Hello, how are you?" ) ) val result = requests.openAICompatibleChat( service = Service.OpenAI, credentials = credentials, messages = messages, tools = emptyList(), // Optional: list of Tool objects requestTimeoutMs = 60_000L ) result.onSuccess { response -> val assistantMessage = response.choices.first().message.content println(assistantMessage) }.onFailure { error -> when (error) { is OpenAICompatibleRateLimitExceededException -> println("Rate limited") is OpenAICompatibleQuotaExhaustedException -> println("Out of credits") is OpenAICompatibleInvalidApiKeyException -> println("Invalid API key") else -> println("Error: ${error.message}") } } // Anthropic chat val anthropicMessages = listOf( AnthropicChatRequestDto.Message( role = "user", content = listOf(AnthropicChatRequestDto.Content.Text("Hello!")) ) ) val anthropicResult = requests.anthropicChat( credentials = ServiceCredentials(apiKey = "sk-ant-...", modelId = "claude-3-opus-20240229"), messages = anthropicMessages, systemInstruction = "You are helpful.", tools = emptyList() ) // Gemini chat val geminiMessages = listOf( GeminiChatRequestDto.Content( role = "user", parts = listOf(GeminiChatRequestDto.Part(text = "Hello!")) ) ) val geminiResult = requests.geminiChat( credentials = ServiceCredentials(apiKey = "AIza...", modelId = "gemini-pro"), messages = geminiMessages, systemInstruction = "You are helpful." ) ``` -------------------------------- ### Implement ChatViewModel for Reactive UI State Source: https://context7.com/simonschubert/kai/llms.txt Shows the integration of ChatViewModel within an Android ComponentActivity and defines the ChatUiState data structure for managing chat history, service availability, and user actions. ```kotlin class ChatScreen : ComponentActivity() { private val viewModel: ChatViewModel by viewModels { ChatViewModelFactory(dataRepository, taskScheduler) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { val state by viewModel.state.collectAsState() ChatContent(history = state.history, isLoading = state.isLoading, onAsk = { question -> state.actions.ask(question) }) } } } data class ChatUiState( val history: List = emptyList(), val isLoading: Boolean = false, val error: UiError? = null, val actions: ChatActions ) ``` -------------------------------- ### android upload_screenshots Source: https://github.com/simonschubert/kai/blob/main/fastlane/README.md Uploads localized screenshots to the Google Play Store. ```APIDOC ## CLI COMMAND: android upload_screenshots ### Description Uploads localized screenshots to the Google Play Store for the Android application. ### Method CLI Execution ### Endpoint fastlane android upload_screenshots ### Parameters None ### Request Example ```bash bundle exec fastlane android upload_screenshots ``` ### Response #### Success Response (0) - **status** (string) - Indicates successful upload of screenshots to the Play Store. ``` -------------------------------- ### Conversation Storage Operations in Kotlin Source: https://context7.com/simonschubert/kai/llms.txt Illustrates the usage of ConversationStorage for managing encrypted conversation persistence. It includes loading conversations, observing them reactively using StateFlow, creating new conversations with messages, saving conversations, deleting conversations, and handling messages with file attachments like images. ```kotlin val conversationStorage = ConversationStorage(appSettings) // Load conversations from storage conversationStorage.loadConversations() // Observe conversations reactively conversationStorage.conversations.collect { conversations -> conversations.forEach { conversation -> println("${conversation.id}: ${conversation.title}") println("Type: ${conversation.type}") // "chat" or "heartbeat" println("Messages: ${conversation.messages.size}") } } // Create a new conversation val conversation = Conversation( id = UUID.randomUUID().toString(), messages = listOf( Conversation.Message( id = UUID.randomUUID().toString(), role = "user", content = "Hello!" ), Conversation.Message( id = UUID.randomUUID().toString(), role = "assistant", content = "Hi there! How can I help?" ) ), createdAt = System.currentTimeMillis(), updatedAt = System.currentTimeMillis(), title = "New Chat", type = Conversation.TYPE_CHAT ) // Save conversation conversationStorage.saveConversation(conversation) // Delete conversation conversationStorage.deleteConversation(conversation.id) // Message with file attachment val messageWithImage = Conversation.Message( id = UUID.randomUUID().toString(), role = "user", content = "What's in this image?", mimeType = "image/png", data = "base64EncodedImageData...", fileName = "screenshot.png" ) ``` -------------------------------- ### MCP Server Management Source: https://context7.com/simonschubert/kai/llms.txt Endpoints and methods for managing MCP servers, including adding, enabling, and discovering tools from external MCP providers. ```APIDOC ## POST /mcp/servers ### Description Adds a new MCP server configuration to the manager for external tool integration. ### Method POST ### Endpoint /mcp/servers ### Parameters #### Request Body - **name** (String) - Required - The display name of the server. - **url** (String) - Required - The endpoint URL of the MCP server. - **headers** (Map) - Optional - Authentication or custom headers. ### Request Example { "name": "Context7", "url": "https://mcp.context7.com/mcp", "headers": {"Authorization": "Bearer token123"} } ### Response #### Success Response (200) - **id** (String) - Unique identifier for the server. - **name** (String) - Server name. - **url** (String) - Server URL. - **isEnabled** (Boolean) - Current status of the server. ``` -------------------------------- ### Memory Store Operations Source: https://context7.com/simonschubert/kai/llms.txt Endpoints and methods for managing persistent memories, including categorization, reinforcement, and promotion candidate retrieval. ```APIDOC ## POST /memory/store ### Description Stores a new memory entry with a specific key, content, and category. Memories are tracked for hit counts to determine system prompt promotion. ### Method POST ### Endpoint /memory/store ### Parameters #### Request Body - **key** (string) - Required - Unique identifier for the memory - **content** (string) - Required - The memory content string - **category** (enum) - Required - GENERAL, PREFERENCE, LEARNING, or ERROR - **source** (string) - Optional - Origin of the memory ### Request Example { "key": "user_name", "content": "John", "category": "GENERAL" } ### Response #### Success Response (200) - **entry** (object) - The created MemoryEntry object including hitCount ## POST /memory/reinforce ### Description Increments the hit count for a specific memory key to indicate usefulness. ### Method POST ### Endpoint /memory/reinforce ### Parameters #### Query Parameters - **key** (string) - Required - The key to reinforce ### Response #### Success Response (200) - **entry** (object) - Updated MemoryEntry with incremented hitCount ``` -------------------------------- ### Schedule Task API Source: https://github.com/simonschubert/kai/blob/main/docs/features/tasks.md Allows the AI to schedule a one-time or recurring task. Requires either an execution time or a cron expression. ```APIDOC ## POST /tasks/schedule ### Description Schedules a new task for future execution. The task can be a one-time event or a recurring action. ### Method POST ### Endpoint /tasks/schedule ### Parameters #### Request Body - **description** (string) - Required - A human-readable description of the task. - **prompt** (string) - Required - The prompt to be executed by the AI when the task is due. - **execute_at** (string) - Optional - The ISO 8601 formatted timestamp for when the task should execute. Example: "2024-03-24T10:00:00Z". - **cron** (string) - Optional - A cron expression for recurring tasks. Example: "0 9 * * *" for daily at 9:00 AM. ### Request Example ```json { "description": "Send a daily reminder", "prompt": "Remind the user to drink water", "cron": "0 9 * * *" } ``` ### Response #### Success Response (200) - **id** (string) - The unique identifier (UUID) of the created task. - **description** (string) - The description of the task. - **scheduled_time** (string) - The next scheduled execution time. - **cron** (string) - The cron expression, if provided. #### Response Example ```json { "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef", "description": "Send a daily reminder", "scheduled_time": "2026-03-25T09:00:00Z", "cron": "0 9 * * *" } ``` ``` -------------------------------- ### Heartbeat System Configuration Source: https://context7.com/simonschubert/kai/llms.txt Methods for managing the autonomous heartbeat system that performs periodic self-checks on memories, tasks, and emails. ```APIDOC ## PUT /heartbeat/config ### Description Updates the configuration for the autonomous heartbeat system, including interval timing and active hours. ### Method PUT ### Endpoint /heartbeat/config ### Parameters #### Request Body - **enabled** (Boolean) - Required - Whether the heartbeat system is active. - **intervalMinutes** (Integer) - Required - Frequency of checks in minutes. - **activeHoursStart** (Integer) - Required - Start hour (0-23). - **activeHoursEnd** (Integer) - Required - End hour (0-23). ### Request Example { "enabled": true, "intervalMinutes": 60, "activeHoursStart": 8, "activeHoursEnd": 22 } ### Response #### Success Response (200) - **status** (String) - Confirmation of configuration update. ``` -------------------------------- ### List Tasks API Source: https://github.com/simonschubert/kai/blob/main/docs/features/tasks.md Retrieves a list of all scheduled tasks, with optional filtering by status. ```APIDOC ## GET /tasks ### Description Fetches a list of all scheduled tasks. Tasks can be filtered by their status. ### Method GET ### Endpoint /tasks ### Parameters #### Query Parameters - **status** (string) - Optional - Filters tasks by status. Allowed values: "PENDING", "COMPLETED". ### Request Example ``` GET /tasks?status=PENDING ``` ### Response #### Success Response (200) - **tasks** (array) - A list of task objects. - **id** (string) - The unique identifier (UUID) of the task. - **description** (string) - The description of the task. - **status** (string) - The current status of the task (PENDING or COMPLETED). - **scheduled_time** (string) - The next scheduled execution time. - **cron** (string) - The cron expression, if applicable. - **last_result** (string) - The result of the last execution. - **consecutive_failures** (integer) - The number of consecutive failures. #### Response Example ```json { "tasks": [ { "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef", "description": "Send a daily reminder", "status": "PENDING", "scheduled_time": "2026-03-25T09:00:00Z", "cron": "0 9 * * *", "last_result": null, "consecutive_failures": 0 } ] } ``` ```