stackgen-sdk 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. stackgen/__init__.py +52 -0
  2. stackgen/_http.py +96 -0
  3. stackgen/_version.py +24 -0
  4. stackgen/aiden/__init__.py +9 -0
  5. stackgen/aiden/namespace.py +26 -0
  6. stackgen/aiden/runs.py +36 -0
  7. stackgen/aiden/webhook.py +185 -0
  8. stackgen/cli.py +33 -0
  9. stackgen/client.py +31 -0
  10. stackgen/config.py +88 -0
  11. stackgen/errors.py +41 -0
  12. stackgen/generated/.openapi-generator/FILES +141 -0
  13. stackgen/generated/.openapi-generator/VERSION +1 -0
  14. stackgen/generated/.openapi-generator-ignore +23 -0
  15. stackgen/generated/__init__.py +131 -0
  16. stackgen/generated/api/__init__.py +6 -0
  17. stackgen/generated/api/aiden_api.py +1806 -0
  18. stackgen/generated/api/sre_api.py +1618 -0
  19. stackgen/generated/api_client.py +801 -0
  20. stackgen/generated/api_response.py +21 -0
  21. stackgen/generated/configuration.py +600 -0
  22. stackgen/generated/exceptions.py +216 -0
  23. stackgen/generated/models/__init__.py +57 -0
  24. stackgen/generated/models/alert_analysis_status.py +40 -0
  25. stackgen/generated/models/alert_attention.py +39 -0
  26. stackgen/generated/models/alert_categorization_summary.py +97 -0
  27. stackgen/generated/models/alert_role.py +38 -0
  28. stackgen/generated/models/alert_sort_by.py +37 -0
  29. stackgen/generated/models/alert_status.py +38 -0
  30. stackgen/generated/models/alert_summary.py +95 -0
  31. stackgen/generated/models/alert_sync_run_status.py +38 -0
  32. stackgen/generated/models/alert_v1.py +213 -0
  33. stackgen/generated/models/artifact_info.py +98 -0
  34. stackgen/generated/models/error_response.py +91 -0
  35. stackgen/generated/models/investigate_alert_request.py +91 -0
  36. stackgen/generated/models/investigate_response.py +91 -0
  37. stackgen/generated/models/investigation.py +167 -0
  38. stackgen/generated/models/investigation_evidence.py +114 -0
  39. stackgen/generated/models/investigation_evidence_kind.py +44 -0
  40. stackgen/generated/models/investigation_evidence_source.py +39 -0
  41. stackgen/generated/models/investigation_hypothesis.py +112 -0
  42. stackgen/generated/models/investigation_plain_summary.py +104 -0
  43. stackgen/generated/models/investigation_prior_incident.py +109 -0
  44. stackgen/generated/models/investigation_recommended_next_step.py +101 -0
  45. stackgen/generated/models/investigation_ref.py +118 -0
  46. stackgen/generated/models/investigation_status.py +42 -0
  47. stackgen/generated/models/investigation_structured_hypothesis_entry.py +115 -0
  48. stackgen/generated/models/investigation_structured_limitation_entry.py +120 -0
  49. stackgen/generated/models/investigation_structured_rca.py +139 -0
  50. stackgen/generated/models/investigation_triage_metadata.py +134 -0
  51. stackgen/generated/models/json_error.py +91 -0
  52. stackgen/generated/models/list_alerts_response.py +119 -0
  53. stackgen/generated/models/list_investigations_response.py +101 -0
  54. stackgen/generated/models/pagination.py +91 -0
  55. stackgen/generated/models/schedule_run_status.py +39 -0
  56. stackgen/generated/models/schedule_target_type.py +38 -0
  57. stackgen/generated/models/session.py +141 -0
  58. stackgen/generated/models/session_responder_kind.py +40 -0
  59. stackgen/generated/models/signal_severity.py +40 -0
  60. stackgen/generated/models/sync_response.py +136 -0
  61. stackgen/generated/models/trigger_webhook202_response.py +98 -0
  62. stackgen/generated/models/webhook_run.py +129 -0
  63. stackgen/generated/models/webhook_run_detail.py +136 -0
  64. stackgen/generated/models/webhook_run_list_response.py +97 -0
  65. stackgen/generated/rest.py +258 -0
  66. stackgen/sre/__init__.py +5 -0
  67. stackgen/sre/namespace.py +57 -0
  68. stackgen/vault/__init__.py +5 -0
  69. stackgen/vault/namespace.py +17 -0
  70. stackgen_sdk-0.1.1.dist-info/METADATA +60 -0
  71. stackgen_sdk-0.1.1.dist-info/RECORD +73 -0
  72. stackgen_sdk-0.1.1.dist-info/WHEEL +4 -0
  73. stackgen_sdk-0.1.1.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,167 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ StackGen External API
