@@ -405,14 +405,10 @@ extension APIClient {
405405 return response. count
406406 }
407407
408- /// Gets the count of AI chat messages from PostHog
408+ /// Gets the count of AI chat messages
409409 func getChatMessageCount( ) async throws -> Int {
410- struct CountResponse : Decodable {
411- let count : Int
412- }
413-
414- let response : CountResponse = try await get ( " v1/users/stats/chat-messages " )
415- return response. count
410+ // No-op: chat-messages stats endpoint not available in Python backend
411+ return 0
416412 }
417413
418414 /// Merges multiple conversations into a new conversation
@@ -581,7 +577,7 @@ struct ServerConversation: Codable, Identifiable, Equatable {
581577 let container = try decoder. container ( keyedBy: CodingKeys . self)
582578
583579 id = try container. decode ( String . self, forKey: . id)
584- createdAt = try container. decode ( Date . self, forKey: . createdAt)
580+ createdAt = try container. decodeIfPresent ( Date . self, forKey: . createdAt) ?? Date ( )
585581 startedAt = try container. decodeIfPresent ( Date . self, forKey: . startedAt)
586582 finishedAt = try container. decodeIfPresent ( Date . self, forKey: . finishedAt)
587583 structured = try container. decode ( Structured . self, forKey: . structured)
@@ -1454,14 +1450,26 @@ struct UserProfile: Codable {
14541450// MARK: - Action Items API
14551451
14561452/// Response wrapper for paginated action items list
1457- struct ActionItemsListResponse : Codable {
1453+ struct ActionItemsListResponse : Decodable {
14581454 let items : [ TaskActionItem ]
14591455 let hasMore : Bool
14601456
14611457 enum CodingKeys : String , CodingKey {
1458+ case actionItems = " action_items "
14621459 case items
14631460 case hasMore = " has_more "
14641461 }
1462+
1463+ init ( from decoder: Decoder ) throws {
1464+ let container = try decoder. container ( keyedBy: CodingKeys . self)
1465+ hasMore = try container. decodeIfPresent ( Bool . self, forKey: . hasMore) ?? false
1466+ // Python action_items endpoint returns "action_items"; staged-tasks returns "items"
1467+ if let actionItems = try container. decodeIfPresent ( [ TaskActionItem ] . self, forKey: . actionItems) {
1468+ items = actionItems
1469+ } else {
1470+ items = try container. decodeIfPresent ( [ TaskActionItem ] . self, forKey: . items) ?? [ ]
1471+ }
1472+ }
14651473}
14661474
14671475extension APIClient {
@@ -1890,17 +1898,6 @@ extension APIClient {
18901898 return try await post ( " v1/staged-tasks/promote " )
18911899 }
18921900
1893- /// One-time migration of existing AI tasks to staged_tasks
1894- func migrateStagedTasks( ) async throws {
1895- struct StatusResponse : Decodable { let status : String }
1896- let _: StatusResponse = try await post ( " v1/staged-tasks/migrate " )
1897- }
1898-
1899- /// Migrate conversation-extracted action items (no source field) to staged_tasks
1900- func migrateConversationItemsToStaged( ) async throws {
1901- struct MigrateResponse : Decodable { let status : String ; let migrated : Int ; let deleted : Int }
1902- let _: MigrateResponse = try await post ( " v1/staged-tasks/migrate-conversation-items " )
1903- }
19041901}
19051902
19061903/// Response for staged task promotion
@@ -3148,13 +3145,12 @@ extension APIClient {
31483145
31493146 /// Regenerates persona prompt from current public memories
31503147 func regeneratePersonaPrompt( ) async throws -> GeneratePromptResponse {
3151- struct EmptyRequest : Encodable { }
3152- return try await post ( " v1/personas/generate-prompt " , body: EmptyRequest ( ) )
3148+ return try await get ( " v1/app/generate-prompts " )
31533149 }
31543150
31553151 /// Checks if a username is available
31563152 func checkPersonaUsername( _ username: String ) async throws -> UsernameAvailableResponse {
3157- return try await get ( " v1/personas /check-username?username= \( username) " )
3153+ return try await get ( " v1/apps /check-username?username= \( username) " )
31583154 }
31593155}
31603156
@@ -3252,9 +3248,27 @@ struct GeneratePromptResponse: Codable {
32523248}
32533249
32543250/// Response for username availability check
3255- struct UsernameAvailableResponse : Codable {
3251+ struct UsernameAvailableResponse : Decodable {
32563252 let available : Bool
3257- let username : String
3253+ let username : String ?
3254+ let isTaken : Bool ?
3255+
3256+ enum CodingKeys : String , CodingKey {
3257+ case available, username
3258+ case isTaken = " is_taken "
3259+ }
3260+
3261+ init ( from decoder: Decoder ) throws {
3262+ let container = try decoder. container ( keyedBy: CodingKeys . self)
3263+ username = try container. decodeIfPresent ( String . self, forKey: . username)
3264+ isTaken = try container. decodeIfPresent ( Bool . self, forKey: . isTaken)
3265+ // Python returns is_taken; Rust returned available. Support both.
3266+ if let isTaken = isTaken {
3267+ available = !isTaken
3268+ } else {
3269+ available = try container. decodeIfPresent ( Bool . self, forKey: . available) ?? true
3270+ }
3271+ }
32583272}
32593273
32603274// MARK: - User Settings API
@@ -4087,7 +4101,7 @@ extension APIClient {
40874101 }
40884102
40894103 let body = InitialMessageRequest ( sessionId: sessionId, appId: appId)
4090- return try await post ( " v2/chat/ initial-message " , body: body)
4104+ return try await post ( " v2/initial-message " , body: body)
40914105 }
40924106
40934107 /// Generate a title for a chat session based on its messages
@@ -4236,31 +4250,51 @@ extension APIClient {
42364250 // MARK: - Agent VM
42374251
42384252 struct AgentProvisionResponse : Decodable {
4239- let status : String
4240- let vmName : String
4253+ let hasVm : Bool
4254+ let status : String ?
4255+ let vmName : String ?
42414256 let ip : String ?
4242- let authToken : String
4243- let agentStatus : String
4257+ let authToken : String ?
4258+ let agentStatus : String ?
4259+
4260+ enum CodingKeys : String , CodingKey {
4261+ case hasVm = " has_vm "
4262+ case status
4263+ case vmName = " vm_name "
4264+ case ip
4265+ case authToken = " auth_token "
4266+ case agentStatus = " agent_status "
4267+ }
42444268 }
42454269
42464270 /// Provision a cloud agent VM for the current user (fire-and-forget)
42474271 func provisionAgentVM( ) async throws -> AgentProvisionResponse {
4248- return try await post ( " v2 /agent/provision " )
4272+ return try await post ( " v1 /agent/vm-ensure " )
42494273 }
42504274
42514275 struct AgentStatusResponse : Decodable {
4252- let vmName : String
4253- let zone : String
4276+ let hasVm : Bool
4277+ let vmName : String ?
4278+ let zone : String ?
42544279 let ip : String ?
4255- let status : String
4256- let authToken : String
4257- let createdAt : String
4280+ let status : String ?
4281+ let authToken : String ?
4282+ let createdAt : String ?
42584283 let lastQueryAt : String ?
4284+
4285+ enum CodingKeys : String , CodingKey {
4286+ case hasVm = " has_vm "
4287+ case vmName = " vm_name "
4288+ case zone, ip, status
4289+ case authToken = " auth_token "
4290+ case createdAt = " created_at "
4291+ case lastQueryAt = " last_query_at "
4292+ }
42594293 }
42604294
42614295 /// Get current agent VM status
42624296 func getAgentStatus( ) async throws -> AgentStatusResponse ? {
4263- return try await get ( " v2 /agent/status" )
4297+ return try await get ( " v1 /agent/vm- status" )
42644298 }
42654299}
42664300
@@ -4365,41 +4399,13 @@ extension APIClient {
43654399 costUsd: Double ,
43664400 account: String = " omi "
43674401 ) async {
4368- struct Req : Encodable {
4369- let input_tokens : Int
4370- let output_tokens : Int
4371- let cache_read_tokens : Int
4372- let cache_write_tokens : Int
4373- let total_tokens : Int
4374- let cost_usd : Double
4375- let account : String
4376- }
4377- struct Res : Decodable { let status : String }
4378- do {
4379- let _: Res = try await post ( " v1/users/me/llm-usage " , body: Req (
4380- input_tokens: inputTokens,
4381- output_tokens: outputTokens,
4382- cache_read_tokens: cacheReadTokens,
4383- cache_write_tokens: cacheWriteTokens,
4384- total_tokens: totalTokens,
4385- cost_usd: costUsd,
4386- account: account
4387- ) )
4388- } catch {
4389- log ( " APIClient: LLM usage record failed: \( error. localizedDescription) " )
4390- }
4402+ // No-op: LLM usage tracking endpoint not available in Python backend
4403+ log ( " APIClient: recordLlmUsage no-op (endpoint removed) " )
43914404 }
43924405
43934406 func fetchTotalOmiAICost( ) async -> Double ? {
4394- struct Res : Decodable { let total_cost_usd : Double }
4395- do {
4396- log ( " APIClient: Fetching total Omi AI cost from backend " )
4397- let res : Res = try await get ( " v1/users/me/llm-usage/total " )
4398- log ( " APIClient: Total Omi AI cost from backend: $ \( String ( format: " %.4f " , res. total_cost_usd) ) " )
4399- return res. total_cost_usd
4400- } catch {
4401- log ( " APIClient: LLM total cost fetch failed: \( error. localizedDescription) " )
4402- return nil
4403- }
4407+ // No-op: LLM usage total endpoint not available in Python backend
4408+ log ( " APIClient: fetchTotalOmiAICost no-op (endpoint removed) " )
4409+ return nil
44044410 }
44054411}
0 commit comments