pi-agent: Fix final integrated review
This commit is contained in:
@@ -56,32 +56,57 @@ func defaultModelOptions() modelOptions {
|
||||
}
|
||||
|
||||
type presentationState struct {
|
||||
snapshot app.Snapshot
|
||||
page page
|
||||
width int
|
||||
height int
|
||||
selected int
|
||||
profileOffset int
|
||||
profileDetails int
|
||||
profileDelete *profileDeleteConfirmation
|
||||
snapshot app.Snapshot
|
||||
page page
|
||||
terminal terminalDimensions
|
||||
dashboard dashboardPresentationState
|
||||
profile profilePresentationState
|
||||
form formPresentationState
|
||||
help helpPresentationState
|
||||
operation operationPresentationState
|
||||
}
|
||||
|
||||
type terminalDimensions struct {
|
||||
width int
|
||||
height int
|
||||
}
|
||||
|
||||
type dashboardPresentationState struct {
|
||||
selectedTargetID string
|
||||
dashboardFocus dashboardPane
|
||||
focus dashboardPane
|
||||
showUnavailable bool
|
||||
detailsOffset int
|
||||
driftResolutionTargetID string
|
||||
picker profilePickerState
|
||||
form formState
|
||||
help helpDialogState
|
||||
confirmation *app.Confirmation
|
||||
confirmationDialog *confirmationDialog
|
||||
status string
|
||||
operationStatus app.OperationStatus
|
||||
currentError *operationError
|
||||
errorExpanded bool
|
||||
errorOffset int
|
||||
exitDeferred bool
|
||||
operationActive bool
|
||||
operationProgress map[string]app.TargetProgressPhase
|
||||
}
|
||||
|
||||
type profilePresentationState struct {
|
||||
selected int
|
||||
listOffset int
|
||||
detailsOffset int
|
||||
deletion *profileDeleteConfirmation
|
||||
status string
|
||||
}
|
||||
|
||||
type formPresentationState struct {
|
||||
state formState
|
||||
}
|
||||
|
||||
type helpPresentationState struct {
|
||||
dialog helpDialogState
|
||||
}
|
||||
|
||||
type operationPresentationState struct {
|
||||
confirmation *app.Confirmation
|
||||
confirmationDialog *confirmationDialog
|
||||
status app.OperationStatus
|
||||
currentError *operationError
|
||||
errorExpanded bool
|
||||
errorOffset int
|
||||
exitDeferred bool
|
||||
active bool
|
||||
progress map[string]app.TargetProgressPhase
|
||||
spinnerFrame string
|
||||
}
|
||||
|
||||
// terminalPresentation is the terminal-presentation Module. Application
|
||||
@@ -116,7 +141,7 @@ func (p terminalPresentation) Render(state presentationState) string {
|
||||
// semanticTheme style is applied; otherwise an attacker could inject one of
|
||||
// the same allowlisted SGR sequences that the theme legitimately emits.
|
||||
state = sanitizePresentationState(state)
|
||||
width, height := state.width, state.height
|
||||
width, height := state.terminal.width, state.terminal.height
|
||||
if width <= 0 {
|
||||
width = 80
|
||||
}
|
||||
@@ -138,7 +163,7 @@ func (p terminalPresentation) Render(state presentationState) string {
|
||||
default:
|
||||
page = p.mainView(state, width, height)
|
||||
}
|
||||
if state.help.top(state.confirmation) {
|
||||
if state.help.dialog.top(state.operation.confirmation) {
|
||||
help := p.helpDialogView(state)
|
||||
// Retain the underlying page header so Help is visibly contextual and
|
||||
// modal rather than a replacement navigation destination.
|
||||
@@ -151,8 +176,8 @@ func (p terminalPresentation) Render(state presentationState) string {
|
||||
page.dashboard = nil
|
||||
}
|
||||
page.status = renderStatus(state)
|
||||
page.statusExpanded = state.errorExpanded && state.currentError != nil
|
||||
page.statusOffset = state.errorOffset
|
||||
page.statusExpanded = state.operation.errorExpanded && state.operation.currentError != nil
|
||||
page.statusOffset = state.operation.errorOffset
|
||||
page = redactTerminalPage(page)
|
||||
// Untrusted values were redacted and stripped of controls before semantic
|
||||
// styling. The final pass therefore removes unexpected terminal controls
|
||||
@@ -162,17 +187,18 @@ func (p terminalPresentation) Render(state presentationState) string {
|
||||
|
||||
func renderStatus(state presentationState) string {
|
||||
var lines []string
|
||||
if state.exitDeferred {
|
||||
operation := state.operation
|
||||
if operation.exitDeferred {
|
||||
lines = append(lines, "Exit requested — waiting for the current mutation to finish safely")
|
||||
} else if state.operationStatus.Summary != "" {
|
||||
lines = append(lines, state.operationStatus.Summary)
|
||||
} else if state.status != "" {
|
||||
lines = append(lines, state.status)
|
||||
} else if operation.status.Summary != "" {
|
||||
lines = append(lines, operation.status.Summary)
|
||||
} else if state.profile.status != "" {
|
||||
lines = append(lines, state.profile.status)
|
||||
}
|
||||
if state.currentError != nil {
|
||||
errorText := "Current error: " + state.currentError.status.Summary
|
||||
if state.errorExpanded && state.currentError.detail != "" {
|
||||
errorText += "\n" + state.currentError.detail
|
||||
if operation.currentError != nil {
|
||||
errorText := "Current error: " + operation.currentError.status.Summary
|
||||
if operation.errorExpanded && operation.currentError.detail != "" {
|
||||
errorText += "\n" + operation.currentError.detail
|
||||
}
|
||||
lines = append(lines, errorText)
|
||||
}
|
||||
@@ -236,35 +262,35 @@ func sanitizePresentationState(state presentationState) presentationState {
|
||||
// Apply that stronger policy to every status/error ingress before styling.
|
||||
sanitizeStatus = sanitizeUntrustedUserinfoText
|
||||
}
|
||||
state.status = sanitizeStatus(state.status)
|
||||
state.operationStatus.Summary = sanitizeStatus(state.operationStatus.Summary)
|
||||
if state.currentError != nil {
|
||||
current := *state.currentError
|
||||
state.profile.status = sanitizeStatus(state.profile.status)
|
||||
state.operation.status.Summary = sanitizeStatus(state.operation.status.Summary)
|
||||
if state.operation.currentError != nil {
|
||||
current := *state.operation.currentError
|
||||
current.status.Summary = sanitizeStatus(current.status.Summary)
|
||||
current.detail = sanitizeStatus(current.detail)
|
||||
state.currentError = ¤t
|
||||
state.operation.currentError = ¤t
|
||||
}
|
||||
if state.confirmation != nil {
|
||||
confirmation := sanitizePresentationConfirmation(*state.confirmation)
|
||||
state.confirmation = &confirmation
|
||||
if state.operation.confirmation != nil {
|
||||
confirmation := sanitizePresentationConfirmation(*state.operation.confirmation)
|
||||
state.operation.confirmation = &confirmation
|
||||
}
|
||||
if state.confirmationDialog != nil {
|
||||
dialog := *state.confirmationDialog
|
||||
if state.operation.confirmationDialog != nil {
|
||||
dialog := *state.operation.confirmationDialog
|
||||
dialog.request = sanitizePresentationConfirmation(dialog.request)
|
||||
state.confirmationDialog = &dialog
|
||||
state.operation.confirmationDialog = &dialog
|
||||
}
|
||||
if state.profileDelete != nil {
|
||||
confirmation := *state.profileDelete
|
||||
if state.profile.deletion != nil {
|
||||
confirmation := *state.profile.deletion
|
||||
confirmation.name = sanitizeUntrustedText(confirmation.name)
|
||||
confirmation.dialog.request = sanitizePresentationConfirmation(confirmation.dialog.request)
|
||||
state.profileDelete = &confirmation
|
||||
state.profile.deletion = &confirmation
|
||||
}
|
||||
|
||||
state.picker.selectedName = sanitizeUntrustedText(state.picker.selectedName)
|
||||
searchPosition := state.picker.search.Position()
|
||||
state.picker.search.SetValue(sanitizeUntrustedText(state.picker.search.Value()))
|
||||
state.picker.search.SetCursor(searchPosition)
|
||||
state.form = sanitizePresentationForm(state.form)
|
||||
state.dashboard.picker.selectedName = sanitizeUntrustedText(state.dashboard.picker.selectedName)
|
||||
searchPosition := state.dashboard.picker.search.Position()
|
||||
state.dashboard.picker.search.SetValue(sanitizeUntrustedText(state.dashboard.picker.search.Value()))
|
||||
state.dashboard.picker.search.SetCursor(searchPosition)
|
||||
state.form.state = sanitizePresentationForm(state.form.state)
|
||||
return state
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user