5
+
6
+ Allowlisted StackGen API surface for the public SDK. Managed via api-docs/product/allowlists/external.yaml.
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from datetime import datetime
21
+ from pydantic import BaseModel, ConfigDict, Field, StrictStr
22
+ from typing import Any, ClassVar, Dict, List, Optional
23
+ from stackgen.generated.models.investigation_evidence import InvestigationEvidence
24
+ from stackgen.generated.models.investigation_hypothesis import InvestigationHypothesis
25
+ from stackgen.generated.models.investigation_prior_incident import InvestigationPriorIncident
26
+ from stackgen.generated.models.investigation_status import InvestigationStatus
27
+ from stackgen.generated.models.investigation_structured_rca import InvestigationStructuredRCA
28
+ from stackgen.generated.models.investigation_triage_metadata import InvestigationTriageMetadata
29
+ from typing import Optional, Set
30
+ from typing_extensions import Self
31
+
32
+ class Investigation(BaseModel):
33
+ """
34
+ Full investigation record returned by /api/v1/investigations.
35
+ """ # noqa: E501
36
+ id: StrictStr
37
+ alert_id: StrictStr
38
+ guild_trace_id: StrictStr
39
+ guild_session_id: Optional[StrictStr] = None
40
+ status: InvestigationStatus
41
+ result_summary: Optional[StrictStr] = None
42
+ parent_investigation_id: Optional[StrictStr] = Field(default=None, description="When this investigation was created by forking another, the parent investigation it was forked from. Null for normal investigations.")
43
+ started_at: datetime
44
+ finished_at: Optional[datetime] = None
45
+ evidence: Optional[List[InvestigationEvidence]] = Field(default=None, description="Clickable evidence URLs attached to this investigation, in capture order. Empty when the agent has not submitted any citations.")
46
+ structured_rca: Optional[InvestigationStructuredRCA] = None
47
+ hypotheses: Optional[List[InvestigationHypothesis]] = Field(default=None, description="Ranked investigation hypotheses produced during structured triage. Empty when the agent has not submitted hypothesis rows.")
48
+ prior_incidents: Optional[List[InvestigationPriorIncident]] = Field(default=None, description="Similar prior incidents matched from memory or history. Empty when none were found or submitted.")
49
+ triage_metadata: Optional[InvestigationTriageMetadata] = None
50
+ __properties: ClassVar[List[str]] = ["id", "alert_id", "guild_trace_id", "guild_session_id", "status", "result_summary", "parent_investigation_id", "started_at", "finished_at", "evidence", "structured_rca", "hypotheses", "prior_incidents", "triage_metadata"]
51
+
52
+ model_config = ConfigDict(
53
+ populate_by_name=True,
54
+ validate_assignment=True,
55
+ protected_namespaces=(),
56
+ )
57
+
58
+
59
+ def to_str(self) -> str:
60
+ """Returns the string representation of the model using alias"""
61
+ return pprint.pformat(self.model_dump(by_alias=True))
62
+
63
+ def to_json(self) -> str:
64
+ """Returns the JSON representation of the model using alias"""
65
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
66
+ return json.dumps(self.to_dict())
67
+
68
+ @classmethod
69
+ def from_json(cls, json_str: str) -> Optional[Self]:
70
+ """Create an instance of Investigation from a JSON string"""
71
+ return cls.from_dict(json.loads(json_str))
72
+
73
+ def to_dict(self) -> Dict[str, Any]:
74
+ """Return the dictionary representation of the model using alias.
75
+
76
+ This has the following differences from calling pydantic's
77
+ `self.model_dump(by_alias=True)`:
78
+
79
+ * `None` is only added to the output dict for nullable fields that
80
+ were set at model initialization. Other fields with value `None`
81
+ are ignored.
82
+ """
83
+ excluded_fields: Set[str] = set([
84
+ ])
85
+
86
+ _dict = self.model_dump(
87
+ by_alias=True,
88
+ exclude=excluded_fields,
89
+ exclude_none=True,
90
+ )
91
+ # override the default output from pydantic by calling `to_dict()` of each item in evidence (list)
92
+ _items = []
93
+ if self.evidence:
94
+ for _item_evidence in self.evidence:
95
+ if _item_evidence:
96
+ _items.append(_item_evidence.to_dict())
97
+ _dict['evidence'] = _items
98
+ # override the default output from pydantic by calling `to_dict()` of structured_rca
99
+ if self.structured_rca:
100
+ _dict['structured_rca'] = self.structured_rca.to_dict()
101
+ # override the default output from pydantic by calling `to_dict()` of each item in hypotheses (list)
102
+ _items = []
103
+ if self.hypotheses:
104
+ for _item_hypotheses in self.hypotheses:
105
+ if _item_hypotheses:
106
+ _items.append(_item_hypotheses.to_dict())
107
+ _dict['hypotheses'] = _items
108
+ # override the default output from pydantic by calling `to_dict()` of each item in prior_incidents (list)
109
+ _items = []
110
+ if self.prior_incidents:
111
+ for _item_prior_incidents in self.prior_incidents:
112
+ if _item_prior_incidents:
113
+ _items.append(_item_prior_incidents.to_dict())
114
+ _dict['prior_incidents'] = _items
115
+ # override the default output from pydantic by calling `to_dict()` of triage_metadata
116
+ if self.triage_metadata:
117
+ _dict['triage_metadata'] = self.triage_metadata.to_dict()
118
+ # set to None if guild_session_id (nullable) is None
119
+ # and model_fields_set contains the field
120
+ if self.guild_session_id is None and "guild_session_id" in self.model_fields_set:
121
+ _dict['guild_session_id'] = None
122
+
123
+ # set to None if result_summary (nullable) is None
124
+ # and model_fields_set contains the field
125
+ if self.result_summary is None and "result_summary" in self.model_fields_set:
126
+ _dict['result_summary'] = None
127
+
128
+ # set to None if parent_investigation_id (nullable) is None
129
+ # and model_fields_set contains the field
130
+ if self.parent_investigation_id is None and "parent_investigation_id" in self.model_fields_set:
131
+ _dict['parent_investigation_id'] = None
132
+
133
+ # set to None if finished_at (nullable) is None
134
+ # and model_fields_set contains the field
135
+ if self.finished_at is None and "finished_at" in self.model_fields_set:
136
+ _dict['finished_at'] = None
137
+
138
+ return _dict
139
+
140
+ @classmethod
141
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
142
+ """Create an instance of Investigation from a dict"""
143
+ if obj is None:
144
+ return None
145
+
146
+ if not isinstance(obj, dict):
147
+ return cls.model_validate(obj)
148
+
149
+ _obj = cls.model_validate({
150
+ "id": obj.get("id"),
151
+ "alert_id": obj.get("alert_id"),
152
+ "guild_trace_id": obj.get("guild_trace_id"),
153
+ "guild_session_id": obj.get("guild_session_id"),
154
+ "status": obj.get("status"),
155
+ "result_summary": obj.get("result_summary"),
156
+ "parent_investigation_id": obj.get("parent_investigation_id"),
157
+ "started_at": obj.get("started_at"),
158
+ "finished_at": obj.get("finished_at"),
159
+ "evidence": [InvestigationEvidence.from_dict(_item) for _item in obj["evidence"]] if obj.get("evidence") is not None else None,
160
+ "structured_rca": InvestigationStructuredRCA.from_dict(obj["structured_rca"]) if obj.get("structured_rca") is not None else None,
161
+ "hypotheses": [InvestigationHypothesis.from_dict(_item) for _item in obj["hypotheses"]] if obj.get("hypotheses") is not None else None,
162
+ "prior_incidents": [InvestigationPriorIncident.from_dict(_item) for _item in obj["prior_incidents"]] if obj.get("prior_incidents") is not None else None,
163
+ "triage_metadata": InvestigationTriageMetadata.from_dict(obj["triage_metadata"]) if obj.get("triage_metadata") is not None else None
164
+ })
165
+ return _obj
166
+
167
+
@@ -0,0 +1,114 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ StackGen External API
5
+
6
+ Allowlisted StackGen API surface for the public SDK. Managed via api-docs/product/allowlists/external.yaml.
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from datetime import datetime
21
+ from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
22
+ from typing import Any, ClassVar, Dict, List, Optional
23
+ from stackgen.generated.models.investigation_evidence_kind import InvestigationEvidenceKind
24
+ from stackgen.generated.models.investigation_evidence_source import InvestigationEvidenceSource
25
+ from typing import Optional, Set
26
+ from typing_extensions import Self
27
+
28
+ class InvestigationEvidence(BaseModel):
29
+ """
30
+ A single clickable citation attached to an investigation. Submitted by the Aiden agent via the `sre_update_investigation_status` or `sre_submit_investigation_evidence` MCP callbacks. `verified` and `captured_at` are always set server-side regardless of what the caller passes.
31
+ """ # noqa: E501
32
+ kind: InvestigationEvidenceKind
33
+ title: StrictStr = Field(description="Short, human-readable label for the evidence row.")
34
+ url: StrictStr = Field(description="Absolute http(s) URL the user can open.")
35
+ description: Optional[StrictStr] = Field(default=None, description="Plain DevOps context shown below the title: what this link shows and why it matters for triage (breach timing, firing condition, upstream dependency, prior incident match, etc.). Set by the agent when submitting evidence; the server may infer a default from kind or tool when omitted.")
36
+ source: InvestigationEvidenceSource
37
+ tool_name: Optional[StrictStr] = Field(default=None, description="Name of the tool invocation that produced this URL (only set when source=tool_trace).")
38
+ verified: StrictBool = Field(description="True when the URL host matches the per-tenant active-integration allowlist. Always set server-side; clients cannot mark a URL verified.")
39
+ captured_at: datetime = Field(description="Server timestamp when the URL was persisted.")
40
+ __properties: ClassVar[List[str]] = ["kind", "title", "url", "description", "source", "tool_name", "verified", "captured_at"]
41
+
42
+ model_config = ConfigDict(
43
+ populate_by_name=True,
44
+ validate_assignment=True,
45
+ protected_namespaces=(),
46
+ )
47
+
48
+
49
+ def to_str(self) -> str:
50
+ """Returns the string representation of the model using alias"""
51
+ return pprint.pformat(self.model_dump(by_alias=True))
52
+
53
+ def to_json(self) -> str:
54
+ """Returns the JSON representation of the model using alias"""
55
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
56
+ return json.dumps(self.to_dict())
57
+
58
+ @classmethod
59
+ def from_json(cls, json_str: str) -> Optional[Self]:
60
+ """Create an instance of InvestigationEvidence from a JSON string"""
61
+ return cls.from_dict(json.loads(json_str))
62
+
63
+ def to_dict(self) -> Dict[str, Any]:
64
+ """Return the dictionary representation of the model using alias.
65
+
66
+ This has the following differences from calling pydantic's
67
+ `self.model_dump(by_alias=True)`:
68
+
69
+ * `None` is only added to the output dict for nullable fields that
70
+ were set at model initialization. Other fields with value `None`
71
+ are ignored.
72
+ """
73
+ excluded_fields: Set[str] = set([
74
+ ])
75
+
76
+ _dict = self.model_dump(
77
+ by_alias=True,
78
+ exclude=excluded_fields,
79
+ exclude_none=True,
80
+ )
81
+ # set to None if description (nullable) is None
82
+ # and model_fields_set contains the field
83
+ if self.description is None and "description" in self.model_fields_set:
84
+ _dict['description'] = None
85
+
86
+ # set to None if tool_name (nullable) is None
87
+ # and model_fields_set contains the field
88
+ if self.tool_name is None and "tool_name" in self.model_fields_set:
89
+ _dict['tool_name'] = None
90
+
91
+ return _dict
92
+
93
+ @classmethod
94
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
95
+ """Create an instance of InvestigationEvidence from a dict"""
96
+ if obj is None:
97
+ return None
98
+
99
+ if not isinstance(obj, dict):
100
+ return cls.model_validate(obj)
101
+
102
+ _obj = cls.model_validate({
103
+ "kind": obj.get("kind"),
104
+ "title": obj.get("title"),
105
+ "url": obj.get("url"),
106
+ "description": obj.get("description"),
107
+ "source": obj.get("source"),
108
+ "tool_name": obj.get("tool_name"),
109
+ "verified": obj.get("verified"),
110
+ "captured_at": obj.get("captured_at")
111
+ })
112
+ return _obj
113
+
114
+
@@ -0,0 +1,44 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ StackGen External API
5
+
6
+ Allowlisted StackGen API surface for the public SDK. Managed via api-docs/product/allowlists/external.yaml.
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import json
17
+ from enum import Enum
18
+ from typing_extensions import Self
19
+
20
+
21
+ class InvestigationEvidenceKind(str, Enum):
22
+ """
23
+ Categorises an evidence URL so the UI can pick the right icon and group items by signal type.
24
+ """
25
+
26
+ """
27
+ allowed enum values
28
+ """
29
+ DASHBOARD = 'dashboard'
30
+ METRIC = 'metric'
31
+ LOG = 'log'
32
+ TRACE = 'trace'
33
+ RUNBOOK = 'runbook'
34
+ ALERT_RULE = 'alert_rule'
35
+ CONSOLE = 'console'
36
+ CODE = 'code'
37
+ OTHER = 'other'
38
+
39
+ @classmethod
40
+ def from_json(cls, json_str: str) -> Self:
41
+ """Create an instance of InvestigationEvidenceKind from a JSON string"""
42
+ return cls(json.loads(json_str))
43
+
44
+
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ StackGen External API
5
+
6
+ Allowlisted StackGen API surface for the public SDK. Managed via api-docs/product/allowlists/external.yaml.
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import json
17
+ from enum import Enum
18
+ from typing_extensions import Self
19
+
20
+
21
+ class InvestigationEvidenceSource(str, Enum):
22
+ """
23
+ Provenance of an evidence URL. Drives UI trust labelling: `runbook` and `tool_trace` are treated as grounded citations, `llm` items are accepted but optionally labelled if outside the active-integration host allowlist, and `prior_knowledge` items render as non-clickable suggestions unless the host is verified.
24
+ """
25
+
26
+ """
27
+ allowed enum values
28
+ """
29
+ LLM = 'llm'
30
+ TOOL_TRACE = 'tool_trace'
31
+ RUNBOOK = 'runbook'
32
+ PRIOR_KNOWLEDGE = 'prior_knowledge'
33
+
34
+ @classmethod
35
+ def from_json(cls, json_str: str) -> Self:
36
+ """Create an instance of InvestigationEvidenceSource from a JSON string"""
37
+ return cls(json.loads(json_str))
38
+
39
+
@@ -0,0 +1,112 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ StackGen External API
5
+
6
+ Allowlisted StackGen API surface for the public SDK. Managed via api-docs/product/allowlists/external.yaml.
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator
21
+ from typing import Any, ClassVar, Dict, List, Optional, Union
22
+ from typing_extensions import Annotated
23
+ from typing import Optional, Set
24
+ from typing_extensions import Self
25
+
26
+ class InvestigationHypothesis(BaseModel):
27
+ """
28
+ A single ranked hypothesis explored during triage.
29
+ """ # noqa: E501
30
+ statement: StrictStr = Field(description="Plain-language hypothesis statement.")
31
+ confidence: Optional[Union[Annotated[float, Field(le=1, strict=True, ge=0)], Annotated[int, Field(le=1, strict=True, ge=0)]]] = Field(default=None, description="Confidence in this hypothesis (0–1).")
32
+ status: Optional[StrictStr] = Field(default=None, description="Lifecycle status of the hypothesis after evidence review.")
33
+ __properties: ClassVar[List[str]] = ["statement", "confidence", "status"]
34
+
35
+ @field_validator('status')
36
+ def status_validate_enum(cls, value):
37
+ """Validates the enum"""
38
+ if value is None:
39
+ return value
40
+
41
+ if value not in set(['open', 'confirmed', 'rejected']):
42
+ raise ValueError("must be one of enum values ('open', 'confirmed', 'rejected')")
43
+ return value
44
+
45
+ model_config = ConfigDict(
46
+ populate_by_name=True,
47
+ validate_assignment=True,
48
+ protected_namespaces=(),
49
+ )
50
+
51
+
52
+ def to_str(self) -> str:
53
+ """Returns the string representation of the model using alias"""
54
+ return pprint.pformat(self.model_dump(by_alias=True))
55
+
56
+ def to_json(self) -> str:
57
+ """Returns the JSON representation of the model using alias"""
58
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
59
+ return json.dumps(self.to_dict())
60
+
61
+ @classmethod
62
+ def from_json(cls, json_str: str) -> Optional[Self]:
63
+ """Create an instance of InvestigationHypothesis from a JSON string"""
64
+ return cls.from_dict(json.loads(json_str))
65
+
66
+ def to_dict(self) -> Dict[str, Any]:
67
+ """Return the dictionary representation of the model using alias.
68
+
69
+ This has the following differences from calling pydantic's
70
+ `self.model_dump(by_alias=True)`:
71
+
72
+ * `None` is only added to the output dict for nullable fields that
73
+ were set at model initialization. Other fields with value `None`
74
+ are ignored.
75
+ """
76
+ excluded_fields: Set[str] = set([
77
+ ])
78
+
79
+ _dict = self.model_dump(
80
+ by_alias=True,
81
+ exclude=excluded_fields,
82
+ exclude_none=True,
83
+ )
84
+ # set to None if confidence (nullable) is None
85
+ # and model_fields_set contains the field
86
+ if self.confidence is None and "confidence" in self.model_fields_set:
87
+ _dict['confidence'] = None
88
+
89
+ # set to None if status (nullable) is None
90
+ # and model_fields_set contains the field
91
+ if self.status is None and "status" in self.model_fields_set:
92
+ _dict['status'] = None
93
+
94
+ return _dict
95
+
96
+ @classmethod
97
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
98
+ """Create an instance of InvestigationHypothesis from a dict"""
99
+ if obj is None:
100
+ return None
101
+
102
+ if not isinstance(obj, dict):
103
+ return cls.model_validate(obj)
104
+
105
+ _obj = cls.model_validate({
106
+ "statement": obj.get("statement"),
107
+ "confidence": obj.get("confidence"),
108
+ "status": obj.get("status")
109
+ })
110
+ return _obj
111
+
112
+
@@ -0,0 +1,104 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ StackGen External API
5
+
6
+ Allowlisted StackGen API surface for the public SDK. Managed via api-docs/product/allowlists/external.yaml.
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator
21
+ from typing import Any, ClassVar, Dict, List, Optional
22
+ from typing_extensions import Annotated
23
+ from typing import Optional, Set
24
+ from typing_extensions import Self
25
+
26
+ class InvestigationPlainSummary(BaseModel):
27
+ """
28
+ Plain-language investigation answer and reasoning path for developers. Answer fields summarize the conclusion; how_we_got_here lists the short ordered steps that led there. No agent-internal vocabulary. When present, callers should populate verdict, what_broke, what_to_do, and how_we_got_here; fields are not OpenAPI-required so omitted plain_summary does not fail nested Assert on zero-value StructuredRCA.
29
+ """ # noqa: E501
30
+ verdict: Optional[StrictStr] = Field(default=None, description="High-level answer class for the investigation.")
31
+ what_broke: Optional[StrictStr] = Field(default=None, description="One sentence a developer who has never seen this service can understand. Name the service and what users saw or what the alert claimed. No internal agent vocabulary.")
32
+ what_to_do: Optional[StrictStr] = Field(default=None, description="One concrete next action on the customer system (fix the alert, check a dependency, roll back a deploy). Never an action on the investigation agent itself such as rehydrating a signal cache.")
33
+ how_we_got_here: Optional[Annotated[List[StrictStr], Field(min_length=2, max_length=5)]] = Field(default=None, description="Ordered path of 2–5 short plain-language steps. Each step is one sentence: what we checked and what it showed. Developer vocabulary only — no snapshot SHAs, plane names, or ledger jargon.")
34
+ __properties: ClassVar[List[str]] = ["verdict", "what_broke", "what_to_do", "how_we_got_here"]
35
+
36
+ @field_validator('verdict')
37
+ def verdict_validate_enum(cls, value):
38
+ """Validates the enum"""
39
+ if value is None:
40
+ return value
41
+
42
+ if value not in set(['real_problem', 'alert_is_misconfigured', 'not_enough_information']):
43
+ raise ValueError("must be one of enum values ('real_problem', 'alert_is_misconfigured', 'not_enough_information')")
44
+ return value
45
+
46
+ model_config = ConfigDict(
47
+ populate_by_name=True,
48
+ validate_assignment=True,
49
+ protected_namespaces=(),
50
+ )
51
+
52
+
53
+ def to_str(self) -> str:
54
+ """Returns the string representation of the model using alias"""
55
+ return pprint.pformat(self.model_dump(by_alias=True))
56
+
57
+ def to_json(self) -> str:
58
+ """Returns the JSON representation of the model using alias"""
59
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
60
+ return json.dumps(self.to_dict())
61
+
62
+ @classmethod
63
+ def from_json(cls, json_str: str) -> Optional[Self]:
64
+ """Create an instance of InvestigationPlainSummary from a JSON string"""
65
+ return cls.from_dict(json.loads(json_str))
66
+
67
+ def to_dict(self) -> Dict[str, Any]:
68
+ """Return the dictionary representation of the model using alias.
69
+
70
+ This has the following differences from calling pydantic's
71
+ `self.model_dump(by_alias=True)`:
72
+
73
+ * `None` is only added to the output dict for nullable fields that
74
+ were set at model initialization. Other fields with value `None`
75
+ are ignored.
76
+ """
77
+ excluded_fields: Set[str] = set([
78
+ ])
79
+
80
+ _dict = self.model_dump(
81
+ by_alias=True,
82
+ exclude=excluded_fields,
83
+ exclude_none=True,
84
+ )
85
+ return _dict
86
+
87
+ @classmethod
88
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
89
+ """Create an instance of InvestigationPlainSummary from a dict"""
90
+ if obj is None:
91
+ return None
92
+
93
+ if not isinstance(obj, dict):
94
+ return cls.model_validate(obj)
95
+
96
+ _obj = cls.model_validate({
97
+ "verdict": obj.get("verdict"),
98
+ "what_broke": obj.get("what_broke"),
99
+ "what_to_do": obj.get("what_to_do"),
100
+ "how_we_got_here": obj.get("how_we_got_here")
101
+ })
102
+ return _obj
103
+
104
+