stackgen-sdk 0.1.3__tar.gz → 0.1.6__tar.gz
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.
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/.gitignore +6 -0
- stackgen_sdk-0.1.6/PKG-INFO +92 -0
- stackgen_sdk-0.1.6/README.md +71 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/pyproject.toml +4 -1
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/__init__.py +25 -2
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/_version.py +2 -2
- stackgen_sdk-0.1.6/src/stackgen/aiden/__init__.py +29 -0
- stackgen_sdk-0.1.6/src/stackgen/aiden/ask.py +172 -0
- stackgen_sdk-0.1.6/src/stackgen/aiden/namespace.py +170 -0
- stackgen_sdk-0.1.6/src/stackgen/aiden/runs.py +137 -0
- stackgen_sdk-0.1.6/src/stackgen/aiden/sessions.py +46 -0
- stackgen_sdk-0.1.6/src/stackgen/aiden/webhook.py +77 -0
- stackgen_sdk-0.1.6/src/stackgen/aiden/webhook_ops.py +172 -0
- stackgen_sdk-0.1.6/src/stackgen/aiden/workflow_builder.py +198 -0
- stackgen_sdk-0.1.6/src/stackgen/aiden/workflow_publish.py +211 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/cli.py +9 -1
- stackgen_sdk-0.1.6/src/stackgen/config.py +70 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/.openapi-generator/FILES +78 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/__init__.py +52 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/api/aiden_api.py +6054 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/api/sre_api.py +6 -6
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/configuration.py +3 -3
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/__init__.py +26 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/agent_status.py +89 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/ask_guild_request.py +119 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/ask_guild_start_response.py +109 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/candidate_type.py +40 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/dag_edge.py +89 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/dag_node.py +103 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/entity_ref.py +90 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/execution_list_item.py +112 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/execution_meta.py +102 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/execution_structured_output.py +93 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/prior_session_policy.py +110 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/qualified_candidate.py +92 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/register_agent_request.py +107 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/register_agent_request_auto_approve_tools_inner.py +87 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/register_agent_request_hitl.py +87 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/session_export.py +100 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/session_export_part.py +94 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/session_export_part_kind.py +38 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/session_list_response.py +97 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/session_summary.py +119 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/stage_binding_write.py +95 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/terminate_session_response.py +91 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/trace_dag_response.py +119 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/trigger_webhook202_response.py +6 -2
- stackgen_sdk-0.1.6/src/stackgen/generated/models/workflow.py +117 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/workflow_stage_write.py +93 -0
- stackgen_sdk-0.1.6/src/stackgen/generated/models/workflow_write.py +129 -0
- stackgen_sdk-0.1.3/PKG-INFO +0 -59
- stackgen_sdk-0.1.3/README.md +0 -41
- stackgen_sdk-0.1.3/src/stackgen/aiden/__init__.py +0 -9
- stackgen_sdk-0.1.3/src/stackgen/aiden/namespace.py +0 -26
- stackgen_sdk-0.1.3/src/stackgen/aiden/runs.py +0 -36
- stackgen_sdk-0.1.3/src/stackgen/aiden/webhook.py +0 -185
- stackgen_sdk-0.1.3/src/stackgen/config.py +0 -88
- stackgen_sdk-0.1.3/src/stackgen/generated/api/aiden_api.py +0 -1806
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/_http.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/client.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/errors.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/.openapi-generator/VERSION +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/.openapi-generator-ignore +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/api/__init__.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/api_client.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/api_response.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/exceptions.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/alert_analysis_status.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/alert_attention.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/alert_categorization_summary.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/alert_role.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/alert_sort_by.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/alert_status.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/alert_summary.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/alert_sync_run_status.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/alert_v1.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/artifact_info.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/error_response.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigate_alert_request.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigate_response.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation_evidence.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation_evidence_kind.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation_evidence_source.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation_hypothesis.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation_plain_summary.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation_prior_incident.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation_recommended_next_step.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation_ref.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation_status.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation_structured_hypothesis_entry.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation_structured_limitation_entry.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation_structured_rca.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/investigation_triage_metadata.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/json_error.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/list_alerts_response.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/list_investigations_response.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/pagination.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/schedule_run_status.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/schedule_target_type.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/session.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/session_responder_kind.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/signal_severity.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/sync_response.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/webhook_run.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/webhook_run_detail.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/models/webhook_run_list_response.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/generated/rest.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/sre/__init__.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/sre/namespace.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/vault/__init__.py +0 -0
- {stackgen_sdk-0.1.3 → stackgen_sdk-0.1.6}/src/stackgen/vault/namespace.py +0 -0
|
@@ -32,5 +32,11 @@ coverage.out
|
|
|
32
32
|
.env
|
|
33
33
|
.env.*
|
|
34
34
|
|
|
35
|
+
# Jekyll (only if native Ruby was used by mistake)
|
|
36
|
+
docs/_site/
|
|
37
|
+
docs/.jekyll-cache/
|
|
38
|
+
docs/.bundle/
|
|
39
|
+
docs/vendor/
|
|
40
|
+
|
|
35
41
|
# hatch-vcs generated version module (written at build time)
|
|
36
42
|
clients/python/src/stackgen/_version.py
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: stackgen-sdk
|
|
3
|
+
Version: 0.1.6
|
|
4
|
+
Summary: StackGen SDK — Aiden, SRE, and Vault from one client
|
|
5
|
+
Project-URL: Homepage, https://appcd-dev.github.io/stackgen-sdk/
|
|
6
|
+
Project-URL: Documentation, https://appcd-dev.github.io/stackgen-sdk/
|
|
7
|
+
Project-URL: Repository, https://github.com/appcd-dev/stackgen-sdk
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/appcd-dev/stackgen-sdk/issues
|
|
9
|
+
Author: StackGen
|
|
10
|
+
License-Expression: Apache-2.0
|
|
11
|
+
Keywords: aiden,openapi,sre,stackgen
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Requires-Dist: pydantic>=2.0
|
|
14
|
+
Requires-Dist: python-dateutil>=2.8
|
|
15
|
+
Requires-Dist: typing-extensions>=4.0
|
|
16
|
+
Requires-Dist: urllib3>=2.0
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
19
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# StackGen Python SDK
|
|
23
|
+
|
|
24
|
+
**Documentation:** [https://appcd-dev.github.io/stackgen-sdk/](https://appcd-dev.github.io/stackgen-sdk/) — Aiden guide, code samples, FAQ, and CI integration.
|
|
25
|
+
|
|
26
|
+
Install:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install stackgen-sdk
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Import package name is `stackgen`. Construct the client with an explicit config:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from pathlib import Path
|
|
36
|
+
from stackgen import StackgenClient, StackgenConfig
|
|
37
|
+
|
|
38
|
+
client = StackgenClient(
|
|
39
|
+
StackgenConfig(
|
|
40
|
+
base_url="https://app.stackgen.com",
|
|
41
|
+
api_token="stackgen_…",
|
|
42
|
+
org_id="<project-uuid>",
|
|
43
|
+
webhook_token="sg_aios_…", # webhook journeys only
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
result = client.aiden.run_webhook_and_download_report(
|
|
48
|
+
Path("alert.json").read_text(encoding="utf-8")
|
|
49
|
+
)
|
|
50
|
+
print(result.session_id, result.output_path)
|
|
51
|
+
|
|
52
|
+
ask = client.aiden.run_ask_and_download_artifact(
|
|
53
|
+
message="Run triage for checkout CPU alert",
|
|
54
|
+
entity_refs=[{"name": "observe-uber-triage", "type": "workflow"}],
|
|
55
|
+
)
|
|
56
|
+
print(ask.trace_id, ask.output_path)
|
|
57
|
+
|
|
58
|
+
alerts = client.sre.list_alerts()
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Default environment variables
|
|
62
|
+
|
|
63
|
+
`StackgenConfig.from_env()` reads **only** these (optional convenience):
|
|
64
|
+
|
|
65
|
+
| Variable | Purpose |
|
|
66
|
+
|----------|---------|
|
|
67
|
+
| `STACKGEN_URL` | Mothership URL (no path suffix) |
|
|
68
|
+
| `STACKGEN_TOKEN` | API token (`stackgen_…`) |
|
|
69
|
+
| `STACKGEN_PROJECT` | Project / org UUID (`orgId`) |
|
|
70
|
+
|
|
71
|
+
Pass `webhook_token`, `webhook_id`, timeouts, and artifact paths as `StackgenConfig` fields — not via env.
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from dataclasses import replace
|
|
75
|
+
from stackgen import StackgenClient, StackgenConfig
|
|
76
|
+
|
|
77
|
+
client = StackgenClient(
|
|
78
|
+
replace(StackgenConfig.from_env(), webhook_token="sg_aios_…")
|
|
79
|
+
)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Namespaces
|
|
83
|
+
|
|
84
|
+
- `client.aiden` — webhooks, Ask Guild, sessions, artifact download
|
|
85
|
+
- `client.sre` — alerts and investigations
|
|
86
|
+
- `client.vault` — secrets (not enabled in this release)
|
|
87
|
+
|
|
88
|
+
Prefer `StackgenClient` over `stackgen.generated`.
|
|
89
|
+
|
|
90
|
+
Pin versions in CI: `pip install stackgen-sdk==0.1.5`.
|
|
91
|
+
|
|
92
|
+
**Documentation:** [https://appcd-dev.github.io/stackgen-sdk/](https://appcd-dev.github.io/stackgen-sdk/) (Aiden guide, [FAQ](https://appcd-dev.github.io/stackgen-sdk/faq/), [code samples](https://appcd-dev.github.io/stackgen-sdk/code-samples/))
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# StackGen Python SDK
|
|
2
|
+
|
|
3
|
+
**Documentation:** [https://appcd-dev.github.io/stackgen-sdk/](https://appcd-dev.github.io/stackgen-sdk/) — Aiden guide, code samples, FAQ, and CI integration.
|
|
4
|
+
|
|
5
|
+
Install:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install stackgen-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Import package name is `stackgen`. Construct the client with an explicit config:
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from stackgen import StackgenClient, StackgenConfig
|
|
16
|
+
|
|
17
|
+
client = StackgenClient(
|
|
18
|
+
StackgenConfig(
|
|
19
|
+
base_url="https://app.stackgen.com",
|
|
20
|
+
api_token="stackgen_…",
|
|
21
|
+
org_id="<project-uuid>",
|
|
22
|
+
webhook_token="sg_aios_…", # webhook journeys only
|
|
23
|
+
)
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
result = client.aiden.run_webhook_and_download_report(
|
|
27
|
+
Path("alert.json").read_text(encoding="utf-8")
|
|
28
|
+
)
|
|
29
|
+
print(result.session_id, result.output_path)
|
|
30
|
+
|
|
31
|
+
ask = client.aiden.run_ask_and_download_artifact(
|
|
32
|
+
message="Run triage for checkout CPU alert",
|
|
33
|
+
entity_refs=[{"name": "observe-uber-triage", "type": "workflow"}],
|
|
34
|
+
)
|
|
35
|
+
print(ask.trace_id, ask.output_path)
|
|
36
|
+
|
|
37
|
+
alerts = client.sre.list_alerts()
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Default environment variables
|
|
41
|
+
|
|
42
|
+
`StackgenConfig.from_env()` reads **only** these (optional convenience):
|
|
43
|
+
|
|
44
|
+
| Variable | Purpose |
|
|
45
|
+
|----------|---------|
|
|
46
|
+
| `STACKGEN_URL` | Mothership URL (no path suffix) |
|
|
47
|
+
| `STACKGEN_TOKEN` | API token (`stackgen_…`) |
|
|
48
|
+
| `STACKGEN_PROJECT` | Project / org UUID (`orgId`) |
|
|
49
|
+
|
|
50
|
+
Pass `webhook_token`, `webhook_id`, timeouts, and artifact paths as `StackgenConfig` fields — not via env.
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from dataclasses import replace
|
|
54
|
+
from stackgen import StackgenClient, StackgenConfig
|
|
55
|
+
|
|
56
|
+
client = StackgenClient(
|
|
57
|
+
replace(StackgenConfig.from_env(), webhook_token="sg_aios_…")
|
|
58
|
+
)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Namespaces
|
|
62
|
+
|
|
63
|
+
- `client.aiden` — webhooks, Ask Guild, sessions, artifact download
|
|
64
|
+
- `client.sre` — alerts and investigations
|
|
65
|
+
- `client.vault` — secrets (not enabled in this release)
|
|
66
|
+
|
|
67
|
+
Prefer `StackgenClient` over `stackgen.generated`.
|
|
68
|
+
|
|
69
|
+
Pin versions in CI: `pip install stackgen-sdk==0.1.5`.
|
|
70
|
+
|
|
71
|
+
**Documentation:** [https://appcd-dev.github.io/stackgen-sdk/](https://appcd-dev.github.io/stackgen-sdk/) (Aiden guide, [FAQ](https://appcd-dev.github.io/stackgen-sdk/faq/), [code samples](https://appcd-dev.github.io/stackgen-sdk/code-samples/))
|
|
@@ -19,7 +19,10 @@ dependencies = [
|
|
|
19
19
|
]
|
|
20
20
|
|
|
21
21
|
[project.urls]
|
|
22
|
-
Homepage = "https://
|
|
22
|
+
Homepage = "https://appcd-dev.github.io/stackgen-sdk/"
|
|
23
|
+
Documentation = "https://appcd-dev.github.io/stackgen-sdk/"
|
|
24
|
+
Repository = "https://github.com/appcd-dev/stackgen-sdk"
|
|
25
|
+
"Bug Tracker" = "https://github.com/appcd-dev/stackgen-sdk/issues"
|
|
23
26
|
|
|
24
27
|
[project.optional-dependencies]
|
|
25
28
|
dev = ["pytest>=8.0", "build>=1.2"]
|
|
@@ -4,8 +4,13 @@ Public entrypoint::
|
|
|
4
4
|
|
|
5
5
|
from stackgen import StackgenClient, StackgenConfig
|
|
6
6
|
|
|
7
|
-
client = StackgenClient
|
|
8
|
-
|
|
7
|
+
client = StackgenClient(
|
|
8
|
+
StackgenConfig(
|
|
9
|
+
base_url="https://app.stackgen.com",
|
|
10
|
+
api_token="stackgen_…",
|
|
11
|
+
org_id="<project-uuid>",
|
|
12
|
+
)
|
|
13
|
+
)
|
|
9
14
|
"""
|
|
10
15
|
|
|
11
16
|
from __future__ import annotations
|
|
@@ -13,14 +18,32 @@ from __future__ import annotations
|
|
|
13
18
|
from stackgen.client import StackgenClient
|
|
14
19
|
from stackgen.config import StackgenConfig
|
|
15
20
|
from stackgen.errors import HttpError, NotAllowlistedError, StackgenError, TimeoutError
|
|
21
|
+
from stackgen.aiden.workflow_builder import (
|
|
22
|
+
AgentDefinition,
|
|
23
|
+
StageDefinition,
|
|
24
|
+
WorkflowBuilder,
|
|
25
|
+
WorkflowDefinition,
|
|
26
|
+
create_agent,
|
|
27
|
+
create_stage,
|
|
28
|
+
create_workflow,
|
|
29
|
+
)
|
|
30
|
+
from stackgen.aiden.workflow_publish import PublishWorkflowResult
|
|
16
31
|
|
|
17
32
|
__all__ = [
|
|
33
|
+
"AgentDefinition",
|
|
18
34
|
"HttpError",
|
|
19
35
|
"NotAllowlistedError",
|
|
36
|
+
"PublishWorkflowResult",
|
|
20
37
|
"StackgenClient",
|
|
21
38
|
"StackgenConfig",
|
|
22
39
|
"StackgenError",
|
|
40
|
+
"StageDefinition",
|
|
23
41
|
"TimeoutError",
|
|
42
|
+
"WorkflowBuilder",
|
|
43
|
+
"WorkflowDefinition",
|
|
44
|
+
"create_agent",
|
|
45
|
+
"create_stage",
|
|
46
|
+
"create_workflow",
|
|
24
47
|
]
|
|
25
48
|
|
|
26
49
|
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.1.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 1,
|
|
21
|
+
__version__ = version = '0.1.6'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 1, 6)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Aiden (platform) namespace — webhooks, sessions, artifacts, Ask Guild, workflows."""
|
|
2
|
+
|
|
3
|
+
from stackgen.aiden.ask import AskArtifactResult
|
|
4
|
+
from stackgen.aiden.namespace import AidenNamespace
|
|
5
|
+
from stackgen.aiden.webhook import WebhookReportResult
|
|
6
|
+
from stackgen.aiden.workflow_builder import (
|
|
7
|
+
AgentDefinition,
|
|
8
|
+
StageDefinition,
|
|
9
|
+
WorkflowBuilder,
|
|
10
|
+
WorkflowDefinition,
|
|
11
|
+
create_agent,
|
|
12
|
+
create_stage,
|
|
13
|
+
create_workflow,
|
|
14
|
+
)
|
|
15
|
+
from stackgen.aiden.workflow_publish import PublishWorkflowResult
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"AgentDefinition",
|
|
19
|
+
"AidenNamespace",
|
|
20
|
+
"AskArtifactResult",
|
|
21
|
+
"PublishWorkflowResult",
|
|
22
|
+
"StageDefinition",
|
|
23
|
+
"WebhookReportResult",
|
|
24
|
+
"WorkflowBuilder",
|
|
25
|
+
"WorkflowDefinition",
|
|
26
|
+
"create_agent",
|
|
27
|
+
"create_stage",
|
|
28
|
+
"create_workflow",
|
|
29
|
+
]
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""Aiden Ask → execution poll → artifact download journey."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import time
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from stackgen import _http
|
|
12
|
+
from stackgen.aiden import sessions as session_helpers
|
|
13
|
+
from stackgen.config import StackgenConfig
|
|
14
|
+
from stackgen.errors import StackgenError, TimeoutError
|
|
15
|
+
|
|
16
|
+
_TERMINAL_STATUSES = frozenset({"completed", "error"})
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True)
|
|
20
|
+
class AskArtifactResult:
|
|
21
|
+
"""Result of Ask start → wait → download session artifact."""
|
|
22
|
+
|
|
23
|
+
trace_id: str
|
|
24
|
+
run_id: str
|
|
25
|
+
session_id: str
|
|
26
|
+
artifacts: tuple[dict[str, Any], ...]
|
|
27
|
+
output_path: Path
|
|
28
|
+
candidates: tuple[dict[str, Any], ...] = ()
|
|
29
|
+
plan: str = ""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AskArtifactJourney:
|
|
33
|
+
"""Start Ask Guild, poll execution trace, wait for artifact, download it.
|
|
34
|
+
|
|
35
|
+
Uses ``api_token`` and ``org_id`` only (no webhook token).
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def __init__(self, config: StackgenConfig) -> None:
|
|
39
|
+
self._config = config
|
|
40
|
+
|
|
41
|
+
def run(
|
|
42
|
+
self,
|
|
43
|
+
message: str,
|
|
44
|
+
*,
|
|
45
|
+
entity_refs: list[dict[str, str]] | None = None,
|
|
46
|
+
artifact_name: str | None = None,
|
|
47
|
+
output_path: str | None = None,
|
|
48
|
+
inputs: dict[str, str] | None = None,
|
|
49
|
+
session_id: str | None = None,
|
|
50
|
+
source_app: str | None = None,
|
|
51
|
+
source_metadata: dict[str, str] | None = None,
|
|
52
|
+
) -> AskArtifactResult:
|
|
53
|
+
cfg = self._config
|
|
54
|
+
artifact = artifact_name or cfg.artifact_name
|
|
55
|
+
dest = output_path or cfg.output_path
|
|
56
|
+
|
|
57
|
+
start = self.start_ask(
|
|
58
|
+
message,
|
|
59
|
+
entity_refs=entity_refs,
|
|
60
|
+
inputs=inputs,
|
|
61
|
+
session_id=session_id,
|
|
62
|
+
source_app=source_app,
|
|
63
|
+
source_metadata=source_metadata,
|
|
64
|
+
)
|
|
65
|
+
trace_id = _http.text(start.get("trace_id"))
|
|
66
|
+
if not trace_id:
|
|
67
|
+
raise StackgenError(
|
|
68
|
+
"startAskGuild did not return trace_id; "
|
|
69
|
+
f"body={json.dumps(start)}"
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
run_id = _http.text(start.get("run_id"))
|
|
73
|
+
resolved_session = _http.text(start.get("session_id")) or _http.text(session_id)
|
|
74
|
+
plan = _http.text(start.get("plan"))
|
|
75
|
+
candidates = tuple(start.get("candidates") or ())
|
|
76
|
+
|
|
77
|
+
trace = self.wait_for_execution(trace_id)
|
|
78
|
+
if not resolved_session:
|
|
79
|
+
resolved_session = _http.text(trace.get("session_id"))
|
|
80
|
+
execution = trace.get("execution") or {}
|
|
81
|
+
if not resolved_session:
|
|
82
|
+
raise StackgenError(
|
|
83
|
+
f"execution {trace_id} settled without session_id; "
|
|
84
|
+
"cannot download artifacts"
|
|
85
|
+
)
|
|
86
|
+
if not run_id:
|
|
87
|
+
run_id = _http.text(execution.get("run_id"))
|
|
88
|
+
|
|
89
|
+
artifacts = session_helpers.wait_for_artifact(cfg, resolved_session, artifact)
|
|
90
|
+
path = session_helpers.download_artifact(cfg, resolved_session, artifact, dest)
|
|
91
|
+
return AskArtifactResult(
|
|
92
|
+
trace_id=trace_id,
|
|
93
|
+
run_id=run_id,
|
|
94
|
+
session_id=resolved_session,
|
|
95
|
+
artifacts=tuple(artifacts),
|
|
96
|
+
output_path=path,
|
|
97
|
+
candidates=candidates,
|
|
98
|
+
plan=plan,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
def start_ask(
|
|
102
|
+
self,
|
|
103
|
+
message: str,
|
|
104
|
+
*,
|
|
105
|
+
entity_refs: list[dict[str, str]] | None = None,
|
|
106
|
+
inputs: dict[str, str] | None = None,
|
|
107
|
+
session_id: str | None = None,
|
|
108
|
+
source_app: str | None = None,
|
|
109
|
+
source_metadata: dict[str, str] | None = None,
|
|
110
|
+
) -> dict[str, Any]:
|
|
111
|
+
"""POST /guild/api/v1/guild/ask/start."""
|
|
112
|
+
body: dict[str, Any] = {"message": message}
|
|
113
|
+
if entity_refs:
|
|
114
|
+
body["entity_refs"] = entity_refs
|
|
115
|
+
if inputs:
|
|
116
|
+
body["inputs"] = inputs
|
|
117
|
+
if session_id:
|
|
118
|
+
body["session_id"] = session_id
|
|
119
|
+
if source_app:
|
|
120
|
+
body["source_app"] = source_app
|
|
121
|
+
if source_metadata:
|
|
122
|
+
body["source_metadata"] = source_metadata
|
|
123
|
+
|
|
124
|
+
url = (
|
|
125
|
+
f"{self._config.aiden_url()}/api/v1/guild/ask/start"
|
|
126
|
+
f"{_http.query(self._config.org_id)}"
|
|
127
|
+
)
|
|
128
|
+
data = _http.request(
|
|
129
|
+
url,
|
|
130
|
+
self._config.api_token,
|
|
131
|
+
method="POST",
|
|
132
|
+
body=json.dumps(body).encode("utf-8"),
|
|
133
|
+
content_type="application/json",
|
|
134
|
+
)
|
|
135
|
+
if not isinstance(data, dict):
|
|
136
|
+
raise StackgenError(f"unexpected startAskGuild payload: {data!r}")
|
|
137
|
+
|
|
138
|
+
inputs_required = data.get("inputs_required") or []
|
|
139
|
+
if inputs_required:
|
|
140
|
+
raise StackgenError(
|
|
141
|
+
"Ask requires additional inputs before execution can start: "
|
|
142
|
+
f"{inputs_required}"
|
|
143
|
+
)
|
|
144
|
+
return data
|
|
145
|
+
|
|
146
|
+
def wait_for_execution(self, trace_id: str) -> dict[str, Any]:
|
|
147
|
+
"""Poll GET /guild/api/v1/executions/{traceId} until settled."""
|
|
148
|
+
cfg = self._config
|
|
149
|
+
deadline = time.monotonic() + cfg.timeout_seconds
|
|
150
|
+
url = (
|
|
151
|
+
f"{cfg.aiden_url()}/api/v1/executions/{trace_id}"
|
|
152
|
+
f"{_http.query(cfg.org_id)}"
|
|
153
|
+
)
|
|
154
|
+
while time.monotonic() < deadline:
|
|
155
|
+
data = _http.request(url, cfg.api_token)
|
|
156
|
+
if not isinstance(data, dict):
|
|
157
|
+
raise StackgenError(f"unexpected getExecutionTrace payload: {data!r}")
|
|
158
|
+
execution = data.get("execution") or {}
|
|
159
|
+
status = _http.text(execution.get("status")).casefold()
|
|
160
|
+
# Prefer explicit settle when the mothership sends it. Some builds
|
|
161
|
+
# omit trace_settled on the thin getExecutionTrace summary; treat
|
|
162
|
+
# terminal status alone as done so callers are not stuck forever.
|
|
163
|
+
settled = execution.get("trace_settled")
|
|
164
|
+
ready = status in _TERMINAL_STATUSES and settled is not False
|
|
165
|
+
if ready:
|
|
166
|
+
if status == "error":
|
|
167
|
+
raise StackgenError(
|
|
168
|
+
f"execution {trace_id} ended with status error"
|
|
169
|
+
)
|
|
170
|
+
return data
|
|
171
|
+
time.sleep(cfg.poll_interval_seconds)
|
|
172
|
+
raise TimeoutError("execution", cfg.timeout_seconds)
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""Aiden namespace — public methods for platform APIs."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from stackgen.aiden.ask import AskArtifactJourney, AskArtifactResult
|
|
9
|
+
from stackgen.aiden.webhook import WebhookReportJourney, WebhookReportResult
|
|
10
|
+
from stackgen.aiden.webhook_ops import WebhookOps
|
|
11
|
+
from stackgen.aiden.workflow_builder import AgentDefinition, WorkflowDefinition
|
|
12
|
+
from stackgen.aiden.workflow_publish import PublishWorkflowResult, WorkflowPublishJourney
|
|
13
|
+
from stackgen.config import StackgenConfig
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AidenNamespace:
|
|
17
|
+
"""Aiden platform APIs (sessions, webhooks, artifacts, Ask Guild, workflows)."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, config: StackgenConfig) -> None:
|
|
20
|
+
self._config = config
|
|
21
|
+
self._webhook = WebhookReportJourney(config)
|
|
22
|
+
self._ask = AskArtifactJourney(config)
|
|
23
|
+
self._workflows = WorkflowPublishJourney(config)
|
|
24
|
+
self._webhook_ops = WebhookOps(config)
|
|
25
|
+
|
|
26
|
+
def run_webhook_and_download_report(
|
|
27
|
+
self,
|
|
28
|
+
payload: str,
|
|
29
|
+
*,
|
|
30
|
+
artifact_name: str | None = None,
|
|
31
|
+
output_path: str | None = None,
|
|
32
|
+
) -> WebhookReportResult:
|
|
33
|
+
"""Trigger a webhook, wait for the session artifact, download it."""
|
|
34
|
+
return self._webhook.run(
|
|
35
|
+
payload, artifact_name=artifact_name, output_path=output_path
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
def trigger_webhook(self, payload: str) -> dict[str, Any]:
|
|
39
|
+
"""POST /guild/api/v1/webhooks/trigger (stateless; returns 202 body)."""
|
|
40
|
+
return self._webhook_ops.trigger_webhook(payload)
|
|
41
|
+
|
|
42
|
+
def get_webhook_run(self, webhook_id: str, invocation_id: str) -> dict[str, Any]:
|
|
43
|
+
"""GET webhook invocation detail by invocation UUID."""
|
|
44
|
+
return self._webhook_ops.get_webhook_run(webhook_id, invocation_id)
|
|
45
|
+
|
|
46
|
+
def list_webhook_runs(self, webhook_id: str) -> list[dict[str, Any]]:
|
|
47
|
+
"""List webhook invocations for a webhook id."""
|
|
48
|
+
return self._webhook_ops.list_webhook_runs(webhook_id)
|
|
49
|
+
|
|
50
|
+
def wait_for_webhook_session(
|
|
51
|
+
self,
|
|
52
|
+
webhook_id: str,
|
|
53
|
+
invocation_id: str,
|
|
54
|
+
*,
|
|
55
|
+
dispatch_run_id: str = "",
|
|
56
|
+
known_run_ids: frozenset[str] | None = None,
|
|
57
|
+
) -> str:
|
|
58
|
+
"""Poll webhook run detail until session_id is set."""
|
|
59
|
+
return self._webhook_ops.wait_for_webhook_session(
|
|
60
|
+
webhook_id,
|
|
61
|
+
invocation_id,
|
|
62
|
+
dispatch_run_id=dispatch_run_id,
|
|
63
|
+
known_run_ids=known_run_ids,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def get_execution_trace(self, trace_id: str) -> dict[str, Any]:
|
|
67
|
+
"""GET /guild/api/v1/executions/{traceId}."""
|
|
68
|
+
return self._webhook_ops.get_execution_trace(trace_id)
|
|
69
|
+
|
|
70
|
+
def list_executions(self, **params: Any) -> list[dict[str, Any]]:
|
|
71
|
+
"""GET /guild/api/v1/executions (optional session_id filter)."""
|
|
72
|
+
return self._webhook_ops.list_executions(**params)
|
|
73
|
+
|
|
74
|
+
def list_sessions(self, **params: Any) -> dict[str, Any]:
|
|
75
|
+
"""GET /guild/api/v1/sessions (search with q / source_app)."""
|
|
76
|
+
return self._webhook_ops.list_sessions(**params)
|
|
77
|
+
|
|
78
|
+
def get_session(self, session_id: str) -> dict[str, Any]:
|
|
79
|
+
"""GET /guild/api/v1/sessions/{sessionId}."""
|
|
80
|
+
return self._webhook_ops.get_session(session_id)
|
|
81
|
+
|
|
82
|
+
def list_session_artifacts(self, session_id: str) -> list[dict[str, Any]]:
|
|
83
|
+
"""GET session artifact metadata list."""
|
|
84
|
+
return self._webhook_ops.list_session_artifacts(session_id)
|
|
85
|
+
|
|
86
|
+
def download_session_artifact(
|
|
87
|
+
self,
|
|
88
|
+
session_id: str,
|
|
89
|
+
artifact_name: str,
|
|
90
|
+
output_path: str,
|
|
91
|
+
) -> Path:
|
|
92
|
+
"""Download one session artifact to a local path."""
|
|
93
|
+
return self._webhook_ops.download_session_artifact(
|
|
94
|
+
session_id, artifact_name, output_path
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def export_session(
|
|
98
|
+
self,
|
|
99
|
+
session_id: str,
|
|
100
|
+
*,
|
|
101
|
+
parts: str | None = None,
|
|
102
|
+
format: str = "json",
|
|
103
|
+
) -> dict[str, Any]:
|
|
104
|
+
"""GET /guild/api/v1/sessions/{sessionId}/export (report / notes / evidence)."""
|
|
105
|
+
return self._webhook_ops.export_session(session_id, parts=parts, format=format)
|
|
106
|
+
|
|
107
|
+
def terminate_session(self, session_id: str, *, reason: str | None = None) -> dict[str, Any]:
|
|
108
|
+
"""POST /guild/api/v1/sessions/{sessionId}/terminate."""
|
|
109
|
+
return self._webhook_ops.terminate_session(session_id, reason=reason)
|
|
110
|
+
|
|
111
|
+
def run_ask_and_download_artifact(
|
|
112
|
+
self,
|
|
113
|
+
message: str,
|
|
114
|
+
*,
|
|
115
|
+
entity_refs: list[dict[str, str]] | None = None,
|
|
116
|
+
artifact_name: str | None = None,
|
|
117
|
+
output_path: str | None = None,
|
|
118
|
+
inputs: dict[str, str] | None = None,
|
|
119
|
+
session_id: str | None = None,
|
|
120
|
+
source_app: str | None = None,
|
|
121
|
+
source_metadata: dict[str, str] | None = None,
|
|
122
|
+
) -> AskArtifactResult:
|
|
123
|
+
"""Start Ask Guild, poll execution, wait for artifact, download it."""
|
|
124
|
+
return self._ask.run(
|
|
125
|
+
message,
|
|
126
|
+
entity_refs=entity_refs,
|
|
127
|
+
artifact_name=artifact_name,
|
|
128
|
+
output_path=output_path,
|
|
129
|
+
inputs=inputs,
|
|
130
|
+
session_id=session_id,
|
|
131
|
+
source_app=source_app,
|
|
132
|
+
source_metadata=source_metadata,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
def start_ask(
|
|
136
|
+
self,
|
|
137
|
+
message: str,
|
|
138
|
+
*,
|
|
139
|
+
entity_refs: list[dict[str, str]] | None = None,
|
|
140
|
+
inputs: dict[str, str] | None = None,
|
|
141
|
+
session_id: str | None = None,
|
|
142
|
+
source_app: str | None = None,
|
|
143
|
+
source_metadata: dict[str, str] | None = None,
|
|
144
|
+
) -> dict[str, Any]:
|
|
145
|
+
"""POST /guild/api/v1/guild/ask/start (advanced callers)."""
|
|
146
|
+
return self._ask.start_ask(
|
|
147
|
+
message,
|
|
148
|
+
entity_refs=entity_refs,
|
|
149
|
+
inputs=inputs,
|
|
150
|
+
session_id=session_id,
|
|
151
|
+
source_app=source_app,
|
|
152
|
+
source_metadata=source_metadata,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
def wait_for_execution(self, trace_id: str) -> dict[str, Any]:
|
|
156
|
+
"""Poll GET /guild/api/v1/executions/{traceId} until settled."""
|
|
157
|
+
return self._ask.wait_for_execution(trace_id)
|
|
158
|
+
|
|
159
|
+
def publish_workflow(
|
|
160
|
+
self,
|
|
161
|
+
workflow: WorkflowDefinition,
|
|
162
|
+
*,
|
|
163
|
+
agents: list[AgentDefinition] | None = None,
|
|
164
|
+
approve: bool = True,
|
|
165
|
+
) -> PublishWorkflowResult:
|
|
166
|
+
"""Register/update agents and create/update a workflow, optionally approving it.
|
|
167
|
+
|
|
168
|
+
Pass a committed builder from ``create_workflow(...).then(...).commit()``.
|
|
169
|
+
"""
|
|
170
|
+
return self._workflows.publish(workflow, agents=agents, approve=approve)
|