Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions OrbitDockNative/OrbitDock/Services/Server/API/SessionsClient.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,36 @@
import Foundation

struct SessionsClient: Sendable {
enum OptionalStringPatch: Encodable, Sendable {
case set(String)
case clear

func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case let .set(value):
try container.encode(value)
case .clear:
try container.encodeNil()
}
}
}

enum OptionalBoolPatch: Encodable, Sendable {
case set(Bool)
case clear

func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case let .set(value):
try container.encode(value)
case .clear:
try container.encodeNil()
}
}
}

struct SessionsListResponse: Decodable {
let sessions: [ServerSessionListItem]
}
Expand All @@ -25,6 +55,107 @@ struct SessionsClient: Sendable {
var disallowedTools: [String] = []
var effort: String?
var allowBypassPermissions: Bool?
var codexConfigSource: ServerCodexConfigSource?
}

struct CodexPreferencesResponse: Decodable {
let defaultConfigSource: ServerCodexConfigSource

enum CodingKeys: String, CodingKey {
case defaultConfigSource = "default_config_source"
}
}

struct UpdateCodexPreferencesRequest: Encodable {
let defaultConfigSource: ServerCodexConfigSource

enum CodingKeys: String, CodingKey {
case defaultConfigSource = "default_config_source"
}
}

struct CodexInspectRequest: Encodable {
let cwd: String
var codexConfigSource: ServerCodexConfigSource?
var model: String?
var approvalPolicy: String?
var sandboxMode: String?
var collaborationMode: String?
var multiAgent: Bool?
var personality: String?
var serviceTier: String?
var developerInstructions: String?
var effort: String?
}

struct CodexInspectorResponse: Decodable {
let effectiveSettings: CodexEffectiveSettings
let origins: [String: CodexInspectorOrigin]
let layers: [CodexInspectorLayer]
let warnings: [String]

enum CodingKeys: String, CodingKey {
case effectiveSettings = "effective_settings"
case origins
case layers
case warnings
}
}

struct CodexEffectiveSettings: Decodable {
let configSource: ServerCodexConfigSource
let model: String?
let approvalPolicy: String?
let sandboxMode: String?
let collaborationMode: String?
let multiAgent: Bool?
let personality: String?
let serviceTier: String?
let developerInstructions: String?
let effort: String?

enum CodingKeys: String, CodingKey {
case configSource = "config_source"
case model
case approvalPolicy = "approval_policy"
case sandboxMode = "sandbox_mode"
case collaborationMode = "collaboration_mode"
case multiAgent = "multi_agent"
case personality
case serviceTier = "service_tier"
case developerInstructions = "developer_instructions"
case effort
}
}

struct CodexInspectorOrigin: Decodable {
let sourceKind: String
let path: String?
let version: String

enum CodingKeys: String, CodingKey {
case sourceKind = "source_kind"
case path
case version
}
}

struct CodexInspectorLayer: Decodable, Identifiable {
let sourceKind: String
let path: String?
let version: String
let config: AnyCodable
let disabledReason: String?

var id: String { [sourceKind, path ?? "none", version].joined(separator: "|") }

enum CodingKeys: String, CodingKey {
case sourceKind = "source_kind"
case path
case version
case config
case disabledReason = "disabled_reason"
}
}

