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
61 changes: 52 additions & 9 deletions apps/decodex-app/Sources/DecodexApp/AccountPanelView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2878,6 +2878,12 @@ struct OperatorLanePopoverView: View {
)
}

if statusReadoutItems.isEmpty == false {
measuredReadout {
OperatorLaneReadoutRow(title: "Status", items: statusReadoutItems)
}
}

if let modelProgress {
measuredReadout {
OperatorLaneProgressReadoutRow(
Expand Down Expand Up @@ -3007,12 +3013,49 @@ struct OperatorLanePopoverView: View {

private var hasReadoutContent: Bool {
modelProgress != nil
|| statusReadoutItems.isEmpty == false
|| totalOverviewMetrics.isEmpty == false
|| detailBuckets.isEmpty == false
|| lifecycleTableRows.isEmpty == false
|| fallbackRunReadoutItems.isEmpty == false
}

private var statusReadoutItems: [OperatorLaneReadoutItem] {
var items = [OperatorLaneReadoutItem]()

if let runPhase = panelTrimmed(run.runPhase ?? run.phase) {
items.append(
OperatorLaneReadoutItem(label: "run phase", value: rawPanelToken(runPhase))
)
}
if let currentOperation = panelTrimmed(run.currentOperation) {
items.append(
OperatorLaneReadoutItem(
label: "current operation",
value: rawPanelToken(currentOperation)
)
)
}
if let activeGoalPhase = panelTrimmed(run.activeGoalPhase) {
items.append(
OperatorLaneReadoutItem(
label: "active goal phase",
value: rawPanelToken(activeGoalPhase)
)
)
}
if let publicProgressPhase = panelTrimmed(run.publicProgressPhase) {
items.append(
OperatorLaneReadoutItem(
label: "public progress phase",
value: rawPanelToken(publicProgressPhase)
)
)
}

return items
}

private var fallbackRunReadoutItems: [OperatorLaneReadoutItem] {
guard let activity else {
return []
Expand Down Expand Up @@ -3187,9 +3230,9 @@ struct OperatorLanePopoverView: View {

return lifecycleMetrics.phases.map { phase in
lifecycleTableRow(
stage: panelTrimmed(phase.label)
lifecycleBucket: panelTrimmed(phase.label)
?? panelTrimmed(phase.phase).map(rawPanelToken)
?? "Phase",
?? "Lifecycle bucket",
attemptCount: phase.attemptCount,
wallSeconds: phase.wallSeconds,
buckets: phase.buckets,
Expand All @@ -3202,7 +3245,7 @@ struct OperatorLanePopoverView: View {
}

private func lifecycleTableRow(
stage: String,
lifecycleBucket: String,
attemptCount: Int,
wallSeconds: Int,
buckets: [OperatorLifecycleMetricBucket],
Expand All @@ -3223,7 +3266,7 @@ struct OperatorLanePopoverView: View {
let largestOutput = formatLargestOutput(bytes: largestOutputBytes)

return OperatorLifecycleTableRow(
stage: stage,
lifecycleBucket: lifecycleBucket,
attempts: attemptCount > 0 ? formatCompactCount(attemptCount) : "-",
runtime: runtime.text,
inputTokens: inputTokens > 0 ? formatCompactCount(inputTokens) : "-",
Expand Down Expand Up @@ -3560,7 +3603,7 @@ private enum OperatorTotalMetricGridCellRole {
}

struct OperatorLifecycleTableRow: Identifiable {
let stage: String
let lifecycleBucket: String
let attempts: String
let runtime: String
let inputTokens: String
Expand All @@ -3569,7 +3612,7 @@ struct OperatorLifecycleTableRow: Identifiable {
let largestOutput: String

var id: String {
stage
lifecycleBucket
}
}

Expand All @@ -3584,7 +3627,7 @@ struct OperatorLifecycleTableView: View {
verticalSpacing: OperatorLaneReadoutLayout.itemRowSpacing
) {
GridRow(alignment: .firstTextBaseline) {
headerCell("Stage", alignment: .leading)
headerCell("Lifecycle bucket", alignment: .leading)
headerCell("attempts", alignment: .trailing)
headerCell("inference", alignment: .trailing)
headerCell("input", alignment: .trailing)
Expand All @@ -3594,7 +3637,7 @@ struct OperatorLifecycleTableView: View {
}
ForEach(rows) { row in
GridRow(alignment: .firstTextBaseline) {
tableCell(row.stage, alignment: .leading)
tableCell(row.lifecycleBucket, alignment: .leading)
tableCell(row.attempts, alignment: .trailing)
tableCell(row.runtime, alignment: .trailing)
tableCell(row.inputTokens, alignment: .trailing)
Expand All @@ -3611,7 +3654,7 @@ struct OperatorLifecycleTableView: View {

private var accessibilityText: String {
rows.map { row in
"\(row.stage), attempts \(row.attempts), inference \(row.runtime), input \(row.inputTokens), output \(row.outputTokens), tools \(row.toolCalls), max output \(row.largestOutput)"
"\(row.lifecycleBucket), attempts \(row.attempts), inference \(row.runtime), input \(row.inputTokens), output \(row.outputTokens), tools \(row.toolCalls), max output \(row.largestOutput)"
}
.joined(separator: "; ")
}
Expand Down
22 changes: 20 additions & 2 deletions apps/decodex-app/Sources/DecodexApp/OperatorSnapshotModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -427,8 +427,11 @@ struct OperatorRunStatus: Decodable, Identifiable, Sendable {
let attemptStatus: String?
let attemptNumber: Int?
let phase: String?
let runPhase: String?
let waitReason: String?
let currentOperation: String?
let activeGoalPhase: String?
let publicProgressPhase: String?
let threadStatus: String?
let threadActiveFlags: [String]
let idleForSeconds: Int?
Expand Down Expand Up @@ -482,8 +485,8 @@ struct OperatorRunStatus: Decodable, Identifiable, Sendable {
if let operation = trimmed(currentOperation), operation.isEmpty == false, operation != "idle" {
return rawDisplayToken(operation)
}
if let phase = trimmed(phase), phase.isEmpty == false {
return rawDisplayToken(phase)
if let runPhase = trimmed(runPhase ?? phase), runPhase.isEmpty == false {
return rawDisplayToken(runPhase)
}
if let threadStatus = trimmed(threadStatus), threadStatus.isEmpty == false {
return rawDisplayToken(threadStatus)
Expand Down Expand Up @@ -637,8 +640,11 @@ struct OperatorRunStatus: Decodable, Identifiable, Sendable {
attemptStatus: activity.attemptStatus ?? attemptStatus,
attemptNumber: activity.attemptNumber ?? attemptNumber,
phase: activity.phase ?? phase,
runPhase: activity.runPhase ?? runPhase,
waitReason: activity.waitReason ?? waitReason,
currentOperation: activity.currentOperation ?? currentOperation,
activeGoalPhase: activity.activeGoalPhase ?? activeGoalPhase,
publicProgressPhase: activity.publicProgressPhase ?? publicProgressPhase,
threadStatus: activity.threadStatus ?? threadStatus,
threadActiveFlags: activity.threadActiveFlags.isEmpty ? threadActiveFlags : activity.threadActiveFlags,
idleForSeconds: activity.idleForSeconds ?? idleForSeconds,
Expand Down Expand Up @@ -693,8 +699,11 @@ struct OperatorRunStatus: Decodable, Identifiable, Sendable {
case attemptStatus = "attempt_status"
case attemptNumber = "attempt_number"
case phase
case runPhase = "run_phase"
case waitReason = "wait_reason"
case currentOperation = "current_operation"
case activeGoalPhase = "active_goal_phase"
case publicProgressPhase = "public_progress_phase"
case threadStatus = "thread_status"
case threadActiveFlags = "thread_active_flags"
case idleForSeconds = "idle_for_seconds"
Expand Down Expand Up @@ -736,8 +745,11 @@ struct OperatorRunStatus: Decodable, Identifiable, Sendable {
attemptStatus = try container.decodeIfPresent(String.self, forKey: .attemptStatus)
attemptNumber = try container.decodeIfPresent(Int.self, forKey: .attemptNumber)
phase = try container.decodeIfPresent(String.self, forKey: .phase)
runPhase = try container.decodeIfPresent(String.self, forKey: .runPhase)
waitReason = try container.decodeIfPresent(String.self, forKey: .waitReason)
currentOperation = try container.decodeIfPresent(String.self, forKey: .currentOperation)
activeGoalPhase = try container.decodeIfPresent(String.self, forKey: .activeGoalPhase)
publicProgressPhase = try container.decodeIfPresent(String.self, forKey: .publicProgressPhase)
threadStatus = try container.decodeIfPresent(String.self, forKey: .threadStatus)
threadActiveFlags = try container.decodeIfPresent([String].self, forKey: .threadActiveFlags) ?? []
idleForSeconds = try container.decodeIfPresent(Int.self, forKey: .idleForSeconds)
Expand Down Expand Up @@ -784,8 +796,11 @@ struct OperatorRunStatus: Decodable, Identifiable, Sendable {
attemptStatus: String?,
attemptNumber: Int?,
phase: String?,
runPhase: String?,
waitReason: String?,
currentOperation: String?,
activeGoalPhase: String?,
publicProgressPhase: String?,
threadStatus: String?,
threadActiveFlags: [String],
idleForSeconds: Int?,
Expand Down Expand Up @@ -821,8 +836,11 @@ struct OperatorRunStatus: Decodable, Identifiable, Sendable {
self.attemptStatus = attemptStatus
self.attemptNumber = attemptNumber
self.phase = phase
self.runPhase = runPhase
self.waitReason = waitReason
self.currentOperation = currentOperation
self.activeGoalPhase = activeGoalPhase
self.publicProgressPhase = publicProgressPhase
self.threadStatus = threadStatus
self.threadActiveFlags = threadActiveFlags
self.idleForSeconds = idleForSeconds
Expand Down
7 changes: 7 additions & 0 deletions apps/decodex/src/execution_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1253,6 +1253,7 @@ impl ExecutionProgramReadinessContext {
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) struct ExecutionNodeEvaluation {
node_id: String,
stage: ExecutionProgramNodeStage,
state: ExecutionReadinessState,
lifecycle_state: ExecutionProgramNodeLifecycleState,
reasons: Vec<String>,
Expand All @@ -1265,6 +1266,11 @@ impl ExecutionNodeEvaluation {
&self.node_id
}

/// Program node stage.
pub(crate) fn stage(&self) -> ExecutionProgramNodeStage {
self.stage
}

/// Normalized readiness state.
pub(crate) fn state(&self) -> ExecutionReadinessState {
self.state
Expand Down Expand Up @@ -1524,6 +1530,7 @@ fn evaluate_node(input: EvaluateNodeInput<'_>) -> Result<ExecutionNodeEvaluation

Ok(ExecutionNodeEvaluation {
node_id: node.node_id.clone(),
stage: node.stage,
state,
lifecycle_state,
reasons,
Expand Down
4 changes: 2 additions & 2 deletions apps/decodex/src/orchestrator/harness_improvement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ struct HarnessOutcomeProgram {
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
struct HarnessOutcomeProgramNode {
node_id: String,
stage: String,
program_stage: String,
queue_intent: String,
linear_issue_id: Option<String>,
linear_issue_identifier: Option<String>,
Expand Down Expand Up @@ -481,7 +481,7 @@ fn harness_outcome_program(record: &ExecutionProgramRecord) -> HarnessOutcomePro

HarnessOutcomeProgramNode {
node_id: node.node_id().to_owned(),
stage: node.stage().as_str().to_owned(),
program_stage: node.stage().as_str().to_owned(),
queue_intent: node.queue_intent().as_str().to_owned(),
linear_issue_id: linear_issue.map(|issue| issue.issue_id().to_owned()),
linear_issue_identifier: linear_issue
Expand Down
Loading