mirror of
https://github.com/wu736139669/hapi.git
synced 2026-10-10 19:42:21 +00:00
Add current-proposal decoding, dedicated implementation requests and composer-only continuation on iOS and Android. Keep pending/errors across row recycling, reject stale actions and prevent duplicate submissions. Include native regression tests and localized plan controls.
120 lines
4.3 KiB
Swift
120 lines
4.3 KiB
Swift
import Foundation
|
|
|
|
/// A pending tool-approval / user-input request raised by the agent.
|
|
///
|
|
/// Mirrors `AgentStateRequestSchema` (`shared/src/schemas.ts`). Permission
|
|
/// requests are NOT messages: they live on `Session.agentState.requests`
|
|
/// keyed by request id and are resolved over
|
|
/// `POST /api/sessions/:id/permissions/:requestId/approve|deny`.
|
|
public struct AgentStateRequest: Codable, Equatable, Sendable {
|
|
public var tool: String
|
|
/// Correlates a native tool call; approval still uses the request dictionary key.
|
|
public var toolCallId: String?
|
|
/// Free-form tool arguments (`z.unknown()` on the wire).
|
|
public var arguments: JSONValue?
|
|
/// Epoch ms when the request was raised; older CLIs omit it.
|
|
public var createdAt: Int?
|
|
|
|
public init(tool: String, arguments: JSONValue? = nil, createdAt: Int? = nil, toolCallId: String? = nil) {
|
|
self.tool = tool
|
|
self.toolCallId = toolCallId
|
|
self.arguments = arguments
|
|
self.createdAt = createdAt
|
|
}
|
|
}
|
|
|
|
/// A resolved permission request, moved from `requests` to
|
|
/// `completedRequests` once decided.
|
|
///
|
|
/// Mirrors `AgentStateCompletedRequestSchema` (`shared/src/schemas.ts`).
|
|
public struct AgentStateCompletedRequest: Codable, Equatable, Sendable {
|
|
public enum Status: String, Codable, Sendable {
|
|
case resolved
|
|
case canceled
|
|
case denied
|
|
case approved
|
|
}
|
|
|
|
public enum Decision: String, Codable, Sendable {
|
|
case approved
|
|
case approvedForSession = "approved_for_session"
|
|
case denied
|
|
case abort
|
|
}
|
|
|
|
public var tool: String
|
|
/// Correlates a native tool call; approval still uses the request dictionary key.
|
|
public var toolCallId: String?
|
|
public var arguments: JSONValue?
|
|
public var createdAt: Int?
|
|
public var completedAt: Int?
|
|
public var status: Status
|
|
public var reason: String?
|
|
/// Permission mode switched to while approving, when any.
|
|
public var mode: String?
|
|
public var decision: Decision?
|
|
public var allowTools: [String]?
|
|
/// Two wire formats, kept raw:
|
|
/// flat `{question: [answers]}` (AskUserQuestion) or
|
|
/// nested `{question: {answers: [...]}}` (request_user_input).
|
|
public var answers: JSONValue?
|
|
|
|
public init(
|
|
tool: String,
|
|
arguments: JSONValue? = nil,
|
|
createdAt: Int? = nil,
|
|
completedAt: Int? = nil,
|
|
status: Status,
|
|
reason: String? = nil,
|
|
mode: String? = nil,
|
|
decision: Decision? = nil,
|
|
allowTools: [String]? = nil,
|
|
answers: JSONValue? = nil,
|
|
toolCallId: String? = nil
|
|
) {
|
|
self.tool = tool
|
|
self.toolCallId = toolCallId
|
|
self.arguments = arguments
|
|
self.createdAt = createdAt
|
|
self.completedAt = completedAt
|
|
self.status = status
|
|
self.reason = reason
|
|
self.mode = mode
|
|
self.decision = decision
|
|
self.allowTools = allowTools
|
|
self.answers = answers
|
|
}
|
|
}
|
|
|
|
/// Agent-owned session state carried on `Session.agentState` and patched over
|
|
/// SSE under the `agentStateVersion` gate.
|
|
///
|
|
/// Mirrors `AgentStateSchema` (`shared/src/schemas.ts:195-203`).
|
|
public struct AgentState: Codable, Equatable, Sendable {
|
|
/// `true` while the terminal owns the session (remote control paused).
|
|
public var controlledByUser: Bool?
|
|
/// Launch mode the session was started in (persisted for reopen/resume).
|
|
public var startingMode: SessionStartingMode?
|
|
/// Current actionable shared Codex proposal's tool-call id. Nil withdraws
|
|
/// the plan menu; proposals are not entries in `requests`.
|
|
public var codexPlanProposalId: String?
|
|
/// Pending requests keyed by request id.
|
|
public var requests: [String: AgentStateRequest]?
|
|
/// Resolved requests keyed by request id.
|
|
public var completedRequests: [String: AgentStateCompletedRequest]?
|
|
|
|
public init(
|
|
controlledByUser: Bool? = nil,
|
|
startingMode: SessionStartingMode? = nil,
|
|
requests: [String: AgentStateRequest]? = nil,
|
|
completedRequests: [String: AgentStateCompletedRequest]? = nil,
|
|
codexPlanProposalId: String? = nil
|
|
) {
|
|
self.controlledByUser = controlledByUser
|
|
self.startingMode = startingMode
|
|
self.codexPlanProposalId = codexPlanProposalId
|
|
self.requests = requests
|
|
self.completedRequests = completedRequests
|
|
}
|
|
}
|