struct CreateSessionResponse: Decodable {
Expand Down Expand Up @@ -82,6 +213,22 @@ struct SessionsClient: Sendable {
var developerInstructions: String?
}

struct UpdateCodexSessionOverridesRequest: Encodable {
var collaborationMode: OptionalStringPatch?
var multiAgent: OptionalBoolPatch?
var personality: OptionalStringPatch?
var serviceTier: OptionalStringPatch?
var developerInstructions: OptionalStringPatch?

enum CodingKeys: String, CodingKey {
case collaborationMode = "collaboration_mode"
case multiAgent = "multi_agent"
case personality
case serviceTier = "service_tier"
case developerInstructions = "developer_instructions"
}
}

struct ForkRequest: Encodable {
var nthUserMessage: UInt32?
var model: String?
Expand Down Expand Up @@ -154,6 +301,22 @@ struct SessionsClient: Sendable {
try await http.post("/api/sessions", body: request)
}

func fetchCodexPreferences() async throws -> CodexPreferencesResponse {
try await http.get("/api/server/codex-preferences")
}

func updateCodexPreferences(_ request: UpdateCodexPreferencesRequest) async throws -> CodexPreferencesResponse {
try await http.request(
path: "/api/server/codex-preferences",
method: "PUT",
body: request
)
}

func inspectCodexConfig(_ request: CodexInspectRequest) async throws -> CodexInspectorResponse {
try await http.post("/api/codex/config/inspect", body: request)
}

func resumeSession(_ sessionId: String) async throws -> ResumeSessionResponse {
try await http.post(
"/api/sessions/\(requestBuilder.encodePathComponent(sessionId))/resume",
Expand Down Expand Up @@ -192,6 +355,17 @@ struct SessionsClient: Sendable {
)
}

func updateCodexSessionOverrides(
_ sessionId: String,
config: UpdateCodexSessionOverridesRequest
) async throws {
let _: ServerAcceptedResponse = try await http.request(
path: "/api/sessions/\(requestBuilder.encodePathComponent(sessionId))/config",
method: "PATCH",
body: config
)
}

func forkSession(_ sourceSessionId: String, request: ForkRequest) async throws -> ForkResponse {
try await http.post(
"/api/sessions/\(requestBuilder.encodePathComponent(sourceSessionId))/fork",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,35 @@ enum ServerWorkStatus: String, Codable {
case ended
}

enum ServerCodexConfigSource: String, Codable, CaseIterable {
case orbitdock
case user
}

struct ServerCodexSessionOverrides: Codable, Equatable {
let model: String?
let approvalPolicy: String?
let sandboxMode: String?
let collaborationMode: String?
let multiAgent: Bool?
let personality: String?
let serviceTier: String?
let developerInstructions: String?
let effort: String?

enum CodingKeys: String, CodingKey {
case model
case approvalPolicy = "approval_policy"
case sandboxMode = "sandbox_mode"
case collaborationMode = "collaboration_mode"
case multiAgent = "multi_agent"
case personality
case serviceTier = "service_tier"
case developerInstructions = "developer_instructions"
case effort
}
}

struct ServerTokenUsage: Codable, Equatable {
let inputTokens: UInt64
let outputTokens: UInt64
Expand Down Expand Up @@ -222,6 +251,8 @@ struct ServerSessionSummary: Codable, Identifiable {
let personality: String?
let serviceTier: String?
let developerInstructions: String?
let codexConfigSource: ServerCodexConfigSource?
let codexConfigOverrides: ServerCodexSessionOverrides?
let pendingToolName: String?
let pendingToolInput: String?
let pendingQuestion: String?
Expand Down Expand Up @@ -271,6 +302,8 @@ struct ServerSessionSummary: Codable, Identifiable {
case personality
case serviceTier = "service_tier"
case developerInstructions = "developer_instructions"
case codexConfigSource = "codex_config_source"
case codexConfigOverrides = "codex_config_overrides"
case pendingToolName = "pending_tool_name"
case pendingToolInput = "pending_tool_input"
case pendingQuestion = "pending_question"
Expand Down Expand Up @@ -485,6 +518,8 @@ struct ServerSessionState: Codable, Identifiable {
let personality: String?
let serviceTier: String?
let developerInstructions: String?
let codexConfigSource: ServerCodexConfigSource?
let codexConfigOverrides: ServerCodexSessionOverrides?
let pendingToolName: String?
let pendingToolInput: String?
let pendingQuestion: String?
Expand Down Expand Up @@ -547,6 +582,8 @@ struct ServerSessionState: Codable, Identifiable {
case personality
case serviceTier = "service_tier"
case developerInstructions = "developer_instructions"
case codexConfigSource = "codex_config_source"
case codexConfigOverrides = "codex_config_overrides"
case pendingToolName = "pending_tool_name"
case pendingToolInput = "pending_tool_input"
case pendingQuestion = "pending_question"
Expand Down Expand Up @@ -615,6 +652,8 @@ struct ServerSessionState: Codable, Identifiable {
personality = try container.decodeIfPresent(String.self, forKey: .personality)
serviceTier = try container.decodeIfPresent(String.self, forKey: .serviceTier)
developerInstructions = try container.decodeIfPresent(String.self, forKey: .developerInstructions)
codexConfigSource = try container.decodeIfPresent(ServerCodexConfigSource.self, forKey: .codexConfigSource)
codexConfigOverrides = try container.decodeIfPresent(ServerCodexSessionOverrides.self, forKey: .codexConfigOverrides)
pendingToolName = try container.decodeIfPresent(String.self, forKey: .pendingToolName)
pendingToolInput = try container.decodeIfPresent(String.self, forKey: .pendingToolInput)
pendingQuestion = try container.decodeIfPresent(String.self, forKey: .pendingQuestion)
Expand Down Expand Up @@ -677,6 +716,8 @@ struct ServerSessionState: Codable, Identifiable {
try container.encodeIfPresent(personality, forKey: .personality)
try container.encodeIfPresent(serviceTier, forKey: .serviceTier)
try container.encodeIfPresent(developerInstructions, forKey: .developerInstructions)
try container.encodeIfPresent(codexConfigSource, forKey: .codexConfigSource)
try container.encodeIfPresent(codexConfigOverrides, forKey: .codexConfigOverrides)
try container.encodeIfPresent(pendingToolName, forKey: .pendingToolName)
try container.encodeIfPresent(pendingToolInput, forKey: .pendingToolInput)
try container.encodeIfPresent(pendingQuestion, forKey: .pendingQuestion)
Expand Down Expand Up @@ -799,6 +840,8 @@ struct ServerStateChanges: Codable {
let personality: String??
let serviceTier: String??
let developerInstructions: String??
let codexConfigSource: ServerCodexConfigSource??
let codexConfigOverrides: ServerCodexSessionOverrides??
let lastActivityAt: String?
let currentTurnId: String??
let turnCount: UInt64?
Expand Down Expand Up @@ -835,6 +878,8 @@ struct ServerStateChanges: Codable {
personality: String?? = nil,
serviceTier: String?? = nil,
developerInstructions: String?? = nil,
codexConfigSource: ServerCodexConfigSource?? = nil,
codexConfigOverrides: ServerCodexSessionOverrides?? = nil,
lastActivityAt: String? = nil,
currentTurnId: String?? = nil,
turnCount: UInt64? = nil,
Expand Down Expand Up @@ -870,6 +915,8 @@ struct ServerStateChanges: Codable {
self.personality = personality
self.serviceTier = serviceTier
self.developerInstructions = developerInstructions
self.codexConfigSource = codexConfigSource
self.codexConfigOverrides = codexConfigOverrides
self.lastActivityAt = lastActivityAt
self.currentTurnId = currentTurnId
self.turnCount = turnCount
Expand Down Expand Up @@ -907,6 +954,8 @@ struct ServerStateChanges: Codable {
case personality
case serviceTier = "service_tier"
case developerInstructions = "developer_instructions"
case codexConfigSource = "codex_config_source"
case codexConfigOverrides = "codex_config_overrides"
case lastActivityAt = "last_activity_at"
case currentTurnId = "current_turn_id"
case turnCount = "turn_count"
Expand Down Expand Up @@ -954,6 +1003,11 @@ struct ServerStateChanges: Codable {
personality = try container.decodePatchValue(String.self, forKey: .personality)
serviceTier = try container.decodePatchValue(String.self, forKey: .serviceTier)
developerInstructions = try container.decodePatchValue(String.self, forKey: .developerInstructions)
codexConfigSource = try container.decodePatchValue(ServerCodexConfigSource.self, forKey: .codexConfigSource)
codexConfigOverrides = try container.decodePatchValue(
ServerCodexSessionOverrides.self,
forKey: .codexConfigOverrides
)
lastActivityAt = try container.decodeIfPresent(String.self, forKey: .lastActivityAt)
currentTurnId = try container.decodePatchValue(String.self, forKey: .currentTurnId)
turnCount = try container.decodeIfPresent(UInt64.self, forKey: .turnCount)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ extension ServerSessionState {
personality: personality,
serviceTier: serviceTier,
developerInstructions: developerInstructions,
codexConfigSource: codexConfigSource,
codexConfigOverrides: codexConfigOverrides,
summary: summary,
customName: customName,
firstPrompt: firstPrompt,
Expand Down
Loading
Loading