stratonext-core 0.0.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.
- stratonext_core/__init__.py +0 -0
- stratonext_core/agents/__init__.py +3 -0
- stratonext_core/agents/skill.py +76 -0
- stratonext_core/approvals/__init__.py +3 -0
- stratonext_core/approvals/skill.py +109 -0
- stratonext_core/assets/__init__.py +3 -0
- stratonext_core/assets/skill.py +141 -0
- stratonext_core/client.py +15 -0
- stratonext_core/config.py +30 -0
- stratonext_core/dossiers/__init__.py +3 -0
- stratonext_core/dossiers/skill.py +90 -0
- stratonext_core/environments/__init__.py +3 -0
- stratonext_core/environments/skill.py +98 -0
- stratonext_core/jobs/__init__.py +3 -0
- stratonext_core/jobs/skill.py +126 -0
- stratonext_core/projects/__init__.py +3 -0
- stratonext_core/projects/skill.py +92 -0
- stratonext_core/registry.py +17 -0
- stratonext_core/tasks/__init__.py +3 -0
- stratonext_core/tasks/skill.py +128 -0
- stratonext_core-0.0.1.dist-info/METADATA +7 -0
- stratonext_core-0.0.1.dist-info/RECORD +23 -0
- stratonext_core-0.0.1.dist-info/WHEEL +4 -0
|
File without changes
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from types import TracebackType
|
|
4
|
+
|
|
5
|
+
from stratonext_sdk import Client
|
|
6
|
+
from stratonext_sdk.get_agent import GetAgentAgent
|
|
7
|
+
from stratonext_sdk.get_agents import GetAgentsAgentsNodes
|
|
8
|
+
from stratonext_sdk.input_types import CreateAgentInput, UpdateAgentInput
|
|
9
|
+
|
|
10
|
+
from ..client import build_client
|
|
11
|
+
from ..config import ArtemisConfig
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AgentsSkill:
|
|
15
|
+
"""Read and manage Artemis agents via the platform GraphQL API."""
|
|
16
|
+
|
|
17
|
+
def __init__(self, client: Client | None = None, config: ArtemisConfig | None = None) -> None:
|
|
18
|
+
self._client = client or build_client(config)
|
|
19
|
+
|
|
20
|
+
async def __aenter__(self) -> AgentsSkill:
|
|
21
|
+
return self
|
|
22
|
+
|
|
23
|
+
async def __aexit__(
|
|
24
|
+
self,
|
|
25
|
+
exc_type: type[BaseException] | None,
|
|
26
|
+
exc: BaseException | None,
|
|
27
|
+
tb: TracebackType | None,
|
|
28
|
+
) -> None:
|
|
29
|
+
await self._client.__aexit__(exc_type, exc, tb)
|
|
30
|
+
|
|
31
|
+
async def list_agents(
|
|
32
|
+
self, workspace_id: str, after: str | None = None
|
|
33
|
+
) -> list[GetAgentsAgentsNodes]:
|
|
34
|
+
"""List agents in a workspace, paginated 50 at a time."""
|
|
35
|
+
result = await self._client.get_agents(workspace_id=workspace_id, after=after)
|
|
36
|
+
if result.agents is None:
|
|
37
|
+
return []
|
|
38
|
+
return result.agents.nodes or []
|
|
39
|
+
|
|
40
|
+
async def get_agent(self, agent_id: str) -> GetAgentAgent | None:
|
|
41
|
+
"""Fetch a single agent by ID, or None if it doesn't exist."""
|
|
42
|
+
result = await self._client.get_agent(agent_id=agent_id)
|
|
43
|
+
return result.agent
|
|
44
|
+
|
|
45
|
+
async def create_agent(
|
|
46
|
+
self,
|
|
47
|
+
workspace_id: str,
|
|
48
|
+
name: str,
|
|
49
|
+
project_id: str | None = None,
|
|
50
|
+
) -> str:
|
|
51
|
+
"""Register an agent in a workspace, returning its ID. project_id is
|
|
52
|
+
required for Workers and must be omitted for Lead-Agents."""
|
|
53
|
+
result = await self._client.create_agent(
|
|
54
|
+
input=CreateAgentInput(
|
|
55
|
+
workspace_id=workspace_id,
|
|
56
|
+
name=name,
|
|
57
|
+
project_id=project_id,
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
return result.create_agent.id
|
|
61
|
+
|
|
62
|
+
async def update_agent(self, agent_id: str, name: str) -> str:
|
|
63
|
+
"""Rename an agent, returning its ID."""
|
|
64
|
+
result = await self._client.update_agent(
|
|
65
|
+
agent_id=agent_id, input=UpdateAgentInput(name=name)
|
|
66
|
+
)
|
|
67
|
+
return result.update_agent.id
|
|
68
|
+
|
|
69
|
+
async def deactivate_agent(self, agent_id: str) -> str:
|
|
70
|
+
"""Deactivate an agent, returning its ID."""
|
|
71
|
+
result = await self._client.deactivate_agent(agent_id=agent_id)
|
|
72
|
+
return result.deactivate_agent.id
|
|
73
|
+
|
|
74
|
+
async def delete_agent(self, agent_id: str) -> None:
|
|
75
|
+
"""Delete an agent."""
|
|
76
|
+
await self._client.delete_agent(agent_id=agent_id)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from types import TracebackType
|
|
4
|
+
|
|
5
|
+
from stratonext_sdk import Client
|
|
6
|
+
from stratonext_sdk.enums import ApprovalDecision, ApprovalRequestType
|
|
7
|
+
from stratonext_sdk.get_approval import GetApprovalApproval
|
|
8
|
+
from stratonext_sdk.get_approvals import GetApprovalsApprovalsNodes
|
|
9
|
+
from stratonext_sdk.input_types import (
|
|
10
|
+
ArtemisApprovalFilterInput,
|
|
11
|
+
ArtemisApprovalSortInput,
|
|
12
|
+
ResolveApprovalInput,
|
|
13
|
+
SubmitApprovalInput,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
from ..client import build_client
|
|
17
|
+
from ..config import ArtemisConfig
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ApprovalsSkill:
|
|
21
|
+
"""Read and manage Artemis approvals via the platform GraphQL API."""
|
|
22
|
+
|
|
23
|
+
def __init__(self, client: Client | None = None, config: ArtemisConfig | None = None) -> None:
|
|
24
|
+
self._client = client or build_client(config)
|
|
25
|
+
|
|
26
|
+
async def __aenter__(self) -> ApprovalsSkill:
|
|
27
|
+
return self
|
|
28
|
+
|
|
29
|
+
async def __aexit__(
|
|
30
|
+
self,
|
|
31
|
+
exc_type: type[BaseException] | None,
|
|
32
|
+
exc: BaseException | None,
|
|
33
|
+
tb: TracebackType | None,
|
|
34
|
+
) -> None:
|
|
35
|
+
await self._client.__aexit__(exc_type, exc, tb)
|
|
36
|
+
|
|
37
|
+
async def list_approvals(
|
|
38
|
+
self,
|
|
39
|
+
workspace_id: str,
|
|
40
|
+
after: str | None = None,
|
|
41
|
+
where: ArtemisApprovalFilterInput | None = None,
|
|
42
|
+
order: list[ArtemisApprovalSortInput] | None = None,
|
|
43
|
+
) -> list[GetApprovalsApprovalsNodes]:
|
|
44
|
+
"""List approvals in a workspace, paginated 50 at a time. Optionally filter/sort server-side."""
|
|
45
|
+
result = await self._client.get_approvals(
|
|
46
|
+
workspace_id=workspace_id,
|
|
47
|
+
after=after,
|
|
48
|
+
where=where,
|
|
49
|
+
order=order,
|
|
50
|
+
)
|
|
51
|
+
if result.approvals is None:
|
|
52
|
+
return []
|
|
53
|
+
return result.approvals.nodes or []
|
|
54
|
+
|
|
55
|
+
async def get_approval(self, approval_id: str) -> GetApprovalApproval | None:
|
|
56
|
+
"""Fetch a single approval by ID, or None if not found."""
|
|
57
|
+
result = await self._client.get_approval(approval_id=approval_id)
|
|
58
|
+
return result.approval
|
|
59
|
+
|
|
60
|
+
async def submit_approval(
|
|
61
|
+
self,
|
|
62
|
+
task_id: str,
|
|
63
|
+
agent_id: str,
|
|
64
|
+
environment_id: str,
|
|
65
|
+
workspace_id: str,
|
|
66
|
+
request_type: ApprovalRequestType,
|
|
67
|
+
name: str,
|
|
68
|
+
action_description: str,
|
|
69
|
+
payload_ref: str,
|
|
70
|
+
) -> str:
|
|
71
|
+
"""Submit an approval request, returning the approval ID.
|
|
72
|
+
|
|
73
|
+
action_description should be a detailed, human-readable description of what the agent
|
|
74
|
+
intends to do, including affected resource IDs and mutation intent. The platform evaluates
|
|
75
|
+
risk automatically using an LLM — the more detail provided, the more accurate the result.
|
|
76
|
+
|
|
77
|
+
If the environment's automation policy permits it, the approval is resolved immediately
|
|
78
|
+
(status APPROVED) and the task remains dispatchable. Otherwise the task is transitioned
|
|
79
|
+
to APPROVAL_REQUIRED and the approval ID should be surfaced to human approvers.
|
|
80
|
+
"""
|
|
81
|
+
result = await self._client.submit_approval(
|
|
82
|
+
input=SubmitApprovalInput(
|
|
83
|
+
task_id=task_id,
|
|
84
|
+
agent_id=agent_id,
|
|
85
|
+
environment_id=environment_id,
|
|
86
|
+
workspace_id=workspace_id,
|
|
87
|
+
request_type=request_type,
|
|
88
|
+
name=name,
|
|
89
|
+
action_description=action_description,
|
|
90
|
+
payload_ref=payload_ref,
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
return result.submit_approval.id
|
|
94
|
+
|
|
95
|
+
async def approve(self, approval_id: str, notes: str | None = None) -> str:
|
|
96
|
+
"""Approve a pending approval, returning the approval ID."""
|
|
97
|
+
result = await self._client.resolve_approval(
|
|
98
|
+
approval_id=approval_id,
|
|
99
|
+
input=ResolveApprovalInput(decision=ApprovalDecision.APPROVED, notes=notes),
|
|
100
|
+
)
|
|
101
|
+
return result.resolve_approval.id
|
|
102
|
+
|
|
103
|
+
async def reject(self, approval_id: str, notes: str | None = None) -> str:
|
|
104
|
+
"""Reject a pending approval, returning the approval ID."""
|
|
105
|
+
result = await self._client.resolve_approval(
|
|
106
|
+
approval_id=approval_id,
|
|
107
|
+
input=ResolveApprovalInput(decision=ApprovalDecision.REJECTED, notes=notes),
|
|
108
|
+
)
|
|
109
|
+
return result.resolve_approval.id
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import mimetypes
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from types import TracebackType
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
from stratonext_sdk import Client
|
|
9
|
+
from stratonext_sdk.confirm_asset import ConfirmAssetConfirmAsset
|
|
10
|
+
from stratonext_sdk.enums import AssetCategory, ParentType
|
|
11
|
+
from stratonext_sdk.input_types import RegisterAssetInput
|
|
12
|
+
from stratonext_sdk.register_asset import RegisterAssetRegisterAsset
|
|
13
|
+
|
|
14
|
+
from ..client import build_client
|
|
15
|
+
from ..config import ArtemisConfig
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AssetsSkill:
|
|
19
|
+
"""Register, confirm, and fetch download URLs for Artemis assets.
|
|
20
|
+
|
|
21
|
+
``upload_file``/``download_file`` are the preferred entry points: the raw
|
|
22
|
+
register/confirm calls below leave a stale PENDING asset row (and staging
|
|
23
|
+
object) behind if the caller uploads the bytes and forgets to confirm, or
|
|
24
|
+
crashes in between. A single call removes that window entirely.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, client: Client | None = None, config: ArtemisConfig | None = None) -> None:
|
|
28
|
+
self._client = client or build_client(config)
|
|
29
|
+
|
|
30
|
+
async def __aenter__(self) -> AssetsSkill:
|
|
31
|
+
return self
|
|
32
|
+
|
|
33
|
+
async def __aexit__(
|
|
34
|
+
self,
|
|
35
|
+
exc_type: type[BaseException] | None,
|
|
36
|
+
exc: BaseException | None,
|
|
37
|
+
tb: TracebackType | None,
|
|
38
|
+
) -> None:
|
|
39
|
+
await self._client.__aexit__(exc_type, exc, tb)
|
|
40
|
+
|
|
41
|
+
async def register_asset(
|
|
42
|
+
self,
|
|
43
|
+
name: str,
|
|
44
|
+
description: str,
|
|
45
|
+
media_type: str,
|
|
46
|
+
category: AssetCategory,
|
|
47
|
+
filename: str,
|
|
48
|
+
parent_id: str,
|
|
49
|
+
parent_type: ParentType,
|
|
50
|
+
workspace_id: str,
|
|
51
|
+
) -> RegisterAssetRegisterAsset:
|
|
52
|
+
"""Register a new asset, returning its record and a presigned upload URL."""
|
|
53
|
+
result = await self._client.register_asset(
|
|
54
|
+
input=RegisterAssetInput(
|
|
55
|
+
name=name,
|
|
56
|
+
description=description,
|
|
57
|
+
media_type=media_type,
|
|
58
|
+
category=category,
|
|
59
|
+
filename=filename,
|
|
60
|
+
parent_id=parent_id,
|
|
61
|
+
parent_type=parent_type,
|
|
62
|
+
workspace_id=workspace_id,
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
return result.register_asset
|
|
66
|
+
|
|
67
|
+
async def confirm_asset(self, asset_id: str) -> ConfirmAssetConfirmAsset:
|
|
68
|
+
"""Confirm an asset after its bytes have been uploaded to the presigned URL."""
|
|
69
|
+
result = await self._client.confirm_asset(asset_id=asset_id)
|
|
70
|
+
return result.confirm_asset
|
|
71
|
+
|
|
72
|
+
async def get_download_url(self, asset_id: str) -> str | None:
|
|
73
|
+
"""Get a presigned download URL for an existing asset, or None if it doesn't exist."""
|
|
74
|
+
result = await self._client.get_asset_download_url(asset_id=asset_id)
|
|
75
|
+
return result.asset_download_url
|
|
76
|
+
|
|
77
|
+
async def upload_file(
|
|
78
|
+
self,
|
|
79
|
+
path: str | Path,
|
|
80
|
+
parent_id: str,
|
|
81
|
+
parent_type: ParentType,
|
|
82
|
+
workspace_id: str,
|
|
83
|
+
name: str | None = None,
|
|
84
|
+
description: str = "",
|
|
85
|
+
category: AssetCategory = AssetCategory.GENERIC,
|
|
86
|
+
media_type: str | None = None,
|
|
87
|
+
) -> ConfirmAssetConfirmAsset:
|
|
88
|
+
"""Register, upload, and confirm a local file as one call.
|
|
89
|
+
|
|
90
|
+
Reads ``path`` from disk and uploads it to the presigned staging URL.
|
|
91
|
+
If the upload or confirm step fails, the just-registered asset is
|
|
92
|
+
deleted so no PENDING row is left behind — callers never have to
|
|
93
|
+
handle the register/confirm gap themselves.
|
|
94
|
+
"""
|
|
95
|
+
path = Path(path)
|
|
96
|
+
media_type = media_type or mimetypes.guess_type(path.name)[0] or "application/octet-stream"
|
|
97
|
+
registered = await self.register_asset(
|
|
98
|
+
name=name or path.name,
|
|
99
|
+
description=description,
|
|
100
|
+
media_type=media_type,
|
|
101
|
+
category=category,
|
|
102
|
+
filename=path.name,
|
|
103
|
+
parent_id=parent_id,
|
|
104
|
+
parent_type=parent_type,
|
|
105
|
+
workspace_id=workspace_id,
|
|
106
|
+
)
|
|
107
|
+
try:
|
|
108
|
+
# Presigned POST: form fields first, file part last. The signed policy
|
|
109
|
+
# enforces the size cap, so S3 rejects an oversized file here (4xx).
|
|
110
|
+
fields = {f.name: f.value for f in registered.upload.fields}
|
|
111
|
+
async with httpx.AsyncClient() as http_client:
|
|
112
|
+
response = await http_client.post(
|
|
113
|
+
registered.upload.url,
|
|
114
|
+
data=fields,
|
|
115
|
+
files={"file": (path.name, path.read_bytes(), media_type)},
|
|
116
|
+
)
|
|
117
|
+
response.raise_for_status()
|
|
118
|
+
return await self.confirm_asset(registered.asset.id)
|
|
119
|
+
except Exception:
|
|
120
|
+
await self._client.delete_asset(asset_id=registered.asset.id)
|
|
121
|
+
raise
|
|
122
|
+
|
|
123
|
+
async def download_file(self, asset_id: str, dest: str | Path) -> Path:
|
|
124
|
+
"""Download an asset's content to ``dest`` as one call.
|
|
125
|
+
|
|
126
|
+
Raises ``ValueError`` if the asset doesn't exist or has no download URL.
|
|
127
|
+
"""
|
|
128
|
+
url = await self.get_download_url(asset_id)
|
|
129
|
+
if not url:
|
|
130
|
+
raise ValueError(f"Asset {asset_id!r} not found or has no download URL")
|
|
131
|
+
|
|
132
|
+
dest = Path(dest)
|
|
133
|
+
async with httpx.AsyncClient(follow_redirects=True) as http_client:
|
|
134
|
+
response = await http_client.get(url)
|
|
135
|
+
response.raise_for_status()
|
|
136
|
+
dest.write_bytes(response.content)
|
|
137
|
+
return dest
|
|
138
|
+
|
|
139
|
+
async def delete_asset(self, asset_id: str) -> bool:
|
|
140
|
+
"""Delete an asset by ID, returning the platform's deletion result."""
|
|
141
|
+
return (await self._client.delete_asset(asset_id=asset_id)).delete_asset
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from stratonext_sdk import Client
|
|
4
|
+
|
|
5
|
+
from .config import ArtemisConfig
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def build_client(config: ArtemisConfig | None = None) -> Client:
|
|
9
|
+
"""Construct a Client for the Artemis platform GraphQL API.
|
|
10
|
+
|
|
11
|
+
Reads connection settings from the environment via ArtemisConfig.from_env()
|
|
12
|
+
unless an explicit config is passed.
|
|
13
|
+
"""
|
|
14
|
+
config = config or ArtemisConfig.from_env()
|
|
15
|
+
return Client(url=config.endpoint, headers=config.headers)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass(frozen=True)
|
|
8
|
+
class ArtemisConfig:
|
|
9
|
+
"""Connection settings for the Artemis platform GraphQL API, read from the environment.
|
|
10
|
+
|
|
11
|
+
- ARTEMIS_API_URL: GraphQL endpoint URL. Defaults to the local dev API.
|
|
12
|
+
- ARTEMIS_AUTH_API_TOKEN: bearer token sent as `Authorization: Bearer <token>`. Optional
|
|
13
|
+
for local dev deployments running without auth.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
endpoint: str
|
|
17
|
+
api_token: str | None = None
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def headers(self) -> dict[str, str]:
|
|
21
|
+
if not self.api_token:
|
|
22
|
+
return {}
|
|
23
|
+
return {"Authorization": f"Bearer {self.api_token}"}
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def from_env(cls) -> ArtemisConfig:
|
|
27
|
+
return cls(
|
|
28
|
+
endpoint=os.environ.get("ARTEMIS_API_URL", "http://localhost:5555/v1/graphql"),
|
|
29
|
+
api_token=os.environ.get("ARTEMIS_AUTH_API_TOKEN"),
|
|
30
|
+
)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from types import TracebackType
|
|
4
|
+
|
|
5
|
+
from stratonext_sdk import Client
|
|
6
|
+
from stratonext_sdk.enums import DossierStatus, DossierType
|
|
7
|
+
from stratonext_sdk.get_dossier import GetDossierDossier
|
|
8
|
+
from stratonext_sdk.get_dossiers import GetDossiersDossiersNodes
|
|
9
|
+
from stratonext_sdk.input_types import CreateDossierInput, UpdateDossierInput
|
|
10
|
+
|
|
11
|
+
from ..client import build_client
|
|
12
|
+
from ..config import ArtemisConfig
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DossiersSkill:
|
|
16
|
+
"""Read and manage Artemis dossiers via the platform GraphQL API."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, client: Client | None = None, config: ArtemisConfig | None = None) -> None:
|
|
19
|
+
self._client = client or build_client(config)
|
|
20
|
+
|
|
21
|
+
async def __aenter__(self) -> DossiersSkill:
|
|
22
|
+
return self
|
|
23
|
+
|
|
24
|
+
async def __aexit__(
|
|
25
|
+
self,
|
|
26
|
+
exc_type: type[BaseException] | None,
|
|
27
|
+
exc: BaseException | None,
|
|
28
|
+
tb: TracebackType | None,
|
|
29
|
+
) -> None:
|
|
30
|
+
await self._client.__aexit__(exc_type, exc, tb)
|
|
31
|
+
|
|
32
|
+
async def list_dossiers(
|
|
33
|
+
self, workspace_id: str, after: str | None = None
|
|
34
|
+
) -> list[GetDossiersDossiersNodes]:
|
|
35
|
+
"""List dossiers in a workspace, paginated 50 at a time."""
|
|
36
|
+
result = await self._client.get_dossiers(workspace_id=workspace_id, after=after)
|
|
37
|
+
if result.dossiers is None:
|
|
38
|
+
return []
|
|
39
|
+
return result.dossiers.nodes or []
|
|
40
|
+
|
|
41
|
+
async def get_dossier(self, dossier_id: str) -> GetDossierDossier | None:
|
|
42
|
+
"""Fetch a single dossier by ID, or None if it doesn't exist."""
|
|
43
|
+
result = await self._client.get_dossier(dossier_id=dossier_id)
|
|
44
|
+
return result.dossier
|
|
45
|
+
|
|
46
|
+
async def create_dossier(
|
|
47
|
+
self,
|
|
48
|
+
workspace_id: str,
|
|
49
|
+
title: str,
|
|
50
|
+
type: DossierType = DossierType.GENERIC,
|
|
51
|
+
body: str | None = None,
|
|
52
|
+
owner_id: str | None = None,
|
|
53
|
+
) -> str:
|
|
54
|
+
"""Create a dossier in a workspace, returning its ID."""
|
|
55
|
+
result = await self._client.create_dossier(
|
|
56
|
+
input=CreateDossierInput(
|
|
57
|
+
workspace_id=workspace_id,
|
|
58
|
+
title=title,
|
|
59
|
+
type_=type,
|
|
60
|
+
body=body,
|
|
61
|
+
owner_id=owner_id,
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
return result.create_dossier.id
|
|
65
|
+
|
|
66
|
+
async def update_dossier(
|
|
67
|
+
self,
|
|
68
|
+
dossier_id: str,
|
|
69
|
+
title: str | None = None,
|
|
70
|
+
body: str | None = None,
|
|
71
|
+
owner_id: str | None = None,
|
|
72
|
+
status: DossierStatus | None = None,
|
|
73
|
+
project_ids: list[str] | None = None,
|
|
74
|
+
) -> str:
|
|
75
|
+
"""Update a dossier's fields, returning its ID."""
|
|
76
|
+
result = await self._client.update_dossier(
|
|
77
|
+
dossier_id=dossier_id,
|
|
78
|
+
input=UpdateDossierInput(
|
|
79
|
+
title=title,
|
|
80
|
+
body=body,
|
|
81
|
+
owner_id=owner_id,
|
|
82
|
+
status=status,
|
|
83
|
+
project_ids=project_ids,
|
|
84
|
+
),
|
|
85
|
+
)
|
|
86
|
+
return result.update_dossier.id
|
|
87
|
+
|
|
88
|
+
async def delete_dossier(self, dossier_id: str) -> None:
|
|
89
|
+
"""Delete a dossier."""
|
|
90
|
+
await self._client.delete_dossier(dossier_id=dossier_id)
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from types import TracebackType
|
|
4
|
+
|
|
5
|
+
from stratonext_sdk import Client
|
|
6
|
+
from stratonext_sdk.enums import (
|
|
7
|
+
EnvironmentAutomationPolicy,
|
|
8
|
+
EnvironmentClassification,
|
|
9
|
+
EnvironmentProvider,
|
|
10
|
+
)
|
|
11
|
+
from stratonext_sdk.get_environment import GetEnvironmentEnvironment
|
|
12
|
+
from stratonext_sdk.get_environments import GetEnvironmentsEnvironmentsNodes
|
|
13
|
+
from stratonext_sdk.input_types import (
|
|
14
|
+
CreateEnvironmentInput,
|
|
15
|
+
MetadataKvInput,
|
|
16
|
+
UpdateEnvironmentInput,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from ..client import build_client
|
|
20
|
+
from ..config import ArtemisConfig
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class EnvironmentsSkill:
|
|
24
|
+
"""Read and manage Artemis environments via the platform GraphQL API."""
|
|
25
|
+
|
|
26
|
+
def __init__(self, client: Client | None = None, config: ArtemisConfig | None = None) -> None:
|
|
27
|
+
self._client = client or build_client(config)
|
|
28
|
+
|
|
29
|
+
async def __aenter__(self) -> EnvironmentsSkill:
|
|
30
|
+
return self
|
|
31
|
+
|
|
32
|
+
async def __aexit__(
|
|
33
|
+
self,
|
|
34
|
+
exc_type: type[BaseException] | None,
|
|
35
|
+
exc: BaseException | None,
|
|
36
|
+
tb: TracebackType | None,
|
|
37
|
+
) -> None:
|
|
38
|
+
await self._client.__aexit__(exc_type, exc, tb)
|
|
39
|
+
|
|
40
|
+
async def list_environments(
|
|
41
|
+
self, workspace_id: str, after: str | None = None
|
|
42
|
+
) -> list[GetEnvironmentsEnvironmentsNodes]:
|
|
43
|
+
"""List environments in a workspace, paginated 50 at a time."""
|
|
44
|
+
result = await self._client.get_environments(workspace_id=workspace_id, after=after)
|
|
45
|
+
if result.environments is None:
|
|
46
|
+
return []
|
|
47
|
+
return result.environments.nodes or []
|
|
48
|
+
|
|
49
|
+
async def get_environment(self, environment_id: str) -> GetEnvironmentEnvironment | None:
|
|
50
|
+
"""Fetch a single environment by ID, or None if it doesn't exist."""
|
|
51
|
+
result = await self._client.get_environment(environment_id=environment_id)
|
|
52
|
+
return result.environment
|
|
53
|
+
|
|
54
|
+
async def create_environment(
|
|
55
|
+
self,
|
|
56
|
+
workspace_id: str,
|
|
57
|
+
name: str,
|
|
58
|
+
provider: EnvironmentProvider,
|
|
59
|
+
classification: EnvironmentClassification | None = None,
|
|
60
|
+
automation_policy: EnvironmentAutomationPolicy | None = None,
|
|
61
|
+
metadata: list[MetadataKvInput] | None = None,
|
|
62
|
+
) -> str:
|
|
63
|
+
"""Register a new environment in a workspace, returning its ID."""
|
|
64
|
+
result = await self._client.create_environment(
|
|
65
|
+
input=CreateEnvironmentInput(
|
|
66
|
+
workspace_id=workspace_id,
|
|
67
|
+
name=name,
|
|
68
|
+
provider=provider,
|
|
69
|
+
classification=classification,
|
|
70
|
+
automation_policy=automation_policy,
|
|
71
|
+
metadata=metadata,
|
|
72
|
+
)
|
|
73
|
+
)
|
|
74
|
+
return result.create_environment.id
|
|
75
|
+
|
|
76
|
+
async def update_environment(
|
|
77
|
+
self,
|
|
78
|
+
environment_id: str,
|
|
79
|
+
name: str | None = None,
|
|
80
|
+
classification: EnvironmentClassification | None = None,
|
|
81
|
+
automation_policy: EnvironmentAutomationPolicy | None = None,
|
|
82
|
+
metadata: list[MetadataKvInput] | None = None,
|
|
83
|
+
) -> str:
|
|
84
|
+
"""Update an environment's fields, returning its ID."""
|
|
85
|
+
result = await self._client.update_environment(
|
|
86
|
+
environment_id=environment_id,
|
|
87
|
+
input=UpdateEnvironmentInput(
|
|
88
|
+
name=name,
|
|
89
|
+
classification=classification,
|
|
90
|
+
automation_policy=automation_policy,
|
|
91
|
+
metadata=metadata,
|
|
92
|
+
),
|
|
93
|
+
)
|
|
94
|
+
return result.update_environment.id
|
|
95
|
+
|
|
96
|
+
async def delete_environment(self, environment_id: str) -> None:
|
|
97
|
+
"""Delete an environment."""
|
|
98
|
+
await self._client.delete_environment(environment_id=environment_id)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from types import TracebackType
|
|
4
|
+
|
|
5
|
+
from stratonext_sdk import Client
|
|
6
|
+
from stratonext_sdk.get_job import GetJobJob
|
|
7
|
+
from stratonext_sdk.get_job_run import GetJobRunJobRun
|
|
8
|
+
from stratonext_sdk.get_job_runs import GetJobRunsJobRunsNodes
|
|
9
|
+
from stratonext_sdk.get_jobs import GetJobsJobsNodes
|
|
10
|
+
from stratonext_sdk.input_types import CreateJobInput, UpdateJobInput
|
|
11
|
+
from stratonext_sdk.trigger_job_run import TriggerJobRunTriggerJobRun
|
|
12
|
+
|
|
13
|
+
from ..client import build_client
|
|
14
|
+
from ..config import ArtemisConfig
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class JobsSkill:
|
|
18
|
+
"""Read and manage Artemis jobs and job runs via the platform GraphQL API."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, client: Client | None = None, config: ArtemisConfig | None = None) -> None:
|
|
21
|
+
self._client = client or build_client(config)
|
|
22
|
+
|
|
23
|
+
async def __aenter__(self) -> JobsSkill:
|
|
24
|
+
return self
|
|
25
|
+
|
|
26
|
+
async def __aexit__(
|
|
27
|
+
self,
|
|
28
|
+
exc_type: type[BaseException] | None,
|
|
29
|
+
exc: BaseException | None,
|
|
30
|
+
tb: TracebackType | None,
|
|
31
|
+
) -> None:
|
|
32
|
+
await self._client.__aexit__(exc_type, exc, tb)
|
|
33
|
+
|
|
34
|
+
async def list_jobs(self, project_id: str, after: str | None = None) -> list[GetJobsJobsNodes]:
|
|
35
|
+
"""List jobs in a project, paginated 50 at a time."""
|
|
36
|
+
result = await self._client.get_jobs(project_id=project_id, after=after)
|
|
37
|
+
if result.jobs is None:
|
|
38
|
+
return []
|
|
39
|
+
return result.jobs.nodes or []
|
|
40
|
+
|
|
41
|
+
async def get_job(self, job_id: str) -> GetJobJob | None:
|
|
42
|
+
"""Fetch a single job by ID, or None if it doesn't exist."""
|
|
43
|
+
result = await self._client.get_job(job_id=job_id)
|
|
44
|
+
return result.job
|
|
45
|
+
|
|
46
|
+
async def create_job(
|
|
47
|
+
self,
|
|
48
|
+
workspace_id: str,
|
|
49
|
+
project_id: str,
|
|
50
|
+
name: str,
|
|
51
|
+
agent_id: str,
|
|
52
|
+
schedule: str,
|
|
53
|
+
description: str | None = None,
|
|
54
|
+
instructions: str | None = None,
|
|
55
|
+
deployment_ids: list[str] | None = None,
|
|
56
|
+
max_queue_depth: int | None = None,
|
|
57
|
+
) -> str:
|
|
58
|
+
"""Create a job in a project, returning its ID."""
|
|
59
|
+
result = await self._client.create_job(
|
|
60
|
+
input=CreateJobInput(
|
|
61
|
+
workspace_id=workspace_id,
|
|
62
|
+
project_id=project_id,
|
|
63
|
+
name=name,
|
|
64
|
+
agent_id=agent_id,
|
|
65
|
+
schedule=schedule,
|
|
66
|
+
description=description,
|
|
67
|
+
instructions=instructions,
|
|
68
|
+
deployment_ids=deployment_ids,
|
|
69
|
+
max_queue_depth=max_queue_depth,
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
return result.create_job.id
|
|
73
|
+
|
|
74
|
+
async def update_job(
|
|
75
|
+
self,
|
|
76
|
+
job_id: str,
|
|
77
|
+
name: str | None = None,
|
|
78
|
+
description: str | None = None,
|
|
79
|
+
schedule: str | None = None,
|
|
80
|
+
max_queue_depth: int | None = None,
|
|
81
|
+
) -> str:
|
|
82
|
+
"""Update a job's fields, returning its ID."""
|
|
83
|
+
result = await self._client.update_job(
|
|
84
|
+
job_id=job_id,
|
|
85
|
+
input=UpdateJobInput(
|
|
86
|
+
name=name,
|
|
87
|
+
description=description,
|
|
88
|
+
schedule=schedule,
|
|
89
|
+
max_queue_depth=max_queue_depth,
|
|
90
|
+
),
|
|
91
|
+
)
|
|
92
|
+
return result.update_job.id
|
|
93
|
+
|
|
94
|
+
async def pause_job(self, job_id: str) -> str:
|
|
95
|
+
"""Pause a job's schedule, returning its ID."""
|
|
96
|
+
result = await self._client.pause_job(job_id=job_id)
|
|
97
|
+
return result.pause_job.id
|
|
98
|
+
|
|
99
|
+
async def resume_job(self, job_id: str) -> str:
|
|
100
|
+
"""Resume a paused job's schedule, returning its ID."""
|
|
101
|
+
result = await self._client.resume_job(job_id=job_id)
|
|
102
|
+
return result.resume_job.id
|
|
103
|
+
|
|
104
|
+
async def disable_job(self, job_id: str) -> str:
|
|
105
|
+
"""Permanently disable a job and delete its schedule, returning its ID."""
|
|
106
|
+
result = await self._client.disable_job(job_id=job_id)
|
|
107
|
+
return result.disable_job.id
|
|
108
|
+
|
|
109
|
+
async def trigger_job_run(self, job_id: str) -> TriggerJobRunTriggerJobRun:
|
|
110
|
+
"""Manually trigger one job run, bypassing the schedule."""
|
|
111
|
+
result = await self._client.trigger_job_run(job_id=job_id)
|
|
112
|
+
return result.trigger_job_run
|
|
113
|
+
|
|
114
|
+
async def list_job_runs(
|
|
115
|
+
self, job_id: str, after: str | None = None
|
|
116
|
+
) -> list[GetJobRunsJobRunsNodes]:
|
|
117
|
+
"""List runs for a job, paginated 50 at a time."""
|
|
118
|
+
result = await self._client.get_job_runs(job_id=job_id, after=after)
|
|
119
|
+
if result.job_runs is None:
|
|
120
|
+
return []
|
|
121
|
+
return result.job_runs.nodes or []
|
|
122
|
+
|
|
123
|
+
async def get_job_run(self, job_run_id: str) -> GetJobRunJobRun | None:
|
|
124
|
+
"""Fetch a single job run by ID, or None if it doesn't exist."""
|
|
125
|
+
result = await self._client.get_job_run(job_run_id=job_run_id)
|
|
126
|
+
return result.job_run
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from types import TracebackType
|
|
4
|
+
|
|
5
|
+
from stratonext_sdk import Client
|
|
6
|
+
from stratonext_sdk.enums import ProjectStatus, ProjectType
|
|
7
|
+
from stratonext_sdk.get_project import GetProjectProject
|
|
8
|
+
from stratonext_sdk.get_projects import GetProjectsProjectsNodes
|
|
9
|
+
from stratonext_sdk.input_types import CreateProjectInput, ResourceLinkInput, UpdateProjectInput
|
|
10
|
+
|
|
11
|
+
from ..client import build_client
|
|
12
|
+
from ..config import ArtemisConfig
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ProjectsSkill:
|
|
16
|
+
"""Read and manage Artemis projects via the platform GraphQL API."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, client: Client | None = None, config: ArtemisConfig | None = None) -> None:
|
|
19
|
+
self._client = client or build_client(config)
|
|
20
|
+
|
|
21
|
+
async def __aenter__(self) -> ProjectsSkill:
|
|
22
|
+
return self
|
|
23
|
+
|
|
24
|
+
async def __aexit__(
|
|
25
|
+
self,
|
|
26
|
+
exc_type: type[BaseException] | None,
|
|
27
|
+
exc: BaseException | None,
|
|
28
|
+
tb: TracebackType | None,
|
|
29
|
+
) -> None:
|
|
30
|
+
await self._client.__aexit__(exc_type, exc, tb)
|
|
31
|
+
|
|
32
|
+
async def list_projects(
|
|
33
|
+
self, workspace_id: str, after: str | None = None
|
|
34
|
+
) -> list[GetProjectsProjectsNodes]:
|
|
35
|
+
"""List projects in a workspace, paginated 50 at a time."""
|
|
36
|
+
result = await self._client.get_projects(workspace_id=workspace_id, after=after)
|
|
37
|
+
if result.projects is None:
|
|
38
|
+
return []
|
|
39
|
+
return result.projects.nodes or []
|
|
40
|
+
|
|
41
|
+
async def get_project(self, project_id: str) -> GetProjectProject | None:
|
|
42
|
+
"""Fetch a single project by ID, or None if it doesn't exist."""
|
|
43
|
+
result = await self._client.get_project(project_id=project_id)
|
|
44
|
+
return result.project
|
|
45
|
+
|
|
46
|
+
async def create_project(
|
|
47
|
+
self,
|
|
48
|
+
workspace_id: str,
|
|
49
|
+
name: str,
|
|
50
|
+
description: str,
|
|
51
|
+
type: ProjectType | None = None,
|
|
52
|
+
) -> str:
|
|
53
|
+
"""Create a project in a workspace, returning its ID."""
|
|
54
|
+
result = await self._client.create_project(
|
|
55
|
+
input=CreateProjectInput(
|
|
56
|
+
workspace_id=workspace_id,
|
|
57
|
+
name=name,
|
|
58
|
+
description=description,
|
|
59
|
+
type_=type,
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
return result.create_project.id
|
|
63
|
+
|
|
64
|
+
async def update_project(
|
|
65
|
+
self,
|
|
66
|
+
project_id: str,
|
|
67
|
+
name: str | None = None,
|
|
68
|
+
description: str | None = None,
|
|
69
|
+
status: ProjectStatus | None = None,
|
|
70
|
+
instructions: str | None = None,
|
|
71
|
+
notes: list[str] | None = None,
|
|
72
|
+
links: list[ResourceLinkInput] | None = None,
|
|
73
|
+
type: ProjectType | None = None,
|
|
74
|
+
) -> str:
|
|
75
|
+
"""Update a project's fields, returning its ID."""
|
|
76
|
+
result = await self._client.update_project(
|
|
77
|
+
project_id=project_id,
|
|
78
|
+
input=UpdateProjectInput(
|
|
79
|
+
name=name,
|
|
80
|
+
description=description,
|
|
81
|
+
status=status,
|
|
82
|
+
instructions=instructions,
|
|
83
|
+
notes=notes,
|
|
84
|
+
links=links,
|
|
85
|
+
type_=type,
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
return result.update_project.id
|
|
89
|
+
|
|
90
|
+
async def delete_project(self, project_id: str) -> None:
|
|
91
|
+
"""Delete a project."""
|
|
92
|
+
await self._client.delete_project(project_id=project_id)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from .agents import AgentsSkill
|
|
2
|
+
from .approvals import ApprovalsSkill
|
|
3
|
+
from .assets import AssetsSkill
|
|
4
|
+
from .dossiers import DossiersSkill
|
|
5
|
+
from .environments import EnvironmentsSkill
|
|
6
|
+
from .projects import ProjectsSkill
|
|
7
|
+
from .tasks import TasksSkill
|
|
8
|
+
|
|
9
|
+
SKILLS: dict[str, type] = {
|
|
10
|
+
"projects": ProjectsSkill,
|
|
11
|
+
"tasks": TasksSkill,
|
|
12
|
+
"environments": EnvironmentsSkill,
|
|
13
|
+
"agents": AgentsSkill,
|
|
14
|
+
"assets": AssetsSkill,
|
|
15
|
+
"approvals": ApprovalsSkill,
|
|
16
|
+
"dossiers": DossiersSkill,
|
|
17
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from types import TracebackType
|
|
4
|
+
|
|
5
|
+
from stratonext_sdk import Client
|
|
6
|
+
from stratonext_sdk.enums import AssigneeType, TaskStatus, VerificationStatus
|
|
7
|
+
from stratonext_sdk.get_task import GetTaskTask
|
|
8
|
+
from stratonext_sdk.get_tasks import GetTasksTasksNodes, GetTasksTasksPageInfo
|
|
9
|
+
from stratonext_sdk.input_types import (
|
|
10
|
+
ArtemisTaskFilterInput,
|
|
11
|
+
ArtemisTaskSortInput,
|
|
12
|
+
CreateTaskInput,
|
|
13
|
+
ResourceLinkInput,
|
|
14
|
+
UpdateTaskInput,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from ..client import build_client
|
|
18
|
+
from ..config import ArtemisConfig
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TasksSkill:
|
|
22
|
+
"""Read and manage Artemis tasks via the platform GraphQL API."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, client: Client | None = None, config: ArtemisConfig | None = None) -> None:
|
|
25
|
+
self._client = client or build_client(config)
|
|
26
|
+
|
|
27
|
+
async def __aenter__(self) -> TasksSkill:
|
|
28
|
+
return self
|
|
29
|
+
|
|
30
|
+
async def __aexit__(
|
|
31
|
+
self,
|
|
32
|
+
exc_type: type[BaseException] | None,
|
|
33
|
+
exc: BaseException | None,
|
|
34
|
+
tb: TracebackType | None,
|
|
35
|
+
) -> None:
|
|
36
|
+
await self._client.__aexit__(exc_type, exc, tb)
|
|
37
|
+
|
|
38
|
+
async def list_tasks(
|
|
39
|
+
self,
|
|
40
|
+
workspace_id: str,
|
|
41
|
+
after: str | None = None,
|
|
42
|
+
order: list[ArtemisTaskSortInput] | None = None,
|
|
43
|
+
where: ArtemisTaskFilterInput | None = None,
|
|
44
|
+
) -> tuple[list[GetTasksTasksNodes], GetTasksTasksPageInfo | None]:
|
|
45
|
+
"""Fetch one page of tasks (50). Returns (nodes, page_info); page_info.end_cursor is the next-page token."""
|
|
46
|
+
result = await self._client.get_tasks(
|
|
47
|
+
workspace_id=workspace_id, after=after, order=order, where=where
|
|
48
|
+
)
|
|
49
|
+
if result.tasks is None:
|
|
50
|
+
return [], None
|
|
51
|
+
return result.tasks.nodes or [], result.tasks.page_info
|
|
52
|
+
|
|
53
|
+
async def get_task(self, task_id: str) -> GetTaskTask | None:
|
|
54
|
+
"""Fetch a single task by ID, or None if it doesn't exist."""
|
|
55
|
+
result = await self._client.get_task(task_id=task_id)
|
|
56
|
+
return result.task
|
|
57
|
+
|
|
58
|
+
async def create_task(
|
|
59
|
+
self,
|
|
60
|
+
workspace_id: str,
|
|
61
|
+
project_id: str,
|
|
62
|
+
name: str,
|
|
63
|
+
description: str,
|
|
64
|
+
instructions: str | None = None,
|
|
65
|
+
assignee_id: str | None = None,
|
|
66
|
+
assignee_type: AssigneeType | None = None,
|
|
67
|
+
verification_criteria: str | None = None,
|
|
68
|
+
verification_status: VerificationStatus | None = None,
|
|
69
|
+
verification_notes: str | None = None,
|
|
70
|
+
) -> str:
|
|
71
|
+
"""Create a task in a project, returning its ID."""
|
|
72
|
+
result = await self._client.create_task(
|
|
73
|
+
input=CreateTaskInput(
|
|
74
|
+
workspace_id=workspace_id,
|
|
75
|
+
project_id=project_id,
|
|
76
|
+
name=name,
|
|
77
|
+
description=description,
|
|
78
|
+
instructions=instructions,
|
|
79
|
+
assignee_id=assignee_id,
|
|
80
|
+
assignee_type=assignee_type,
|
|
81
|
+
verification_criteria=verification_criteria,
|
|
82
|
+
verification_status=verification_status,
|
|
83
|
+
verification_notes=verification_notes,
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
return result.create_task.id
|
|
87
|
+
|
|
88
|
+
async def update_task(
|
|
89
|
+
self,
|
|
90
|
+
task_id: str,
|
|
91
|
+
name: str | None = None,
|
|
92
|
+
description: str | None = None,
|
|
93
|
+
instructions: str | None = None,
|
|
94
|
+
assignee_id: str | None = None,
|
|
95
|
+
assignee_type: AssigneeType | None = None,
|
|
96
|
+
status: TaskStatus | None = None,
|
|
97
|
+
result: str | None = None,
|
|
98
|
+
verification_criteria: str | None = None,
|
|
99
|
+
verification_status: VerificationStatus | None = None,
|
|
100
|
+
verification_notes: str | None = None,
|
|
101
|
+
links: list[ResourceLinkInput] | None = None,
|
|
102
|
+
) -> str:
|
|
103
|
+
"""Update a task's fields, returning its ID.
|
|
104
|
+
|
|
105
|
+
``links`` replaces the whole task links array — fetch the current links,
|
|
106
|
+
modify the list, and pass the full result (see the CLI add-link/remove-link).
|
|
107
|
+
"""
|
|
108
|
+
response = await self._client.update_task(
|
|
109
|
+
task_id=task_id,
|
|
110
|
+
input=UpdateTaskInput(
|
|
111
|
+
name=name,
|
|
112
|
+
description=description,
|
|
113
|
+
instructions=instructions,
|
|
114
|
+
assignee_id=assignee_id,
|
|
115
|
+
assignee_type=assignee_type,
|
|
116
|
+
status=status,
|
|
117
|
+
result=result,
|
|
118
|
+
verification_criteria=verification_criteria,
|
|
119
|
+
verification_status=verification_status,
|
|
120
|
+
verification_notes=verification_notes,
|
|
121
|
+
links=links,
|
|
122
|
+
),
|
|
123
|
+
)
|
|
124
|
+
return response.update_task.id
|
|
125
|
+
|
|
126
|
+
async def delete_task(self, task_id: str) -> None:
|
|
127
|
+
"""Delete a task."""
|
|
128
|
+
await self._client.delete_task(task_id=task_id)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
stratonext_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
stratonext_core/client.py,sha256=5gpdf10sCDBfs3ONqpujv2mGRupua5GnHSLycwKwrZ0,477
|
|
3
|
+
stratonext_core/config.py,sha256=iQzk0hq7qo5KbONfPqM3dKZDRFapOZSciFcXK_6-vwA,917
|
|
4
|
+
stratonext_core/registry.py,sha256=YP-VtNB96JDpWHV4Z8kkBtgFoWzbG6lbt9-75A7dHV0,492
|
|
5
|
+
stratonext_core/agents/__init__.py,sha256=BZGFmDkBoa6PDHPrI-08yykY-xWjMNtXKpmlya3gBKI,58
|
|
6
|
+
stratonext_core/agents/skill.py,sha256=4PW04dXzvCJWtsWC2vBJ1yKACPbiU9mncqy2R29D6Lc,2706
|
|
7
|
+
stratonext_core/approvals/__init__.py,sha256=Xx8jTRQeU3Gc_FHxw8sKl7TVm_RAL6rvGCL4mIzpyl4,64
|
|
8
|
+
stratonext_core/approvals/skill.py,sha256=Zwd43Mss796raPAYY8_xVuxFr7nYNyEZXXp7MaExfwk,4160
|
|
9
|
+
stratonext_core/assets/__init__.py,sha256=0227dc-e2OJbWXF7NiG_bRF--xrBBnckeSstkHlSrFA,58
|
|
10
|
+
stratonext_core/assets/skill.py,sha256=9OB858w2N4XM5YxAzi3iQWMS_5_V85c1oo7v4xf5hk0,5507
|
|
11
|
+
stratonext_core/dossiers/__init__.py,sha256=Flyxv_hSVaC1JieAOXD9oeVkGX0JXgNmC2xZ9CfEdG8,62
|
|
12
|
+
stratonext_core/dossiers/skill.py,sha256=Mzs6yfrMzHS1h_n65WHzUz6U3jL2m-r2OzX6uLfr_SY,3075
|
|
13
|
+
stratonext_core/environments/__init__.py,sha256=XjUOrgEtiYhwsFG91PAMjNWEZTZXaUQ-XdGUpQYb7nY,70
|
|
14
|
+
stratonext_core/environments/skill.py,sha256=EzQ2s55WNel_qhmZcalaC821gDIk7Yg6sqR5VjugUsg,3581
|
|
15
|
+
stratonext_core/jobs/__init__.py,sha256=pKI3pkaCsHvREwebju5C-6GEoY766H1lxS67p5rqzHU,54
|
|
16
|
+
stratonext_core/jobs/skill.py,sha256=C_pjT2C4LR0snuh-Vc4WSISMxF9wi290q-4GYJkKTeE,4662
|
|
17
|
+
stratonext_core/projects/__init__.py,sha256=vTdNpiLzpfgHbYlvTAQSxRCa6FXE3Jalva7rWiQz2-A,62
|
|
18
|
+
stratonext_core/projects/skill.py,sha256=g6YRcMV19_t6sWjxd6ND8vX6eAn9sBXjn4lq3hBKFHA,3182
|
|
19
|
+
stratonext_core/tasks/__init__.py,sha256=PssT4i0Rdg1Gls-BTMPf1GYIpezpYsqRUcYKvKPotw4,56
|
|
20
|
+
stratonext_core/tasks/skill.py,sha256=qjun5wjdflW7r4N16YmTbwZ-WyKuYwYoouORypgzfTE,4655
|
|
21
|
+
stratonext_core-0.0.1.dist-info/METADATA,sha256=Ii8aKmoVWEcAGozuHx5GWtd4ivurZEMMw-APsd2MmJ4,217
|
|
22
|
+
stratonext_core-0.0.1.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
23
|
+
stratonext_core-0.0.1.dist-info/RECORD,,
|