1use serde::{Deserialize, Serialize};
2
3#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
4#[serde(rename_all = "snake_case")]
5pub enum WorkflowDiagnosticCode {
6 WorkflowSyntaxInvalid,
7 WorkflowShapeInvalid,
8 WorkflowRequiredFieldMissing,
9 WorkflowFieldTypeInvalid,
10 WorkflowFieldValueInvalid,
11 WorkflowUnknownField,
12 WorkflowSchemaUnsupported,
13 WorkflowMetadataIdInvalid,
14 WorkflowMetadataNameInvalid,
15 WorkflowMetadataVersionInvalid,
16 WorkflowStateLimit,
17 WorkflowTransitionLimit,
18 WorkflowBindingLimit,
19 WorkflowRuntimeLimit,
20 WorkflowParallelismInvalid,
21 WorkflowWorksetLimitInvalid,
22 WorkflowRetryLimitInvalid,
23 WorkflowBindingIdInvalid,
24 WorkflowBindingDuplicate,
25 WorkflowBindingLabelInvalid,
26 WorkflowFallbackInvalid,
27 WorkflowEntrySlotInvalid,
28 WorkflowRuntimeIdInvalid,
29 WorkflowRuntimeBindingInvalid,
30 WorkflowWorksetIdInvalid,
31 WorkflowWorksetItemBindingInvalid,
32 WorkflowWorksetPredecessorFieldInvalid,
33 WorkflowWorksetFieldConflict,
34 WorkflowStateIdInvalid,
35 WorkflowStateLabelInvalid,
36 WorkflowStateInstructionInvalid,
37 WorkflowStateDuplicate,
38 WorkflowStateRetryInvalid,
39 WorkflowActorBindingInvalid,
40 WorkflowStateFieldInvalid,
41 WorkflowScriptRuntimeInvalid,
42 WorkflowScriptEntryMissing,
43 WorkflowScriptEntryInvalid,
44 WorkflowWorksetReferenceInvalid,
45 WorkflowWorksetBindingInvalid,
46 WorkflowInitialUnknown,
47 WorkflowTransitionIdInvalid,
48 WorkflowTransitionDuplicate,
49 WorkflowTransitionStateUnknown,
50 WorkflowGuardInvalid,
51 WorkflowGuardAmbiguous,
52 WorkflowRoutingInvalid,
53 WorkflowTransitionModeInvalid,
54 WorkflowFlowTargetIncomplete,
55 WorkflowTopologyInvalid,
56 WorkflowStateUnreachable,
57 WorkflowTerminalUnreachable,
58 WorkflowEffectCycle,
59 WorkflowInvalid,
60 GraphIdentityNotAssistantTemporary,
61 GraphRuntimeAssetUnavailable,
62 GraphAssistantMembershipRejected,
63 GraphAssistantDesignationRejected,
64 GraphAssistantSkillUnavailable,
65 GraphAuthorityRejected,
66 GraphBindingDuplicate,
67 GraphBindingUnknown,
68 GraphBindingKindRejected,
69 GraphBindingIncomplete,
70 GraphMembershipRejected,
71 GraphModelUnavailable,
72 GraphModelRejected,
73 GraphReadinessRejected,
74 GraphEnvironmentUnavailable,
75 GraphProfileRejected,
76 ConversationStateUnavailable,
77 ConversationNotFound,
78 GraphRouteStale,
79}
80
81impl WorkflowDiagnosticCode {
82 pub const fn wire(self) -> &'static str {
83 match self {
84 Self::WorkflowSyntaxInvalid => "workflow_syntax_invalid",
85 Self::WorkflowShapeInvalid => "workflow_shape_invalid",
86 Self::WorkflowRequiredFieldMissing => "workflow_required_field_missing",
87 Self::WorkflowFieldTypeInvalid => "workflow_field_type_invalid",
88 Self::WorkflowFieldValueInvalid => "workflow_field_value_invalid",
89 Self::WorkflowUnknownField => "workflow_unknown_field",
90 Self::WorkflowSchemaUnsupported => "workflow_schema_unsupported",
91 Self::WorkflowMetadataIdInvalid => "workflow_metadata_id_invalid",
92 Self::WorkflowMetadataNameInvalid => "workflow_metadata_name_invalid",
93 Self::WorkflowMetadataVersionInvalid => "workflow_metadata_version_invalid",
94 Self::WorkflowStateLimit => "workflow_state_limit",
95 Self::WorkflowTransitionLimit => "workflow_transition_limit",
96 Self::WorkflowBindingLimit => "workflow_binding_limit",
97 Self::WorkflowRuntimeLimit => "workflow_runtime_limit",
98 Self::WorkflowParallelismInvalid => "workflow_parallelism_invalid",
99 Self::WorkflowWorksetLimitInvalid => "workflow_workset_limit_invalid",
100 Self::WorkflowRetryLimitInvalid => "workflow_retry_limit_invalid",
101 Self::WorkflowBindingIdInvalid => "workflow_binding_id_invalid",
102 Self::WorkflowBindingDuplicate => "workflow_binding_duplicate",
103 Self::WorkflowBindingLabelInvalid => "workflow_binding_label_invalid",
104 Self::WorkflowFallbackInvalid => "workflow_fallback_invalid",
105 Self::WorkflowEntrySlotInvalid => "workflow_entry_slot_invalid",
106 Self::WorkflowRuntimeIdInvalid => "workflow_runtime_id_invalid",
107 Self::WorkflowRuntimeBindingInvalid => "workflow_runtime_binding_invalid",
108 Self::WorkflowWorksetIdInvalid => "workflow_workset_id_invalid",
109 Self::WorkflowWorksetItemBindingInvalid => "workflow_workset_item_binding_invalid",
110 Self::WorkflowWorksetPredecessorFieldInvalid => {
111 "workflow_workset_predecessor_field_invalid"
112 }
113 Self::WorkflowWorksetFieldConflict => "workflow_workset_field_conflict",
114 Self::WorkflowStateIdInvalid => "workflow_state_id_invalid",
115 Self::WorkflowStateLabelInvalid => "workflow_state_label_invalid",
116 Self::WorkflowStateInstructionInvalid => "workflow_state_instruction_invalid",
117 Self::WorkflowStateDuplicate => "workflow_state_duplicate",
118 Self::WorkflowStateRetryInvalid => "workflow_state_retry_invalid",
119 Self::WorkflowActorBindingInvalid => "workflow_actor_binding_invalid",
120 Self::WorkflowStateFieldInvalid => "workflow_state_field_invalid",
121 Self::WorkflowScriptRuntimeInvalid => "workflow_script_runtime_invalid",
122 Self::WorkflowScriptEntryMissing => "workflow_script_entry_missing",
123 Self::WorkflowScriptEntryInvalid => "workflow_script_entry_invalid",
124 Self::WorkflowWorksetReferenceInvalid => "workflow_workset_reference_invalid",
125 Self::WorkflowWorksetBindingInvalid => "workflow_workset_binding_invalid",
126 Self::WorkflowInitialUnknown => "workflow_initial_unknown",
127 Self::WorkflowTransitionIdInvalid => "workflow_transition_id_invalid",
128 Self::WorkflowTransitionDuplicate => "workflow_transition_duplicate",
129 Self::WorkflowTransitionStateUnknown => "workflow_transition_state_unknown",
130 Self::WorkflowGuardInvalid => "workflow_guard_invalid",
131 Self::WorkflowGuardAmbiguous => "workflow_guard_ambiguous",
132 Self::WorkflowRoutingInvalid => "workflow_routing_invalid",
133 Self::WorkflowTransitionModeInvalid => "workflow_transition_mode_invalid",
134 Self::WorkflowFlowTargetIncomplete => "workflow_flow_target_incomplete",
135 Self::WorkflowTopologyInvalid => "workflow_topology_invalid",
136 Self::WorkflowStateUnreachable => "workflow_state_unreachable",
137 Self::WorkflowTerminalUnreachable => "workflow_terminal_unreachable",
138 Self::WorkflowEffectCycle => "workflow_effect_cycle",
139 Self::WorkflowInvalid => "workflow_invalid",
140 Self::GraphIdentityNotAssistantTemporary => "graph_identity_not_assistant_temporary",
141 Self::GraphRuntimeAssetUnavailable => "graph_runtime_asset_unavailable",
142 Self::GraphAssistantMembershipRejected => "graph_assistant_membership_rejected",
143 Self::GraphAssistantDesignationRejected => "graph_assistant_designation_rejected",
144 Self::GraphAssistantSkillUnavailable => "graph_assistant_skill_unavailable",
145 Self::GraphAuthorityRejected => "graph_authority_rejected",
146 Self::GraphBindingDuplicate => "graph_binding_duplicate",
147 Self::GraphBindingUnknown => "graph_binding_unknown",
148 Self::GraphBindingKindRejected => "graph_binding_kind_rejected",
149 Self::GraphBindingIncomplete => "graph_binding_incomplete",
150 Self::GraphMembershipRejected => "graph_membership_rejected",
151 Self::GraphModelUnavailable => "graph_model_unavailable",
152 Self::GraphModelRejected => "graph_model_rejected",
153 Self::GraphReadinessRejected => "graph_readiness_rejected",
154 Self::GraphEnvironmentUnavailable => "graph_environment_unavailable",
155 Self::GraphProfileRejected => "graph_profile_rejected",
156 Self::ConversationStateUnavailable => "conversation_state_unavailable",
157 Self::ConversationNotFound => "conversation_not_found",
158 Self::GraphRouteStale => "graph_route_stale",
159 }
160 }
161
162 pub fn from_wire(value: &str) -> Option<Self> {
163 const VALUES: &[WorkflowDiagnosticCode] = &[
164 WorkflowDiagnosticCode::WorkflowSyntaxInvalid,
165 WorkflowDiagnosticCode::WorkflowShapeInvalid,
166 WorkflowDiagnosticCode::WorkflowRequiredFieldMissing,
167 WorkflowDiagnosticCode::WorkflowFieldTypeInvalid,
168 WorkflowDiagnosticCode::WorkflowFieldValueInvalid,
169 WorkflowDiagnosticCode::WorkflowUnknownField,
170 WorkflowDiagnosticCode::WorkflowSchemaUnsupported,
171 WorkflowDiagnosticCode::WorkflowMetadataIdInvalid,
172 WorkflowDiagnosticCode::WorkflowMetadataNameInvalid,
173 WorkflowDiagnosticCode::WorkflowMetadataVersionInvalid,
174 WorkflowDiagnosticCode::WorkflowStateLimit,
175 WorkflowDiagnosticCode::WorkflowTransitionLimit,
176 WorkflowDiagnosticCode::WorkflowBindingLimit,
177 WorkflowDiagnosticCode::WorkflowRuntimeLimit,
178 WorkflowDiagnosticCode::WorkflowParallelismInvalid,
179 WorkflowDiagnosticCode::WorkflowWorksetLimitInvalid,
180 WorkflowDiagnosticCode::WorkflowRetryLimitInvalid,
181 WorkflowDiagnosticCode::WorkflowBindingIdInvalid,
182 WorkflowDiagnosticCode::WorkflowBindingDuplicate,
183 WorkflowDiagnosticCode::WorkflowBindingLabelInvalid,
184 WorkflowDiagnosticCode::WorkflowFallbackInvalid,
185 WorkflowDiagnosticCode::WorkflowEntrySlotInvalid,
186 WorkflowDiagnosticCode::WorkflowRuntimeIdInvalid,
187 WorkflowDiagnosticCode::WorkflowRuntimeBindingInvalid,
188 WorkflowDiagnosticCode::WorkflowWorksetIdInvalid,
189 WorkflowDiagnosticCode::WorkflowWorksetItemBindingInvalid,
190 WorkflowDiagnosticCode::WorkflowWorksetPredecessorFieldInvalid,
191 WorkflowDiagnosticCode::WorkflowWorksetFieldConflict,
192 WorkflowDiagnosticCode::WorkflowStateIdInvalid,
193 WorkflowDiagnosticCode::WorkflowStateLabelInvalid,
194 WorkflowDiagnosticCode::WorkflowStateInstructionInvalid,
195 WorkflowDiagnosticCode::WorkflowStateDuplicate,
196 WorkflowDiagnosticCode::WorkflowStateRetryInvalid,
197 WorkflowDiagnosticCode::WorkflowActorBindingInvalid,
198 WorkflowDiagnosticCode::WorkflowStateFieldInvalid,
199 WorkflowDiagnosticCode::WorkflowScriptRuntimeInvalid,
200 WorkflowDiagnosticCode::WorkflowScriptEntryMissing,
201 WorkflowDiagnosticCode::WorkflowScriptEntryInvalid,
202 WorkflowDiagnosticCode::WorkflowWorksetReferenceInvalid,
203 WorkflowDiagnosticCode::WorkflowWorksetBindingInvalid,
204 WorkflowDiagnosticCode::WorkflowInitialUnknown,
205 WorkflowDiagnosticCode::WorkflowTransitionIdInvalid,
206 WorkflowDiagnosticCode::WorkflowTransitionDuplicate,
207 WorkflowDiagnosticCode::WorkflowTransitionStateUnknown,
208 WorkflowDiagnosticCode::WorkflowGuardInvalid,
209 WorkflowDiagnosticCode::WorkflowGuardAmbiguous,
210 WorkflowDiagnosticCode::WorkflowRoutingInvalid,
211 WorkflowDiagnosticCode::WorkflowTransitionModeInvalid,
212 WorkflowDiagnosticCode::WorkflowFlowTargetIncomplete,
213 WorkflowDiagnosticCode::WorkflowTopologyInvalid,
214 WorkflowDiagnosticCode::WorkflowStateUnreachable,
215 WorkflowDiagnosticCode::WorkflowTerminalUnreachable,
216 WorkflowDiagnosticCode::WorkflowEffectCycle,
217 WorkflowDiagnosticCode::WorkflowInvalid,
218 WorkflowDiagnosticCode::GraphIdentityNotAssistantTemporary,
219 WorkflowDiagnosticCode::GraphRuntimeAssetUnavailable,
220 WorkflowDiagnosticCode::GraphAssistantMembershipRejected,
221 WorkflowDiagnosticCode::GraphAssistantDesignationRejected,
222 WorkflowDiagnosticCode::GraphAssistantSkillUnavailable,
223 WorkflowDiagnosticCode::GraphAuthorityRejected,
224 WorkflowDiagnosticCode::GraphBindingDuplicate,
225 WorkflowDiagnosticCode::GraphBindingUnknown,
226 WorkflowDiagnosticCode::GraphBindingKindRejected,
227 WorkflowDiagnosticCode::GraphBindingIncomplete,
228 WorkflowDiagnosticCode::GraphMembershipRejected,
229 WorkflowDiagnosticCode::GraphModelUnavailable,
230 WorkflowDiagnosticCode::GraphModelRejected,
231 WorkflowDiagnosticCode::GraphReadinessRejected,
232 WorkflowDiagnosticCode::GraphEnvironmentUnavailable,
233 WorkflowDiagnosticCode::GraphProfileRejected,
234 WorkflowDiagnosticCode::ConversationStateUnavailable,
235 WorkflowDiagnosticCode::ConversationNotFound,
236 WorkflowDiagnosticCode::GraphRouteStale,
237 ];
238 VALUES
239 .iter()
240 .copied()
241 .find(|candidate| candidate.wire() == value)
242 }
243}
244
245impl PartialEq<&str> for WorkflowDiagnosticCode {
246 fn eq(&self, other: &&str) -> bool {
247 self.wire() == *other
248 }
249}
250
251#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
252pub enum WorkflowDiagnosticStage {
253 #[serde(rename = "workflow/parse")]
254 WorkflowParse,
255 #[serde(rename = "workflow/compile")]
256 WorkflowCompile,
257 #[serde(rename = "package/validate")]
258 PackageValidate,
259 #[serde(rename = "assistant-workflow/preflight")]
260 AssistantWorkflowPreflight,
261 #[serde(rename = "assistant-workflow/revalidate")]
262 AssistantWorkflowRevalidate,
263}
264
265impl WorkflowDiagnosticStage {
266 pub const fn wire(self) -> &'static str {
267 match self {
268 Self::WorkflowParse => "workflow/parse",
269 Self::WorkflowCompile => "workflow/compile",
270 Self::PackageValidate => "package/validate",
271 Self::AssistantWorkflowPreflight => "assistant-workflow/preflight",
272 Self::AssistantWorkflowRevalidate => "assistant-workflow/revalidate",
273 }
274 }
275
276 pub fn from_wire(value: &str) -> Option<Self> {
277 match value {
278 "workflow/parse" => Some(Self::WorkflowParse),
279 "workflow/compile" => Some(Self::WorkflowCompile),
280 "package/validate" => Some(Self::PackageValidate),
281 "assistant-workflow/preflight" => Some(Self::AssistantWorkflowPreflight),
282 "assistant-workflow/revalidate" => Some(Self::AssistantWorkflowRevalidate),
283 _ => None,
284 }
285 }
286}
287
288#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
289#[serde(rename_all = "snake_case")]
290pub enum WorkflowDiagnosticExpected {
291 Object,
292 Array,
293 String,
294 Integer,
295 Boolean,
296 EnumValue,
297 Identifier,
298 NonEmptyText,
299 UniqueId,
300 ExistingReference,
301 SupportedSchema,
302 ValidRouting,
303 ValidTopology,
304}
305
306#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
307#[serde(rename_all = "snake_case")]
308pub enum WorkflowDiagnosticActualKind {
309 Missing,
310 Null,
311 Object,
312 Array,
313 String,
314 Number,
315 Boolean,
316}
317
318#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
319#[serde(rename_all = "snake_case")]
320pub enum WorkflowDiagnosticRecovery {
321 AddRequiredField,
322 CorrectField,
323 RemoveUnknownField,
324 RemoveDuplicate,
325 CorrectReference,
326 ReduceResource,
327 CorrectRouting,
328 CorrectTopology,
329 UpdateAssistantProfile,
330 UpdateBinding,
331 RefreshConversationState,
332}
333
334#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
335#[serde(rename_all = "camelCase", deny_unknown_fields)]
336pub struct PreflightDiagnostic {
337 pub code: WorkflowDiagnosticCode,
338 pub stage: WorkflowDiagnosticStage,
339 #[serde(default, skip_serializing_if = "Option::is_none")]
340 pub path: Option<String>,
341 #[serde(default, skip_serializing_if = "Vec::is_empty")]
342 pub related_paths: Vec<String>,
343 #[serde(default, skip_serializing_if = "Option::is_none")]
344 pub membership_id: Option<String>,
345 #[serde(default, skip_serializing_if = "Option::is_none")]
346 pub actual: Option<u64>,
347 #[serde(default, skip_serializing_if = "Option::is_none")]
348 pub limit: Option<u64>,
349 #[serde(default, skip_serializing_if = "Option::is_none")]
350 pub expected: Option<WorkflowDiagnosticExpected>,
351 #[serde(default, skip_serializing_if = "Option::is_none")]
352 pub actual_kind: Option<WorkflowDiagnosticActualKind>,
353 #[serde(default, skip_serializing_if = "Option::is_none")]
354 pub recovery: Option<WorkflowDiagnosticRecovery>,
355 #[serde(default, skip_serializing_if = "Option::is_none")]
356 pub line: Option<u64>,
357 #[serde(default, skip_serializing_if = "Option::is_none")]
358 pub column: Option<u64>,
359}
360
361impl From<acativa::workflow::diagnostic::PreflightDiagnostic> for PreflightDiagnostic {
362 fn from(diagnostic: acativa::workflow::diagnostic::PreflightDiagnostic) -> Self {
366 let wire = serde_json::to_value(&diagnostic).expect("an engine diagnostic always encodes");
367 serde_json::from_value(wire).expect("engine diagnostics are a strict subset of this record")
368 }
369}