@@ -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 {
@@ -1917,17 +1925,6 @@ extension APIClient {
19171925 return try await post ( " v1/staged-tasks/promote " )
19181926 }
19191927
1920- /// One-time migration of existing AI tasks to staged_tasks
1921- func migrateStagedTasks( ) async throws {
1922- struct StatusResponse : Decodable { let status : String }
1923- let _: StatusResponse = try await post ( " v1/staged-tasks/migrate " )
1924- }
1925-
1926- /// Migrate conversation-extracted action items (no source field) to staged_tasks
1927- func migrateConversationItemsToStaged( ) async throws {
1928- struct MigrateResponse : Decodable { let status : String ; let migrated : Int ; let deleted : Int }
1929- let _: MigrateResponse = try await post ( " v1/staged-tasks/migrate-conversation-items " )
1930- }
19311928}
19321929
19331930/// Response for staged task promotion
@@ -3175,13 +3172,12 @@ extension APIClient {
31753172
31763173 /// Regenerates persona prompt from current public memories
31773174 func regeneratePersonaPrompt( ) async throws -> GeneratePromptResponse {
3178- struct EmptyRequest : Encodable { }
3179- return try await post ( " v1/personas/generate-prompt " , body: EmptyRequest ( ) )
3175+ return try await get ( " v1/app/generate-prompts " )
31803176 }
31813177
31823178 /// Checks if a username is available
31833179 func checkPersonaUsername( _ username: String ) async throws -> UsernameAvailableResponse {
3184- return try await get ( " v1/personas /check-username?username= \( username) " )
3180+ return try await get ( " v1/apps /check-username?username= \( username) " )
31853181 }
31863182}
31873183
@@ -3279,9 +3275,27 @@ struct GeneratePromptResponse: Codable {
32793275}
32803276
32813277/// Response for username availability check
3282- struct UsernameAvailableResponse : Codable {
3278+ struct UsernameAvailableResponse : Decodable {
32833279 let available : Bool
3284- let username : String
3280+ let username : String ?
3281+ let isTaken : Bool ?
3282+
3283+ enum CodingKeys : String , CodingKey {
3284+ case available, username
3285+ case isTaken = " is_taken "
3286+ }
3287+
3288+ init ( from decoder: Decoder ) throws {
3289+ let container = try decoder. container ( keyedBy: CodingKeys . self)
3290+ username = try container. decodeIfPresent ( String . self, forKey: . username)
3291+ isTaken = try container. decodeIfPresent ( Bool . self, forKey: . isTaken)
3292+ // Python returns is_taken; Rust returned available. Support both.
3293+ if let isTaken = isTaken {
3294+ available = !isTaken
3295+ } else {
3296+ available = try container. decodeIfPresent ( Bool . self, forKey: . available) ?? true
3297+ }
3298+ }
32853299}
32863300
32873301// MARK: - User Settings API
@@ -4119,7 +4133,7 @@ extension APIClient {
41194133 }
41204134
41214135 let body = InitialMessageRequest ( sessionId: sessionId, appId: appId)
4122- return try await post ( " v2/chat/ initial-message " , body: body)
4136+ return try await post ( " v2/initial-message " , body: body)
41234137 }
41244138
41254139 /// Generate a title for a chat session based on its messages
@@ -4268,31 +4282,51 @@ extension APIClient {
42684282 // MARK: - Agent VM
42694283
42704284 struct AgentProvisionResponse : Decodable {
4271- let status : String
4272- let vmName : String
4285+ let hasVm : Bool
4286+ let status : String ?
4287+ let vmName : String ?
42734288 let ip : String ?
4274- let authToken : String
4275- let agentStatus : String
4289+ let authToken : String ?
4290+ let agentStatus : String ?
4291+
4292+ enum CodingKeys : String , CodingKey {
4293+ case hasVm = " has_vm "
4294+ case status
4295+ case vmName = " vm_name "
4296+ case ip
4297+ case authToken = " auth_token "
4298+ case agentStatus = " agent_status "
4299+ }
42764300 }
42774301
42784302 /// Provision a cloud agent VM for the current user (fire-and-forget)
42794303 func provisionAgentVM( ) async throws -> AgentProvisionResponse {
4280- return try await post ( " v2 /agent/provision " )
4304+ return try await post ( " v1 /agent/vm-ensure " )
42814305 }
42824306
42834307 struct AgentStatusResponse : Decodable {
4284- let vmName : String
4285- let zone : String
4308+ let hasVm : Bool
4309+ let vmName : String ?
4310+ let zone : String ?
42864311 let ip : String ?
4287- let status : String
4288- let authToken : String
4289- let createdAt : String
4312+ let status : String ?
4313+ let authToken : String ?
4314+ let createdAt : String ?
42904315 let lastQueryAt : String ?
4316+
4317+ enum CodingKeys : String , CodingKey {
4318+ case hasVm = " has_vm "
4319+ case vmName = " vm_name "
4320+ case zone, ip, status
4321+ case authToken = " auth_token "
4322+ case createdAt = " created_at "
4323+ case lastQueryAt = " last_query_at "
4324+ }
42914325 }
42924326
42934327 /// Get current agent VM status
42944328 func getAgentStatus( ) async throws -> AgentStatusResponse ? {
4295- return try await get ( " v2 /agent/status" )
4329+ return try await get ( " v1 /agent/vm- status" )
42964330 }
42974331}
42984332
@@ -4397,41 +4431,13 @@ extension APIClient {
43974431 costUsd: Double ,
43984432 account: String = " omi "
43994433 ) async {
4400- struct Req : Encodable {
4401- let input_tokens : Int
4402- let output_tokens : Int
4403- let cache_read_tokens : Int
4404- let cache_write_tokens : Int
4405- let total_tokens : Int
4406- let cost_usd : Double
4407- let account : String
4408- }
4409- struct Res : Decodable { let status : String }
4410- do {
4411- let _: Res = try await post ( " v1/users/me/llm-usage " , body: Req (
4412- input_tokens: inputTokens,
4413- output_tokens: outputTokens,
4414- cache_read_tokens: cacheReadTokens,
4415- cache_write_tokens: cacheWriteTokens,
4416- total_tokens: totalTokens,
4417- cost_usd: costUsd,
4418- account: account
4419- ) )
4420- } catch {
4421- log ( " APIClient: LLM usage record failed: \( error. localizedDescription) " )
4422- }
4434+ // No-op: LLM usage tracking endpoint not available in Python backend
4435+ log ( " APIClient: recordLlmUsage no-op (endpoint removed) " )
44234436 }
44244437
44254438 func fetchTotalOmiAICost( ) async -> Double ? {
4426- struct Res : Decodable { let total_cost_usd : Double }
4427- do {
4428- log ( " APIClient: Fetching total Omi AI cost from backend " )
4429- let res : Res = try await get ( " v1/users/me/llm-usage/total " )
4430- log ( " APIClient: Total Omi AI cost from backend: $ \( String ( format: " %.4f " , res. total_cost_usd) ) " )
4431- return res. total_cost_usd
4432- } catch {
4433- log ( " APIClient: LLM total cost fetch failed: \( error. localizedDescription) " )
4434- return nil
4435- }
4439+ // No-op: LLM usage total endpoint not available in Python backend
4440+ log ( " APIClient: fetchTotalOmiAICost no-op (endpoint removed) " )
4441+ return nil
44364442 }
44374443}
0 commit comments